/*
* 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;
import org.fhcrc.cpl.toolbox.proteomics.feature.Spectrum;
import org.fhcrc.cpl.toolbox.proteomics.Scan;
import org.fhcrc.cpl.toolbox.datastructure.FloatRange;
import org.fhcrc.cpl.viewer.feature.extraction.SpectrumResampler;
import java.util.ArrayList;
/**
* User: mbellew
* Date: Sep 15, 2004
* Time: 6:42:33 PM
*
* 20100802: dhmay making resample frequency into a variable that can be modified
*/
public class ExtractMaxima2D
{
static float smoothYfactor = 4.0F;
static float smoothXfactor = 4.0F;
private ExtractMaxima2D()
{
}
public static Spectrum.Peak[] analyze(Scan[] scans, FloatRange rangePeaks)
{
return analyze(scans, rangePeaks, new Smooth2D(), 1);
}
/** find local maxima after smoothing using smooth2d,
*
* peaks returned with scan numbers
*/
public static Spectrum.Peak[] analyze(Scan[] scans, FloatRange rangePeaks, Smooth2D smooth2d, float minPeak)
{
// use larger ranger for resample to avoid edge checking later
FloatRange range = new FloatRange(rangePeaks.min - .5F, rangePeaks.max + .5F);
// allocate two extra scans to avoid edge checking later
float[][] spectra = new float[scans.length + 2][];
for (int i = 0; i < scans.length; i++)
spectra[i + 1] = Spectrum.Resample(scans[i].getSpectrum(), range, SpectrumResampler.resampleFrequency);
spectra[0] = spectra[1];
spectra[spectra.length - 1] = spectra[spectra.length - 2];
Spectrum.Peak[] peaks = analyze(spectra, range.min, SpectrumResampler.resampleInterval, smooth2d, minPeak);
// fix up peaks to use scan num
for (int p=0 ; p<peaks.length ; p++)
{
peaks[p].setScan(scans[peaks[p].scan-1].getNum());
}
return peaks;
}
/**
* scans.length should be 2^n for efficiency
*
* NOTE: will not return maxima in first or last scan, or bottom/top mz value
* NOTE: returns array index, not scan numbers
*/
public static Spectrum.Peak[] analyze(float[][] spectra, float startMz, double interval, Smooth2D smooth2d, float minPeak)
{
//
// smooth
//
if (null != smooth2d)
smooth2d.smooth(spectra);
//
// find maxima
//
ArrayList peaks = new ArrayList();
float[] s0 = null;
float[] s1 = spectra[0];
float[] s2 = spectra[1];
int imzMax = spectra[0].length;
for (int ispectra=1 ; ispectra<spectra.length-1 ; ispectra++)
{
s0 = s1;
s1 = s2;
s2 = spectra[ispectra+1];
int[] scanPeaks = Spectrum.PickPeakIndexes(s1, minPeak);
for (int p = 0 ; p<scanPeaks.length ; p++)
{
int imz = scanPeaks[p];
float mz = (float)(startMz + imz * interval);
if (imz < 1 || imz >= imzMax-1 )
continue;
float intensity = s1[imz];
assert intensity >= s1[imz-1] && intensity >= s1[imz+1];
if ( intensity < s0[imz - 1] ||
intensity < s0[imz] ||
intensity < s0[imz + 1] ||
intensity < s2[imz - 1] ||
intensity < s2[imz] ||
intensity < s2[imz + 1])
continue;
//int scanNum =scans[ispectra-1].getNum();
peaks.add(new Spectrum.Peak(ispectra, mz, intensity));
}
}
Spectrum.Peak[] arr = (Spectrum.Peak[]) peaks.toArray(new Spectrum.Peak[peaks.size()]);
return arr;
}
}