io.github.msdk.util.FeatureTableUtil.java Source code

Java tutorial

Introduction

Here is the source code for io.github.msdk.util.FeatureTableUtil.java

Source

/* 
 * (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.util;

import java.util.List;

import javax.annotation.Nonnull;

import com.google.common.base.Preconditions;
import com.google.common.collect.Range;

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.impl.converter.CopyConverter;
import io.github.msdk.datamodel.impl.converter.IonAnnotationConverter;
import io.github.msdk.datamodel.ionannotations.IonAnnotation;
import io.github.msdk.datamodel.rawdata.ChromatographyInfo;
import io.github.msdk.datamodel.rawdata.SeparationType;

/**
 * <p>
 * FeatureTableUtil class.
 * </p>
 */
public class FeatureTableUtil {

    /**
     * Re-calculates the average m/z and RT values for a feature table
     *
     * @param featureTable
     *            the
     *            {@link io.github.msdk.datamodel.featuretables.FeatureTable} to
     *            apply the recalculation on.
     */
    public static void recalculateAverages(@Nonnull FeatureTable featureTable) {

        List<FeatureTableRow> rows = featureTable.getRows();
        Double mz;
        Float rt;
        double totalMz;
        float totalRt;
        int mzCount, rtCount;

        // Create row m/z and RT columns is they are missing in the table
        FeatureTableColumn<?> column;
        if (featureTable.getColumn(ColumnName.MZ, null) == null) {
            column = MSDKObjectBuilder.getMzFeatureTableColumn();
            featureTable.addColumn(column);
        }
        if (featureTable.getColumn("Chromatography Info", null, ChromatographyInfo.class) == null) {
            column = MSDKObjectBuilder.getChromatographyInfoFeatureTableColumn();
            featureTable.addColumn(column);
        }

        for (FeatureTableRow row : rows) {
            List<Sample> samples = featureTable.getSamples();

            totalMz = 0;
            totalRt = 0;
            mzCount = 0;
            rtCount = 0;
            for (Sample sample : samples) {
                FeatureTableColumn<Double> mzColumn = featureTable.getColumn(ColumnName.MZ, sample);
                if (mzColumn != null) {
                    mz = row.getData(mzColumn);
                    if (mz != null) {
                        totalMz += mz;
                        mzCount++;
                    }
                }

                FeatureTableColumn<ChromatographyInfo> rtColumn = featureTable.getColumn(ColumnName.RT, sample);
                if (rtColumn != null) {
                    ChromatographyInfo ri = row.getData(rtColumn);
                    if (ri != null) {
                        rt = ri.getRetentionTime();
                        if (rt != null) {
                            totalRt += rt;
                            rtCount++;
                        }
                    }
                }
            }

            // Update m/z
            FeatureTableColumn<Double> mzColumn = featureTable.getColumn(ColumnName.MZ, null);
            Double newMz = totalMz / mzCount;
            row.setData(mzColumn, newMz);

            // Update ppm
            FeatureTableColumn<List<IonAnnotation>> ionAnnotationColumn = featureTable
                    .getColumn(ColumnName.IONANNOTATION, null);
            if (ionAnnotationColumn != null) {
                List<IonAnnotation> ionAnnotations = row.getData(ionAnnotationColumn);
                if (ionAnnotations != null) {
                    Double totalIonMz = 0d;
                    Integer counter = 0;
                    for (IonAnnotation ionAnnotation : ionAnnotations) {
                        if (ionAnnotation != null) {
                            Double ionMz = ionAnnotation.getExpectedMz();
                            if (ionMz != null) {
                                totalIonMz = totalIonMz + ionMz;
                                counter++;
                            }
                        }
                    }
                    if (counter > 0) {
                        Double ionMz = totalIonMz / counter;
                        FeatureTableColumn<Double> ppmColumn = featureTable.getColumn(ColumnName.PPM, null);
                        Double diff = Math.abs(newMz - ionMz);
                        row.setData(ppmColumn, (diff / ionMz) * 1000000);
                    }
                }
            }

            // Update RT
            FeatureTableColumn<ChromatographyInfo> chromInfoColumn = featureTable.getColumn("Chromatography Info",
                    null, ChromatographyInfo.class);
            if (chromInfoColumn != null) {
                ChromatographyInfo currentChromatographyInfo = row.getData(chromInfoColumn);
                SeparationType separationType;
                if (currentChromatographyInfo == null) {
                    separationType = SeparationType.UNKNOWN;
                } else {
                    separationType = currentChromatographyInfo.getSeparationType();
                }
                ChromatographyInfo chromatographyInfo = MSDKObjectBuilder.getChromatographyInfo1D(separationType,
                        totalRt / rtCount);
                row.setData(chromInfoColumn, chromatographyInfo);
            }
        }
    }

