/******************************************************************************* * GenPlay, Einstein Genome Analyzer * Copyright (C) 2009, 2014 Albert Einstein College of Medicine * * 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 3 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, see <http://www.gnu.org/licenses/>. * Authors: Julien Lajugie <julien.lajugie@einstein.yu.edu> * Nicolas Fourel <nicolas.fourel@einstein.yu.edu> * Eric Bouhassira <eric.bouhassira@einstein.yu.edu> * * Website: <http://genplay.einstein.yu.edu> ******************************************************************************/ package edu.yu.einstein.genplay.core.operation.SCWList; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import edu.yu.einstein.genplay.core.operation.Operation; import edu.yu.einstein.genplay.core.operationPool.OperationPool; import edu.yu.einstein.genplay.dataStructure.list.genomeWideList.SCWList.SCWList; import edu.yu.einstein.genplay.dataStructure.list.listView.ListView; import edu.yu.einstein.genplay.dataStructure.scoredChromosomeWindow.ScoredChromosomeWindow; /** * Computes the distribution of the scores of a {@link SCWList} * @author Julien Lajugie */ public class SCWLOScoreDistribution implements Operation<double [][][]>{ private final SCWList[] scwListArray; // input list private final double scoreBinSize; // size of the bins of score private final int graphType; // type of the plot (window count or bp count) private boolean stopped = false; // true if the operation must be stopped /** * Window count plot */ public static final int WINDOW_COUNT_GRAPH = 1; /** * Base count plot */ public static final int BASE_COUNT_GRAPH = 2; /** * Creates an instance of {@link SCWLOScoreDistribution} * @param scwListArray input list * @param scoreBinSize size of the bins of score * @param graphType type of graph (window count or base count) */ public SCWLOScoreDistribution(SCWList[] scwListArray, double scoreBinSize, int graphType) { this.scwListArray = scwListArray; this.scoreBinSize = scoreBinSize; this.graphType = graphType; } @Override public double[][][] compute() throws IllegalArgumentException, IOException, InterruptedException, ExecutionException { if(scoreBinSize <= 0) { throw new IllegalArgumentException("the size of the score bins must be strictly positive"); } double[][][] finalResult = new double[scwListArray.length][][]; for (int i = 0; i < scwListArray.length; i++) { finalResult[i] = singleSCWListResult(scwListArray[i]); } return finalResult; } @Override public String getDescription() { return "Operation: Show Score Distribution Histogram"; } @Override public String getProcessingDescription() { return "Plotting Score Distribution"; } @Override public int getStepCount() { return scwListArray.length; } /** * Generates the scatter plot data for the specified list * @param scwList {@link SCWList} * @return the scater plot data for the specified list * @throws InterruptedException * @throws ExecutionException */ public double[][] singleSCWListResult (final SCWList scwList) throws InterruptedException, ExecutionException { // search the greatest and smallest score double max = Math.max(0, scwList.getStatistics().getMaximum()); double min = Math.min(0, scwList.getStatistics().getMinimum()); // search the score of the first bin final double startPoint = Math.floor(min / scoreBinSize) * scoreBinSize; // distance from the max to the first score final double distanceMinMax = max - startPoint; // the +2 is because of the rounding (+1) and also because we want one more value // because the data are arrange this way: // count(res[i][1] to res[i+1][1]) = res[i][1] // meaning that we need to have the value for i + 1 double result[][] = new double[(int)(distanceMinMax / scoreBinSize) + 2][2]; int i = 0; // we add max + scoreBinSize to have a value for i + 1 (cf previous comment) while (((startPoint + (i * scoreBinSize)) <= (max + scoreBinSize)) && !stopped) { result[i][0] = startPoint + (i * scoreBinSize); i++; } final OperationPool op = OperationPool.getInstance(); final Collection<Callable<double[]>> threadList = new ArrayList<Callable<double[]>>(); for (final ListView<ScoredChromosomeWindow> currentList: scwList) { Callable<double[]> currentThread = new Callable<double[]>() { @Override public double[] call() throws Exception { if (currentList == null) { return null; } // create an array for the counts double[] chromoResult = new double[(int)(distanceMinMax / scoreBinSize) + 2]; // count the bins for(int j = 0; (j < currentList.size()) && !stopped; j++) { if (currentList.get(j).getScore() != 0) { if (graphType == WINDOW_COUNT_GRAPH) { chromoResult[(int)((currentList.get(j).getScore() - startPoint) / scoreBinSize)]++; } else if (graphType == BASE_COUNT_GRAPH) { chromoResult[(int)((currentList.get(j).getScore() - startPoint) / scoreBinSize)] += currentList.get(j).getStop() - currentList.get(j).getStart(); } else { throw new IllegalArgumentException("Invalid Plot Type"); } } } op.notifyDone(); return chromoResult; } }; threadList.add(currentThread); } List<double[]> threadResult = op.startPool(threadList); if (threadResult == null) { return null; } for (double [] currentResult: threadResult) { if (currentResult != null) { for (i = 0; i < currentResult.length; i++) { result[i][1] += currentResult[i]; } } } return result; } @Override public void stop() { stopped = true; } }