/*
* Copyright (c) 2003-2012 Fred Hutchinson Cancer Research Center
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fhcrc.cpl.toolbox.normalize;
import org.apache.log4j.Logger;
import org.fhcrc.cpl.toolbox.ApplicationContext;
import org.fhcrc.cpl.toolbox.gui.chart.PanelWithLineChart;
import org.fhcrc.cpl.toolbox.gui.chart.PanelWithScatterPlot;
import org.fhcrc.cpl.toolbox.statistics.RInterface;
import org.fhcrc.cpl.toolbox.filehandler.TempFileManager;
import java.io.*;
import java.util.List;
import java.util.ArrayList;
/**
* Apply Pei's normalization code to a peptide array
*
*/
public class Normalizer
{
private static Logger _log = Logger.getLogger(Normalizer.class);
private static final String normalizationScriptName = "normalize_array.R";
private static final String intensityFileName = "ArrayIntensities.tsv";
private static final String normalizedFileName = "NormalizedIntensities.tsv";
public static boolean normalize(List<float[]> rows)
{
return normalize(rows, false);
}
/**
* Returns true on success, false otherwise
*/
public static boolean normalize(List<float[]> rows, boolean showCharts)
{
StringBuffer fakeTempFileCaller =
new StringBuffer("fake StringBuffer to identify files that should be cleaned up for Normalizer");
File normalizationScript;
File intensityFile;
File normalizedFile;
List<float[]> origCols = null;
if (showCharts)
{
origCols = new ArrayList<float[]>();
for (float dummy : rows.get(0))
origCols.add(new float[rows.size()]);
for (int i=0; i<rows.get(0).length; i++)
{
for (int j=0; j<rows.size(); j++)
origCols.get(i)[j] = rows.get(j)[i];
}
}
try
{
InputStream in = Normalizer.class.getResourceAsStream(normalizationScriptName);
normalizationScript = TempFileManager.createTempFile(normalizationScriptName, fakeTempFileCaller);
OutputStream out = new FileOutputStream(normalizationScript);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0)
out.write(buf, 0, len);
in.close();
out.close();
}
catch (IOException e)
{
ApplicationContext.errorMessage("Error writing temp files", e);
TempFileManager.deleteTempFiles(fakeTempFileCaller);
return false;
}
try
{
intensityFile = TempFileManager.createTempFile(intensityFileName, fakeTempFileCaller);
writeIntensityFile(rows, intensityFile);
RInterface.runRScript(normalizationScript, fakeTempFileCaller);
normalizedFile = TempFileManager.createTempFile(normalizedFileName, fakeTempFileCaller);
readIntensityFile(rows, normalizedFile);
}
catch (Exception e)
{
ApplicationContext.errorMessage("Error running normalization in R. Make sure R is on your path before launching msInspect. R temporary files can be viewed in the directory " + TempFileManager.getTmpDir(), e);
return false;
}
_log.debug("Normalization complete.");
if (showCharts)
{
List<float[]> newCols = new ArrayList<float[]>();
for (float dummy : rows.get(0))
newCols.add(new float[rows.size()]);
for (int i=0; i<rows.get(0).length; i++)
{
for (int j=0; j<rows.size(); j++)
newCols.get(i)[j] = rows.get(j)[i];
}
PanelWithLineChart pwlc = new PanelWithLineChart();
pwlc.setName("IntensityNorm");
for (int i=0; i<origCols.size(); i++)
{
pwlc.addData(origCols.get(i), newCols.get(i), "Set" + (i+1));
}
pwlc.displayInTab();
}
TempFileManager.deleteTempFiles(fakeTempFileCaller);
return true;
}
/**
* Write a tsv file containing *only* the intensities for the array
*/
private static void writeIntensityFile(List rows, File intensityFile) throws IOException
{
PrintWriter pw = new PrintWriter(new FileOutputStream(intensityFile));
float[] intensities = (float[])rows.get(1);
for (int i = 1; i <= intensities.length; i++)
pw.print((i > 1 ? "\t" : "" ) + "intensity" + i);
pw.print("\n");
for (int r = 0; r < rows.size(); r++)
{
intensities = (float[])rows.get(r);
for (int i = 0; i < intensities.length; i++)
pw.print((i > 0 ? "\t" : "" ) + intensities[i]);
pw.print("\n");
}
pw.close();
}
/**
* Read a tsv file containing the normalized intensities for the array.
* Assumes that the normalization script wrote everything in the same
* order as it read them in.
*/
private static void readIntensityFile(List<float[]> rows, File normalizedFile)
throws IOException
{
BufferedReader br = new BufferedReader(new FileReader(normalizedFile));
String header = br.readLine();
for (int r = 0; r < rows.size(); r++)
{
String line = br.readLine();
String[] tokens = line.split("\t");
float[] intensities = rows.get(r);
if (tokens.length != intensities.length)
_log.error("Length mismatch on reading normalized intensities " + line);
for (int i = 0; i < tokens.length; i++)
intensities[i] = Float.parseFloat(tokens[i]);
}
br.close();
}
}