package plugins.qtlfinder2;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.TreeMap;
import matrix.DataMatrixInstance;
import matrix.general.DataMatrixHandler;
import org.molgenis.cluster.DataName;
import org.molgenis.cluster.DataSet;
import org.molgenis.cluster.DataValue;
import org.molgenis.data.Data;
import org.molgenis.framework.db.Database;
import org.molgenis.framework.db.DatabaseException;
import org.molgenis.framework.db.Query;
import org.molgenis.framework.db.QueryRule;
import org.molgenis.framework.db.QueryRule.Operator;
import org.molgenis.model.elements.Field;
import org.molgenis.pheno.ObservableFeature;
import org.molgenis.util.Entity;
import org.molgenis.xgap.Locus;
import org.molgenis.xgap.Marker;
import plugins.qtlfinder.QTLInfo;
import plugins.qtlfinder.QtlFinder;
import plugins.qtlfinder.QtlPlotDataPoint;
import plugins.reportbuilder.Statistics;
import plugins.rplot.MakeRPlot;
public class PlotHelper
{
public static List<QTLInfo> createQTLReportFor(Entity entity, int plotWidth, int plotHeight, Database db)
throws Exception
{
List<QTLInfo> result = new ArrayList<QTLInfo>();
List<Data> allData = db.find(Data.class);
DataMatrixHandler dmh = new DataMatrixHandler(db);
// List<MatrixLocation> matrixLocations = new
// ArrayList<MatrixLocation>();
for (Data d : allData)
{
// if something fails with this matrix, don't break the loop
// e.g. backend file is missing
try
{
// loop over Text data (can't be QTL)
if (d.getValueType().equals("Text"))
{
continue;
}
// match row/col type of the matrix to the type of entity
// queried
// and one of the dimensions is Marker
if ((d.getTargetType().equals(entity.get(Field.TYPE_FIELD)) || d.getFeatureType().equals(
entity.get(Field.TYPE_FIELD)))
&& (d.getTargetType().equals("Marker") || d.getFeatureType().equals("Marker")))
{
// create instance and get name of the row/col we want
DataMatrixInstance instance = dmh.createInstance(d, db);
String name = entity.get(ObservableFeature.NAME).toString();
long locus;
if (entity instanceof Locus)
{
locus = ((Locus) entity).getBpStart();
}
else
{
locus = 0;
}
// find out if the name is in the row or col names
List<String> rowNames = instance.getRowNames();
List<String> colNames = instance.getColNames();
int rowIndex = rowNames.indexOf(name);
int colIndex = colNames.indexOf(name);
// if its in row, do row stuff
if (rowIndex != -1)
{
Double[] Dvalues = Statistics.getAsDoubles(instance.getRow(rowIndex));
Double[] absDvalues = Statistics.getAsAbsDoubles(instance.getRow(rowIndex));
int maxIndex = Statistics.getIndexOfMax(absDvalues);
double peakDouble = Dvalues[maxIndex];
String peakMarker = colNames.get(maxIndex);
List<Double> DvaluesList = Arrays.asList(Dvalues);
QTLInfo qtl = new QTLInfo(d, peakMarker, peakDouble, colNames, DvaluesList);
HashMap<String, Marker> markerInfo = QtlFinder.getMarkerInfo(colNames, db);
qtl.setMarkerAnnotations(markerInfo);
try
{
File img;
TreeMap<Long, QtlPlotDataPoint> data = QtlFinder.sortQtlPlotData(colNames, DvaluesList,
markerInfo);
if (isEffectSizeData(db, d))
{
img = new MakeRPlot().qtlPlot(name, data, locus, plotWidth, plotHeight, "Effect size",
"eff");
}
else
{
img = new MakeRPlot().qtlPlot(name, data, locus, plotWidth, plotHeight, "LOD score",
"qtl");
}
qtl.setPlot(img.getName());
}
catch (Exception e)
{
e.printStackTrace();
// too bad, image failed
}
result.add(qtl);
}
// if its in col, and not in row, do col stuff
// we assume its not in row and col at the same time, then
// its not QTL data but correlations or so
if (rowIndex == -1 && colIndex != -1)
{
Double[] Dvalues = Statistics.getAsDoubles(instance.getCol(colIndex));
Double[] absDvalues = Statistics.getAsAbsDoubles(instance.getCol(colIndex));
int maxIndex = Statistics.getIndexOfMax(absDvalues);
double peakDouble = Dvalues[maxIndex];
String peakMarker = rowNames.get(maxIndex);
List<Double> DvaluesList = Arrays.asList(Dvalues);
QTLInfo qtl = new QTLInfo(d, peakMarker, peakDouble, rowNames, DvaluesList);
HashMap<String, Marker> markerInfo = QtlFinder.getMarkerInfo(rowNames, db);
qtl.setMarkerAnnotations(markerInfo);
try
{
File img;
TreeMap<Long, QtlPlotDataPoint> data = QtlFinder.sortQtlPlotData(rowNames, DvaluesList,
markerInfo);
if (isEffectSizeData(db, d))
{
img = new MakeRPlot().qtlPlot(name, data, locus, plotWidth, plotHeight, "Effect size",
"eff");
}
else
{
img = new MakeRPlot().qtlPlot(name, data, locus, plotWidth, plotHeight, "LOD score",
"qtl");
}
qtl.setPlot(img.getName());
}
catch (Exception e)
{
e.printStackTrace();
// too bad, image failed
}
result.add(qtl);
}
}
}
catch (Exception e)
{
e.printStackTrace();
// too bad, data matrix failed
}
}
return result;
}
public static boolean isEffectSizeData(Database db, Data data) throws DatabaseException
{
List<DataSet> dsRef = db.find(DataSet.class, new QueryRule(DataSet.NAME, Operator.EQUALS, "Default_tags"));
if (dsRef.size() != 1)
{
throw new DatabaseException("0 or >1 results when querying dataset");
}
Query<DataName> q = db.query(DataName.class);
q.addRules(new QueryRule(DataName.NAME, Operator.EQUALS, "Effect_size"));
q.addRules(new QueryRule(DataName.DATASET, Operator.EQUALS, dsRef.get(0).getId()));
List<DataName> dnRef = q.find();
if (dnRef.size() != 1)
{
throw new DatabaseException("0 or >1 results when querying dataname");
}
Query<DataValue> q2 = db.query(DataValue.class);
q2.addRules(new QueryRule(DataValue.DATANAME, Operator.EQUALS, dnRef.get(0).getId()));
q2.addRules(new QueryRule(DataValue.VALUE, Operator.EQUALS, data.getId()));
List<DataValue> dvRef = q2.find();
if (dvRef.size() == 0)
{
return false;
}
else
{
return true;
}
}
}