From: jprocter Date: Fri, 13 Jul 2007 14:57:26 +0000 (+0000) Subject: refactored form of vamsas document interaction code X-Git-Tag: Release_2_4~359 X-Git-Url: http://source.jalview.org/gitweb/?a=commitdiff_plain;h=2ac1013336a5ea08943daed3552acf4b7a8c18b2;p=jalview.git refactored form of vamsas document interaction code --- diff --git a/src/jalview/io/vamsas/DatastoreItem.java b/src/jalview/io/vamsas/DatastoreItem.java index b77cc8c..c0464ff 100644 --- a/src/jalview/io/vamsas/DatastoreItem.java +++ b/src/jalview/io/vamsas/DatastoreItem.java @@ -13,6 +13,8 @@ import uk.ac.vamsas.client.IClientDocument; import uk.ac.vamsas.client.Vobject; import uk.ac.vamsas.client.VorbaId; import uk.ac.vamsas.objects.core.Entry; +import uk.ac.vamsas.objects.core.Provenance; +import uk.ac.vamsas.objects.core.Seg; /** * Holds all the common machinery for binding objects to vamsas objects @@ -54,6 +56,8 @@ public class DatastoreItem */ protected Object getvObj2jv(uk.ac.vamsas.client.Vobject vobj) { + if (vobj2jv==null) + return null; VorbaId id = vobj.getVorbaId(); if (id == null) { @@ -143,4 +147,88 @@ public class DatastoreItem } return vObjs; } + // utility functions + /** + * get start0) + { + // TODO: Jalview ignores all the other maps + if (dbref.getMapCount()>1) + { + jalview.bin.Cache.log.debug("Ignoring additional mappings on DbRef: "+dbentry.getSource()+":"+dbentry.getAccessionId()); + } + jalview.datamodel.Mapping mp = new jalview.datamodel.Mapping(parsemapType(dbref.getMap(0))); + dbentry.setMap(mp); + } + // TODO: jalview ignores links and properties because it doesn't know what to do with them. + + bindjvvobj(dbentry, dbref); + } + private void add() + { + DbRef dbref = new DbRef(); + bindjvvobj(dbentry, dbref); + dbref.setAccessionId(dbentry.getAccessionId()); + dbref.setSource(dbentry.getSource()); + dbref.setVersion(dbentry.getVersion()); + if (dbentry.getMap()!=null) + { + jalview.datamodel.Mapping mp = dbentry.getMap(); + if (mp.getMap()!=null) + { + Map vMap = new Map(); + initMapType(vMap, mp.getMap(), true); + dbref.addMap(vMap); + } else { + jalview.bin.Cache.log.debug("Ignoring mapless DbRef.Map "+dbentry.getSrcAccString()); + } + } + sequence.addDbRef(dbref); + } + +} diff --git a/src/jalview/io/vamsas/Rangetype.java b/src/jalview/io/vamsas/Rangetype.java new file mode 100644 index 0000000..f6a6ecc --- /dev/null +++ b/src/jalview/io/vamsas/Rangetype.java @@ -0,0 +1,270 @@ +package jalview.io.vamsas; + + +import java.util.Vector; + +import uk.ac.vamsas.objects.core.Local; +import uk.ac.vamsas.objects.core.Map; +import uk.ac.vamsas.objects.core.MapType; +import uk.ac.vamsas.objects.core.Mapped; +import uk.ac.vamsas.objects.core.RangeType; +import uk.ac.vamsas.objects.core.Seg; +import jalview.datamodel.Mapping; +import jalview.io.VamsasAppDatastore; + +public class Rangetype extends DatastoreItem +{ + + public Rangetype() + { + super(); + } + + public Rangetype(VamsasAppDatastore datastore) + { + super(datastore); + } + + /** + * get real bounds of a RangeType's specification. start and end are an + * inclusive range within which all segments and positions lie. + * TODO: refactor to vamsas utils + * @param dseta + * @return int[] { start, end} + */ + protected int[] getBounds(RangeType dseta) + { + if (dseta != null) + { + int[] se = null; + if (dseta.getSegCount() > 0 && dseta.getPosCount() > 0) + { + throw new Error("Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice!"); + } + if (dseta.getSegCount() > 0) + { + se = getSegRange(dseta.getSeg(0), true); + for (int s = 1, sSize = dseta.getSegCount(); s < sSize; s++) + { + int nse[] = getSegRange(dseta.getSeg(s), true); + if (se[0] > nse[0]) + { + se[0] = nse[0]; + } + if (se[1] < nse[1]) + { + se[1] = nse[1]; + } + } + } + if (dseta.getPosCount() > 0) + { + // could do a polarity for pos range too. and pass back indication of discontinuities. + int pos = dseta.getPos(0).getI(); + se = new int[] + { + pos, pos}; + for (int p = 0, pSize = dseta.getPosCount(); p < pSize; p++) + { + pos = dseta.getPos(p).getI(); + if (se[0] > pos) + { + se[0] = pos; + } + if (se[1] < pos) + { + se[1] = pos; + } + } + } + return se; + } + return null; + } + + /** + * map from a rangeType's internal frame to the referenced object's coordinate frame. + * @param dseta + * @return int [] { ref(pos)...} for all pos in rangeType's frame. + */ + protected int[] getMapping(RangeType dseta) + { + Vector posList = new Vector(); + if (dseta != null) + { + int[] se = null; + if (dseta.getSegCount() > 0 && dseta.getPosCount() > 0) + { + throw new Error("Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice!"); + } + if (dseta.getSegCount() > 0) + { + for (int s = 0, sSize = dseta.getSegCount(); s < sSize; s++) + { + se = getSegRange(dseta.getSeg(s), false); + int se_end = se[1 - se[2]] + (se[2] == 0 ? 1 : -1); + for (int p = se[se[2]]; p != se_end; p += se[2] == 0 ? 1 : -1) + { + posList.add(new Integer(p)); + } + } + } + else if (dseta.getPosCount() > 0) + { + int pos = dseta.getPos(0).getI(); + + for (int p = 0, pSize = dseta.getPosCount(); p < pSize; p++) + { + pos = dseta.getPos(p).getI(); + posList.add(new Integer(pos)); + } + } + } + if (posList != null && posList.size() > 0) + { + int[] range = new int[posList.size()]; + for (int i = 0; i < range.length; i++) + { + range[i] = ( (Integer) posList.elementAt(i)).intValue(); + } + posList.clear(); + return range; + } + return null; + } + + protected int[] getIntervals(RangeType range) + { + int[] intervals=null; + Vector posList = new Vector(); + if (range != null) + { + int[] se = null; + if (range.getSegCount() > 0 && range.getPosCount() > 0) + { + throw new Error("Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice!"); + } + if (range.getSegCount() > 0) + { + for (int s = 0, sSize = range.getSegCount(); s < sSize; s++) + { + se = getSegRange(range.getSeg(s), false); + posList.addElement(new Integer(se[0])); + posList.addElement(new Integer(se[1])); + } + } + else if (range.getPosCount() > 0) + { + int pos = range.getPos(0).getI(); + + for (int p = 0, pSize = range.getPosCount(); p < pSize; p++) + { + pos = range.getPos(p).getI(); + posList.add(new Integer(pos)); + posList.add(new Integer(pos)); + } + } + } + if (posList != null && posList.size() > 0) + { + intervals=new int[posList.size()]; + java.util.Enumeration e = posList.elements(); + int i=0; + while (e.hasMoreElements()) + { + intervals[i++] = ((Integer)e.nextElement()).intValue(); + } + } + return intervals; + } + /** + * initialise a range type object from a set of start/end inclusive intervals + * @param mrt + * @param range + */ + protected void initRangeType(RangeType mrt, int[] range) + { + for (int i=0; i "+map.toString()))); + } + return parsemapType(map, 1, 1); + } + + /** + * initialise a MapType object from a MapList object. + * @param maprange + * @param ml + * @param setUnits + */ + protected void initMapType(MapType maprange, jalview.util.MapList ml, boolean setUnits) + { + initMapType(maprange, ml, setUnits, false); + } + /** + * + * @param maprange + * @param ml + * @param setUnits + * @param reverse - reverse MapList mapping for Local and Mapped ranges and units + */ + protected void initMapType(MapType maprange, jalview.util.MapList ml, boolean setUnits, boolean reverse) + { + if (ml==null) + { + throw new Error("Implementation error. MapList is null for initMapType."); + } + maprange.setLocal(new Local()); + maprange.setMapped(new Mapped()); + if (!reverse) + { + initRangeType(maprange.getLocal(), ml.getFromRanges()); + initRangeType(maprange.getMapped(), ml.getToRanges()); + } else { + initRangeType(maprange.getLocal(), ml.getToRanges()); + initRangeType(maprange.getMapped(), ml.getFromRanges()); + } + if (setUnits) + { + if (!reverse) + { + maprange.getLocal().setUnit(ml.getFromRatio()); + maprange.getMapped().setUnit(ml.getToRatio()); + } else { + maprange.getLocal().setUnit(ml.getToRatio()); + maprange.getMapped().setUnit(ml.getFromRatio()); + } + } + } + +} \ No newline at end of file diff --git a/src/jalview/io/vamsas/Sequencemapping.java b/src/jalview/io/vamsas/Sequencemapping.java new file mode 100644 index 0000000..48b2982 --- /dev/null +++ b/src/jalview/io/vamsas/Sequencemapping.java @@ -0,0 +1,245 @@ +package jalview.io.vamsas; + +import java.util.Vector; + +import jalview.datamodel.AlignedCodonFrame; +import jalview.datamodel.Mapping; +import jalview.datamodel.SequenceI; +import jalview.io.VamsasAppDatastore; +import uk.ac.vamsas.client.Vobject; +import uk.ac.vamsas.objects.core.AlignmentSequence; +import uk.ac.vamsas.objects.core.DataSet; +import uk.ac.vamsas.objects.core.Local; +import uk.ac.vamsas.objects.core.RangeType; +import uk.ac.vamsas.objects.core.Seg; +import uk.ac.vamsas.objects.core.Sequence; +import uk.ac.vamsas.objects.core.SequenceMapping; +import uk.ac.vamsas.objects.core.SequenceType; + +public class Sequencemapping extends Rangetype +{ + public Sequencemapping(VamsasAppDatastore datastore, SequenceMapping sequenceMapping) + { + super(datastore); + Object mjvmapping = getvObj2jv(sequenceMapping); + if (mjvmapping==null) + { + add(sequenceMapping); + } else { + if (sequenceMapping.isUpdated()) + { + update((jalview.datamodel.Mapping) mjvmapping, sequenceMapping); + } + } + } + /** + * create or update a vamsas sequence mapping corresponding to a jalview + * Mapping between two dataset sequences + * + * @param datastore + * @param mjvmapping + * @param from + * @param ds + */ + public Sequencemapping(VamsasAppDatastore datastore, jalview.datamodel.Mapping mjvmapping, uk.ac.vamsas.objects.core.SequenceType from, uk.ac.vamsas.objects.core.DataSet ds) + { + super(datastore); + SequenceMapping sequenceMapping = (SequenceMapping) getjv2vObj(mjvmapping); + if (sequenceMapping==null) + { + add(mjvmapping, from, ds); + } else { + if (from!=null && sequenceMapping.getLoc()!=from) + { + jalview.bin.Cache.log.warn("Probable IMPLEMENTATION ERROR: "+from+" doesn't match the local mapping sequence."); + } + if (ds!=null && sequenceMapping.getV_parent()!=ds) + { + jalview.bin.Cache.log.warn("Probable IMPLEMENTATION ERROR: "+ds+" doesn't match the parent of the bound sequence mapping object."); + } + if (sequenceMapping.isUpdated()) + { + conflict(mjvmapping, sequenceMapping); + } else { + update(mjvmapping, sequenceMapping); + } + } + } + private void conflict(Mapping mjvmapping, SequenceMapping sequenceMapping) + { + // TODO Auto-generated method stub + + } + private void add(Mapping mjvmapping, uk.ac.vamsas.objects.core.SequenceType from, DataSet ds) + { + SequenceI jvto = mjvmapping.getTo(); + while (jvto.getDatasetSequence()!=null) + { + jvto = jvto.getDatasetSequence(); + } + SequenceType to = (SequenceType) getjv2vObj(jvto); + if (to==null) + { + jalview.bin.Cache.log.warn("NONFATAL - do a second update: Ignoring Forward Reference to seuqence not yet bound to vamsas seuqence object"); + return; + } + SequenceMapping sequenceMapping = new SequenceMapping(); + sequenceMapping.setLoc(from); + sequenceMapping.setMap(to); + boolean dnaToProt=false,sense=false; + // ensure that we create a mapping with the correct sense + if (((Sequence) sequenceMapping.getLoc()) + .getDictionary() + .equals(uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_NA)) + { + if (((Sequence) sequenceMapping.getMap()) + .getDictionary() + .equals(uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_AA)) + { + dnaToProt=true; + sense=true; + } + } else { + if (((Sequence) sequenceMapping.getMap()) + .getDictionary() + .equals(uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_NA)) + { + dnaToProt=true; + sense=false; + } + } + + if (!dnaToProt) + { + jalview.bin.Cache.log.warn("Ignoring Mapping - don't support protein to protein mapping in vamsas document yet."); + return; + } + if (ds==null) + { + // locate dataset for storage of SequenceMapping + if (sense) + { + ds = (DataSet) ((uk.ac.vamsas.client.Vobject) sequenceMapping.getLoc()).getV_parent(); + } else { + ds = (DataSet) ((uk.ac.vamsas.client.Vobject) sequenceMapping.getMap()).getV_parent(); + } + } + if (sense) + { + this.initMapType(sequenceMapping, mjvmapping.getMap(), true); + } else { + this.initMapType(sequenceMapping, mjvmapping.getMap().getInverse(), true); + } + ds.addSequenceMapping(sequenceMapping); + sequenceMapping.setProvenance(this.dummyProvenance("user defined coding region translation")); // TODO: + // correctly + // construct + // provenance + // based + // on + // source + // of + // mapping + bindjvvobj(mjvmapping, sequenceMapping); + + jalview.bin.Cache.log.debug("Successfully created mapping "+sequenceMapping.getVorbaId()); + } + private void update(jalview.datamodel.Mapping mjvmapping, SequenceMapping sequenceMapping) + { + jalview.bin.Cache.log.error("Not implemented: Jalview Update Mapping"); + } + /** + * limitations: Currently, jalview only deals with mappings between dataset + * sequences, and even then, only between those that map from DNA to Protein. + * + * @param sequenceMapping + */ + private void add(SequenceMapping sequenceMapping) + { + Object mobj; + SequenceI from=null,to=null; + boolean dnaToProt=false,sense=false; + Sequence sdloc=null, sdmap=null; + if (sequenceMapping.getLoc() instanceof AlignmentSequence) + { + sdloc = (Sequence) ((AlignmentSequence) sequenceMapping.getLoc()).getRefid(); + } else { + sdloc = ((Sequence) sequenceMapping.getLoc()); + } + if (sequenceMapping.getMap() instanceof AlignmentSequence) + { + sdmap = (Sequence) ((AlignmentSequence) sequenceMapping.getMap()).getRefid(); + } else { + sdmap = ((Sequence) sequenceMapping.getMap()); + } + if (sdloc==null || sdmap == null) + { + jalview.bin.Cache.log.info("Ignoring non sequence-sequence mapping"); + return; + } + mobj = this.getvObj2jv((Vobject) sdloc); + if (mobj instanceof SequenceI) + { + from = (SequenceI) mobj; + } + mobj = this.getvObj2jv((Vobject) sdmap); + if (mobj instanceof SequenceI) + { + to = (SequenceI) mobj; + } + if (from == null || to == null) + { + + jalview.bin.Cache.log.error("Probable Vamsas implementation error : unbound dataset sequences involved in a mapping are being parsed!"); + return; + } + if (sdloc.getDictionary() + .equals(uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_NA)) + { + if (sdmap.getDictionary() + .equals(uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_AA)) + { + dnaToProt=true; + sense=true; + } + // else { + + // } + } else { + if (sdmap.getDictionary() + .equals(uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_NA)) + { + dnaToProt=true; + sense=false; + } + } + // create mapping storage object and make each dataset alignment reference + // it. + jalview.datamodel.AlignmentI dsLoc = (jalview.datamodel.AlignmentI) getvObj2jv(sdloc.getV_parent()); + jalview.datamodel.AlignmentI dsMap = (jalview.datamodel.AlignmentI) getvObj2jv(sdmap.getV_parent()); + AlignedCodonFrame afc = new AlignedCodonFrame(0); + + if (dsLoc!=null && dsLoc!=dsMap) + { + dsMap.addCodonFrame(afc); + } + if (dsMap!=null) + { + dsMap.addCodonFrame(afc); + } + // create and add the new mapping to (each) dataset's codonFrame + + jalview.util.MapList mapping = null; + if (!sense) + { + mapping = this.parsemapType(sequenceMapping, 1, 3); // invert sense + mapping = new jalview.util.MapList(mapping.getToRanges(), mapping.getFromRanges(), mapping.getToRatio(), mapping.getFromRatio()); + afc.addMap(to, from, mapping); + } else { + mapping = this.parsemapType(sequenceMapping, 3, 1); // correct sense + afc.addMap(from, to, mapping); + } + bindjvvobj(mapping, sequenceMapping); + jalview.structure.StructureSelectionManager.getStructureSelectionManager().addMappings(new AlignedCodonFrame[] { afc }); + } +} \ No newline at end of file diff --git a/src/jalview/io/vamsas/Tree.java b/src/jalview/io/vamsas/Tree.java index 3946a98..12c471e 100644 --- a/src/jalview/io/vamsas/Tree.java +++ b/src/jalview/io/vamsas/Tree.java @@ -5,10 +5,14 @@ import java.util.Hashtable; import java.util.Vector; import jalview.analysis.NJTree; +import jalview.bin.Cache; import jalview.datamodel.AlignmentI; +import jalview.datamodel.AlignmentView; import jalview.datamodel.SeqCigar; import jalview.datamodel.SequenceI; +import jalview.gui.AlignViewport; import jalview.gui.TreePanel; +import jalview.io.NewickFile; import jalview.io.VamsasAppDatastore; import uk.ac.vamsas.client.Vobject; import uk.ac.vamsas.objects.core.Entry; @@ -25,7 +29,51 @@ public class Tree extends DatastoreItem AlignmentI jal; TreePanel tp; uk.ac.vamsas.objects.core.Tree tree; - uk.ac.vamsas.objects.core.Alignment alignment; // may be null => dataset or other kind of tree + uk.ac.vamsas.objects.core.Alignment alignment; // may be null => dataset or + // other kind of tree + private NewickFile ntree; + private String title; + private AlignmentView inputData = null; + public static void updateFrom(VamsasAppDatastore datastore, jalview.gui.AlignFrame alignFrame, uk.ac.vamsas.objects.core.Tree vtree) { + Tree toTree = new Tree(datastore, alignFrame, vtree); + + } + public Tree(VamsasAppDatastore datastore, jalview.gui.AlignFrame alignFrame, uk.ac.vamsas.objects.core.Tree vtree) + { + super(datastore); + tree = vtree; + TreePanel tp = (TreePanel) getvObj2jv(tree); + if (tp != null) { + if (tree.isUpdated()) + { + Cache.log.info( + "Update from vamsas document to alignment associated tree not implemented yet."); + } + } + else + { + // make a new tree + Object[] idata = this.recoverInputData(tree.getProvenance()); + try + { + if (idata != null && idata[0] != null) + { + inputData = (AlignmentView) idata[0]; + } + ntree = new jalview.io.NewickFile(tree.getNewick(0).getContent()); + title = tree.getNewick(0).getTitle(); + if (title==null || title.length()==0) + { + title = tree.getTitle(); // hack!!!! + } + } + catch (Exception e) + { + Cache.log.warn("Problems parsing treefile '" + + tree.getNewick(0).getContent() + "'", e); + } + } + } public Tree(VamsasAppDatastore datastore, TreePanel tp2, AlignmentI jal2, uk.ac.vamsas.objects.core.Alignment alignment2) { super(datastore); @@ -58,13 +106,14 @@ public class Tree extends DatastoreItem /** * correctly creates provenance for trees calculated on an alignment by * jalview. - * + * * @param jal * @param tp * @return */ private Provenance makeTreeProvenance(AlignmentI jal, TreePanel tp) { + Cache.log.debug("Making Tree provenance for "+tp.getTitle()); Provenance prov = new Provenance(); prov.addEntry(new Entry()); prov.getEntry(0).setAction("imported " + tp.getTitle()); @@ -75,7 +124,8 @@ public class Tree extends DatastoreItem { Input vInput = new Input(); // LATER: check to see if tree input data is contained in this alignment - - // or just correctly resolve the tree's seqData to the correct alignment in + // or just correctly resolve the tree's seqData to the correct alignment + // in // the document. Vector alsqrefs = getjv2vObjs(findAlignmentSequences(jal, tp.getTree().seqData.getSequences())); Object[] alsqs = new Object[alsqrefs.size()]; @@ -91,7 +141,8 @@ public class Tree extends DatastoreItem prov.getEntry(0).getParam(0).setType("utf8"); prov.getEntry(0).getParam(0).setContent("NJ"); int ranges[] = tp.getTree().seqData.getVisibleContigs(); - // VisibleContigs are with respect to alignment coordinates. Still need offsets + // VisibleContigs are with respect to alignment coordinates. Still need + // offsets int start = tp.getTree().seqData.getAlignmentOrigin(); for (int r = 0; r < ranges.length; r += 2) { @@ -102,13 +153,16 @@ public class Tree extends DatastoreItem vInput.addSeg(visSeg); } } + Cache.log.debug("Finished Tree provenance for "+tp.getTitle()); return prov; } /** * look up SeqCigars in an existing alignment. + * * @param jal * @param sequences - * @return vector of alignment sequences in order of SeqCigar array (but missing unfound seqcigars) + * @return vector of alignment sequences in order of SeqCigar array (but + * missing unfound seqcigars) */ private Vector findAlignmentSequences(AlignmentI jal, SeqCigar[] sequences) { @@ -122,16 +176,24 @@ public class Tree extends DatastoreItem for (int t = 0; t=asq.getStart() && tseqs[t].getEnd()<=asq.getEnd()) + && (tseqs[t].getRefSeq()==asq || tseqs[t].getRefSeq() == asq.getDatasetSequence())) + // && tseqs[t].getStart()>=asq.getStart() && tseqs[t].getEnd()<=asq.getEnd()) { tseqs[t] = null; alsq.add(asq); } } } + if (alsq.size() 0) + { + if (tp.getEntry(pe).getInputCount() > 1) + { + Cache.log.warn("Ignoring additional input spec in provenance entry " + + tp.getEntry(pe).toString()); + } + // LATER: deal sensibly with multiple inputs + Input vInput = tp.getEntry(pe).getInput(0); + // is this the whole alignment or a specific set of sequences ? + if (vInput.getObjRefCount()==0) + continue; + if (vInput.getObjRefCount()==1 && vInput.getObjRef(0) instanceof uk.ac.vamsas.objects.core.Alignment) + { + // recover an AlignmentView for the input data + javport = (AlignViewport) getvObj2jv( (uk.ac.vamsas. + client.Vobject) vInput + .getObjRef(0)); + jal = javport.getAlignment(); + view = javport.getAlignment(). + getCompactAlignment(); + } else + if (vInput.getObjRef(0) instanceof uk.ac.vamsas.objects.core.AlignmentSequence) { + // recover an AlignmentView for the input data + javport = (AlignViewport) getvObj2jv(((Vobject)vInput.getObjRef(0)).getV_parent()); + jal = javport.getAlignment(); + jalview.datamodel.SequenceI[] seqs = new jalview.datamodel.SequenceI[vInput.getObjRefCount()]; + for (int i=0,iSize=vInput.getObjRefCount(); i from) + { + view.deleteRange(offset + from - 1, offset + se[0] - 2); + offset -= se[0] - from; + } + from = se[1] + 1; + } + } + if (from < to) + { + view.deleteRange(offset + from - 1, offset + to - 1); // final + // deletion - + // TODO: check + // off by + // one for to + } + return new Object[]{new AlignmentView(view), jal}; + } + } + Cache.log.debug("Returning null for input data recovery from provenance."); + return null; + } + public NewickFile getNewickTree() + { + return ntree; + } + public String getTitle() + { + return title; + } + public AlignmentView getInputData() + { + return inputData; + } + }