    /**
     * Copies common values such as identification results and comments from the
     * source row to the target row.
     *
     * @param sourceFeatureTableRow
     *            the source
     *            {@link io.github.msdk.datamodel.featuretables.FeatureTableRow}
     *            to copy the common values from.
     * @param targetFeatureTableRow
     *            a
     *            {@link io.github.msdk.datamodel.featuretables.FeatureTableRow}
     *            object.
     * @param combineData
     *            a {@link java.lang.Boolean} object which specifies if data
     *            will be added or replaced.
     */
    @SuppressWarnings("null")
    public static void copyCommonValues(@Nonnull FeatureTableRow sourceFeatureTableRow,
            @Nonnull FeatureTableRow targetFeatureTableRow, @Nonnull Boolean combineData) {

        List<FeatureTableColumn<?>> sourceColumns = sourceFeatureTableRow.getFeatureTable().getColumns();
        List<FeatureTableColumn<?>> targetColumns = targetFeatureTableRow.getFeatureTable().getColumns();

        for (FeatureTableColumn sourceColumn : sourceColumns) {

            // Only add common values and ignore ID column
            if (sourceColumn.getSample() == null & !sourceColumn.getName().equals(ColumnName.ID.getName())) {

                // Find target column
                FeatureTableColumn targetColumn = null;
                for (FeatureTableColumn<?> column : targetColumns) {
                    boolean equalName = sourceColumn.getName().equals(column.getName());
                    boolean equalSample = true;
                    if (sourceColumn.getSample() == null & column.getSample() != null)
                        equalSample = false;
                    else if (sourceColumn.getSample() != null & column.getSample() == null)
                        equalSample = false;
                    else if (sourceColumn.getSample() != null & column.getSample() != null)
                        equalSample = sourceColumn.getSample().getName().equals(column.getSample().getName());

                    if (equalName & equalSample) {
                        targetColumn = column;
                        continue;
                    }
                }

                // Handle combine option
                if (combineData) {
                    switch (sourceColumn.getName()) {
                    case "Ion Annotation":
                        new IonAnnotationConverter().apply(sourceFeatureTableRow, sourceColumn,
                                targetFeatureTableRow, targetColumn);
                        break;
                    }
                } else {
                    // Only add common values
                    if (sourceColumn.getSample() == null) {
                        new CopyConverter().apply(sourceFeatureTableRow, sourceColumn, targetFeatureTableRow,
                                targetColumn);

                    }
                }
            }
        }
    }

    /**
     * Copies sample specific feature values from the source row to the target
     * row.
     *
     * @param sourceFeatureTableRow
     *            the source
     *            {@link io.github.msdk.datamodel.featuretables.FeatureTableRow}
     *            to copy the common values from.
     * @param sample
     *            the target {@link Sample}.
     * @param targetFeatureTableRow
     *            a
     *            {@link io.github.msdk.datamodel.featuretables.FeatureTableRow}
     *            object.
     */
    public static void copyFeatureValues(@Nonnull FeatureTableRow sourceFeatureTableRow,
            @Nonnull FeatureTableRow targetFeatureTableRow, @Nonnull Sample sample) {

        List<FeatureTableColumn<?>> sourceColumns = sourceFeatureTableRow.getFeatureTable().getColumns();
        List<FeatureTableColumn<?>> targetColumns = targetFeatureTableRow.getFeatureTable().getColumns();

        for (final FeatureTableColumn<?> sourceColumn : sourceColumns) {

            // Only add sample specific values
            if (sourceColumn.getSample() != null) {
                if (sourceColumn.getSample().equals(sample)) {

                    // Find target column
                    FeatureTableColumn targetColumn = null;
                    for (FeatureTableColumn<?> column : targetColumns) {
                        boolean equalName = sourceColumn.getName().equals(column.getName());
                        boolean equalSample = true;
                        if (sourceColumn.getSample() != null & column.getSample() != null)
                            equalSample = sourceColumn.getSample().getName().equals(column.getSample().getName());

                        if (equalName & equalSample) {
                            targetColumn = column;
                            continue;
                        }
                    }

                    Object data = sourceFeatureTableRow.getData(sourceColumn);
                    if (data != null) {
                        new CopyConverter().apply(sourceFeatureTableRow, sourceColumn, targetFeatureTableRow,
                                targetColumn);
                    }
                }
            }
        }
    }

