org.jcamp.parser.MSJCAMPReader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jcamp-dx Show documentation
Show all versions of jcamp-dx Show documentation
The JCAMP-DX project is the reference implemention of the IUPAC JCAMP-DX spectroscopy data standard.
The newest version!
package org.jcamp.parser;
import org.jcamp.math.IArray2D;
import org.jcamp.math.IOrderedArray1D;
import org.jcamp.spectrum.ArrayData;
import org.jcamp.spectrum.Assignment;
import org.jcamp.spectrum.EquidistantData;
import org.jcamp.spectrum.GCMSSpectrum;
import org.jcamp.spectrum.IDataArray1D;
import org.jcamp.spectrum.IOrderedDataArray1D;
import org.jcamp.spectrum.ISpectrumIdentifier;
import org.jcamp.spectrum.MassSpectrum;
import org.jcamp.spectrum.OrderedArrayData;
import org.jcamp.spectrum.Pattern;
import org.jcamp.spectrum.Peak1D;
import org.jcamp.spectrum.Spectrum;
import org.jcamp.units.CommonUnit;
import org.jcamp.units.Unit;
/**
* adapter between MS spectrum class and JCAMPWriter.
*
* @author Thomas Weber
*/
public class MSJCAMPReader
extends CommonSpectrumJCAMPReader
implements ISpectrumJCAMPReader {
/**
* MSJCAMPAdapter constructor comment.
*/
protected MSJCAMPReader() {
super();
}
/**
* gets mass spectrum.
*
* @return com.creon.chem.spectrum.MassSpectrum
* @param block com.creon.chem.jcamp.JCAMPBlock
*/
private MassSpectrum createFS(JCAMPBlock block) throws JCAMPException {
MassSpectrum spectrum;
Unit xUnit = getXUnits(block);
if (xUnit == null)
xUnit = CommonUnit.mz;
Unit yUnit = getYUnits(block);
if (yUnit == null)
yUnit = CommonUnit.percentIntensity;
double xFactor = getXFactor(block);
double yFactor = getYFactor(block);
int nPoints = getNPoints(block);
IOrderedDataArray1D x;
IDataArray1D y;
if (block.getDataRecord("XYDATA") != null) {
double firstX = getFirstX(block);
double lastX = getLastX(block);
double[] intensities = getXYData(block, firstX, lastX, nPoints, xFactor, yFactor);
if (intensities.length != nPoints)
throw new JCAMPException("incorrect ##NPOINTS= or bad ##XYDATA=");
x = new EquidistantData(firstX, lastX, nPoints, xUnit);
y = new ArrayData(intensities, yUnit);
} else if (block.getDataRecord("XYPOINTS") != null) {
double xy[][] = getXYPoints(block, nPoints, xFactor, yFactor);
x = new OrderedArrayData(xy[0], xUnit);
y = new ArrayData(xy[1], yUnit);
} else
throw new JCAMPException("missing data: ##XYDATA= or ##XYPOINTS= required.");
spectrum = new MassSpectrum(x, y, true);
return spectrum;
}
/**
* NTUPLE mass spectra.
*
* @return com.creon.chem.spectrum.GCMSSpectrum
* @param block com.creon.chem.jcamp.JCAMPBlock
*/
private GCMSSpectrum createGCMS(JCAMPBlock block) throws JCAMPException {
GCMSSpectrum spectrum;
String title = getTitle(block);
JCAMPNTuple ntuple = block.getNTuple();
int nPages = ntuple.numPages();
MassSpectrum[] ms = new MassSpectrum[nPages];
double[] times = getRetentionTimes(ntuple);
double[] tics = getTICs(ntuple);
Unit xUnit = getXUnits(block);
if (xUnit == null)
xUnit = CommonUnit.mz;
Unit yUnit = getYUnits(block);
if (yUnit == null)
yUnit = CommonUnit.relativeAbundance;
for (int i = 0; i < nPages; i++) {
JCAMPNTuplePage page = block.getNTuple().getPage(i);
IArray2D msxy = page.getXYData();
/* double[][] msxy = getNTupleXYPoints(block, page);
for (int j = 0; j < msxy[0].length; j++) {
msxy[0][j] *= xFactor;
msxy[1][j] *= yFactor;
}
*/
IOrderedDataArray1D x = new OrderedArrayData((IOrderedArray1D) msxy.getXArray(), xUnit);
IDataArray1D y = new ArrayData(msxy.getYArray(), yUnit);
ms[i] = new MassSpectrum(x, y, false);
if (Double.isNaN(times[i]))
ms[i].setTitle(title + "(mass spectrum [" + i + "]");
else
ms[i].setTitle(title + "(mass spectrum [" + i + "]: t=" + times[i] + ")");
}
IOrderedDataArray1D x = new OrderedArrayData(times, CommonUnit.second);
if (tics != null) {
IDataArray1D y = new ArrayData(tics, CommonUnit.intensity);
spectrum = new GCMSSpectrum(x, y, ms);
} else
spectrum = new GCMSSpectrum(x, ms);
return spectrum;
}
/**
* create mass spectrum peak spectrum from JCAMPBlock.
*
* @return MassSpectrum
* @param block JCAMPBlock
* @exception JCAMPException exception thrown if parsing fails.
*/
private MassSpectrum createPeakTable(JCAMPBlock block) throws JCAMPException {
MassSpectrum spectrum = null;
String title = getTitle(block);
Unit xUnit = null;
try {
xUnit = getXUnits(block);
} catch (JCAMPException e) {
xUnit = CommonUnit.mz;
}
Unit yUnit = null;
try {
yUnit = getYUnits(block);
} catch (JCAMPException e) {
yUnit = CommonUnit.intensity;
}
double xFactor;
try {
xFactor = getXFactor(block);
} catch (JCAMPException e) {
xFactor = 1.0;
}
double yFactor;
try {
yFactor = getYFactor(block);
} catch (JCAMPException e) {
yFactor = 1.0;
}
int nPoints = getNPoints(block);
Object[] tables = getPeaktable(block, nPoints, xFactor, yFactor);
if (tables == null)
throw new JCAMPException("missing data table");
Peak1D[] peaks = (Peak1D[]) tables[0];
double[][] xy = peakTableToPeakSpectrum(peaks);
IOrderedDataArray1D x = new OrderedArrayData(xy[0], xUnit);
IDataArray1D y = new ArrayData(xy[1], yUnit);
spectrum = new MassSpectrum(x, y, false);
//shk3: removed this condition, since I see not reason for it
//and it breaks reading files with more than 50 peaks.
//if (peaks.length < 50) // save check
spectrum.setPeakTable(peaks);
if (tables.length > 1) {
Pattern[] pattern = (Pattern[]) tables[1];
if (pattern != null && pattern.length < 50)
spectrum.setPatternTable(pattern);
if (tables.length > 2) {
Assignment[] assigns = (Assignment[]) tables[2];
if (assigns != null && assigns.length < 50)
spectrum.setAssignments(assigns);
}
}
spectrum.setTitle(title);
try {
String owner = getOwner(block);
spectrum.setOwner(owner);
} catch (JCAMPException e) {
// label is normally required, but often it is missing
}
try {
String origin = getOrigin(block);
spectrum.setOrigin(origin);
} catch (JCAMPException e) {
// label is normally required, but often it is missing
}
return spectrum;
}
/**
* createSpectrum method comment.
*/
@Override
public Spectrum createSpectrum(JCAMPBlock block) throws JCAMPException {
if (block.getSpectrumID() != ISpectrumIdentifier.MS)
block.getErrorHandler().fatal("JCAMP reader adapter missmatch");
if (block.isNTupleBlock()) { // chromatogram!
GCMSSpectrum spectrum = createGCMS(block);
setNotes(block, spectrum);
return spectrum;
} else {
MassSpectrum spectrum = null;
JCAMPBlock.Type type = block.getType();
if (type.equals(JCAMPBlock.Type.FULLSPECTRUM))
spectrum = createFS(block);
else if (type.equals(JCAMPBlock.Type.PEAKTABLE))
spectrum = createPeakTable(block);
else if (type.equals(JCAMPBlock.Type.ASSIGNMENT))
spectrum = createPeakTable(block);
else // never reached
block.getErrorHandler().fatal("illegal block type");
setNotes(block, spectrum);
return spectrum;
}
}
/**
* get retention times for GC/MS
*
* @return double[]
*/
private double[] getRetentionTimes(JCAMPNTuple ntuple) {
int nPages = ntuple.numPages();
JCAMPVariable vTime = ntuple.getVariableByName("RETENTIONTIME");
String[] timeValues = ntuple.getVariableValues(".RETENTIONTIME", vTime);
double[] times = new double[nPages];
double timeFactor = 1.0;
double firstTime = Double.NaN;
double lastTime = Double.NaN;
double deltaTime = 0.;
if (vTime != null) {
if (vTime.getFactor() != null)
timeFactor = vTime.getFactor().doubleValue();
if (vTime.getFirst() != null)
firstTime = vTime.getFirst().doubleValue();
if (vTime.getLast() != null)
lastTime = vTime.getLast().doubleValue();
deltaTime = (lastTime - firstTime) / nPages;
}
for (int i = 0; i < times.length; i++) {
if (timeValues[i] != null)
times[i] = Double.parseDouble(timeValues[i]) * timeFactor;
else
times[i] = firstTime + i * deltaTime;
}
return times;
}
/**
* get total ion counts for GC/MS
*
* @return double[]
*/
private double[] getTICs(JCAMPNTuple ntuple) {
int nPages = ntuple.numPages();
JCAMPVariable vtic = ntuple.getVariableByName("RIC");
String[] ticValues = ntuple.getVariableValues(".RIC", vtic);
double[] tics = new double[nPages];
double ticFactor = 1.0;
boolean hasTIC = false;
if (vtic != null) {
if (vtic.getFactor() != null)
ticFactor = vtic.getFactor().doubleValue();
}
for (int i = 0; i < tics.length; i++) {
if (ticValues[i] != null) {
hasTIC = true;
tics[i] = Double.parseDouble(ticValues[i]) * ticFactor;
} else
tics[i] = Double.NaN;
}
if (hasTIC)
return tics;
else
return null;
}
}