/*******************************************************************************
* Copyright (c) 2008 The Bioclipse Project and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Ola Spjuth
* Jonathan Alvarsson
* Stefan Kuhn
*
******************************************************************************/
package net.bioclipse.spectrum.business;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringBufferInputStream;
import java.io.StringWriter;
import java.util.Iterator;
import java.util.List;
import net.bioclipse.core.ResourcePathTransformer;
import net.bioclipse.core.business.BioclipseException;
import net.bioclipse.core.domain.ISpectrum;
import net.bioclipse.managers.business.IBioclipseManager;
import net.bioclipse.spectrum.domain.IJumboSpectrum;
import net.bioclipse.spectrum.domain.JumboSpectrum;
import net.bioclipse.spectrum.editor.SpectrumEditor;
import nu.xom.Element;
import nu.xom.ParsingException;
import nu.xom.ValidityException;
import org.apache.log4j.Logger;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.jcamp.parser.JCAMPException;
import org.jcamp.parser.JCAMPWriter;
import org.jcamp.spectrum.Spectrum;
import org.xmlcml.cml.base.CMLBuilder;
import org.xmlcml.cml.base.CMLElement;
import org.xmlcml.cml.base.CMLSerializer;
import org.xmlcml.cml.base.CMLUtil;
import org.xmlcml.cml.element.CMLPeak;
import org.xmlcml.cml.element.CMLPeakList;
import org.xmlcml.cml.element.CMLSpectrum;
import org.xmlcml.cml.element.CMLSpectrumData;
import spok.parser.CMLToJcampSpectrumMapper;
import spok.parser.JcampParser;
import spok.parser.JcampToCMLSpectrumMapper;
import spok.utils.PeakPicker;
import spok.utils.SpectrumUtils;
import spok.utils.WCCTool;
/**
* The manager class for CDK. Contains CDK related methods.
*
* @author Stefan Kuhn
*
*/
public class SpectrumManager implements IBioclipseManager {
private static final Logger logger
= Logger.getLogger(SpectrumManager.class);
public String getManagerName() {
return "spectrum";
}
public IJumboSpectrum create(ISpectrum s) throws BioclipseException {
return new JumboSpectrum(parseCML(new StringBufferInputStream(s.getCML())));
}
public JumboSpectrum loadSpectrum(String path) throws IOException,
BioclipseException, CoreException {
return loadSpectrum(ResourcePathTransformer.getInstance().transform( path ).getContents(),ResourcePathTransformer.getInstance().transform( path ).getFileExtension());
}
public JumboSpectrum loadSpectrum(IFile file, IProgressMonitor monitor)
throws IOException, BioclipseException, CoreException {
if ( monitor == null ) {
monitor = new NullProgressMonitor();
}
int ticks = 10000;
monitor.beginTask( "Reading file", ticks );
JumboSpectrum result;
try{
result=loadSpectrum( file.getContents(), file.getFileExtension() );
}finally {
monitor.done();
}
return result;
}
public JumboSpectrum loadSpectrum(InputStream instream, String fileExtension) throws IOException,
BioclipseException, CoreException{
String filetype = detectFileType( fileExtension );
if(filetype.equals( SpectrumEditor.JCAMP_TYPE )){
return new JumboSpectrum(parseJDX(instream));
}else if(filetype.equals( SpectrumEditor.CML_TYPE )){
return new JumboSpectrum(parseCML(instream));
}else{
throw new BioclipseException("Unknown file extension");
}
}
private static CMLSpectrum parseCML( InputStream instream ) {
CMLBuilder builder = new CMLBuilder( false );
CMLElement cmlElement = null;
Element element = null;
StringBuffer buffer = new StringBuffer();
try {
int character;
while ( (character = instream.read()) != -1 ) {
buffer.append( (char) character );
}
instream.close();
cmlElement = (CMLElement) builder.parseString( buffer.toString() );
} catch ( IOException e ) {
StringWriter strWr = new StringWriter();
PrintWriter prWr = new PrintWriter( strWr );
e.printStackTrace( prWr );
logger.error( strWr.toString() );
} catch ( ValidityException e ) {
StringWriter strWr = new StringWriter();
PrintWriter prWr = new PrintWriter( strWr );
e.printStackTrace( prWr );
logger.error( strWr.toString() );
} catch ( ParsingException e ) {
StringWriter strWr = new StringWriter();
PrintWriter prWr = new PrintWriter( strWr );
e.printStackTrace( prWr );
logger.error( strWr.toString() );
}
// dirty! but for some reason if there is no cml namespace,
// parsing fails with a ClassCastException
// so i parse string into an nu.xom.element, set the namespace to
// cml namespace for
// all subelements an reParse the toXML() of the nu.xom.element into
// cml - not elegant, but
// works for the moment
catch ( ClassCastException ex ) {
try {
element = (Element) builder.parseString( buffer.toString() );
SpectrumUtils.namespaceThemAll( element
.getChildElements() );
element.setNamespaceURI( CMLUtil.CML_NS );
cmlElement = (CMLElement) builder.parseString( element.toXML() );
} catch ( ValidityException e ) {
StringWriter strWr = new StringWriter();
PrintWriter prWr = new PrintWriter( strWr );
e.printStackTrace( prWr );
logger.error( strWr.toString() );
} catch ( ParsingException e ) {
StringWriter strWr = new StringWriter();
PrintWriter prWr = new PrintWriter( strWr );
e.printStackTrace( prWr );
logger.error( strWr.toString() );
} catch ( IOException e ) {
StringWriter strWr = new StringWriter();
PrintWriter prWr = new PrintWriter( strWr );
e.printStackTrace( prWr );
logger.error( strWr.toString() );
}
}
if ( cmlElement == null ) {
logger.error( "Errors trying to parse a JCamp spectrum." );
return null;
}
List<CMLElement> spectrumList =
cmlElement.getDescendants( "spectrum", null, true );
// spectrumList = cmlElement.getDescendants("spectrum");
if ( spectrumList != null && spectrumList.size() != 0
|| cmlElement.getLocalName().compareTo( "spectrum" ) == 0 ) {
// Only one spectrum
if ( cmlElement.getLocalName().compareTo( "spectrum" ) == 0 ) {
return (CMLSpectrum) cmlElement;
} else {
// TODO the describer needs to handle these as well
// Only one spectrum, but in a spectrumList
if ( spectrumList.size() == 1 ) {
return (CMLSpectrum) spectrumList.get( 0 );
}
}
}
return null;
}
private static CMLSpectrum parseJDX( InputStream inputStream ) {
Spectrum jdxSpectrum = null;
try {
jdxSpectrum = new JcampParser( inputStream ).getSpectrum();
CMLSpectrum spectrum =
JcampToCMLSpectrumMapper
.mapJcampToCMLSpectrum( jdxSpectrum );
if ( spectrum != null )
return spectrum;
} catch ( Exception e ) {
logger.error( "Errors trying to parse a JCamp spectrum." );
e.printStackTrace();
return null;
}
return null;
}
public void saveSpectrum(IJumboSpectrum spectrum, IFile target,
String filetype) throws BioclipseException, CoreException {
IProgressMonitor monitor = new NullProgressMonitor();
try{
int ticks = 10000;
monitor.beginTask( "Writing file", ticks );
String towrite;
if (filetype.equals(SpectrumEditor.JCAMP_TYPE)) {
Spectrum jdxspectrum = CMLToJcampSpectrumMapper
.mapCMLSpectrumToJcamp(spectrum.getJumboObject());
JCAMPWriter jcamp = JCAMPWriter.getInstance();
String jcampString;
try {
jcampString = jcamp.toJCAMP(jdxspectrum);
} catch (JCAMPException e) {
throw new BioclipseException(e.getMessage());
}
towrite = jcampString;
} else if (filetype.equals(SpectrumEditor.CML_TYPE)) {
CMLSerializer ser = new CMLSerializer();
ser.setIndent(2);
String xml = ser.getXML(spectrum.getJumboObject());
towrite = xml;
} else {
throw new BioclipseException("Filetype "+filetype+" not supported!");
}
if(target.exists()){
target.setContents(new StringBufferInputStream(towrite), false, true, monitor);
} else {
target.create(new StringBufferInputStream(towrite), false, monitor);
}
monitor.worked(ticks);
}
finally {
monitor.done();
}
}
public IJumboSpectrum fromCml(String cml) throws BioclipseException,
IOException {
return new JumboSpectrum(parseCML(new StringBufferInputStream(cml)));
}
public IJumboSpectrum pickPeaks(IJumboSpectrum spectruminput) throws BioclipseException{
CMLSpectrumData spectrumData = SpectrumUtils.getSpectrumData(spectruminput.getJumboObject());
if(spectrumData==null)
throw new BioclipseException("No continuous data in this spectrum");
PeakPicker picker = new PeakPicker(spectrumData);
CMLPeakList peaks = picker.getPeakArray();
spectruminput.getJumboObject().addPeakList(peaks);
return spectruminput;
}
public void saveSpectrum(IJumboSpectrum spectrum, String filename,
String filetype) throws BioclipseException, CoreException {
if(filename.indexOf("."+filetype)==-1)
filename=filename+"."+filetype;
IFile target = ResourcePathTransformer.getInstance().transform(filename);
//IFile target=ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(filename));
if(target.exists()){
throw new BioclipseException("File already exists!");
}
this.saveSpectrum(spectrum, target, filetype);
}
public double calculateSimilarityWCC( double[] positions1, double[] positions2,
double width ) {
// one carbon per peak
double[] intensities1 = new double[positions1.length];
for ( int i = 0; i < intensities1.length; i++ )
intensities1[i] = 1.0;
double[] intensities2 = new double[positions2.length];
for ( int i = 0; i < intensities2.length; i++ )
intensities2[i] = 1.0;
return WCCTool.wcc( positions1, intensities1, positions2, intensities2,
width );
}
public double calculateSimilarityWCC( double[] positions1, double[] intensities1,
double[] positions2, double[] intensities2,
double width ) {
return WCCTool.wcc( positions1, intensities1, positions2, intensities2,
width );
}
public double calculateSimilarityWCC( ISpectrum spectrum1, ISpectrum spectrum2,
double width ) throws BioclipseException {
CMLSpectrum cmlspectrum1;
if(spectrum1 instanceof IJumboSpectrum)
cmlspectrum1 = ((IJumboSpectrum)spectrum1).getJumboObject();
else
cmlspectrum1 = create( spectrum1 ).getJumboObject();
CMLSpectrum cmlspectrum2;
if(spectrum2 instanceof IJumboSpectrum)
cmlspectrum2 = ((IJumboSpectrum)spectrum2).getJumboObject();
else
cmlspectrum2 = create( spectrum2 ).getJumboObject();
if(cmlspectrum1.getPeakListElements().size()==0 || cmlspectrum2.getPeakListElements().size()==0)
throw new BioclipseException("Spectra do not contain peak lists");
List<CMLElement> peaks1 = SpectrumUtils.getPeakElements(cmlspectrum1);
Iterator<CMLElement> it = peaks1.iterator();
double[] shifts1 = new double[peaks1.size()];
double[] intensities1 = new double[peaks1.size()];
int i = 0;
while (it.hasNext()) {
CMLPeak peak = (CMLPeak) it.next();
shifts1[i] = peak.getXValue();
if(peak.getYValueAttribute()!=null)
intensities1[i]=peak.getYValue();
else
intensities1[i]=1;
i += 1;
}
List<CMLElement> peaks2 = SpectrumUtils.getPeakElements(cmlspectrum2);
it = peaks2.iterator();
double[] shifts2 = new double[peaks2.size()];
double[] intensities2 = new double[peaks2.size()];
i = 0;
while (it.hasNext()) {
CMLPeak peak = (CMLPeak) it.next();
shifts2[i] = peak.getXValue();
if(peak.getYValueAttribute()!=null)
intensities2[i]=peak.getYValue();
else
intensities2[i]=1;
i += 1;
}
return calculateSimilarityWCC( shifts1, intensities1, shifts2, intensities2, width );
}
public String detectFileType( String extension ) throws BioclipseException {
String filetype = extension;
if(filetype==null)
filetype="";
if("jx,dx,JX,DX,jdx".indexOf(filetype)>-1){
return SpectrumEditor.JCAMP_TYPE;
}else if("cml,xml".indexOf(filetype)>-1){
return SpectrumEditor.CML_TYPE;
}else{
throw new BioclipseException("Unknown file extension");
}
}
public IJumboSpectrum createEmpty() throws BioclipseException{
IJumboSpectrum spectrum = new JumboSpectrum();
spectrum.getJumboObject().addPeakList(new CMLPeakList());
return spectrum;
}
}