package org.seqcode.math.diff; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.seqcode.gseutils.Pair; import org.seqcode.viz.scatter.ScatterPlotConfigured; import Jama.Matrix; /** * Normalization: parent class for normalization methods that calculate scaling factors. * * @author Shaun Mahony * @version %I%, %G% */ public abstract class Normalization { protected double [] scalingFactors; //Overall scaling factors protected double [] depthScaling; //Seq depth scaling factor protected double [] propScaling; //RNA composition proportion scaling protected final double LOG_2 = Math.log(2.0); public Normalization(int numSamples){ scalingFactors = new double[numSamples]; depthScaling = new double[numSamples]; propScaling = new double[numSamples]; for(int c=0; c<numSamples; c++){ scalingFactors[c]=1.0; depthScaling[c]=1.0; propScaling[c] =1.0; } } /** * normalize: method that must be implemented by Normalization classes. * Input a CountsDataset object, output the scaling factors array. * @param data * @return */ public abstract double[] normalize(CountsDataset data); /** * Return a string describing the normalization method. * @return */ public abstract String selfDescriptor(); /** * Get scaling factors array * @return */ public double[] getScalingFactors(){return scalingFactors;} /** * Get scaling factor for experiment x * @param x * @return */ public double getScalingFactor(int x){return scalingFactors[x];} /** * Print pairwise MA values to files * @param data */ public void printPairwiseMAData(CountsDataset data){ int ref = 0; //Set one sample as the reference (the deepest sequenced sample in the focal condition) double maxTotal=0; for(int s=0; s<data.numSamples; s++) if(data.design[s] == data.focalCondition) if(data.totals[s]>maxTotal){ ref=s; maxTotal=data.totals[s]; } //Scale all samples against the reference for(int x=0; x<data.numSamples; x++){ if(x!=ref){ //Make an MAval set from the current sample List<MAval> MA = new ArrayList<MAval>(); for(int d=0; d<data.numUnits; d++) if(data.getCount(d,x)>0 && data.getCount(d,ref)>0) MA.add(new MAval(data.getCount(d,x), data.getCount(d,ref), data.getTotal(x), data.getTotal(ref))); //Print to file Pair<String,String> refName = data.getExptName(ref); Pair<String,String> currName = data.getExptName(x); String fileName = refName.car()+"-"+refName.cdr()+"_vs_"+currName.car()+"-"+currName.cdr()+".ma.txt"; try { FileWriter fw = new FileWriter(fileName); fw.write("Point\tA\tM\n"); int count=0; for(MAval v : MA){ fw.write(count+"\t"+v.A+"\t"+v.M+"\n"); count++; } fw.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * Generate MA images. May be over-ridden by subclasses. * @param data */ public void savePairwiseMAPlots(CountsDataset data, boolean rasterImage){ int ref = 0; //Set one sample as the reference (the deepest sequenced sample in the focal condition) double maxTotal=0; for(int s=0; s<data.numSamples; s++) if(data.design[s] == data.focalCondition) if(data.totals[s]>maxTotal){ ref=s; maxTotal=data.totals[s]; } //Scale all samples against the reference for(int x=0; x<data.numSamples; x++){ if(x!=ref){ //Make an MAval set from the current sample List<MAval> MA = new ArrayList<MAval>(); for(int d=0; d<data.numUnits; d++) if(data.getCount(d,x)>0 && data.getCount(d,ref)>0) MA.add(new MAval(data.getCount(d,x), data.getCount(d,ref), data.getTotal(x), data.getTotal(ref))); //Make the MA matrix Matrix maMatrix = new Matrix(MA.size(),2); int count=0; for(MAval v : MA){ maMatrix.set(count, 0, v.A); maMatrix.set(count, 1, v.M); count++; } //Image name Pair<String,String> refName = data.getExptName(ref); Pair<String,String> currName = data.getExptName(x); String fileName = refName.car()+"-"+refName.cdr()+"_vs_"+currName.car()+"-"+currName.cdr()+".ma"; if(rasterImage) fileName = fileName+".png"; else fileName = fileName+".svg"; //Generate image ScatterPlotConfigured plotter = new ScatterPlotConfigured("MA plot"); plotter.saveMAplot(maMatrix, null, Math.log(propScaling[x]/propScaling[ref])/LOG_2, fileName, rasterImage); } } } }