    /**
     * Calculates in how many sample the feature is found. It is assumed that at
     * least one of the following columns are present in the feature table: m/z,
     * area or height.
     *
     * @param featureTableRow
     *            the
     *            {@link io.github.msdk.datamodel.featuretables.FeatureTableRow}
     *            to apply the calculation on.
     * @return a int.
     */
    public static int getRowCount(FeatureTableRow featureTableRow) {
        int count = 0;
        FeatureTable featureTable = featureTableRow.getFeatureTable();
        FeatureTableColumn<?> column;
        for (Sample sample : featureTable.getSamples()) {
            column = featureTable.getColumn(ColumnName.MZ, sample);
            if (column != null) {
                if (featureTableRow.getData(column) != null) {
                    count++;
                    continue;
                }
            }
            column = featureTable.getColumn(ColumnName.AREA, sample);
            if (column != null) {
                if (featureTableRow.getData(column) != null) {
                    count++;
                    continue;
                }
            }
            column = featureTable.getColumn(ColumnName.HEIGHT, sample);
            if (column != null) {
                if (featureTableRow.getData(column) != null) {
                    count++;
                    continue;
                }
            }
        }
        return count;
    }

    /**
     * Calculates the average duration of a feature across a set of samples in a
     * feature table row.
     *
     * @param featureTableRow
     *            the
     *            {@link io.github.msdk.datamodel.featuretables.FeatureTableRow}
     *            to apply the calculation on.
     * @return a {@link java.lang.Double} object.
     */
    public static Double getAverageFeatureDuration(FeatureTableRow featureTableRow) {
        FeatureTable featureTable = featureTableRow.getFeatureTable();
        FeatureTableColumn<?> column;
        Double averageDuration = 0d;
        int sampleCount = 0;

        for (Sample sample : featureTable.getSamples()) {
            column = featureTable.getColumn(ColumnName.DURATION, sample);
            if (column != null) {
                double duration = (Double) featureTableRow.getData(column);
                averageDuration = averageDuration + duration;
                sampleCount++;
            }
        }

        // Return null if no duration is found
        if (sampleCount == 0) {
            averageDuration = null;
        } else {
            averageDuration /= sampleCount;
        }

        return averageDuration;
    }

