/*  
 *  src/org/metaqtl/adapter/QtlPartitionAdapter.java
 * 
 *  $Author: veyrieras $, $Date: 2006-10-17 15:41:55 $, $Version$
 *
 *  MetaQTL : a Java package for QTL Meta-Analysis
 * 
 *  Copyright (C) 2003-2006  Jean-Baptiste Veyrieras, INRA, France.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * 
 */
package org.metaqtl.adapter;

import org.metaqtl.EMResult;
import org.metaqtl.MetaQtlAnalysis;
import org.metaqtl.MetaQtlData;
import org.metaqtl.MetaQtlResult;
import org.metaqtl.Qtl;
import org.metaqtl.QtlPartition;
import org.metaqtl.Tree;
import org.metaqtl.numrec.NumericalUtilities;

/**
 * This class defines some methods to adapt complient
 * objects into a {@link QtlPartition} object.
 */
public class QtlPartitionAdapter {
	/**
	 * Adapt the given {@link MetaQtlData} into a 
	 * <code>QtlPartition</code> and returns it.
	 * 
	 * @param qtlData the <code>MetaQtlData</code> instance to adapt.
	 * @return a new instance of <code>QtlPartition</code>.
	 */
	public static QtlPartition adapt(MetaQtlData qtlData) {
		
		if (qtlData == null) return null;
		
		QtlPartition qtlPart = new QtlPartition();
		
		qtlPart.nqtl   = qtlData.getQtlNumber();
		qtlPart.np     = qtlData.getTraitClusterNumber();
		qtlPart.pnames = qtlData.getTraitClusterNames();
		qtlPart.proba  = new double[qtlPart.nqtl][qtlPart.np];
		
		qtlPart.qtlPos      = new double[qtlPart.nqtl];
		qtlPart.qtlCI       = new double[qtlPart.nqtl];
		qtlPart.qtlNames    = new String[qtlPart.nqtl];
		
		int k=0;
		
		for(int i=0;i<qtlPart.np;i++) {
			
			Double[][] X = qtlData.getDataPoints(i, false);
			
			for(int j=0;j<qtlData.getTraitClusterSize(i);j++) {
				
				qtlPart.proba[k][i] = 1.0;
				qtlPart.qtlPos[k]   = X[0][j].doubleValue();
				qtlPart.qtlCI[k]    = X[1][j].doubleValue()*3.92;
				
				Qtl qtl = qtlData.getQtl(i, j);
				
				if (qtl.name!=null)
					qtlPart.qtlNames[k]=qtl.name;
				else
					qtlPart.qtlNames[k]=new String("QTL_"+k);
				
				k++;
			}
		}	
		
		return qtlPart;
	}
	/**
	 * Adapt the {@link MetaQtlAnalysis} <code>analysis</code> for
	 * a given value of the number of clusters <code>k</code> and a 
	 * given trait name <code>code</code>.
	 * into a new instance of {@link QtlPartition}.
	 *  
	 * @param result a meta-analysis result.
	 * @param k the number of clusters.
	 * @return a new instance of <code>QtlPartition</code> with
	 * as many partitions as the value of <code>k</code>.
	 */
	public static QtlPartition adapt(MetaQtlAnalysis analysis, String chrom, String trait, int k) {
		
		if (analysis == null) return null;
		
		int cidx = analysis.getChromIdx(chrom);
		
		MetaQtlResult result = analysis.getResult(cidx, trait);
		
		return adapt(result, analysis.qtlByChrom[cidx], k);
		
	}
	
	public static QtlPartition adapt(MetaQtlResult result, Qtl[] qtls, int k) {
		
		if (result == null) return null; 
		// Chek if k is in the correct range
		if (k > result.nmqc) k = result.nmqc;
		if (k < 0) k = 1;
		
		QtlPartition qtlPart = new QtlPartition();
		
		qtlPart.nqtl   		= result.nqtl;
		qtlPart.np     		= k;
		qtlPart.pnames 		= new String[k];
		qtlPart.proba  		= new double[qtlPart.nqtl][k];
		qtlPart.qtlPos      = new double[qtlPart.nqtl];
		qtlPart.qtlCI       = new double[qtlPart.nqtl];
		qtlPart.qtlNames    = new String[qtlPart.nqtl];
		
		for(int i=0;i<result.nqtl;i++) {
			qtlPart.qtlPos[i]   = result.x[i];
			qtlPart.qtlCI[i]    = NumericalUtilities.sd2ci(result.sd[i]);
			qtlPart.qtlNames[i] = qtls[result.qtlIdx[i]].name;
		}
		
		EMResult clustering = result.getClustering(k);
		
		if (clustering != null) {
		
			for(int i=0;i<result.nqtl;i++) {
				for(int j=0;j<clustering.k;j++) {
					qtlPart.proba[i][j] = clustering.z[j][i];
				}				
			}	
		
		}
		
		Tree tree = result.getQtlTree();
		
		if (tree != null) {
			
			qtlPart.setTree(tree);
			
		}
		
		return qtlPart;
	}
	
}
