All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.msdk.features.joinaligner.JoinAlignerMethod Maven / Gradle / Ivy

There is a newer version: 0.0.9
Show newest version
/* 
 * (C) Copyright 2015-2016 by MSDK Development Team
 *
 * This software is dual-licensed under either
 *
 * (a) the terms of the GNU Lesser General Public License version 2.1
 * as published by the Free Software Foundation
 *
 * or (per the licensee's choosing)
 *
 * (b) the terms of the Eclipse Public License v1.0 as published by
 * the Eclipse Foundation.
 */

package io.github.msdk.features.joinaligner;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import com.google.common.collect.Range;

import io.github.msdk.MSDKException;
import io.github.msdk.MSDKMethod;
import io.github.msdk.datamodel.datastore.DataPointStore;
import io.github.msdk.datamodel.featuretables.ColumnName;
import io.github.msdk.datamodel.featuretables.FeatureTable;
import io.github.msdk.datamodel.featuretables.FeatureTableColumn;
import io.github.msdk.datamodel.featuretables.FeatureTableRow;
import io.github.msdk.datamodel.featuretables.Sample;
import io.github.msdk.datamodel.impl.MSDKObjectBuilder;
import io.github.msdk.datamodel.ionannotations.IonAnnotation;
import io.github.msdk.datamodel.rawdata.ChromatographyInfo;
import io.github.msdk.util.FeatureTableUtil;
import io.github.msdk.util.tolerances.MzTolerance;
import io.github.msdk.util.tolerances.RTTolerance;

/**
 * This class aligns feature tables based on a match score. The score is
 * calculated based on the mass and retention time of each peak using a set of
 * tolerances.
 */
public class JoinAlignerMethod implements MSDKMethod {

    // Variables
    private final @Nonnull MzTolerance mzTolerance;
    private final @Nonnull RTTolerance rtTolerance;
    private final int mzWeight;
    private final int rtWeight;
    private final boolean requireSameCharge;
    private final boolean requireSameAnnotation;
    private final @Nonnull String featureTableName;
    private final @Nonnull DataPointStore dataStore;
    private final @Nonnull List featureTables;
    private final @Nonnull FeatureTable result;
    private boolean canceled = false;
    private int processedFeatures = 0, totalFeatures = 0;

    // ID counter for the new feature table
    private int newRowID = 1;