    /**
     * <p>
     * clone.
     * </p>
     *
     * @param dataStore
     *            a {@link io.github.msdk.datamodel.datastore.DataPointStore}
     *            object.
     * @param featureTable
     *            a {@link io.github.msdk.datamodel.featuretables.FeatureTable}
     *            object.
     * @param newName
     *            {@link java.lang.String} object.
     * @return a {@link io.github.msdk.datamodel.featuretables.FeatureTable}
     *         object.
     */
    @Nonnull
    static public FeatureTable clone(@Nonnull DataPointStore dataStore, @Nonnull FeatureTable featureTable,
            @Nonnull String newName) {

        Preconditions.checkNotNull(dataStore);
        Preconditions.checkNotNull(featureTable);
        Preconditions.checkNotNull(newName);

        // Create new feature table
        FeatureTable newFeatureTable = MSDKObjectBuilder.getFeatureTable(newName, dataStore);

        // Copy columns
        for (FeatureTableColumn<?> column : featureTable.getColumns()) {
            FeatureTableColumn<?> newColumn = MSDKObjectBuilder.getFeatureTableColumn(column.getName(),
                    column.getDataTypeClass(), column.getSample());

            // Common columns
            if (column.getSample() == null) {
                if (column.getName() == ColumnName.MZ.getName())
                    newColumn = MSDKObjectBuilder.getMzFeatureTableColumn();
                if (column.getName() == ColumnName.CHARGE.getName())
                    MSDKObjectBuilder.getChargeFeatureTableColumn();
                if (column.getName() == "Chromatography Info")
                    MSDKObjectBuilder.getChromatographyInfoFeatureTableColumn();
                if (column.getName() == ColumnName.ID.getName())
                    MSDKObjectBuilder.getIdFeatureTableColumn();
                if (column.getName() == "Ion Annotation")
                    MSDKObjectBuilder.getIonAnnotationFeatureTableColumn();
                if (column.getName() == ColumnName.PPM.getName())
                    MSDKObjectBuilder.getPpmFeatureTableColumn();
            }

            newFeatureTable.addColumn(newColumn);
        }

        // Copy rows
        for (FeatureTableRow row : featureTable.getRows()) {

            // Create a new row with the common feature data
            FeatureTableRow newRow = MSDKObjectBuilder.getFeatureTableRow(newFeatureTable, row.getId());
            copyCommonValues(row, newRow, false);

            // ID column
            FeatureTableColumn<Integer> column = featureTable.getColumn(ColumnName.ID, null);
            newRow.setData(column, row.getId());

            // Copy the feature data for the samples
            for (Sample sample : row.getFeatureTable().getSamples()) {
                copyFeatureValues(row, newRow, sample);
            }

            // Add the feature row to the table if it is not null
            if (newRow != null)
                newFeatureTable.addRow(newRow);
        }

        return newFeatureTable;
    }

    /**
     * <p>getFeatureMzRange.</p>
     *
     * @param row a {@link io.github.msdk.datamodel.featuretables.FeatureTableRow} object.
     * @return a {@link com.google.common.collect.Range} object.
     */
    public static Range<Double> getFeatureMzRange(FeatureTableRow row) {
        FeatureTable featureTable = row.getFeatureTable();
        FeatureTableColumn<?> column;
        double min = 0d;
        double max = 0d;

        for (Sample sample : featureTable.getSamples()) {
            column = featureTable.getColumn(ColumnName.MZ, sample);
            if (column != null) {
                if (row.getData(column) != null) {
                    double mz = (double) row.getData(column);
                    if (mz < min || min == 0d)
                        min = mz;
                    if (mz > max || max == 0d)
                        max = mz;
                }
            }
        }

        return Range.closed(min, max);
    }

    /**
     * <p>getFeatureRt1Range.</p>
     *
     * @param row a {@link io.github.msdk.datamodel.featuretables.FeatureTableRow} object.
     * @return a {@link com.google.common.collect.Range} object.
     */
    public static Range<Float> getFeatureRt1Range(FeatureTableRow row) {
        FeatureTable featureTable = row.getFeatureTable();
        FeatureTableColumn<ChromatographyInfo> column;
        float min = 0f;
        float max = 0f;

        for (Sample sample : featureTable.getSamples()) {
            column = featureTable.getColumn(ColumnName.RT, sample);
            if (column != null) {
                if (row.getData(column) != null) {
                    ChromatographyInfo chromatographyInfo = row.getData(column);
                    if (chromatographyInfo.getRetentionTime() != null) {
                        float rt = (float) chromatographyInfo.getRetentionTime();
                        if (rt < min || min == 0d)
                            min = rt;
                        if (rt > max || max == 0d)
                            max = rt;
                    }
                }
            }
        }

        return Range.closed(min, max);
    }

    /**
     * <p>copyIdValues.</p>
     *
     * @param featureTable a {@link io.github.msdk.datamodel.featuretables.FeatureTable} object.
     * @param result a {@link io.github.msdk.datamodel.featuretables.FeatureTable} object.
     */
    public static void copyIdValues(FeatureTable featureTable, FeatureTable result) {

        // Copy rows
        List<FeatureTableRow> sourceRows = featureTable.getRows();
        List<FeatureTableRow> targetRows = result.getRows();
        for (int i = 0; i < sourceRows.size(); i++) {
            FeatureTableColumn<Integer> sourceIdColumn = featureTable.getColumn(ColumnName.ID, null);
            FeatureTableColumn<Integer> targetIdColumn = result.getColumn(ColumnName.ID, null);
            new CopyConverter().apply(sourceRows.get(i), sourceIdColumn, targetRows.get(i), targetIdColumn);

        }

    }

}