/*
* EuroCarbDB, a framework for carbohydrate bioinformatics
*
* Copyright (c) 2006-2009, Eurocarb project, or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
* A copy of this license accompanies this distribution in the file LICENSE.txt.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* Last commit: $Rev: 1930 $ by $Author: david@nixbioinf.org $ on $Date:: 2010-07-29 #$
*/
package org.eurocarbdb.application.glycoworkbench;
import org.eurocarbdb.application.glycanbuilder.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import org.omegahat.Environment.ObjectDataStructures.numeric;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import javax.xml.transform.sax.TransformerHandler;
import org.xml.sax.helpers.AttributesImpl;
/**
* Represent a labeled peak centroid in a mass spectrum
*
* @author Alessio Ceroni (a.ceroni@imperial.ac.uk)
*/
public class Peak implements Comparable<Peak>, SAXUtils.SAXWriter {
static final protected Pattern pattern1;
static final protected Pattern pattern2;
static final protected Pattern pattern3;
static final protected Pattern pattern4;
static {
String number = "(\\S+)";
String separator = "(?:\\s+|[,;])";
pattern1 = Pattern.compile("^\\s*" + number + "\\s*$" );
pattern2 = Pattern.compile("^\\s*" + number + separator + number + "\\s*$");
pattern3 = Pattern.compile("^\\s*" + number + separator + number+ separator + number + "\\s*$");
pattern4 = Pattern.compile("^\\s*" + number + separator + number+ separator + number + separator + number + "\\s*$");
}
protected Double mz_ratio;
protected Double intensity;
private Integer charge=Integer.MIN_VALUE;
/**
* Create a new peak object with 0 values for mass/charge and intensity
*/
public Peak() {
mz_ratio = 0.;
intensity = 0.;
}
/**
* Create a new peak object with specific values for mass/charge and
* intensity
*
* @param _mz
* the mass/charge value
* @param _int
* the intensity value
*/
public Peak(double _mz, double _int) {
mz_ratio = _mz;
intensity = _int;
}
public Peak(double _mz, double _int, int _charge) {
mz_ratio = _mz;
intensity = _int;
charge = _charge;
}
/**
* Create a copy of this object
*/
public Peak clone() {
Peak clone=new Peak(mz_ratio, intensity);
clone.setCharge(this.charge);
return clone;
}
public int compareTo(Peak p) {
if (this.mz_ratio < p.mz_ratio){
return -1;
}
if (this.mz_ratio > p.mz_ratio)
return +1;
return 0;
}
public boolean equals(Object other) {
if (!(other instanceof Peak))
return false;
Peak p = (Peak) other;
return (Math.abs(this.mz_ratio - p.mz_ratio) < 0.0000000001 && Math
.abs(this.intensity - p.intensity) < 0.0000000001);
}
public boolean mzEquals(Peak it){
return (Math.abs(this.mz_ratio - it.mz_ratio) < 0.0000000001);
}
public boolean mzEquals(Peak it, MassUnit unit, double accuracy){
if(unit==MassUnit.PPM){
return (Math.abs(1. - it.getMZ() / mz_ratio) < (0.000001 * accuracy));
}
return (Math.abs(mz_ratio - it.getMZ()) < accuracy);
}
public int hashCode() {
return mz_ratio.hashCode() + intensity.hashCode();
}
/**
* Return the mass/charge value for this peak
*/
public double getMZ() {
return mz_ratio;
}
/**
* Set the mass/charge value for this peak
*/
public void setMZ(double _mz) {
mz_ratio = _mz;
}
/**
* Return the intensity value for this peak
*/
public double getIntensity() {
return intensity;
}
/**
* Set the intensity value for this peak
*/
public void setIntensity(double _int) {
intensity = _int;
}
// serializaation
public String toString() {
return mz_ratio + " " + intensity;
}
/**
* Create a new object from its string representation composed of a space
* separated list of numbers that must contain the mass/charge value and
* that can also contain the intensity and area of the peak (ignored, here
* for compatibility)
*/
static public Peak parseString(String str) {
try {
Matcher m = pattern4.matcher(str);
if (m.matches())
return new Peak(Double.valueOf(m.group(1)), Double.valueOf(m
.group(2)),Integer.valueOf(m.group(4)));
m = pattern3.matcher(str);
if (m.matches())
return new Peak(Double.valueOf(m.group(1)), Double.valueOf(m
.group(2)),Integer.valueOf(m.group(3)));
m = pattern2.matcher(str);
if (m.matches())
return new Peak(Double.valueOf(m.group(1)), Double.valueOf(m
.group(2)));
m = pattern1.matcher(str);
if (m.matches())
return new Peak(Double.valueOf(m.group(1)), 1);
} catch (NumberFormatException nfe) {
}
return null;
}
/**
* Create a new object from its XML representation as part of a DOM tree.
*/
static public Peak fromXML(Node peak_node) throws Exception {
Peak ret = new Peak();
ret.mz_ratio = Double.valueOf(XMLUtils.getAttribute(peak_node,
"mz_ratio"));
ret.intensity = Double.valueOf(XMLUtils.getAttribute(peak_node,
"intensity"));
if (XMLUtils.getAttribute(peak_node, "charge") != null) {
ret.charge = Integer.valueOf(XMLUtils.getAttribute(peak_node,
"charge"));
}
return ret;
}
/**
* Create an XML representation of this object to be part of a DOM tree.
*/
public Element toXML(Document document) {
if (document == null)
return null;
Element peak_node = document.createElement("Peak");
if (peak_node == null)
return null;
peak_node.setAttribute("mz_ratio", "" + mz_ratio);
peak_node.setAttribute("intensity", "" + intensity);
if(this.getCharge()!=Integer.MIN_VALUE){
peak_node.setAttribute("charge", "" + this.getCharge());
}else{
}
return peak_node;
}
/**
* Default SAX handler to read a representation of this object from an XML
* stream.
*/
public static class SAXHandler extends SAXUtils.ObjectTreeHandler {
public boolean isElement(String namespaceURI, String localName,
String qName) {
return qName.equals(getNodeElementName());
}
public static String getNodeElementName() {
return "Peak";
}
protected void initContent(String namespaceURI, String localName,
String qName, Attributes atts) throws SAXException {
super.initContent(namespaceURI, localName, qName, atts);
Peak ret = new Peak();
ret.mz_ratio = doubleAttribute(atts, "mz_ratio", 0.);
ret.intensity = doubleAttribute(atts, "intensity", 0.);
ret.charge = integerAttribute(atts,"charge",Integer.MIN_VALUE);
object = ret;
}
}
public void write(TransformerHandler th) throws SAXException {
AttributesImpl atts = new AttributesImpl();
atts.addAttribute("", "", "mz_ratio", "CDATA", "" + mz_ratio);
atts.addAttribute("", "", "intensity", "CDATA", "" + intensity);
if(this.charge!=Integer.MIN_VALUE){
atts.addAttribute("", "", "charge", "CDATA", "" + charge);
}
th.startElement("", "", "Peak", atts);
th.endElement("", "", "Peak");
}
public void setCharge(int charge) {
// TODO Auto-generated method stub
this.charge = charge;
}
public int getCharge() {
return this.charge;
}
}