    /**
     * 

* Constructor for MatchAlignerMethod. *

* * @param featureTables * a {@link java.util.List} object. * @param dataStore * a {@link io.github.msdk.datamodel.datastore.DataPointStore} * object. * @param mzTolerance * an objectt * @param mzWeight * a {@link java.lang.Integer} object. * @param rtWeight * a {@link java.lang.Integer} object. * @param requireSameCharge * a {@link java.lang.Boolean} object. * @param requireSameAnnotation * a {@link java.lang.Boolean} object. * @param featureTableName * a {@link java.lang.String} object. * @param rtTolerance * a {@link io.github.msdk.util.tolerances.RTTolerance} object. */ public JoinAlignerMethod(@Nonnull List featureTables, @Nonnull DataPointStore dataStore, @Nonnull MzTolerance mzTolerance, @Nonnull RTTolerance rtTolerance, int mzWeight, int rtWeight, boolean requireSameCharge, boolean requireSameAnnotation, @Nonnull String featureTableName) { this.featureTables = featureTables; this.dataStore = dataStore; this.mzTolerance = mzTolerance; this.rtTolerance = rtTolerance; this.mzWeight = mzWeight; this.rtWeight = rtWeight; this.requireSameCharge = requireSameCharge; this.requireSameAnnotation = requireSameAnnotation; this.featureTableName = featureTableName; // Make a new feature table result = MSDKObjectBuilder.getFeatureTable(featureTableName, dataStore); } /** {@inheritDoc} */ @Override public FeatureTable execute() throws MSDKException { // Calculate number of feature to process. Each feature will be // processed twice: first for score calculation and then for actual // alignment. for (FeatureTable featureTable : featureTables) { totalFeatures += featureTable.getRows().size() * 2; } // Iterate through all feature tables Boolean firstFeatureTable = true; for (FeatureTable featureTable : featureTables) { // Add columns from the original feature table to the result table for (FeatureTableColumn column : featureTable.getColumns()) { if (firstFeatureTable) result.addColumn(column); else if (column.getSample() != null) result.addColumn(column); } firstFeatureTable = false; // Create a sorted array of matching scores between two rows List scoreSet = new ArrayList(); // Calculate scores for all possible alignments of this row for (FeatureTableRow row : featureTable.getRows()) { final Double mz = row.getMz(); if (mz == null) continue; // Calculate the m/z range limit for the current row Range mzRange = mzTolerance.getToleranceRange(mz); // Continue if no chromatography info is available ChromatographyInfo chromatographyInfo = row .getChromatographyInfo(); if (chromatographyInfo == null) continue; // Calculate the RT range limit for the current row Range rtRange = rtTolerance.getToleranceRange( chromatographyInfo.getRetentionTime()); // Get all rows of the aligned feature table within the m/z and // RT limits List candidateRows = result .getRowsInsideRange(rtRange, mzRange); // Calculate scores and store them for (FeatureTableRow candidateRow : candidateRows) { // Check charge if (requireSameCharge) { FeatureTableColumn chargeColumn1 = featureTable .getColumn(ColumnName.CHARGE, null); FeatureTableColumn chargeColumn2 = result .getColumn(ColumnName.CHARGE, null); Integer charge1 = row.getData(chargeColumn1); Integer charge2 = candidateRow.getData(chargeColumn2); if (!charge1.equals(charge2)) continue; } // Check ion annotation if (requireSameAnnotation) { FeatureTableColumn> ionAnnotationColumn1 = featureTable .getColumn(ColumnName.IONANNOTATION, null); FeatureTableColumn> ionAnnotationColumn2 = result .getColumn(ColumnName.IONANNOTATION, null); List ionAnnotations1 = row .getData(ionAnnotationColumn1); List ionAnnotations2 = candidateRow .getData(ionAnnotationColumn2); // Check that all ion annotations in first row are in // the candidate row boolean equalIons = false; if (ionAnnotations1 != null && ionAnnotations2 != null) { for (IonAnnotation ionAnnotation : ionAnnotations1) { for (IonAnnotation targetIonAnnotation : ionAnnotations2) { if (targetIonAnnotation .compareTo(ionAnnotation) == 0) equalIons = true; } } } if (!equalIons) continue; } // Calculate score double mzLength = mzRange.upperEndpoint() - mzRange.lowerEndpoint(); double rtLength = rtRange.upperEndpoint() - rtRange.lowerEndpoint(); RowVsRowScore score = new RowVsRowScore(row, candidateRow, mzLength / 2.0, mzWeight, rtLength / 2.0, rtWeight); // Add the score to the array scoreSet.add(score); } processedFeatures++; if (canceled) return null; } // Create a table of mappings for best scores Hashtable alignmentMapping = new Hashtable(); // Iterate scores by descending order Iterator scoreIterator = scoreSet.iterator(); while (scoreIterator.hasNext()) { RowVsRowScore score = scoreIterator.next(); // Check if the row is already mapped if (alignmentMapping.containsKey(score.getFeatureTableRow())) continue; // Check if the aligned row is already filled if (alignmentMapping.containsValue(score.getAlignedRow())) continue; alignmentMapping.put(score.getFeatureTableRow(), score.getAlignedRow()); } // Align all rows using the mapping for (FeatureTableRow sourceRow : featureTable.getRows()) { FeatureTableRow targetRow = alignmentMapping.get(sourceRow); // If we have no mapping for this row, add a new one if (targetRow == null) { targetRow = MSDKObjectBuilder.getFeatureTableRow(result, newRowID); result.addRow(targetRow); FeatureTableColumn column = result .getColumn(ColumnName.ID, null); targetRow.setData(column, newRowID); newRowID++; } // Add all features from the original row to the aligned row for (Sample sample : sourceRow.getFeatureTable().getSamples()) { FeatureTableUtil.copyFeatureValues(sourceRow, targetRow, sample); } // Combine common values from the original row with the aligned // row FeatureTableUtil.copyCommonValues(sourceRow, targetRow, true); processedFeatures++; } // Re-calculate average row averages FeatureTableUtil.recalculateAverages(result); if (canceled) return null; } // Return the new feature table return result; } /** {@inheritDoc} */ @Override @Nullable public Float getFinishedPercentage() { return totalFeatures == 0 ? null : (float) processedFeatures / totalFeatures; } /** {@inheritDoc} */ @Override @Nullable public FeatureTable getResult() { return result; } /** {@inheritDoc} */ @Override public void cancel() { canceled = true; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy