MzMLFileExportMethod.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;
import java.io.File;
import java.io.FileOutputStream;
import java.security.DigestOutputStream;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import javax.annotation.Nonnull;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.github.msdk.MSDKException;
import io.github.msdk.MSDKMethod;
import io.github.msdk.datamodel.chromatograms.Chromatogram;
import io.github.msdk.datamodel.msspectra.MsSpectrumType;
import io.github.msdk.datamodel.rawdata.ActivationInfo;
import io.github.msdk.datamodel.rawdata.IsolationInfo;
import io.github.msdk.datamodel.rawdata.MsScan;
import io.github.msdk.datamodel.rawdata.PolarityType;
import io.github.msdk.datamodel.rawdata.RawDataFile;
import io.github.msdk.io.mzml.data.MzMLArrayType;
import io.github.msdk.io.mzml.data.MzMLBitLength;
import io.github.msdk.io.mzml.data.MzMLCV;
import io.github.msdk.io.mzml.data.MzMLCVGroup;
import io.github.msdk.io.mzml.data.MzMLCVParam;
import io.github.msdk.io.mzml.data.MzMLCompressionType;
import io.github.msdk.io.mzml.data.MzMLMsScan;
import io.github.msdk.io.mzml.data.MzMLPeaksEncoder;
import io.github.msdk.io.mzml.data.MzMLPrecursorElement;
import io.github.msdk.io.mzml.data.MzMLPrecursorSelectedIon;
import io.github.msdk.io.mzml.data.MzMLProduct;
import io.github.msdk.io.mzml.data.MzMLRawDataFile;
import io.github.msdk.io.mzml.data.MzMLTags;
import javolution.xml.internal.stream.XMLStreamWriterImpl;
import javolution.xml.stream.XMLStreamException;
/**
* <p>
* This class contains methods which can be used to write data contained in a
* {@link o.github.msdk.datamodel.rawdata.RawDataFile RawDataFile} to a file, in mzML format
* </p>
*/
public class MzMLFileExportMethod implements MSDKMethod<Void> {
private static final String dataProcessingId = "MSDK_mzml_export";
private static final String softwareId = "MSDK";
private static final String XML_ENCODING = "UTF-8";
private static final String XML_VERSION = "1.0";
private static final String MZML_NAMESPACE = "http://psi.hupo.org/ms/mzml";
private static final String XML_SCHEMA_INSTANCE = "http://www.w3.org/2001/XMLSchema-instance";
private static final String XML_SCHEMA_LOCATION =
"http://psi.hupo.org/ms/mzml http://psidev.info/files/ms/mzML/xsd/mzML1.1.0.xsd";
private static final String DEFAULT_VERSION = "1.1.0";
private static final String CV_REF_MS = "MS";
private static final String PREFIX_XSI = "xsi";
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private final @Nonnull RawDataFile rawDataFile;
private final @Nonnull File target;
private final @Nonnull MzMLCompressionType doubleArrayCompression;
private final @Nonnull MzMLCompressionType floatArrayCompression;
private boolean canceled = false;
private long totalScans = 0, totalChromatograms = 0, parsedScans, parsedChromatograms,
indexListOffset;
/**
* <p>
* Constructor for MzMLFileExportMethod.
* </p>
*
* @param rawDataFile the input {@link o.github.msdk.datamodel.rawdata.RawDataFile RawDataFile}
* which contains the data to be exported
* @param target the target {@link java.io.File File} to write the data, in mzML format
* @param doubleArrayCompression compression type for <code>double[]</code> which are encoded
* @param floatArrayCompression compression type for <code>float[]</code> which are encoded
*/
public MzMLFileExportMethod(@Nonnull RawDataFile rawDataFile, @Nonnull File target,
@Nonnull MzMLCompressionType doubleArrayCompression,
MzMLCompressionType floatArrayCompression) {
this.rawDataFile = rawDataFile;
this.target = target;
this.doubleArrayCompression = doubleArrayCompression;
this.floatArrayCompression = floatArrayCompression;
}
/**
* {@inheritDoc}
*
* <p>
* Execute the process of writing the data from the the input
* {@link o.github.msdk.datamodel.rawdata.RawDataFile RawDataFile} to the target
* {@link java.io.File File}
* </p>
*/
@Override
public Void execute() throws MSDKException {
logger.info("Started export of " + rawDataFile.getName() + " to " + target);
List<MsScan> scans = rawDataFile.getScans();
List<Chromatogram> chromatograms = rawDataFile.getChromatograms();
totalScans = scans.size();
totalChromatograms = chromatograms.size();
// index offsets
List<Long> spectrumIndices = new ArrayList<>();
List<Long> chromatogramIndices = new ArrayList<>();
try {
FileOutputStream fos = new FileOutputStream(target);
MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
DigestOutputStream dos = new DigestOutputStream(fos, sha1);
dos.on(true);
XMLStreamWriterImpl xmlStreamWriter = new XMLStreamWriterImpl();
xmlStreamWriter.setOutput(dos);
// Setting namespace and prefixes
xmlStreamWriter.setDefaultNamespace(MZML_NAMESPACE);
xmlStreamWriter.setPrefix(PREFIX_XSI, XML_SCHEMA_INSTANCE);
// <?xml>
xmlStreamWriter.writeStartDocument(XML_ENCODING, XML_VERSION);
// <indexedmzML>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_INDEXED_MZML);
xmlStreamWriter.writeDefaultNamespace(MZML_NAMESPACE);
xmlStreamWriter.writeNamespace(PREFIX_XSI, XML_SCHEMA_INSTANCE);
xmlStreamWriter.writeAttribute(XML_SCHEMA_INSTANCE, MzMLTags.ATTR_SCHEME_LOCATION,
XML_SCHEMA_LOCATION);
// <mzML>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_MZML);
xmlStreamWriter.writeDefaultNamespace(MZML_NAMESPACE);
xmlStreamWriter.writeNamespace(PREFIX_XSI, XML_SCHEMA_INSTANCE);
xmlStreamWriter.writeAttribute(XML_SCHEMA_INSTANCE, MzMLTags.ATTR_SCHEME_LOCATION,
XML_SCHEMA_LOCATION);
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_ID, rawDataFile.getName());
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_VERSION, DEFAULT_VERSION);
// <cvList>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_CV_LIST);
// TODO: Hold cvList in the existing RawDataFile model
xmlStreamWriter.writeEndElement();
// <dataProcessingList>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_DATA_PROCESSING_LIST);
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_COUNT, "1");
// <dataProcessing>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_DATA_PROCESSING);
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_ID, dataProcessingId);
// <processingMethod>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_PROCESSING_METHOD);
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_SOFTWARE_REF, softwareId);
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_ORDER, "0");
// Closing tags
xmlStreamWriter.writeEndElement(); // </processingMethod>
xmlStreamWriter.writeEndElement(); // </dataProcessing>
xmlStreamWriter.writeEndElement(); // </dataProcessingList>
// <run>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_RUN);
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_ID, rawDataFile.getName());
// <spectrumList>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_SPECTRUM_LIST);
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_COUNT, String.valueOf(scans.size()));
byte[] mzBuffer = null;
byte[] intensityBuffer = null;
for (MsScan scan : scans) {
if (canceled) {
dos.close();
fos.close();
xmlStreamWriter.close();
target.delete();
return null;
}
// <spectrum>
spectrumIndices.add(xmlStreamWriter.getLocation().getCharacterOffsetInLong());
xmlStreamWriter.writeStartElement(MzMLTags.TAG_SPECTRUM);
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_INDEX, String.valueOf(parsedScans));
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_ID, "scan=" + scan.getScanNumber());
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_DEFAULT_ARRAY_LENGTH,
String.valueOf(scan.getNumberOfDataPoints()));
MzMLMsScan spectrum = null;
if (scan instanceof MzMLMsScan)
spectrum = (MzMLMsScan) scan;
// spectrum type CV param
if (!(rawDataFile instanceof MzMLRawDataFile) || (rawDataFile instanceof MzMLRawDataFile
&& !spectrum.getCVValue(MzMLCV.cvCentroidSpectrum).isPresent()
&& !spectrum.getCVValue(MzMLCV.cvProfileSpectrum).isPresent())) {
if (scan.getSpectrumType() == MsSpectrumType.CENTROIDED)
writeCVParam(xmlStreamWriter, MzMLCV.centroidCvParam);
else
writeCVParam(xmlStreamWriter, MzMLCV.profileCvParam);
}
// ms level CV param
if (!(rawDataFile instanceof MzMLRawDataFile) || (rawDataFile instanceof MzMLRawDataFile
&& !spectrum.getCVValue(MzMLCV.cvMSLevel).isPresent())) {
if (scan.getMsLevel() != null) {
Integer msLevel = scan.getMsLevel();
writeCVParam(xmlStreamWriter,
new MzMLCVParam(MzMLCV.cvMSLevel, String.valueOf(msLevel), "ms level", null));
}
}
// total ion current CV param
if (!(rawDataFile instanceof MzMLRawDataFile) || (rawDataFile instanceof MzMLRawDataFile
&& !spectrum.getCVValue(MzMLCV.cvTIC).isPresent())) {
if (scan.getTIC() != null) {
Float tic = scan.getTIC();
writeCVParam(xmlStreamWriter,
new MzMLCVParam(MzMLCV.cvTIC, String.valueOf(tic), "total ion current", null));
}
}
// m/z range CV param
if (!(rawDataFile instanceof MzMLRawDataFile) || (rawDataFile instanceof MzMLRawDataFile
&& !spectrum.getCVValue(MzMLCV.cvLowestMz).isPresent()
|| !spectrum.getCVValue(MzMLCV.cvHighestMz).isPresent())) {
if (scan.getMzRange() != null) {
Double lowestMz = scan.getMzRange().lowerEndpoint();
Double highestMz = scan.getMzRange().upperEndpoint();
writeCVParam(xmlStreamWriter, new MzMLCVParam(MzMLCV.cvLowestMz,
String.valueOf(lowestMz), "lowest observed m/z", MzMLCV.cvMz));
writeCVParam(xmlStreamWriter, new MzMLCVParam(MzMLCV.cvHighestMz,
String.valueOf(highestMz), "highest observed m/z", MzMLCV.cvMz));
}
}
// Write the missing CV params parsed
if (rawDataFile instanceof MzMLRawDataFile)
writeCVGroup(xmlStreamWriter, spectrum.getCVParams());
// <scanList>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_SCAN_LIST);
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_COUNT, "1");
// <scan>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_SCAN);
// scan definition CV param
if (scan.getScanDefinition() != null) {
String scanDefinition = scan.getScanDefinition();
writeCVParam(xmlStreamWriter,
new MzMLCVParam(MzMLCV.cvScanFilterString, scanDefinition, "filter string", null));
}
// retention time CV param
if (scan.getRetentionTime() != null) {
Float rt = scan.getRetentionTime();
writeCVParam(xmlStreamWriter, new MzMLCVParam(MzMLCV.MS_RT_SCAN_START, String.valueOf(rt),
"scan time", MzMLCV.cvUnitsSec));
}
// scan polarity CV param
if (scan.getPolarity() == PolarityType.POSITIVE)
writeCVParam(xmlStreamWriter, MzMLCV.polarityPositiveCvParam);
else if (scan.getPolarity() == PolarityType.NEGATIVE)
writeCVParam(xmlStreamWriter, MzMLCV.polarityNegativeCvParam);
// <scanWindowList>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_SCAN_WINDOW_LIST);
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_COUNT, "1");
// <scanWindow>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_SCAN_WINDOW);
// scan window range CV param
if (scan.getScanningRange() != null) {
Double lowerLimit = scan.getScanningRange().lowerEndpoint();
Double upperLimit = scan.getScanningRange().upperEndpoint();
writeCVParam(xmlStreamWriter, new MzMLCVParam(MzMLCV.cvScanWindowLowerLimit,
String.valueOf(lowerLimit), "scan window lower limit", MzMLCV.cvMz));
writeCVParam(xmlStreamWriter, new MzMLCVParam(MzMLCV.cvScanWindowUpperLimit,
String.valueOf(upperLimit), "scan window upper limit", MzMLCV.cvMz));
}
// Closing tags
xmlStreamWriter.writeEndElement(); // </scanWindow>
xmlStreamWriter.writeEndElement(); // </scanWindowList>
xmlStreamWriter.writeEndElement(); // </scan>
xmlStreamWriter.writeEndElement(); // </scanList>
if (rawDataFile instanceof MzMLRawDataFile
&& spectrum.getPrecursorList().getPrecursorElements().size() > 0) {
// <precursorList>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_PRECURSOR_LIST);
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_COUNT,
String.valueOf(spectrum.getPrecursorList().getPrecursorElements().size()));
for (MzMLPrecursorElement precursor : spectrum.getPrecursorList()
.getPrecursorElements()) {
// <precursor>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_PRECURSOR);
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_SPECTRUM_REF,
precursor.getSpectrumRef().orElse(""));
if (precursor.getSelectedIonList().isPresent()) {
// <slectedIonList>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_SELECTED_ION_LIST);
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_COUNT,
String.valueOf(precursor.getSelectedIonList().get().getSelectedIonList().size()));
for (MzMLPrecursorSelectedIon selectedIon : precursor.getSelectedIonList().get()
.getSelectedIonList()) {
// <selectedIon>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_SELECTED_ION);
writeCVGroup(xmlStreamWriter, selectedIon);
xmlStreamWriter.writeEndElement(); // </selectedIon>
}
xmlStreamWriter.writeEndElement(); // </selectedIonList>
}
xmlStreamWriter.writeEndElement(); // </precursor>
if (precursor.getIsolationWindow().isPresent()) {
// <isolationWindow>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_ISOLATION_WINDOW);
writeCVGroup(xmlStreamWriter, precursor.getIsolationWindow().get());
xmlStreamWriter.writeEndElement(); // </isolationWindow>
}
// <activation>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_ACTIVATION);
writeCVGroup(xmlStreamWriter, precursor.getActivation());
xmlStreamWriter.writeEndElement(); // </activation>
}
xmlStreamWriter.writeEndElement(); // </precursorList>
if (!spectrum.getProductList().getProducts().isEmpty()) {
// <productList>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_PRODUCT_LIST);
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_COUNT,
String.valueOf(spectrum.getProductList().getProducts().size()));
for (MzMLProduct product : spectrum.getProductList().getProducts()) {
// <product>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_PRODUCT);
// <isolationWindow>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_ISOLATION_WINDOW);
if (product.getIsolationWindow().isPresent())
writeCVGroup(xmlStreamWriter, product.getIsolationWindow().get());
xmlStreamWriter.writeEndElement(); // </isolationWindow>
xmlStreamWriter.writeEndElement(); // </product>
}
xmlStreamWriter.writeEndElement(); // </productList>
}
}
// <binaryDataArrayList>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_BINARY_DATA_ARRAY_LIST);
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_COUNT, "2");
// <binaryDataArray> (m/z)
mzBuffer = MzMLPeaksEncoder.encodeDouble(scan.getMzValues(), doubleArrayCompression);
xmlStreamWriter.writeStartElement(MzMLTags.TAG_BINARY_DATA_ARRAY);
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_ENCODED_LENGTH,
String.valueOf(mzBuffer.length));
// data array precision CV param
writeCVParam(xmlStreamWriter, new MzMLCVParam(MzMLBitLength.SIXTY_FOUR_BIT_FLOAT.getValue(),
"", "64-bit float", null));
// data array compression CV param
writeCVParam(xmlStreamWriter, new MzMLCVParam(doubleArrayCompression.getAccession(), "",
doubleArrayCompression.getName(), null));
// data array type CV param
writeCVParam(xmlStreamWriter,
new MzMLCVParam(MzMLArrayType.MZ.getAccession(), "", "m/z array", MzMLCV.cvMz));
// <binary>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_BINARY);
xmlStreamWriter.writeCharacters(new String(mzBuffer));
// Closing tags
xmlStreamWriter.writeEndElement(); // </binary>
xmlStreamWriter.writeEndElement(); // </binaryDataArray>
// <binaryDataArray> (intensity)
intensityBuffer =
MzMLPeaksEncoder.encodeFloat(scan.getIntensityValues(), floatArrayCompression);
xmlStreamWriter.writeStartElement(MzMLTags.TAG_BINARY_DATA_ARRAY);
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_ENCODED_LENGTH,
String.valueOf(intensityBuffer.length));
// data array precision CV param
writeCVParam(xmlStreamWriter, new MzMLCVParam(MzMLBitLength.THIRTY_TWO_BIT_FLOAT.getValue(),
"", "32-bit float", null));
// data array compression CV param
writeCVParam(xmlStreamWriter, new MzMLCVParam(floatArrayCompression.getAccession(), "",
floatArrayCompression.getName(), null));
// data array type CV param
writeCVParam(xmlStreamWriter, new MzMLCVParam(MzMLArrayType.INTENSITY.getAccession(), "",
"intensity array", MzMLCV.cvUnitsIntensity1));
// <binary>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_BINARY);
xmlStreamWriter.writeCharacters(new String(intensityBuffer));
// Closing tags
xmlStreamWriter.writeEndElement(); // </binary>
xmlStreamWriter.writeEndElement(); // </binaryDataArray>
xmlStreamWriter.writeEndElement(); // </binaryDataArrayList
xmlStreamWriter.writeEndElement(); // </spectrum>
parsedScans++;
}
xmlStreamWriter.writeEndElement(); // </spectrumList>
// <chromatogramList>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_CHROMATOGRAM_LIST);
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_COUNT, String.valueOf(chromatograms.size()));
byte[] rtBuffer = null;
byte[] intensityBuffer2 = null;
for (Chromatogram chromatogram : chromatograms) {
if (canceled) {
dos.close();
fos.close();
xmlStreamWriter.close();
target.delete();
return null;
}
// <chromatogram>
chromatogramIndices.add(xmlStreamWriter.getLocation().getCharacterOffsetInLong());
xmlStreamWriter.writeStartElement(MzMLTags.TAG_CHROMATOGRAM);
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_INDEX, String.valueOf(parsedChromatograms));
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_ID, chromatogram.getChromatogramType().name());
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_DEFAULT_ARRAY_LENGTH,
String.valueOf(chromatogram.getNumberOfDataPoints()));
// chromatogram type CV param
switch (chromatogram.getChromatogramType()) {
case BPC:
writeCVParam(xmlStreamWriter,
new MzMLCVParam(MzMLCV.cvChromatogramBPC, "", "basepeak chromatogram", null));
break;
case MRM_SRM:
writeCVParam(xmlStreamWriter, new MzMLCVParam(MzMLCV.cvChromatogramMRM_SRM, "",
"selected reaction monitoring chromatogram", null));
break;
case SIC:
writeCVParam(xmlStreamWriter, new MzMLCVParam(MzMLCV.cvChromatogramSIC, "",
"selected ion current chromatogram", null));
break;
case TIC:
writeCVParam(xmlStreamWriter, new MzMLCVParam(MzMLCV.cvChromatogramTIC, "",
"total ion current chromatogram", null));
break;
default:
break;
}
// Isolation info
if (!chromatogram.getIsolations().isEmpty()) {
IsolationInfo isolationInfo = chromatogram.getIsolations().get(0);
// <precursor>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_PRECURSOR);
if (isolationInfo.getPrecursorMz() != null) {
// <isolationWindow>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_ISOLATION_WINDOW);
Double mz = isolationInfo.getPrecursorMz();
writeCVParam(xmlStreamWriter, new MzMLCVParam(MzMLCV.cvIsolationWindowTarget,
String.valueOf(mz), "isolation window target m/z", MzMLCV.cvMz));
xmlStreamWriter.writeEndElement(); // </isolationWindow>
}
if (isolationInfo.getActivationInfo() != null) {
// <activation>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_ACTIVATION);
ActivationInfo activationInfo = isolationInfo.getActivationInfo();
switch (activationInfo.getActivationType()) {
case CID:
writeCVParam(xmlStreamWriter, new MzMLCVParam(MzMLCV.cvActivationCID, "",
"collision-induced dissociation", null));
break;
default:
break;
}
if (activationInfo.getActivationEnergy() != null)
writeCVParam(xmlStreamWriter, new MzMLCVParam(MzMLCV.cvActivationEnergy,
String.valueOf(activationInfo.getActivationEnergy()), "collision energy", null));
xmlStreamWriter.writeEndElement(); // </activation>
}
xmlStreamWriter.writeEndElement(); // </precursor>
}
// product m/z value CV param
if (chromatogram.getMz() != null) {
// <product>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_PRODUCT);
// <isolationWindow>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_ISOLATION_WINDOW);
Double mz = chromatogram.getMz();
writeCVParam(xmlStreamWriter, new MzMLCVParam(MzMLCV.cvIsolationWindowTarget,
String.valueOf(mz), "isolation window target m/z", MzMLCV.cvMz));
// Closing tags
xmlStreamWriter.writeEndElement(); // </isolationWindow>
xmlStreamWriter.writeEndElement(); // </product>
}
// <binaryDataArrayList>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_BINARY_DATA_ARRAY_LIST);
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_COUNT, "2");
// <binaryDataArray> (time)
rtBuffer = MzMLPeaksEncoder.encodeFloat(chromatogram.getRetentionTimes(null),
floatArrayCompression);
xmlStreamWriter.writeStartElement(MzMLTags.TAG_BINARY_DATA_ARRAY);
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_ENCODED_LENGTH,
String.valueOf(rtBuffer.length));
// data array precision CV param
writeCVParam(xmlStreamWriter, new MzMLCVParam(MzMLBitLength.THIRTY_TWO_BIT_FLOAT.getValue(),
"", "32-bit float", null));
// data array compression CV param
writeCVParam(xmlStreamWriter, new MzMLCVParam(floatArrayCompression.getAccession(), "",
floatArrayCompression.getName(), null));
// data array type CV param
writeCVParam(xmlStreamWriter, new MzMLCVParam(MzMLArrayType.TIME.getAccession(), "",
"time array", MzMLCV.cvUnitsMin2));
// <binary>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_BINARY);
xmlStreamWriter.writeCharacters(new String(rtBuffer));
// Closing tags
xmlStreamWriter.writeEndElement(); // </binary>
xmlStreamWriter.writeEndElement(); // </binaryDataArray>
// <binaryDataArray> (intensity)
intensityBuffer2 =
MzMLPeaksEncoder.encodeFloat(chromatogram.getIntensityValues(), floatArrayCompression);
xmlStreamWriter.writeStartElement(MzMLTags.TAG_BINARY_DATA_ARRAY);
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_ENCODED_LENGTH,
String.valueOf(intensityBuffer2.length));
// data array precision CV param
writeCVParam(xmlStreamWriter, new MzMLCVParam(MzMLBitLength.THIRTY_TWO_BIT_FLOAT.getValue(),
"", "32-bit float", null));
// data array compression CV param
writeCVParam(xmlStreamWriter, new MzMLCVParam(floatArrayCompression.getAccession(), "",
floatArrayCompression.getName(), null));
// data array type CV param
writeCVParam(xmlStreamWriter, new MzMLCVParam(MzMLArrayType.INTENSITY.getAccession(), "",
"intensity array", MzMLCV.cvUnitsIntensity1));
// <binary>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_BINARY);
xmlStreamWriter.writeCharacters(new String(intensityBuffer2));
// Closing tags
xmlStreamWriter.writeEndElement(); // </binary>
xmlStreamWriter.writeEndElement(); // </binaryDataArray>
xmlStreamWriter.writeEndElement(); // </binaryDataArrayList
xmlStreamWriter.writeEndElement(); // </chromatogram>
parsedChromatograms++;
}
// Closing tags
xmlStreamWriter.writeEndElement(); // </chromatogramList>
xmlStreamWriter.writeEndElement(); // </run>
xmlStreamWriter.writeEndElement(); // </mzML>
// <indexList>
indexListOffset = xmlStreamWriter.getLocation().getCharacterOffsetInLong();
xmlStreamWriter.writeStartElement(MzMLTags.TAG_INDEX_LIST);
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_COUNT, "2");
// <index> (spectrum)
xmlStreamWriter.writeStartElement(MzMLTags.TAG_INDEX);
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_NAME, MzMLTags.TAG_SPECTRUM);
for (int i = 0; i < scans.size(); i++) {
// offset
xmlStreamWriter.writeStartElement(MzMLTags.TAG_OFFSET);
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_ID_REF,
"scan=" + scans.get(i).getScanNumber());
xmlStreamWriter.writeCharacters(String.valueOf(spectrumIndices.get(i)));
xmlStreamWriter.writeEndElement(); // </offset>
}
xmlStreamWriter.writeEndElement(); // </index>
// <index> (chromatogram)
xmlStreamWriter.writeStartElement(MzMLTags.TAG_INDEX);
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_NAME, MzMLTags.TAG_CHROMATOGRAM);
for (int i = 0; i < chromatograms.size(); i++) {
// offset
xmlStreamWriter.writeStartElement(MzMLTags.TAG_OFFSET);
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_ID_REF,
chromatograms.get(i).getChromatogramType().name());
xmlStreamWriter.writeCharacters(String.valueOf(chromatogramIndices.get(i)));
xmlStreamWriter.writeEndElement(); // </offset>
}
xmlStreamWriter.writeEndElement(); // </index>
xmlStreamWriter.writeEndElement(); // </indexList>
// <indexListOffset>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_INDEX_LIST_OFFSET);
xmlStreamWriter.writeCharacters(String.valueOf(indexListOffset));
xmlStreamWriter.writeEndElement(); // </indexListOffset>
// <fileChecksum>
dos.on(false);
String sha1Checksum = DigestUtils.shaHex(sha1.digest());
xmlStreamWriter.writeStartElement(MzMLTags.TAG_FILE_CHECKSUM);
xmlStreamWriter.writeCharacters(sha1Checksum);
xmlStreamWriter.writeEndElement(); // </fileChecksum>
xmlStreamWriter.writeEndElement(); // </indexedmzML>
// Wrapping up
xmlStreamWriter.writeEndDocument();
xmlStreamWriter.close();
} catch (
Exception e) {
throw new MSDKException(e);
}
return null;
}
/** {@inheritDoc} */
@Override
public Float getFinishedPercentage() {
return (totalScans + totalChromatograms) == 0 ? null
: (float) (parsedScans + parsedChromatograms) / (totalScans + totalChromatograms);
}
/** {@inheritDoc} */
@Override
public Void getResult() {
return null;
}
/** {@inheritDoc} */
@Override
public void cancel() {
this.canceled = true;
}
/**
* <p>
* Write a <code><cvParam></code> to the <code>xmlStreamWriter</code>
* </p>
*
* @param xmlStreamWriter an {@link javolution.xml.internal.stream.XMLStreamWriterImpl
* XMLStreamWriterImpl} instance
* @param cvParam the CV Parameter to be written to the target {@link java.io.File File}
* @throws XMLStreamException
*/
private void writeCVParam(XMLStreamWriterImpl xmlStreamWriter, MzMLCVParam cvParam)
throws XMLStreamException {
// <cvParam>
xmlStreamWriter.writeStartElement(MzMLTags.TAG_CV_PARAM);
// cvRef="MS"
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_CV_REF, CV_REF_MS);
// accession="..."
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_ACCESSION, cvParam.getAccession());
// Get optional CV param attribute such as value, name and unitAccession and write if they are
// present
Optional<String> value = cvParam.getValue(), name = cvParam.getName(),
unitAccession = cvParam.getUnitAccession();
if (name.isPresent())
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_NAME, name.get());
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_VALUE, value.orElse(""));
if (unitAccession.isPresent())
xmlStreamWriter.writeAttribute(MzMLTags.ATTR_UNIT_ACCESSION, unitAccession.get());
xmlStreamWriter.writeEndElement(); // </cvParam>
}
/**
* <p>
* Write a group (or list) of <code><cvParam></code> to the <code>xmlStreamWriter</code>
* </p>
*
* @param xmlStreamWriter an {@link javolution.xml.internal.stream.XMLStreamWriterImpl
* XMLStreamWriterImpl} instance
* @param cvGroup the list (or group) of CV Parameters to be written to the target
* {@link java.io.File File}
* @throws XMLStreamException
*/
private void writeCVGroup(XMLStreamWriterImpl xmlStreamWriter, MzMLCVGroup cvGroup)
throws XMLStreamException {
for (MzMLCVParam cvParam : cvGroup.getCVParamsList())
writeCVParam(xmlStreamWriter, cvParam);
}
}