/* * 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.proteomics.feature; import org.fhcrc.cpl.toolbox.proteomics.Clusterer2D; import org.apache.log4j.Logger; import java.util.*; /** * 2-dimensional clusterer for clustering Features */ public class FeatureClusterer extends Clusterer2D { private static Logger _log = Logger.getLogger(FeatureClusterer.class); private List<FeatureSet> _featureSets = new ArrayList<FeatureSet>(); //different modes for clustering by mass or mz public static final int MASS_MZ_MODE_MASS=0; public static final int MASS_MZ_MODE_MZ=1; public static final int DEFAULT_MASS_MZ_MODE=MASS_MZ_MODE_MZ; //constants used to specify how mass tolerance should be calculated public static final int DELTA_MASS_TYPE_ABSOLUTE = 0; public static final int DELTA_MASS_TYPE_PPM = 1; public static final int DEFAULT_DELTA_MASS_TYPE = DELTA_MASS_TYPE_ABSOLUTE; //different modes for clustering by elution time public static final int ELUTION_MODE_TIME=0; public static final int ELUTION_MODE_SCAN=1; public static final int DEFAULT_ELUTION_MODE=ELUTION_MODE_TIME; protected int _massMzMode = DEFAULT_MASS_MZ_MODE; protected int _elutionMode = DEFAULT_ELUTION_MODE; protected int _massType = DEFAULT_DELTA_MASS_TYPE; /** * Initialize the list of featuresets */ public FeatureClusterer() { _featureSets = new ArrayList<FeatureSet>(); } public FeatureClusterer(int massMzMode, int elutionMode) { this(); _massMzMode = massMzMode; _elutionMode = elutionMode; } public FeatureClusterer(int massMzMode, int elutionMode, FeatureSet featureSet) { this(); _massMzMode = massMzMode; _elutionMode = elutionMode; addSet(featureSet); } /** * Add a featureset to be clustered * @param featureSet */ public void addSet(FeatureSet featureSet) { _featureSets.add(featureSet); FeatureClusterable[] featureClusterables = createClusterablesForFeatures(featureSet.getFeatures()); super.addSet(featureClusterables); } public FeatureSet getSet(int i) { return _featureSets.get(i); } /** * Given an array of features, create an array of Clusterables. The Clusterables should * be of the appropriate type for the mass/mz and elution mode * @param features * @return */ public FeatureClusterable[] createClusterablesForFeatures(Feature[] features) { FeatureClusterable[] result = new FeatureClusterable[features.length]; for (int i = 0; i < features.length; i++) { switch (_massMzMode) { case MASS_MZ_MODE_MASS: switch (_elutionMode) { case ELUTION_MODE_TIME: result[i] = new FeatureMassTimeClusterable(features[i]); break; case ELUTION_MODE_SCAN: result[i] = new FeatureMassScanClusterable(features[i]); break; } break; case MASS_MZ_MODE_MZ: switch (_elutionMode) { case ELUTION_MODE_TIME: result[i] = new FeatureMzTimeClusterable(features[i]); break; case ELUTION_MODE_SCAN: result[i] = new FeatureMzScanClusterable(features[i]); break; } break; } } return result; } //getters and setters public int getElutionMode() { return _elutionMode; } public void setElutionMode(int _elutionMode) { this._elutionMode = _elutionMode; setDimension2IsInt(true); } public int getMassMzMode() { return _massMzMode; } public void setMassMzMode(int _massMzMode) { this._massMzMode = _massMzMode; } //Clusterable classes specific to clustering Features /** * Pragmatic abstract class to help you cluster sets of features. */ public abstract static class FeatureClusterable implements Clusterer2D.Clusterable { public Feature parentFeature; public FeatureClusterable(Feature feature) { setParentFeature(feature); } public void setParentFeature(Feature feature) { parentFeature = feature; } public Feature getParentFeature() { return parentFeature; } } /** * Clusterable for clustering based on feature mass and scan. * Allows access to the original Feature */ public static class FeatureMassScanClusterable extends FeatureClusterer.FeatureClusterable { public FeatureMassScanClusterable(Feature feature) { super(feature); } public double getDimension1Value() { return parentFeature.mass; } public double getDimension2Value() { return parentFeature.getScan(); } } /** * Clusterable for clustering based on feature mass and time. */ public static class FeatureMassTimeClusterable extends FeatureClusterer.FeatureClusterable { public FeatureMassTimeClusterable(Feature feature) { super(feature); } public double getDimension1Value() { return parentFeature.mass; } public double getDimension2Value() { return parentFeature.getTime(); } } /** * Clusterable for clustering based on feature mz and scan. */ public static class FeatureMzScanClusterable extends FeatureClusterer.FeatureClusterable { public FeatureMzScanClusterable(Feature feature) { super(feature); } public double getDimension1Value() { return parentFeature.mz; } public double getDimension2Value() { return parentFeature.getScan(); } } /** * Clusterable for clustering based on feature mz and time. */ public static class FeatureMzTimeClusterable extends FeatureClusterer.FeatureClusterable { public FeatureMzTimeClusterable(Feature feature) { super(feature); } public double getDimension1Value() { return parentFeature.mz; } public double getDimension2Value() { return parentFeature.getTime(); } } public int getMassType() { return _massType; } public void setMassType(int _massType) { if (_massMzMode == MASS_MZ_MODE_MZ) throw new RuntimeException("FeatureClusterer: Tried to set mass type when in m/z mode"); this._massType = _massType; if (_massType == DELTA_MASS_TYPE_PPM) { setDimensionSplitCalculator(new Clusterer2D.ClusterDimensionSplitCalculator() { public double calculateDimension1ForSplit(double referenceValue, double dimensionValue) { double dim1 = calculateAbsoluteDeltaMass((float) referenceValue, (float) dimensionValue, DELTA_MASS_TYPE_PPM); return dim1; } public double calculateDimension2ForSplit(double referenceValue, double dimensionValue) { return dimensionValue; } public String toString() { return "THE RIGHT ONE"; } }); } else { setDimensionSplitCalculator(new DefaultClusterDimensionSplitCalculator()); } } /** * Utility method to calculate the absolute mass tolerance, given a mass tolerance * parameter that may be absolute or relative * @param centerMass * @param deltaMass * @param deltaMassType * @return */ public static float calculateAbsoluteDeltaMass(float centerMass, float deltaMass, int deltaMassType) { if (deltaMassType == DELTA_MASS_TYPE_ABSOLUTE) return deltaMass; //deltamass must be in ppm return (deltaMass * centerMass) / 1000000; } }