/*
* 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 #$
*/
/**
@author Alessio Ceroni (a.ceroni@imperial.ac.uk)
*/
package org.eurocarbdb.application.glycoworkbench.plugin.reporting;
import org.eurocarbdb.application.glycoworkbench.plugin.*;
import org.eurocarbdb.application.glycoworkbench.*;
import org.eurocarbdb.application.glycanbuilder.*;
import java.io.*;
import java.util.*;
import java.util.regex.*;
import java.awt.geom.*;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import org.xml.sax.Attributes;
import javax.xml.transform.sax.TransformerHandler;
import org.xml.sax.helpers.AttributesImpl;
public class AnnotationReportDocument extends BaseDocument implements SAXUtils.SAXWriter {
private static final int ANNOTATION = 1;
private static final int ANCHOR = 2;
private static final int SCALE = 3;
private static final int CP = 4;
private MMFCreator mmfc = null;
private BuilderWorkspace theWorkspace;
private AnnotationReportOptions theOptions = null;
private GraphicOptions theGraphicOptions = null;
private boolean show_rel_int = false;
private boolean show_empty_annotations = false;
private double start_mz = 0;
private double end_mz = 0;
private PeakData thePeakData = null;
private Glycan theParentStructure = null;
private PeakAnnotationCollection thePeakAnnotationCollection = new PeakAnnotationCollection();
private Vector<AnnotationObject> annotations = new Vector<AnnotationObject>();
private HashMap<AnnotationObject,Point2D> anchors = new HashMap<AnnotationObject,Point2D>();
private HashMap<AnnotationObject,Point2D> control_points = new HashMap<AnnotationObject,Point2D>();
private HashMap<AnnotationObject,Double> scales = new HashMap<AnnotationObject,Double>();
public AnnotationReportDocument() {
theWorkspace = new BuilderWorkspace(null,false);
theOptions = new AnnotationReportOptions();
theGraphicOptions = theWorkspace.getGraphicOptions();
theWorkspace.setDisplay(GraphicOptions.DISPLAY_COMPACT);
theGraphicOptions.SHOW_INFO = false;
theGraphicOptions.SHOW_MASSES = false;
theGraphicOptions.SHOW_REDEND = false;
}
public AnnotationReportDocument(double smz, double emz, PeakData pd, Glycan parent, PeakAnnotationCollection pac, AnnotationReportOptions opt, GraphicOptions gopt) {
this();
assert pac!=null;
theOptions = opt;
show_rel_int = opt.SHOW_RELATIVE_INTENSITIES;
show_empty_annotations = opt.SHOW_EMPTY_ANNOTATIONS;
start_mz = smz;
end_mz = emz;
thePeakData = (opt.SHOW_RAW_SPECTRUM) ?pd :null;
theParentStructure = parent;
thePeakAnnotationCollection = pac;
theWorkspace.setNotation(gopt.NOTATION);
theGraphicOptions.ORIENTATION = (thePeakAnnotationCollection.isProfile()) ?GraphicOptions.BT :GraphicOptions.RL;
initData();
}
private MMFCreator getMMFCreator() {
try {
if( mmfc==null )
mmfc = new MMFCreator();
return mmfc;
}
catch(Exception e) {
LogUtils.report(e);
return null;
}
}
// member access
public BuilderWorkspace getWorkspace() {
return theWorkspace;
}
public AnnotationReportOptions getAnnotationReportOptions() {
return theOptions;
}
public GraphicOptions getGraphicOptions() {
return theGraphicOptions;
}
public int size() {
return annotations.size();
}
public String getName() {
return "Annotation report";
}
public javax.swing.ImageIcon getIcon() {
return FileUtils.defaultThemeManager.getImageIcon("annrepdoc");
}
public Collection<javax.swing.filechooser.FileFilter> getFileFormats() {
Vector<javax.swing.filechooser.FileFilter> filters = new Vector<javax.swing.filechooser.FileFilter>();
filters.add(new ExtensionFileFilter("gwr", "Annotation report file"));
return filters;
}
public javax.swing.filechooser.FileFilter getAllFileFormats() {
return new ExtensionFileFilter("gwr", "Annotation report file");
}
public boolean isShowRelativeIntensities() {
return show_rel_int;
}
public boolean isShowEmptyAnnotations() {
return show_empty_annotations;
}
public double getStartMZ() {
return start_mz;
}
public double getEndMZ() {
return end_mz;
}
public PeakData getPeakData() {
return thePeakData;
}
public Glycan getParentStructure() {
return theParentStructure;
}
public PeakAnnotationCollection getPeakAnnotationCollection() {
return thePeakAnnotationCollection;
}
public Vector<AnnotationObject> getAnnotations() {
return annotations;
}
public Vector<PeakAnnotation> getPeakAnnotations() {
Vector<PeakAnnotation> ret = new Vector<PeakAnnotation>();
for( AnnotationObject a : annotations)
ret.addAll(a.getPeakAnnotations());
return ret;
}
public Point2D getAnchor(AnnotationObject a) {
return anchors.get(a);
}
public HashMap<AnnotationObject,Point2D> getAnchors() {
return anchors;
}
public Point2D getControlPoint(AnnotationObject a) {
return control_points.get(a);
}
public HashMap<AnnotationObject,Point2D> getControlPoints() {
return control_points;
}
public Double getScale(AnnotationObject a) {
return scales.get(a);
}
public HashMap<AnnotationObject,Double> getScales() {
return scales;
}
public boolean isDisplayed(AnnotationObject a) {
return annotations.contains(a);
}
public double[][] getData(Rectangle2D data_area) {
return getData(data_area,show_rel_int);
}
public double[][] getData(Rectangle2D data_area, boolean rel_int) {
if( thePeakData!=null ) {
if( start_mz!=end_mz ) {
double mz_toll = (end_mz-start_mz)/data_area.getWidth()/2;
return thePeakData.getData(start_mz,end_mz,mz_toll,rel_int);
}
else {
double mz_toll = thePeakData.getMZRange().getLength()/data_area.getWidth()/2;
return thePeakData.getData(mz_toll,rel_int);
}
}
else {
if( start_mz!=end_mz )
return thePeakAnnotationCollection.getPeakData(start_mz,end_mz,1.,rel_int);
else
return thePeakAnnotationCollection.getPeakData(1.,rel_int);
}
}
// actions
private Peak findNearestPeak(TreeMap<Double,Double> theData, double mz, double mz_toll) {
double max_mz = mz;
double max_int = 0.;
Object[] before = theData.subMap(mz-mz_toll,mz).entrySet().toArray();
if( before!=null ) {
for( int i=before.length-1; i>=0; i-- ) {
Map.Entry<Double,Double> e = (Map.Entry<Double,Double>)before[i];
if( e.getValue()<max_int )
break;
max_mz = e.getKey();
max_int = e.getValue();
}
}
Object[] after = theData.subMap(mz,mz+mz_toll).entrySet().toArray();
if( after!=null ) {
for( int i=0; i<after.length; i++ ) {
Map.Entry<Double,Double> e = (Map.Entry<Double,Double>)after[i];
if( e.getValue()<max_int )
break;
max_mz = e.getKey();
max_int = e.getValue();
}
}
return new Peak(max_mz,max_int);
}
public void initData() {
if( annotations==null )
return;
annotations.clear();
anchors.clear();
control_points.clear();
scales.clear();
// update visible data
double max_int = 0.;
TreeMap<Double,Double> visibleData = new TreeMap<Double,Double>();
if( thePeakData!=null ) {
double[][] data;
if( start_mz!=end_mz )
data = thePeakData.getData(start_mz,end_mz,0.1);
else
data = thePeakData.getData(0.1,show_rel_int);
for( int i=0; i<data[0].length; i++ ) {
visibleData.put(data[0][i],data[1][i]);
max_int = Math.max(max_int,data[1][i]);
}
}
else {
if( start_mz!=end_mz )
max_int = thePeakAnnotationCollection.getMaxIntensity(start_mz,end_mz);
else
max_int = thePeakAnnotationCollection.getMaxIntensity();
}
// add annotations
AnnotationObject last = null;
for( PeakAnnotation pa : thePeakAnnotationCollection.getPeakAnnotations() ) {
if( show_empty_annotations || pa.isAnnotated() ) {
Peak p = pa.getPeak();
if( start_mz==end_mz || p.getMZ()>=start_mz && p.getMZ()<=end_mz ) {
// get peak point
if( thePeakData!=null )
p = findNearestPeak(visibleData,p.getMZ(),1.);
double x = p.getMZ();
double y = (show_rel_int) ?100.*p.getIntensity()/max_int :p.getIntensity();
// create annotation object
AnnotationObject a = new AnnotationObject(x,y,pa);
if( last!=null && last.canGroup(a) )
last.group(a);
else {
annotations.add(a);
anchors.put(a,new Point2D.Double(x,y));
control_points.put(a,new Point2D.Double(x,y));
scales.put(a,1.);
last = a;
}
}
}
}
fireDocumentInit();
}
/*
public boolean contains(Collection<PeakAnnotation> annotations, PeakAnnotation pa) {
for( PeakAnnotation a : annotations ) {
if( a.getPeak().equals(pa.getPeak()) ) {
if( !a.equals(pa) ) {
System.out.println(a + " <> " + pa);
if( !a.getAnnotation().getFragmentEntry().equals(pa.getAnnotation().getFragmentEntry()) ) {
System.out.println("different fragmententry");
FragmentEntry fa = a.getAnnotation().getFragmentEntry();
FragmentEntry fb = pa.getAnnotation().getFragmentEntry();
if( !fa.name.equals(fb.name) )
System.out.println( "\t" + fa.name + " <> " + fb.name);
if( !fa.mass.equals(fb.mass) )
System.out.println( "\t" + fa.mass + " <> " + fb.mass);
if( !fa.fragment.equalsStructure(fb.fragment) )
System.out.println( "\t" + fa.fragment + " <> " + fb.fragment);
}
if( !a.getAnnotation().getIons().equals(pa.getAnnotation().getIons()) )
System.out.println("different ions");
if( !a.getAnnotation().getNeutralExchanges().equals(pa.getAnnotation().getNeutralExchanges()) )
System.out.println("different exchanges");
}
else
return true;
}
}
return false;
}
*/
public boolean updateData(Glycan parent, PeakAnnotationCollection pac, Collection<AnnotationObject> added, boolean fire, boolean merge) {
// update objects
theParentStructure = parent;
thePeakAnnotationCollection = pac;
// refresh visible data
double max_int = 0.;
TreeMap<Double,Double> visibleData = new TreeMap<Double,Double>();
if( thePeakData!=null ) {
double[][] data;
if( start_mz!=end_mz )
data = thePeakData.getData(start_mz,end_mz,0.1);
else
data = thePeakData.getData(0.1,show_rel_int);
for( int i=0; i<data[0].length; i++ ) {
visibleData.put(data[0][i],data[1][i]);
max_int = Math.max(max_int,data[1][i]);
}
}
else {
if( start_mz!=end_mz )
max_int = thePeakAnnotationCollection.getMaxIntensity(start_mz,end_mz);
else
max_int = thePeakAnnotationCollection.getMaxIntensity();
}
// remove non existing annotations
boolean removed = false;
if( !merge ) {
for( int i=0; i<annotations.size(); i++ ) {
AnnotationObject a = annotations.get(i);
// check if peak annotations are still existing
for( int l=0; l<a.getPeakAnnotations().size(); l++ ) {
PeakAnnotation pa = a.getPeakAnnotations().get(l);
if( !thePeakAnnotationCollection.getPeakAnnotations().contains(pa) ) {
//System.out.println("removing " + i + " " + l);
removed = true;
a.remove(pa);
l--;
}
}
// if not remove the annotation object
if( a.size()==0 ) {
//System.out.println("removing " + i);
removed = true;
annotations.removeElementAt(i);
anchors.remove(a);
control_points.remove(a);
scales.remove(a);
i--;
}
}
}
// add new annotations
AnnotationObject last = null;
for( PeakAnnotation pa : thePeakAnnotationCollection.getPeakAnnotations() ) {
if( getAnnotation(pa)==null && (show_empty_annotations || pa.isAnnotated()) ) {
Peak p = pa.getPeak();
if( start_mz==end_mz || p.getMZ()>=start_mz && p.getMZ()<=end_mz ) {
// get peak point
if( thePeakData!=null )
p = findNearestPeak(visibleData,p.getMZ(),1.);
double x = p.getMZ();
double y = (show_rel_int) ?100.*p.getIntensity()/max_int :p.getIntensity();
// create annotation object
AnnotationObject a = new AnnotationObject(x,y,pa);
if( last!=null && last.canGroup(a) )
last.group(a);
else {
added.add(a);
annotations.add(a);
anchors.put(a,new Point2D.Double(x,y));
control_points.put(a,new Point2D.Double(x,y));
scales.put(a,1.);
last = a;
}
}
}
}
boolean changed = (removed || (added.size()>0));
if( changed && fire )
fireDocumentChanged();
return changed;
}
public AnnotationObject getAnnotation(PeakAnnotation pa) {
for( AnnotationObject a : annotations ) {
if( a.getPeakAnnotations().contains(pa) )
return a;
}
return null;
}
public void remove(AnnotationObject a) {
if( a.size()==0 || !show_empty_annotations ) {
annotations.remove(a);
anchors.remove(a);
control_points.remove(a);
scales.remove(a);
}
else
a.clear();
fireDocumentChanged();
}
public void remove(Collection<AnnotationObject> toremove) {
for( AnnotationObject a : toremove ) {
if( a.size()==0 || !show_empty_annotations ) {
annotations.remove(a);
anchors.remove(a);
control_points.remove(a);
scales.remove(a);
}
else
a.clear();
}
fireDocumentChanged();
}
public Point2D computeControlPoint(Point2D anchor, double mz, double intensity) {
return computeControlPoint(anchor,new Point2D.Double(mz,intensity));
}
public Point2D computeControlPoint(Point2D anchor, Point2D peak) {
if( anchor.getY()<=peak.getY() )
return new Point2D.Double((anchor.getX()+peak.getX())/2,(anchor.getY()+peak.getY())/2);
return new Point2D.Double(peak.getX(),(anchor.getY()+peak.getY())/2);
}
public void move(Collection<AnnotationObject> tomove, double ddx, double ddy) {
for( AnnotationObject a : tomove ) {
Point2D anchor = anchors.get(a);
if( anchor!=null ) {
anchor.setLocation(anchor.getX()+ddx,anchor.getY()-ddy);
control_points.put(a,computeControlPoint(anchor,a.getPeakPoint()));
}
}
fireDocumentChanged();
}
public void move(AnnotationObject tomove, double ddx, double ddy) {
Point2D anchor = anchors.get(tomove);
if( anchor!=null ) {
anchor.setLocation(anchor.getX()+ddx,anchor.getY()-ddy);
control_points.put(tomove,computeControlPoint(anchor,tomove.getPeakPoint()));
fireDocumentChanged();
}
}
public void moveTo(AnnotationObject tomove, double x, double y) {
Point2D anchor = anchors.get(tomove);
if( anchor!=null ) {
anchor.setLocation(x,y);
control_points.put(tomove,computeControlPoint(anchor,tomove.getPeakPoint()));
fireDocumentChanged();
}
}
public void moveControlPointTo(AnnotationObject tomove, double x, double y) {
Point2D cp = control_points.get(tomove);
if( cp!=null ) {
cp.setLocation(x,y);
fireDocumentChanged();
}
}
public void rescale(Collection<AnnotationObject> toscale, double factor) {
for( AnnotationObject a : toscale )
scales.put(a,scales.get(a)*factor);
fireDocumentChanged();
}
public void resetScale(Collection<AnnotationObject> toscale) {
for( AnnotationObject a : toscale )
scales.put(a,1.);
fireDocumentChanged();
}
public void setHighlighted(Collection<AnnotationObject> toset, boolean highlight) {
for( AnnotationObject a : toset )
a.setHighlighted(highlight);
fireDocumentChanged();
}
public boolean canGroup(Collection<AnnotationObject> togroup) {
if( togroup==null || togroup.size()<2 )
return false;
AnnotationObject first = togroup.iterator().next();
for( AnnotationObject a : togroup ) {
if( a!=first && !first.canGroup(a) )
return false;
}
return true;
}
public void group(Collection<AnnotationObject> togroup) {
if( canGroup(togroup) ) {
AnnotationObject grouped = togroup.iterator().next();
for( AnnotationObject a : togroup ) {
if( a!=grouped ) {
annotations.remove(a);
anchors.remove(a);
control_points.remove(a);
scales.remove(a);
grouped.group(a);
}
}
fireDocumentChanged();
}
}
public void ungroup(Collection<AnnotationObject> toungroup, AnnotationReportCanvas theCanvas) {
boolean changed = false;
for( AnnotationObject grouped : toungroup ) {
if( grouped.size()>1 ) {
// compute new objects
int ind = annotations.indexOf(grouped);
Point2D anchor = anchors.get(grouped);
Double scale = scales.get(grouped);
for( AnnotationObject a : grouped.ungroup() ) {
annotations.insertElementAt(a,ind++);
anchors.put(a,anchor);
control_points.put(a,computeControlPoint(anchor,a.getPeakPoint()));
scales.put(a,scale);
anchor = new Point2D.Double(anchor.getX(), anchor.getY()+theCanvas.computeSizeData(a).getHeight());
}
// remove old group
annotations.remove(grouped);
anchors.remove(grouped);
control_points.remove(grouped);
scales.remove(grouped);
changed = true;
}
}
if( changed )
fireDocumentChanged();
}
// serialization
public String toString() {
StringBuilder ret = new StringBuilder();
if( annotations!=null ) {
for( AnnotationObject a : annotations ) {
ret.append(ANNOTATION);
ret.append(' ');
ret.append(a.isHighlighted());
ret.append(' ');
ret.append(a.getPeakPoint().getX());
ret.append(' ');
ret.append(a.getPeakPoint().getY());
ret.append(' ');
ret.append(a.getPeakAnnotations().size());
for( PeakAnnotation pa : a.getPeakAnnotations() ) {
ret.append(' ');
ret.append(thePeakAnnotationCollection.indexOf(pa));
}
ret.append('\n');
}
}
if( anchors!=null ) {
for( Map.Entry<AnnotationObject,Point2D> e : anchors.entrySet()) {
ret.append(ANCHOR);
ret.append(' ');
ret.append(annotations.indexOf(e.getKey()));
ret.append(' ');
ret.append(e.getValue().getX());
ret.append(' ');
ret.append(e.getValue().getY());
ret.append('\n');
}
}
if( control_points!=null ) {
for( Map.Entry<AnnotationObject,Point2D> e : control_points.entrySet()) {
ret.append(CP);
ret.append(' ');
ret.append(annotations.indexOf(e.getKey()));
ret.append(' ');
ret.append(e.getValue().getX());
ret.append(' ');
ret.append(e.getValue().getY());
ret.append('\n');
}
}
if( scales!=null ) {
for( Map.Entry<AnnotationObject,Double> e : scales.entrySet()) {
ret.append(SCALE);
ret.append(' ');
ret.append(annotations.indexOf(e.getKey()));
ret.append(' ');
ret.append(e.getValue());
ret.append('\n');
}
}
return ret.toString();
}
public void fromString(String str, boolean merge) throws Exception {
if( !merge ) {
annotations.clear();
anchors.clear();
control_points.clear();
scales.clear();
}
String line;
BufferedReader br = new BufferedReader(new StringReader(str));
while( (line=br.readLine())!=null ) {
String[] tokens = line.split("\\s");
int type = Integer.valueOf(tokens[0]);
if( type==ANNOTATION ) {
if( tokens.length<4 )
throw new Exception("Invalid format for ANNOTATION line: " + line);
int off = 0;
boolean highlighted = false;
if( tokens[1].equals("true") || tokens[1].equals("false") ) {
highlighted = Boolean.valueOf(tokens[1]);
off = 1;
}
double x = Double.valueOf(tokens[1+off]);
double y = Double.valueOf(tokens[2+off]);
int size = Integer.valueOf(tokens[3+off]);
if( tokens.length!=(size+4+off) )
throw new Exception("Invalid format for ANNOTATION line: " + line);
AnnotationObject read = new AnnotationObject(x,y);
read.setHighlighted(highlighted);
for( int i=0; i<size; i++ ) {
int ind = Integer.valueOf(tokens[i+4+off]);
read.add(thePeakAnnotationCollection.getPeakAnnotation(ind));
}
annotations.add(read);
}
else if( type==ANCHOR ) {
if( tokens.length!=4 )
throw new Exception("Invalid format for ANCHOR line: " + line);
int ind = Integer.valueOf(tokens[1]);
double x = Double.valueOf(tokens[2]);
double y = Double.valueOf(tokens[3]);
anchors.put(annotations.elementAt(ind),new Point2D.Double(x,y));
}
else if( type==CP ) {
if( tokens.length!=4 )
throw new Exception("Invalid format for CP line: " + line);
int ind = Integer.valueOf(tokens[1]);
double x = Double.valueOf(tokens[2]);
double y = Double.valueOf(tokens[3]);
control_points.put(annotations.elementAt(ind),new Point2D.Double(x,y));
}
else if( type==SCALE ) {
if( tokens.length!=3 )
throw new Exception("Invalid format for SCALE line: " + line);
int ind = Integer.valueOf(tokens[1]);
double s = Double.valueOf(tokens[2]);
scales.put(annotations.elementAt(ind),s);
}
else
throw new Exception("Invalid type: " + type);
}
}
public void fromXMLString(String src) throws Exception
{
ByteArrayInputStream bis = new ByteArrayInputStream(src.getBytes());
read(bis,false);
//
setFilename("");
fireDocumentInit();
}
public void fromXMLString(byte[] src) throws Exception
{
ByteArrayInputStream bis = new ByteArrayInputStream(src);
read(bis,false);
//
setFilename("");
fireDocumentInit();
}
public String toXMLString() {
try{
// open stream
ByteArrayOutputStream baos = new ByteArrayOutputStream();
write(baos);
return baos.toString();
}
catch( Exception e ) {
LogUtils.report(e);
return "";
}
}
public void read(InputStream is, boolean merge) throws Exception {
/*Document document = XMLUtils.read(is);
if( document==null )
throw new Exception("Cannot read from file");
fromXML(XMLUtils.assertChild(document,"AnnotationReportDocument")); */
SAXUtils.read(is,new SAXHandler(this));
}
public void write(OutputStream os) throws Exception {
/*
// create XML
Document document = XMLUtils.newDocument();
if( document==null )
return "";
Element ard_node = toXML(document);
if( ard_node == null )
return "";
document.appendChild(ard_node);
// write XML
XMLUtils.write(baos,document);
*/
SAXUtils.write(os,this);
}
public void fromXML(Node ard_node) throws Exception {
if( ard_node==null )
throw new Exception("empty node");
show_rel_int = Boolean.valueOf(XMLUtils.getAttribute(ard_node,"show_relative_intensities"));
show_empty_annotations = Boolean.valueOf(XMLUtils.getAttribute(ard_node,"show_empty_annotations"));
start_mz = Double.valueOf(XMLUtils.getAttribute(ard_node,"start_mz"));
end_mz = Double.valueOf(XMLUtils.getAttribute(ard_node,"end_mz"));
// read settings
Node c_node = XMLUtils.findChild(ard_node,"Configuration");
if( c_node!=null ) {
Configuration config = new Configuration();
config.fromXML(c_node);
theOptions.retrieve(config);
theGraphicOptions.retrieve(config);
}
// read peak data
Node pd_node = XMLUtils.findChild(ard_node,"PeakData");
if( pd_node!=null )
thePeakData = PeakData.fromXML(pd_node,this.getMMFCreator());
else
thePeakData = null;
// read peak annotations
thePeakAnnotationCollection = PeakAnnotationCollection.fromXML(XMLUtils.assertChild(ard_node,"PeakAnnotationCollection"));
// read graphic information
annotations = new Vector<AnnotationObject>();
for( Node node : XMLUtils.findAllChildren(ard_node, "Annotation") ) {
double x = Double.valueOf(XMLUtils.getAttribute(node,"x"));
double y = Double.valueOf(XMLUtils.getAttribute(node,"y"));
int size = Integer.valueOf(XMLUtils.getAttribute(node,"size"));
AnnotationObject read = new AnnotationObject(x,y);
for( int i=0; i<size; i++ ) {
int ind = Integer.valueOf(XMLUtils.getAttribute(node,"pa"+i));
read.add(thePeakAnnotationCollection.getPeakAnnotation(ind));
}
annotations.add(read);
}
anchors = new HashMap<AnnotationObject,Point2D>();
for( Node node : XMLUtils.findAllChildren(ard_node, "Anchor") ) {
int ind = Integer.valueOf(XMLUtils.getAttribute(node,"ind"));
double x = Double.valueOf(XMLUtils.getAttribute(node,"x"));
double y = Double.valueOf(XMLUtils.getAttribute(node,"y"));
anchors.put(annotations.elementAt(ind),new Point2D.Double(x,y));
}
control_points = new HashMap<AnnotationObject,Point2D>();
for( Node node : XMLUtils.findAllChildren(ard_node, "ControlPoint") ) {
int ind = Integer.valueOf(XMLUtils.getAttribute(node,"ind"));
double x = Double.valueOf(XMLUtils.getAttribute(node,"x"));
double y = Double.valueOf(XMLUtils.getAttribute(node,"y"));
control_points.put(annotations.elementAt(ind),new Point2D.Double(x,y));
}
scales = new HashMap<AnnotationObject,Double>();
for( Node node : XMLUtils.findAllChildren(ard_node, "Scale") ) {
int ind = Integer.valueOf(XMLUtils.getAttribute(node,"ind"));
double s = Double.valueOf(XMLUtils.getAttribute(node,"s"));
scales.put(annotations.elementAt(ind),s);
}
}
public Element toXML(Document document) {
if( document==null )
return null;
// create root node
Element ard_node = document.createElement("AnnotationReportDocument");
// add settings
Configuration config = new Configuration();
theOptions.store(config);
theGraphicOptions.store(config);
ard_node.appendChild(config.toXML(document));
ard_node.setAttribute("show_relative_intensities",""+show_rel_int);
ard_node.setAttribute("show_empty_annotations",""+show_empty_annotations);
ard_node.setAttribute("start_mz", ""+start_mz);
ard_node.setAttribute("end_mz",""+end_mz);
// add peak data
if( thePeakData!=null )
ard_node.appendChild(thePeakData.toXML(document));
// add peak annotations
ard_node.appendChild(thePeakAnnotationCollection.toXML(document));
// add graphic information
if( annotations!=null ) {
for( AnnotationObject a : annotations ) {
int i=0;
Element node = document.createElement("Annotation");
node.setAttribute("x",""+a.getPeakPoint().getX());
node.setAttribute("y",""+a.getPeakPoint().getY());
node.setAttribute("size",""+a.getPeakAnnotations().size());
for( PeakAnnotation pa : a.getPeakAnnotations() )
node.setAttribute("pa"+(i++),""+thePeakAnnotationCollection.indexOf(pa));
ard_node.appendChild(node);
}
}
if( anchors!=null ) {
for( Map.Entry<AnnotationObject,Point2D> e : anchors.entrySet()) {
Element node = document.createElement("Anchor");
node.setAttribute("ind",""+annotations.indexOf(e.getKey()));
node.setAttribute("x",""+e.getValue().getX());
node.setAttribute("y",""+e.getValue().getY());
ard_node.appendChild(node);
}
}
if( control_points!=null ) {
for( Map.Entry<AnnotationObject,Point2D> e : control_points.entrySet()) {
Element node = document.createElement("ControlPoint");
node.setAttribute("ind",""+annotations.indexOf(e.getKey()));
node.setAttribute("x",""+e.getValue().getX());
node.setAttribute("y",""+e.getValue().getY());
ard_node.appendChild(node);
}
}
if( scales!=null ) {
for( Map.Entry<AnnotationObject,Double> e : scales.entrySet()) {
Element node = document.createElement("Scale");
node.setAttribute("ind",""+annotations.indexOf(e.getKey()));
node.setAttribute("s",""+e.getValue());
ard_node.appendChild(node);
}
}
return ard_node;
}
public static class SAXHandler extends SAXUtils.ObjectTreeHandler {
private AnnotationReportDocument theDocument;
public SAXHandler(AnnotationReportDocument _doc) {
theDocument = _doc;
}
public boolean isElement(String namespaceURI, String localName, String qName) {
return qName.equals(getNodeElementName());
}
public static String getNodeElementName() {
return "AnnotationReportDocument";
}
protected SAXUtils.ObjectTreeHandler getHandler(String namespaceURI, String localName, String qName) {
if( qName.equals(Configuration.SAXHandler.getNodeElementName()) )
return new Configuration.SAXHandler(new Configuration());
if( qName.equals(Glycan.SAXHandler.getNodeElementName()) )
return new Glycan.SAXHandler(theDocument.theWorkspace.getDefaultMassOptions());
if( qName.equals(PeakAnnotationCollection.SAXHandler.getNodeElementName()) )
return new PeakAnnotationCollection.SAXHandler();
if( qName.equals(PeakData.SAXHandler.getNodeElementName()) )
return new PeakData.SAXHandler(theDocument.getMMFCreator());
if( qName.equals(AnnotationSAXHandler.getNodeElementName()) )
return new AnnotationSAXHandler(theDocument.thePeakAnnotationCollection);
if( qName.equals(AnchorSAXHandler.getNodeElementName()) )
return new AnchorSAXHandler();
if( qName.equals(ControlPointSAXHandler.getNodeElementName()) )
return new ControlPointSAXHandler();
if( qName.equals(ScaleSAXHandler.getNodeElementName()) )
return new ScaleSAXHandler();
return null;
}
protected void initContent(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
super.initContent(namespaceURI,localName,qName,atts);
theDocument.show_rel_int = booleanAttribute(atts,"show_relative_intensities",false);
theDocument.show_empty_annotations = booleanAttribute(atts,"show_empty_annotations",false);
theDocument.start_mz = doubleAttribute(atts,"start_mz",0.);
theDocument.end_mz = doubleAttribute(atts,"end_mz",0.);
}
protected Object finalizeContent(String namespaceURI, String localName, String qName) throws SAXException{
// read configuration
Configuration config = (Configuration)getSubObject(Configuration.SAXHandler.getNodeElementName(),false);
if( config!=null ) {
theDocument.theOptions.retrieve(config);
theDocument.theGraphicOptions.retrieve(config);
}
// read peak data
theDocument.thePeakData = (PeakData)getSubObject(PeakData.SAXHandler.getNodeElementName(),false);
// read parent structure
theDocument.theParentStructure = (Glycan)getSubObject(Glycan.SAXHandler.getNodeElementName(),false);
// read peak annotations
theDocument.thePeakAnnotationCollection = (PeakAnnotationCollection)getSubObject(PeakAnnotationCollection.SAXHandler.getNodeElementName(),true);
// graphic objects
theDocument.annotations = new Vector<AnnotationObject>();
for( Object o : getSubObjects(AnnotationSAXHandler.getNodeElementName()) ) {
Pair<AnnotationObject,int[]> annotation = (Pair<AnnotationObject,int[]>)o;
for( int ind : annotation.getSecond() )
annotation.getFirst().add(theDocument.thePeakAnnotationCollection.getPeakAnnotation(ind));
theDocument.annotations.add(annotation.getFirst());
}
theDocument.anchors = new HashMap<AnnotationObject,Point2D>();
for( Object o : getSubObjects(AnchorSAXHandler.getNodeElementName()) ) {
Pair<Integer,Point2D> anchor = (Pair<Integer,Point2D>)o;
theDocument.anchors.put(theDocument.annotations.elementAt(anchor.getFirst()),anchor.getSecond());
}
theDocument.control_points = new HashMap<AnnotationObject,Point2D>();
for( Object o : getSubObjects(ControlPointSAXHandler.getNodeElementName()) ) {
Pair<Integer,Point2D> control_point = (Pair<Integer,Point2D>)o;
theDocument.control_points.put(theDocument.annotations.elementAt(control_point.getFirst()),control_point.getSecond());
}
theDocument.scales = new HashMap<AnnotationObject,Double>();
for( Object o : getSubObjects(ScaleSAXHandler.getNodeElementName()) ) {
Pair<Integer,Double> scale = (Pair<Integer,Double>)o;
theDocument.scales.put(theDocument.annotations.elementAt(scale.getFirst()),scale.getSecond());
}
return (object = theDocument);
}
}
public static class AnnotationSAXHandler extends SAXUtils.ObjectTreeHandler {
private PeakAnnotationCollection thePeakAnnotationCollection;
public AnnotationSAXHandler(PeakAnnotationCollection pac) {
thePeakAnnotationCollection = pac;
}
public boolean isElement(String namespaceURI, String localName, String qName) {
return qName.equals(getNodeElementName());
}
public static String getNodeElementName() {
return "Annotation";
}
protected void initContent(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
super.initContent(namespaceURI,localName,qName,atts);
double x = doubleAttribute(atts,"x",0.);
double y = doubleAttribute(atts,"y",0.);
boolean h = booleanAttribute(atts,"highlighted",false);
AnnotationObject read = new AnnotationObject(x,y);
read.setHighlighted(h);
int[] inds = new int[integerAttribute(atts,"size",0)];
for( int i=0; i<inds.length; i++ )
inds[i] = integerAttribute(atts,"pa"+i,-1);
object = new Pair<AnnotationObject,int[]>(read,inds);
}
}
public static class AnchorSAXHandler extends SAXUtils.ObjectTreeHandler {
public boolean isElement(String namespaceURI, String localName, String qName) {
return qName.equals(getNodeElementName());
}
public static String getNodeElementName() {
return "Anchor";
}
protected void initContent(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
super.initContent(namespaceURI,localName,qName,atts);
int ind = integerAttribute(atts,"ind",-1);
double x = doubleAttribute(atts,"x",0.);
double y = doubleAttribute(atts,"y",0.);
object = new Pair<Integer,Point2D>(ind,new Point2D.Double(x,y));
}
}
public static class ControlPointSAXHandler extends SAXUtils.ObjectTreeHandler {
public boolean isElement(String namespaceURI, String localName, String qName) {
return qName.equals(getNodeElementName());
}
public static String getNodeElementName() {
return "ControlPoint";
}
protected void initContent(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
super.initContent(namespaceURI,localName,qName,atts);
int ind = integerAttribute(atts,"ind",-1);
double x = doubleAttribute(atts,"x",0.);
double y = doubleAttribute(atts,"y",0.);
object = new Pair<Integer,Point2D>(ind,new Point2D.Double(x,y));
}
}
public static class ScaleSAXHandler extends SAXUtils.ObjectTreeHandler {
public boolean isElement(String namespaceURI, String localName, String qName) {
return qName.equals(getNodeElementName());
}
public static String getNodeElementName() {
return "Scale";
}
protected void initContent(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
super.initContent(namespaceURI,localName,qName,atts);
int ind = integerAttribute(atts,"ind",-1);
double s = doubleAttribute(atts,"s",0.);
object = new Pair<Integer,Double>(ind,s);
}
}
public void write(TransformerHandler th) throws SAXException {
// create root node
AttributesImpl atts = new AttributesImpl();
atts.addAttribute("","","show_relative_intensities","CDATA",""+show_rel_int);
atts.addAttribute("","","show_empty_annotations","CDATA",""+show_empty_annotations);
atts.addAttribute("","","start_mz","CDATA", ""+start_mz);
atts.addAttribute("","","end_mz","CDATA",""+end_mz);
th.startElement("","","AnnotationReportDocument",atts);
// add settings
Configuration config = new Configuration();
theOptions.store(config);
theGraphicOptions.store(config);
config.write(th);
// add peak data
if( thePeakData!=null )
thePeakData.write(th);
// add parent structure
if( theParentStructure!=null )
theParentStructure.write(th);
// add peak annotations
thePeakAnnotationCollection.write(th);
// add graphic information
if( annotations!=null ) {
for( AnnotationObject a : annotations ) {
int i=0;
AttributesImpl aatts = new AttributesImpl();
aatts.addAttribute("","","x","CDATA",""+a.getPeakPoint().getX());
aatts.addAttribute("","","y","CDATA",""+a.getPeakPoint().getY());
aatts.addAttribute("","","highlighted","CDATA",""+a.isHighlighted());
aatts.addAttribute("","","size","CDATA",""+a.getPeakAnnotations().size());
for( PeakAnnotation pa : a.getPeakAnnotations() )
aatts.addAttribute("","","pa"+(i++),"CDATA",""+thePeakAnnotationCollection.indexOf(pa));
th.startElement("","","Annotation",aatts);
th.endElement("","","Annotation");
}
}
if( anchors!=null ) {
for( Map.Entry<AnnotationObject,Point2D> e : anchors.entrySet()) {
AttributesImpl aatts = new AttributesImpl();
aatts.addAttribute("","","ind","CDATA",""+annotations.indexOf(e.getKey()));
aatts.addAttribute("","","x","CDATA",""+e.getValue().getX());
aatts.addAttribute("","","y","CDATA",""+e.getValue().getY());
th.startElement("","","Anchor",aatts);
th.endElement("","","Anchor");
}
}
if( control_points!=null ) {
for( Map.Entry<AnnotationObject,Point2D> e : control_points.entrySet()) {
AttributesImpl cpatts = new AttributesImpl();
cpatts.addAttribute("","","ind","CDATA",""+annotations.indexOf(e.getKey()));
cpatts.addAttribute("","","x","CDATA",""+e.getValue().getX());
cpatts.addAttribute("","","y","CDATA",""+e.getValue().getY());
th.startElement("","","ControlPoint",cpatts);
th.endElement("","","ControlPoint");
}
}
if( scales!=null ) {
for( Map.Entry<AnnotationObject,Double> e : scales.entrySet()) {
AttributesImpl satts = new AttributesImpl();
satts.addAttribute("","","ind","CDATA",""+annotations.indexOf(e.getKey()));
satts.addAttribute("","","s","CDATA",""+e.getValue());
th.startElement("","","Scale",satts);
th.endElement("","","Scale");
}
}
th.endElement("","","AnnotationReportDocument");
}
}