MzMLChromatogram.java
/*
* (C) Copyright 2015-2017 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.io.mzml.data;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.Range;
import io.github.msdk.MSDKRuntimeException;
import io.github.msdk.datamodel.chromatograms.Chromatogram;
import io.github.msdk.datamodel.chromatograms.ChromatogramType;
import io.github.msdk.datamodel.impl.SimpleActivationInfo;
import io.github.msdk.datamodel.impl.SimpleIsolationInfo;
import io.github.msdk.datamodel.ionannotations.IonAnnotation;
import io.github.msdk.datamodel.rawdata.ActivationInfo;
import io.github.msdk.datamodel.rawdata.ActivationType;
import io.github.msdk.datamodel.rawdata.IsolationInfo;
import io.github.msdk.datamodel.rawdata.RawDataFile;
import io.github.msdk.datamodel.rawdata.SeparationType;
import io.github.msdk.io.mzml.MzMLFileImportMethod;
class MzMLChromatogram implements Chromatogram {
private final @Nonnull MzMLRawDataFile dataFile;
private @Nonnull InputStream inputStream;
private final @Nonnull String chromatogramId;
private final @Nonnull Integer chromatogramNumber;
private final @Nonnull Integer numOfDataPoints;
private MzMLCVGroup cvParams;
private MzMLPrecursorElement precursor;
private MzMLProduct product;
private MzMLBinaryDataInfo rtBinaryDataInfo;
private MzMLBinaryDataInfo intensityBinaryDataInfo;
private ChromatogramType chromatogramType;
private Double mz;
private SeparationType separationType;
private Range<Float> rtRange;
private float[] rtValues;
private float[] intensityValues;
private Logger logger = LoggerFactory.getLogger(MzMLFileImportMethod.class);
/**
* <p>
* Constructor for {@link io.github.msdk.io.mzml.data.MzMLChromatogram MzMLChromatogram}
* </p>
*
* @param dataFile a {@link io.github.msdk.io.mzml.data.MzMLRawDataFile MzMLRawDataFile} object
* the parser stores the data in
* @param is an {@link java.io.InputStream InputStream} of the MzML format data
* @param chromatogramId the Chromatogram ID
* @param chromatogramNumber the Chromatogram number
* @param numOfDataPoints the number of data points in the retention time and intensity arrays
*/
MzMLChromatogram(@Nonnull MzMLRawDataFile dataFile, InputStream is, String chromatogramId,
Integer chromatogramNumber, Integer numOfDataPoints) {
this.cvParams = new MzMLCVGroup();
this.dataFile = dataFile;
this.inputStream = is;
this.chromatogramId = chromatogramId;
this.chromatogramNumber = chromatogramNumber;
this.numOfDataPoints = numOfDataPoints;
this.separationType = SeparationType.UNKNOWN;
this.rtBinaryDataInfo = null;
this.intensityBinaryDataInfo = null;
this.chromatogramType = ChromatogramType.UNKNOWN;
this.mz = null;
this.rtRange = null;
this.rtValues = null;
this.intensityValues = null;
}
/** {@inheritDoc} */
@Override
@Nullable
public RawDataFile getRawDataFile() {
return dataFile;
}
/** {@inheritDoc} */
@Override
@Nonnull
public Integer getChromatogramNumber() {
return chromatogramNumber;
}
/**
* <p>
* getCVParams.
* </p>
*
* @return a {@link java.util.ArrayList} object.
*/
public MzMLCVGroup getCVParams() {
return cvParams;
}
/**
* <p>
* Getter for the field <code>mzBinaryDataInfo</code>.
* </p>
*
* @return a {@link io.github.msdk.io.mzml.data.MzMLBinaryDataInfo} object.
*/
public MzMLBinaryDataInfo getRtBinaryDataInfo() {
return rtBinaryDataInfo;
}
/**
* <p>
* Setter for the field <code>mzBinaryDataInfo</code>.
* </p>
*
* @param rtBinaryDataInfo a {@link io.github.msdk.io.mzml.data.MzMLBinaryDataInfo} object.
*/
public void setRtBinaryDataInfo(MzMLBinaryDataInfo rtBinaryDataInfo) {
this.rtBinaryDataInfo = rtBinaryDataInfo;
}
/**
* <p>
* Getter for the field <code>intensityBinaryDataInfo</code>.
* </p>
*
* @return a {@link io.github.msdk.io.mzml.data.MzMLBinaryDataInfo} object.
*/
public MzMLBinaryDataInfo getIntensityBinaryDataInfo() {
return intensityBinaryDataInfo;
}
/**
* <p>
* Setter for the field <code>intensityBinaryDataInfo</code>.
* </p>
*
* @param intensityBinaryDataInfo a {@link io.github.msdk.io.mzml.data.MzMLBinaryDataInfo} object.
*/
public void setIntensityBinaryDataInfo(MzMLBinaryDataInfo intensityBinaryDataInfo) {
this.intensityBinaryDataInfo = intensityBinaryDataInfo;
}
/**
* <p>
* getInputStream.
* </p>
*
* @return a {@link io.github.msdk.io.mzml2.util.io.ByteBufferInputStream} object.
*/
public InputStream getInputStream() {
return inputStream;
}
/**
* <p>
* setInputStream.
* </p>
*
* @param inputStream a {@link java.io.InputStream} object.
*/
public void setInputStream(InputStream inputStream) {
this.inputStream = inputStream;
}
/**
* <p>
* getPrecursor.
* </p>
*
* @return a {@link io.github.msdk.io.mzml.data.MzMLPrecursorElement} object.
*/
public MzMLPrecursorElement getPrecursor() {
return precursor;
}
/**
* <p>
* Setter for the field <code>precursor</code>.
* </p>
*
* @param precursor a {@link io.github.msdk.io.mzml.data.MzMLPrecursorElement} object.
*/
public void setPrecursor(MzMLPrecursorElement precursor) {
this.precursor = precursor;
}
/**
* <p>
* getProduct.
* </p>
*
* @return a {@link io.github.msdk.io.mzml.data.MzMLProduct} object.
*/
public MzMLProduct getProduct() {
return product;
}
/**
* <p>
* Setter for the field <code>precursor</code>.
* </p>
*
* @param product a {@link io.github.msdk.io.mzml.data.MzMLProduct} object.
*/
public void setProdcut(MzMLProduct product) {
this.product = product;
}
/**
* <p>
* Getter for the field <code>chromatogramId</code>.
* </p>
*
* @return a {@link java.lang.String} object.
*/
public String getId() {
return chromatogramId;
}
/** {@inheritDoc} */
@Override
@Nonnull
public ChromatogramType getChromatogramType() {
if (chromatogramType != ChromatogramType.UNKNOWN)
return chromatogramType;
int count = 0;
if (getCVValue(MzMLCV.cvChromatogramTIC).isPresent()) {
chromatogramType = ChromatogramType.TIC;
count++;
}
if (getCVValue(MzMLCV.cvChromatogramMRM_SRM).isPresent()) {
chromatogramType = ChromatogramType.MRM_SRM;
count++;
}
if (getCVValue(MzMLCV.cvChromatogramSIC).isPresent()) {
chromatogramType = ChromatogramType.SIC;
count++;
}
if (getCVValue(MzMLCV.cvChromatogramBPC).isPresent()) {
chromatogramType = ChromatogramType.BPC;
count++;
}
if (count > 1) {
logger.error("More than one chromatogram type defined by CV terms not allowed");
chromatogramType = ChromatogramType.UNKNOWN;
}
return chromatogramType;
}
/** {@inheritDoc} */
@Override
@Nullable
public Double getMz() {
// Set mz value only if it hasn't been fetched before
if (mz == null) {
// Try getting the mz value from the product isolation window
// set mz value to the respective cv value only if the value is present
if (product != null) {
if (product.getIsolationWindow().isPresent()) {
Optional<String> cvval =
getCVValue(product.getIsolationWindow().get(), MzMLCV.cvIsolationWindowTarget);
if (cvval.isPresent())
mz = Double.valueOf(cvval.get());
}
}
}
return mz;
}
/** {@inheritDoc} */
@Override
@Nonnull
public List<IsolationInfo> getIsolations() {
if (getChromatogramType() == ChromatogramType.MRM_SRM) {
Optional<MzMLIsolationWindow> precursorIsolationWindow = getPrecursor().getIsolationWindow();
Optional<MzMLIsolationWindow> productIsolationWindow = getProduct().getIsolationWindow();
if (!precursorIsolationWindow.isPresent()) {
logger.error("Couldn't find precursor isolation window for chromotgram (#"
+ getChromatogramNumber() + ")");
return Collections.emptyList();
}
if (!productIsolationWindow.isPresent()) {
logger.error("Couldn't find product isolation window for chromotgram (#"
+ getChromatogramNumber() + ")");
return Collections.emptyList();
}
Optional<String> precursorIsolationMz =
getCVValue(precursorIsolationWindow.get(), MzMLCV.cvIsolationWindowTarget);
Optional<String> precursorActivationEnergy =
getCVValue(getPrecursor().getActivation(), MzMLCV.cvActivationEnergy);
Optional<String> productIsolationMz =
getCVValue(productIsolationWindow.get(), MzMLCV.cvIsolationWindowTarget);
ActivationType precursorActivation = ActivationType.UNKNOWN;
ActivationInfo activationInfo = null;
if (getCVValue(getPrecursor().getActivation(), MzMLCV.cvActivationCID).isPresent())
precursorActivation = ActivationType.CID;
if (precursorActivationEnergy != null) {
activationInfo = new SimpleActivationInfo(Double.valueOf(precursorActivationEnergy.get()),
precursorActivation);
}
List<IsolationInfo> isolations = new ArrayList<>();
IsolationInfo isolationInfo = null;
if (precursorIsolationMz.isPresent()) {
isolationInfo =
new SimpleIsolationInfo(Range.singleton(Double.valueOf(precursorIsolationMz.get())),
null, Double.valueOf(precursorIsolationMz.get()), null, activationInfo);
isolations.add(isolationInfo);
}
if (productIsolationMz.isPresent()) {
isolationInfo =
new SimpleIsolationInfo(Range.singleton(Double.valueOf(productIsolationMz.get())), null,
Double.valueOf(productIsolationMz.get()), null, null);
isolations.add(isolationInfo);
}
return Collections.unmodifiableList(isolations);
}
return Collections.emptyList();
}
/** {@inheritDoc} */
@Override
@Nonnull
public SeparationType getSeparationType() {
return separationType;
}
/** {@inheritDoc} */
@Override
public IonAnnotation getIonAnnotation() {
return null;
}
/** {@inheritDoc} */
@Override
@Nonnull
public Integer getNumberOfDataPoints() {
return numOfDataPoints;
}
/** {@inheritDoc} */
@Override
@Nonnull
public float[] getRetentionTimes(@Nullable float array[]) {
if (rtValues == null) {
if (getRtBinaryDataInfo().getArrayLength() != numOfDataPoints) {
logger.warn(
"Retention time binary data array contains a different array length from the default array length of the scan (#"
+ getChromatogramNumber() + ")");
}
try {
rtValues = MzMLPeaksDecoder.decodeToFloat(inputStream, getRtBinaryDataInfo(), array);
} catch (Exception e) {
throw (new MSDKRuntimeException(e));
}
}
if (array == null || array.length < numOfDataPoints) {
array = new float[numOfDataPoints];
System.arraycopy(rtValues, 0, array, 0, numOfDataPoints);
}
return array;
}
/** {@inheritDoc} */
@Override
@Nonnull
public float[] getIntensityValues(@Nullable float[] array) {
if (intensityValues == null) {
if (getIntensityBinaryDataInfo().getArrayLength() != numOfDataPoints) {
logger.warn(
"Intensity binary data array contains a different array length from the default array length of the chromatogram (#"
+ getChromatogramNumber() + ")");
}
try {
intensityValues =
MzMLPeaksDecoder.decodeToFloat(inputStream, getIntensityBinaryDataInfo(), array);
} catch (Exception e) {
throw (new MSDKRuntimeException(e));
}
}
if (array == null || array.length < numOfDataPoints) {
array = new float[numOfDataPoints];
System.arraycopy(intensityValues, 0, array, 0, numOfDataPoints);
}
return array;
}
/** {@inheritDoc} */
@Override
@Nullable
public double[] getMzValues(@Nullable double array[]) {
return null;
}
/** {@inheritDoc} */
@Override
@Nullable
public Range<Float> getRtRange() {
if (rtRange == null) {
float[] rtValues = getRetentionTimes();
rtRange = Range.closed(rtValues[0], rtValues[numOfDataPoints - 1]);
}
return rtRange;
}
/**
* <p>
* Search for the CV Parameter value for the given accession in the
* {@link io.github.msdk.datamodel.chromatograms.Chromatogram Chromatogram}'s CV Parameters
* </p>
*
* @param accession the CV Parameter accession as {@link java.lang.String String}
* @return an {@link java.util.Optional Optional<String>} containing the CV Parameter value for
* the given accession, if present <br>
* An empty {@link java.util.Optional Optional<String>} otherwise
*/
public Optional<String> getCVValue(String accession) {
return getCVValue(cvParams, accession);
}
/**
* <p>
* Search for the CV Parameter value for the given accession in the given
* {@link io.github.msdk.io.mzml.data.MzMLCVGroup MzMLCVGroup}
* </p>
*
* @param group the {@link io.github.msdk.io.mzml.data.MzMLCVGroup MzMLCVGroup} to search through
* @param accession the CV Parameter accession as {@link java.lang.String String}
* @return an {@link java.util.Optional Optional<String>} containing the CV Parameter value for
* the given accession, if present <br>
* An empty {@link java.util.Optional Optional<String>} otherwise
*/
public Optional<String> getCVValue(MzMLCVGroup group, String accession) {
Optional<String> value;
for (MzMLCVParam cvParam : group.getCVParamsList()) {
if (cvParam.getAccession().equals(accession)) {
value = cvParam.getValue();
if (!value.isPresent())
value = Optional.of("");
return value;
}
}
return Optional.empty();
}
}