/*
* 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.viewer.feature.extraction;
import org.apache.log4j.Logger;
import org.fhcrc.cpl.toolbox.proteomics.feature.Feature;
import org.fhcrc.cpl.toolbox.proteomics.feature.FeatureSet;
import org.fhcrc.cpl.viewer.feature.extraction.strategy.FeatureStrategy;
import org.fhcrc.cpl.viewer.feature.extraction.strategy.BaseFeatureStrategy;
import org.fhcrc.cpl.viewer.feature.extraction.strategy.FeatureStrategyPeakClusters;
import org.fhcrc.cpl.toolbox.proteomics.MSRun;
import org.fhcrc.cpl.toolbox.datastructure.FloatRange;
import org.fhcrc.cpl.toolbox.ApplicationContext;
import org.fhcrc.cpl.toolbox.CPUTimer;
import org.fhcrc.cpl.toolbox.proteomics.Scan;
import org.fhcrc.cpl.viewer.feature.extraction.strategy.FeatureStrategyWindow;
import java.util.*;
/**
* 20110917: adding scan window size parameters
*/
public class FeatureFinder
{
static Logger _log = Logger.getLogger(FeatureFinder.class);
public static final int DEFAULT_ACCURATE_MASS_ADJUSTMENT_SCANS = 3;
public static final Class<? extends FeatureStrategy> DEFAULT_FEATURE_FINDING_CLASS =
FeatureStrategyPeakClusters.class;
protected MSRun _run;
protected int _maxCharge;
protected FloatRange _mzRange;
protected int _startScan;
protected int _scanCount;
int _accurateMassAdjustmentScans = 0; // Number of scans around a feature to consider for accurate mass adjustment
protected FeatureStrategy _featureStrategy;
protected CPUTimer timerMassAdjustment = new CPUTimer("FeatureFinder.massAdjustment");
protected int _dumpWindowSize = 0;
protected boolean _peakRidgeWalkSmoothed =
PeakExtractor.DEFAULT_PEAK_RIDGE_WALK_SMOOTHED;
protected boolean _plotStatistics = false;
protected int _scanWindowSize = FeatureStrategyWindow.DEFAULT_WINDOW_WIDTH;
public FeatureFinder()
{
}
public FeatureFinder(MSRun run, int startScan, int scanCount, int maxCharge,
FloatRange mzRange, Class<? extends FeatureStrategy> featureStrategyClass,
boolean plotStatistics) {
this(run, startScan, scanCount, maxCharge, mzRange, featureStrategyClass, plotStatistics, FeatureStrategyWindow.DEFAULT_WINDOW_WIDTH);
}
public FeatureFinder(MSRun run, int startScan, int scanCount, int maxCharge,
FloatRange mzRange, Class<? extends FeatureStrategy> featureStrategyClass,
boolean plotStatistics, int scanWindowSize)
{
this();
init(run, startScan, scanCount, maxCharge, mzRange,
featureStrategyClass, plotStatistics, scanWindowSize);
}
public void init(MSRun run, int startScan, int scanCount, int maxCharge,
FloatRange mzRange, Class<? extends FeatureStrategy> featureStrategyClass,
boolean plotStatistics, int scanWindowSize)
{
assert(mzRange.min < mzRange.max);
_run = run;
_startScan = startScan;
_scanCount = scanCount;
_maxCharge = maxCharge;
_mzRange = mzRange;
_plotStatistics = plotStatistics;
_featureStrategy =
BaseFeatureStrategy.getInstance(run, startScan,
scanCount,
maxCharge, mzRange,
featureStrategyClass, _plotStatistics);
_featureStrategy.setDumpWindowSize(_dumpWindowSize);
if (_featureStrategy instanceof FeatureStrategyWindow)
((FeatureStrategyWindow) _featureStrategy).setWindowWidth(scanWindowSize);
}
/**
* Return the mz range for the given scan. If computed lowMz and highMz were
* supplied, use those; otherwise try startMz and endMz.
*/
public static FloatRange getMzExtractionRange(MSRun.MSScan scan)
{
if (scan.getLowMz() >= 0 && scan.getHighMz() >= 0)
return new FloatRange(scan.getLowMz() - 1, scan.getHighMz() + 1);
return new FloatRange(scan.getStartMz() - 1, scan.getEndMz() + 1);
}
/**
* Return the mz range for the given run. First, check scan zero.
* If range is no good, use the mzRange computed when the run was
* read.
*/
public static FloatRange getMzExtractionRange(MSRun run)
{
FloatRange range = getMzExtractionRange(run.getScan(0));
if (range.min >= 0 && range.max >= 0)
return range;
return new FloatRange(run.getMzRange().min - 1, run.getMzRange().max + 1);
}
// protected float[][] CombineScans(Scan[] scans, FloatRange range, int resample_freq)
// {
// float[][] zeroChargeSpectrum = null;
// int countScans = 0;
// for (int s = 0; s < scans.length; s++)
// {
// if (null == scans[s]) continue;
// countScans++;
// float[][] spectrumRaw = scans[s].getSpectrum();
// float[][] t = Spectrum.ResampleSpectrum(spectrumRaw, range, resample_freq, true);
// if (null == zeroChargeSpectrum)
// zeroChargeSpectrum = t;
// else
// {
// int len = t[1].length;
// for (int i = 0; i < len; i++)
// zeroChargeSpectrum[1][i] += t[1][i];
// }
// }
// int len = zeroChargeSpectrum[1].length;
// if (countScans > 1)
// for (int i = 0; i < len; i++)
// zeroChargeSpectrum[1][i] /= countScans;
// return zeroChargeSpectrum;
// }
// implement this in order to use the analyzeScanAtATime() helper
protected Collection<Feature> analyze1D(Scan scan) throws InterruptedException
{
throw new java.lang.UnsupportedOperationException();
}
// implement this in order to use the analyzeWindow() helper
protected Collection<Feature> analyze2D(Scan[] scans) throws InterruptedException
{
throw new java.lang.UnsupportedOperationException();
}
protected static void _logDebug(String s)
{
_log.debug(s);
}
public FeatureSet findPeptides() throws InterruptedException
{
Feature[] features = _featureStrategy.findPeptides();
FeatureSet featureSet = new FeatureSet(features);
assert timerMassAdjustment.start();
// if data are centroided, or if requested explicitly for profile
// mode data, attempt to get accurate masses
if (getAccurateMassAdjustmentScans() > 0 ||
_run.getHeaderInfo().getDataProcessing().getCentroided() == 1)
{
//dhmay changing 20100316, to allow default-setting for the mass adjustment within the strategy
AccurateMassAdjuster massAdjuster = _featureStrategy.getAccurateMassAdjuster();
if (massAdjuster == null)
massAdjuster = new AccurateMassAdjuster();
massAdjuster.setScanWindowSize(getAccurateMassAdjustmentScans());
massAdjuster.adjustAllMasses(_run, features);
}
assert timerMassAdjustment.stop();
addInfoToFeatureSet(featureSet);
Arrays.sort(features, new Feature.IntensityDescComparator());
return featureSet;
}
protected void addInfoToFeatureSet(FeatureSet featureSet)
{
String revision = (String)ApplicationContext.getProperty("REVISION");
if (null == revision) revision = "";
if (revision.toLowerCase().startsWith("revision:"))
revision = revision.substring("Revision:".length()).trim();
Map<String, Object> m = featureSet.getProperties();
m.put("revision", revision);
m.put("algorithm", this.getClass().getName());
m.put("java.vendor", System.getProperty("java.vendor"));
m.put("java.version", System.getProperty("java.version"));
m.put("user.name", System.getProperty("user.name"));
m.put("date", (new Date()).toString());
}
/**
* Utility method
* @param run
* @param start
* @param count
* @return
*/
public static Scan[] getScans(MSRun run, int start, int count)
{
//eh?
boolean bSkipLockSpray = false;
start = Math.max(0, start);
int maxScanIndex = run.getScanCount();
List<Scan> scanList = new ArrayList<Scan>();
for (int i = start; i < maxScanIndex && scanList.size() < count; i++)
{
Scan scan = run.getScan(i);
if (bSkipLockSpray && 1 == (scan.getNum() % 20))
continue;
scanList.add(scan);
}
return scanList.toArray(new Scan[scanList.size()]);
}
public void setStatusListener(BaseFeatureStrategy.StatusListener status)
{
_featureStrategy.setStatusListener(status);
}
public void setAccurateMassAdjustmentScans(int accurateMassAdjustmentScans)
{
_accurateMassAdjustmentScans = accurateMassAdjustmentScans;
}
public int getAccurateMassAdjustmentScans()
{
return _accurateMassAdjustmentScans;
}
public void setDumpWindowSize(int dumpWindowSize)
{
_dumpWindowSize = dumpWindowSize;
if (_featureStrategy != null)
_featureStrategy.setDumpWindowSize(dumpWindowSize);
}
public int getDumpWindowSize()
{
return _dumpWindowSize;
}
public boolean isPeakRidgeWalkSmoothed()
{
return _peakRidgeWalkSmoothed;
}
public void setPeakRidgeWalkSmoothed(boolean peakRidgeWalkSmoothed)
{
_peakRidgeWalkSmoothed = peakRidgeWalkSmoothed;
if (_featureStrategy != null)
_featureStrategy.setPeakRidgeWalkSmoothed(peakRidgeWalkSmoothed);
}
public void plotStatistics()
{
if (_plotStatistics && _featureStrategy != null)
_featureStrategy.plotStatistics();
}
}