2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.1)
3 * Copyright (C) 2014 The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
11 * Jalview is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with Jalview. If not, see <http://www.gnu.org/licenses/>.
17 * The Jalview Authors are detailed in the 'AUTHORS' file.
21 import java.awt.Rectangle;
23 import java.lang.reflect.InvocationTargetException;
26 import java.util.Map.Entry;
27 import java.util.jar.*;
31 import org.exolab.castor.xml.*;
33 import jalview.bin.Cache;
34 import jalview.datamodel.Alignment;
35 import jalview.datamodel.AlignmentAnnotation;
36 import jalview.datamodel.AlignmentI;
37 import jalview.datamodel.SequenceI;
38 import jalview.schemabinding.version2.*;
39 import jalview.schemes.*;
40 import jalview.util.Platform;
41 import jalview.util.jarInputStreamProvider;
42 import jalview.viewmodel.AlignmentViewport;
43 import jalview.ws.jws2.Jws2Discoverer;
44 import jalview.ws.jws2.dm.AAConSettings;
45 import jalview.ws.jws2.jabaws2.Jws2Instance;
46 import jalview.ws.params.ArgumentI;
47 import jalview.ws.params.AutoCalcSetting;
48 import jalview.ws.params.WsParamSetI;
51 * Write out the current jalview desktop state as a Jalview XML stream.
53 * Note: the vamsas objects referred to here are primitive versions of the
54 * VAMSAS project schema elements - they are not the same and most likely never
58 * @version $Revision: 1.134 $
60 public class Jalview2XML
63 * create/return unique hash string for sq
66 * @return new or existing unique string for sq
68 String seqHash(SequenceI sq)
70 if (seqsToIds == null)
74 if (seqsToIds.containsKey(sq))
76 return (String) seqsToIds.get(sq);
80 // create sequential key
81 String key = "sq" + (seqsToIds.size() + 1);
82 key = makeHashCode(sq, key); // check we don't have an external reference
84 seqsToIds.put(sq, key);
93 if (seqRefIds != null)
97 if (seqsToIds != null)
107 warn("clearSeqRefs called when _cleartables was not set. Doing nothing.");
108 // seqRefIds = new Hashtable();
109 // seqsToIds = new IdentityHashMap();
115 if (seqsToIds == null)
117 seqsToIds = new IdentityHashMap();
119 if (seqRefIds == null)
121 seqRefIds = new Hashtable();
126 * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
127 * of sequence objects are created.
129 java.util.IdentityHashMap seqsToIds = null;
132 * jalview XML Sequence ID to jalview sequence object reference (both dataset
133 * and alignment sequences. Populated as XML reps of sequence objects are
136 java.util.Hashtable seqRefIds = null; // key->SequenceI resolution
138 Vector frefedSequence = null;
140 boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
146 public Jalview2XML(boolean raiseGUI)
148 this.raiseGUI = raiseGUI;
151 public void resolveFrefedSequences()
153 if (frefedSequence.size() > 0)
155 int r = 0, rSize = frefedSequence.size();
158 Object[] ref = (Object[]) frefedSequence.elementAt(r);
161 String sref = (String) ref[0];
162 if (seqRefIds.containsKey(sref))
164 if (ref[1] instanceof jalview.datamodel.Mapping)
166 SequenceI seq = (SequenceI) seqRefIds.get(sref);
167 while (seq.getDatasetSequence() != null)
169 seq = seq.getDatasetSequence();
171 ((jalview.datamodel.Mapping) ref[1]).setTo(seq);
175 if (ref[1] instanceof jalview.datamodel.AlignedCodonFrame)
177 SequenceI seq = (SequenceI) seqRefIds.get(sref);
178 while (seq.getDatasetSequence() != null)
180 seq = seq.getDatasetSequence();
183 && ref[2] instanceof jalview.datamodel.Mapping)
185 jalview.datamodel.Mapping mp = (jalview.datamodel.Mapping) ref[2];
186 ((jalview.datamodel.AlignedCodonFrame) ref[1]).addMap(
187 seq, mp.getTo(), mp.getMap());
192 .println("IMPLEMENTATION ERROR: Unimplemented forward sequence references for AlcodonFrames involving "
193 + ref[2].getClass() + " type objects.");
199 .println("IMPLEMENTATION ERROR: Unimplemented forward sequence references for "
200 + ref[1].getClass() + " type objects.");
203 frefedSequence.remove(r);
209 .println("IMPLEMENTATION WARNING: Unresolved forward reference for hash string "
211 + " with objecttype "
212 + ref[1].getClass());
219 frefedSequence.remove(r);
227 * This maintains a list of viewports, the key being the seqSetId. Important
228 * to set historyItem and redoList for multiple views
230 Hashtable viewportsAdded;
232 Hashtable annotationIds = new Hashtable();
234 String uniqueSetSuffix = "";
237 * List of pdbfiles added to Jar
239 Vector pdbfiles = null;
241 // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
242 public void SaveState(File statefile)
246 FileOutputStream fos = new FileOutputStream(statefile);
247 JarOutputStream jout = new JarOutputStream(fos);
250 } catch (Exception e)
252 // TODO: inform user of the problem - they need to know if their data was
254 if (errorMessage == null)
256 errorMessage = "Couldn't write Jalview Archive to output file '"
257 + statefile + "' - See console error log for details";
261 errorMessage += "(output file was '" + statefile + "')";
269 * Writes a jalview project archive to the given Jar output stream.
273 public void SaveState(JarOutputStream jout)
275 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
282 Hashtable<String, AlignFrame> dsses = new Hashtable<String, AlignFrame>();
287 // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
288 // //////////////////////////////////////////////////
289 // NOTE ALSO new PrintWriter must be used for each new JarEntry
290 PrintWriter out = null;
292 Vector shortNames = new Vector();
295 for (int i = frames.length - 1; i > -1; i--)
297 if (frames[i] instanceof AlignFrame)
299 AlignFrame af = (AlignFrame) frames[i];
302 && skipList.containsKey(af.getViewport()
303 .getSequenceSetId()))
308 String shortName = af.getTitle();
310 if (shortName.indexOf(File.separatorChar) > -1)
312 shortName = shortName.substring(shortName
313 .lastIndexOf(File.separatorChar) + 1);
318 while (shortNames.contains(shortName))
320 if (shortName.endsWith("_" + (count - 1)))
322 shortName = shortName
323 .substring(0, shortName.lastIndexOf("_"));
326 shortName = shortName.concat("_" + count);
330 shortNames.addElement(shortName);
332 if (!shortName.endsWith(".xml"))
334 shortName = shortName + ".xml";
337 int ap, apSize = af.alignPanels.size();
339 for (ap = 0; ap < apSize; ap++)
341 AlignmentPanel apanel = (AlignmentPanel) af.alignPanels
343 String fileName = apSize == 1 ? shortName : ap + shortName;
344 if (!fileName.endsWith(".xml"))
346 fileName = fileName + ".xml";
349 SaveState(apanel, fileName, jout);
351 String dssid = getDatasetIdRef(af.getViewport().getAlignment()
353 if (!dsses.containsKey(dssid))
355 dsses.put(dssid, af);
362 writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix,
368 } catch (Exception foo)
373 } catch (Exception ex)
375 // TODO: inform user of the problem - they need to know if their data was
377 if (errorMessage == null)
379 errorMessage = "Couldn't write Jalview Archive - see error output for details";
381 ex.printStackTrace();
385 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
386 public boolean SaveAlignment(AlignFrame af, String jarFile,
391 int ap, apSize = af.alignPanels.size();
392 FileOutputStream fos = new FileOutputStream(jarFile);
393 JarOutputStream jout = new JarOutputStream(fos);
394 Hashtable<String, AlignFrame> dsses = new Hashtable<String, AlignFrame>();
395 for (ap = 0; ap < apSize; ap++)
397 AlignmentPanel apanel = (AlignmentPanel) af.alignPanels
399 String jfileName = apSize == 1 ? fileName : fileName + ap;
400 if (!jfileName.endsWith(".xml"))
402 jfileName = jfileName + ".xml";
404 SaveState(apanel, jfileName, jout);
405 String dssid = getDatasetIdRef(af.getViewport().getAlignment()
407 if (!dsses.containsKey(dssid))
409 dsses.put(dssid, af);
412 writeDatasetFor(dsses, fileName, jout);
416 } catch (Exception foo)
422 } catch (Exception ex)
424 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
425 ex.printStackTrace();
430 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
431 String fileName, JarOutputStream jout)
434 for (String dssids : dsses.keySet())
436 AlignFrame _af = dsses.get(dssids);
437 String jfileName = fileName + " Dataset for " + _af.getTitle();
438 if (!jfileName.endsWith(".xml"))
440 jfileName = jfileName + ".xml";
442 SaveState(_af.alignPanel, jfileName, true, jout);
447 * create a JalviewModel from an algnment view and marshall it to a
451 * panel to create jalview model for
453 * name of alignment panel written to output stream
459 public JalviewModel SaveState(AlignmentPanel ap, String fileName,
460 JarOutputStream jout)
462 return SaveState(ap, fileName, false, jout);
466 * create a JalviewModel from an algnment view and marshall it to a
470 * panel to create jalview model for
472 * name of alignment panel written to output stream
474 * when true, only write the dataset for the alignment, not the data
475 * associated with the view.
481 public JalviewModel SaveState(AlignmentPanel ap, String fileName,
482 boolean storeDS, JarOutputStream jout)
485 Vector jmolViewIds = new Vector(); //
486 Vector userColours = new Vector();
488 AlignViewport av = ap.av;
490 JalviewModel object = new JalviewModel();
491 object.setVamsasModel(new jalview.schemabinding.version2.VamsasModel());
493 object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
494 object.setVersion(jalview.bin.Cache.getDefault("VERSION",
495 "Development Build"));
497 jalview.datamodel.AlignmentI jal = av.getAlignment();
499 if (av.hasHiddenRows())
501 jal = jal.getHiddenSequences().getFullAlignment();
504 SequenceSet vamsasSet = new SequenceSet();
506 JalviewModelSequence jms = new JalviewModelSequence();
508 vamsasSet.setGapChar(jal.getGapCharacter() + "");
510 if (jal.getDataset() != null)
512 // dataset id is the dataset's hashcode
513 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
516 // switch jal and the dataset
517 jal = jal.getDataset();
520 if (jal.getProperties() != null)
522 Enumeration en = jal.getProperties().keys();
523 while (en.hasMoreElements())
525 String key = en.nextElement().toString();
526 SequenceSetProperties ssp = new SequenceSetProperties();
528 ssp.setValue(jal.getProperties().get(key).toString());
529 vamsasSet.addSequenceSetProperties(ssp);
534 Set<String> calcIdSet = new HashSet<String>();
538 jalview.datamodel.SequenceI jds, jdatasq;
539 for (int i = 0; i < jal.getHeight(); i++)
541 jds = jal.getSequenceAt(i);
542 jdatasq = jds.getDatasetSequence() == null ? jds : jds
543 .getDatasetSequence();
546 if (seqRefIds.get(id) != null)
548 // This happens for two reasons: 1. multiple views are being serialised.
549 // 2. the hashCode has collided with another sequence's code. This DOES
550 // HAPPEN! (PF00072.15.stk does this)
551 // JBPNote: Uncomment to debug writing out of files that do not read
552 // back in due to ArrayOutOfBoundExceptions.
553 // System.err.println("vamsasSeq backref: "+id+"");
554 // System.err.println(jds.getName()+"
555 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
556 // System.err.println("Hashcode: "+seqHash(jds));
557 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
558 // System.err.println(rsq.getName()+"
559 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
560 // System.err.println("Hashcode: "+seqHash(rsq));
564 vamsasSeq = createVamsasSequence(id, jds);
565 vamsasSet.addSequence(vamsasSeq);
566 seqRefIds.put(id, jds);
570 jseq.setStart(jds.getStart());
571 jseq.setEnd(jds.getEnd());
572 jseq.setColour(av.getSequenceColour(jds).getRGB());
574 jseq.setId(id); // jseq id should be a string not a number
577 // Store any sequences this sequence represents
578 if (av.hasHiddenRows())
580 jseq.setHidden(av.getAlignment().getHiddenSequences()
583 if (av.isHiddenRepSequence(jal.getSequenceAt(i)))
585 jalview.datamodel.SequenceI[] reps = av
586 .getRepresentedSequences(jal.getSequenceAt(i))
587 .getSequencesInOrder(jal);
589 for (int h = 0; h < reps.length; h++)
591 if (reps[h] != jal.getSequenceAt(i))
593 jseq.addHiddenSequences(jal.findIndex(reps[h]));
600 if (jdatasq.getSequenceFeatures() != null)
602 jalview.datamodel.SequenceFeature[] sf = jdatasq
603 .getSequenceFeatures();
605 while (index < sf.length)
607 Features features = new Features();
609 features.setBegin(sf[index].getBegin());
610 features.setEnd(sf[index].getEnd());
611 features.setDescription(sf[index].getDescription());
612 features.setType(sf[index].getType());
613 features.setFeatureGroup(sf[index].getFeatureGroup());
614 features.setScore(sf[index].getScore());
615 if (sf[index].links != null)
617 for (int l = 0; l < sf[index].links.size(); l++)
619 OtherData keyValue = new OtherData();
620 keyValue.setKey("LINK_" + l);
621 keyValue.setValue(sf[index].links.elementAt(l).toString());
622 features.addOtherData(keyValue);
625 if (sf[index].otherDetails != null)
628 Enumeration keys = sf[index].otherDetails.keys();
629 while (keys.hasMoreElements())
631 key = keys.nextElement().toString();
632 OtherData keyValue = new OtherData();
633 keyValue.setKey(key);
634 keyValue.setValue(sf[index].otherDetails.get(key).toString());
635 features.addOtherData(keyValue);
639 jseq.addFeatures(features);
644 if (jdatasq.getPDBId() != null)
646 Enumeration en = jdatasq.getPDBId().elements();
647 while (en.hasMoreElements())
649 Pdbids pdb = new Pdbids();
650 jalview.datamodel.PDBEntry entry = (jalview.datamodel.PDBEntry) en
653 pdb.setId(entry.getId());
654 pdb.setType(entry.getType());
656 // store any JMol views associated with this seqeunce
657 // this section copes with duplicate entries in the project, so a
658 // dataset only view *should* be coped with sensibly
660 // This must have been loaded, is it still visible?
661 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
662 String matchedFile = null;
663 for (int f = frames.length - 1; f > -1; f--)
665 if (frames[f] instanceof AppJmol)
667 jmol = (AppJmol) frames[f];
668 for (int peid = 0; peid < jmol.jmb.pdbentry.length; peid++)
670 if (!jmol.jmb.pdbentry[peid].getId().equals(entry.getId())
671 && !(entry.getId().length() > 4 && entry
675 jmol.jmb.pdbentry[peid].getId()
678 if (matchedFile == null)
680 matchedFile = jmol.jmb.pdbentry[peid].getFile();
682 else if (!matchedFile.equals(jmol.jmb.pdbentry[peid]
686 .warn("Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
687 + jmol.jmb.pdbentry[peid].getFile());
691 // can get at it if the ID
692 // match is ambiguous (e.g.
694 String statestring = jmol.jmb.viewer.getStateInfo();
696 for (int smap = 0; smap < jmol.jmb.sequence[peid].length; smap++)
698 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
699 if (jds == jmol.jmb.sequence[peid][smap])
701 StructureState state = new StructureState();
702 state.setVisible(true);
703 state.setXpos(jmol.getX());
704 state.setYpos(jmol.getY());
705 state.setWidth(jmol.getWidth());
706 state.setHeight(jmol.getHeight());
707 state.setViewId(jmol.getViewId());
708 state.setAlignwithAlignPanel(jmol.isUsedforaligment(ap));
709 state.setColourwithAlignPanel(jmol
710 .isUsedforcolourby(ap));
711 state.setColourByJmol(jmol.isColouredByJmol());
712 if (!jmolViewIds.contains(state.getViewId()))
714 // Make sure we only store a Jmol state once in each XML
716 jmolViewIds.addElement(state.getViewId());
717 state.setContent(statestring.replaceAll("\n", ""));
721 state.setContent("# duplicate state");
723 pdb.addStructureState(state);
731 if (matchedFile != null || entry.getFile() != null)
733 if (entry.getFile() != null)
736 matchedFile = entry.getFile();
738 pdb.setFile(matchedFile); // entry.getFile());
739 if (pdbfiles == null)
741 pdbfiles = new Vector();
744 if (!pdbfiles.contains(entry.getId()))
746 pdbfiles.addElement(entry.getId());
749 File file = new File(matchedFile);
750 if (file.exists() && jout != null)
752 byte[] data = new byte[(int) file.length()];
753 jout.putNextEntry(new JarEntry(entry.getId()));
754 DataInputStream dis = new DataInputStream(
755 new FileInputStream(file));
758 DataOutputStream dout = new DataOutputStream(jout);
759 dout.write(data, 0, data.length);
763 } catch (Exception ex)
765 ex.printStackTrace();
771 if (entry.getProperty() != null)
773 PdbentryItem item = new PdbentryItem();
774 Hashtable properties = entry.getProperty();
775 Enumeration en2 = properties.keys();
776 while (en2.hasMoreElements())
778 Property prop = new Property();
779 String key = en2.nextElement().toString();
781 prop.setValue(properties.get(key).toString());
782 item.addProperty(prop);
784 pdb.addPdbentryItem(item);
794 if (!storeDS && av.hasHiddenRows())
796 jal = av.getAlignment();
799 if (jal.getCodonFrames() != null && jal.getCodonFrames().length > 0)
801 jalview.datamodel.AlignedCodonFrame[] jac = jal.getCodonFrames();
802 for (int i = 0; i < jac.length; i++)
804 AlcodonFrame alc = new AlcodonFrame();
805 vamsasSet.addAlcodonFrame(alc);
806 for (int p = 0; p < jac[i].aaWidth; p++)
808 Alcodon cmap = new Alcodon();
809 if (jac[i].codons[p] != null)
811 // Null codons indicate a gapped column in the translated peptide
813 cmap.setPos1(jac[i].codons[p][0]);
814 cmap.setPos2(jac[i].codons[p][1]);
815 cmap.setPos3(jac[i].codons[p][2]);
817 alc.addAlcodon(cmap);
819 if (jac[i].getProtMappings() != null
820 && jac[i].getProtMappings().length > 0)
822 SequenceI[] dnas = jac[i].getdnaSeqs();
823 jalview.datamodel.Mapping[] pmaps = jac[i].getProtMappings();
824 for (int m = 0; m < pmaps.length; m++)
826 AlcodMap alcmap = new AlcodMap();
827 alcmap.setDnasq(seqHash(dnas[m]));
828 alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
830 alc.addAlcodMap(alcmap);
837 // /////////////////////////////////
838 if (!storeDS && av.currentTree != null)
840 // FIND ANY ASSOCIATED TREES
841 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
842 if (Desktop.desktop != null)
844 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
846 for (int t = 0; t < frames.length; t++)
848 if (frames[t] instanceof TreePanel)
850 TreePanel tp = (TreePanel) frames[t];
852 if (tp.treeCanvas.av.getAlignment() == jal)
854 Tree tree = new Tree();
855 tree.setTitle(tp.getTitle());
856 tree.setCurrentTree((av.currentTree == tp.getTree()));
857 tree.setNewick(tp.getTree().toString());
858 tree.setThreshold(tp.treeCanvas.threshold);
860 tree.setFitToWindow(tp.fitToWindow.getState());
861 tree.setFontName(tp.getTreeFont().getName());
862 tree.setFontSize(tp.getTreeFont().getSize());
863 tree.setFontStyle(tp.getTreeFont().getStyle());
864 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
866 tree.setShowBootstrap(tp.bootstrapMenu.getState());
867 tree.setShowDistances(tp.distanceMenu.getState());
869 tree.setHeight(tp.getHeight());
870 tree.setWidth(tp.getWidth());
871 tree.setXpos(tp.getX());
872 tree.setYpos(tp.getY());
873 tree.setId(makeHashCode(tp, null));
882 * store forward refs from an annotationRow to any groups
884 IdentityHashMap groupRefs = new IdentityHashMap();
887 for (SequenceI sq : jal.getSequences())
889 // Store annotation on dataset sequences only
890 jalview.datamodel.AlignmentAnnotation[] aa = sq.getAnnotation();
891 if (aa != null && aa.length > 0)
893 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
900 if (jal.getAlignmentAnnotation() != null)
902 // Store the annotation shown on the alignment.
903 jalview.datamodel.AlignmentAnnotation[] aa = jal
904 .getAlignmentAnnotation();
905 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
910 if (jal.getGroups() != null)
912 JGroup[] groups = new JGroup[jal.getGroups().size()];
914 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
916 groups[++i] = new JGroup();
918 groups[i].setStart(sg.getStartRes());
919 groups[i].setEnd(sg.getEndRes());
920 groups[i].setName(sg.getName());
921 if (groupRefs.containsKey(sg))
923 // group has references so set it's ID field
924 groups[i].setId(groupRefs.get(sg).toString());
928 if (sg.cs.conservationApplied())
930 groups[i].setConsThreshold(sg.cs.getConservationInc());
932 if (sg.cs instanceof jalview.schemes.UserColourScheme)
934 groups[i].setColour(SetUserColourScheme(sg.cs, userColours,
940 .setColour(ColourSchemeProperty.getColourName(sg.cs));
943 else if (sg.cs instanceof jalview.schemes.AnnotationColourGradient)
945 groups[i].setColour("AnnotationColourGradient");
946 groups[i].setAnnotationColours(constructAnnotationColours(
947 (jalview.schemes.AnnotationColourGradient) sg.cs,
950 else if (sg.cs instanceof jalview.schemes.UserColourScheme)
953 .setColour(SetUserColourScheme(sg.cs, userColours, jms));
957 groups[i].setColour(ColourSchemeProperty.getColourName(sg.cs));
960 groups[i].setPidThreshold(sg.cs.getThreshold());
963 groups[i].setOutlineColour(sg.getOutlineColour().getRGB());
964 groups[i].setDisplayBoxes(sg.getDisplayBoxes());
965 groups[i].setDisplayText(sg.getDisplayText());
966 groups[i].setColourText(sg.getColourText());
967 groups[i].setTextCol1(sg.textColour.getRGB());
968 groups[i].setTextCol2(sg.textColour2.getRGB());
969 groups[i].setTextColThreshold(sg.thresholdTextColour);
970 groups[i].setShowUnconserved(sg.getShowNonconserved());
971 groups[i].setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
972 groups[i].setShowConsensusHistogram(sg.isShowConsensusHistogram());
973 groups[i].setShowSequenceLogo(sg.isShowSequenceLogo());
974 groups[i].setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
975 for (int s = 0; s < sg.getSize(); s++)
977 jalview.datamodel.Sequence seq = (jalview.datamodel.Sequence) sg
979 groups[i].addSeq(seqHash(seq));
983 jms.setJGroup(groups);
987 // /////////SAVE VIEWPORT
988 Viewport view = new Viewport();
989 view.setTitle(ap.alignFrame.getTitle());
990 view.setSequenceSetId(makeHashCode(av.getSequenceSetId(),
991 av.getSequenceSetId()));
992 view.setId(av.getViewId());
993 view.setViewName(av.viewName);
994 view.setGatheredViews(av.gatherViewsHere);
996 if (ap.av.explodedPosition != null)
998 view.setXpos(av.explodedPosition.x);
999 view.setYpos(av.explodedPosition.y);
1000 view.setWidth(av.explodedPosition.width);
1001 view.setHeight(av.explodedPosition.height);
1005 view.setXpos(ap.alignFrame.getBounds().x);
1006 view.setYpos(ap.alignFrame.getBounds().y);
1007 view.setWidth(ap.alignFrame.getBounds().width);
1008 view.setHeight(ap.alignFrame.getBounds().height);
1011 view.setStartRes(av.startRes);
1012 view.setStartSeq(av.startSeq);
1014 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1016 view.setBgColour(SetUserColourScheme(av.getGlobalColourScheme(),
1019 else if (av.getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1021 AnnotationColours ac = constructAnnotationColours(
1022 (jalview.schemes.AnnotationColourGradient) av
1023 .getGlobalColourScheme(),
1026 view.setAnnotationColours(ac);
1027 view.setBgColour("AnnotationColourGradient");
1031 view.setBgColour(ColourSchemeProperty.getColourName(av
1032 .getGlobalColourScheme()));
1035 ColourSchemeI cs = av.getGlobalColourScheme();
1039 if (cs.conservationApplied())
1041 view.setConsThreshold(cs.getConservationInc());
1042 if (cs instanceof jalview.schemes.UserColourScheme)
1044 view.setBgColour(SetUserColourScheme(cs, userColours, jms));
1048 if (cs instanceof ResidueColourScheme)
1050 view.setPidThreshold(cs.getThreshold());
1054 view.setConservationSelected(av.getConservationSelected());
1055 view.setPidSelected(av.getAbovePIDThreshold());
1056 view.setFontName(av.font.getName());
1057 view.setFontSize(av.font.getSize());
1058 view.setFontStyle(av.font.getStyle());
1059 view.setRenderGaps(av.renderGaps);
1060 view.setShowAnnotation(av.getShowAnnotation());
1061 view.setShowBoxes(av.getShowBoxes());
1062 view.setShowColourText(av.getColourText());
1063 view.setShowFullId(av.getShowJVSuffix());
1064 view.setRightAlignIds(av.rightAlignIds);
1065 view.setShowSequenceFeatures(av.showSequenceFeatures);
1066 view.setShowText(av.getShowText());
1067 view.setShowUnconserved(av.getShowUnconserved());
1068 view.setWrapAlignment(av.getWrapAlignment());
1069 view.setTextCol1(av.textColour.getRGB());
1070 view.setTextCol2(av.textColour2.getRGB());
1071 view.setTextColThreshold(av.thresholdTextColour);
1072 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1073 view.setShowSequenceLogo(av.isShowSequenceLogo());
1074 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1075 view.setShowGroupConsensus(av.isShowGroupConsensus());
1076 view.setShowGroupConservation(av.isShowGroupConservation());
1077 view.setShowNPfeatureTooltip(av.isShowNpFeats());
1078 view.setShowDbRefTooltip(av.isShowDbRefs());
1079 view.setFollowHighlight(av.followHighlight);
1080 view.setFollowSelection(av.followSelection);
1081 view.setIgnoreGapsinConsensus(av.getIgnoreGapsConsensus());
1082 if (av.featuresDisplayed != null)
1084 jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
1086 String[] renderOrder = ap.seqPanel.seqCanvas.getFeatureRenderer().renderOrder;
1088 Vector settingsAdded = new Vector();
1089 Object gstyle = null;
1090 GraduatedColor gcol = null;
1091 if (renderOrder != null)
1093 for (int ro = 0; ro < renderOrder.length; ro++)
1095 gstyle = ap.seqPanel.seqCanvas.getFeatureRenderer()
1096 .getFeatureStyle(renderOrder[ro]);
1097 Setting setting = new Setting();
1098 setting.setType(renderOrder[ro]);
1099 if (gstyle instanceof GraduatedColor)
1101 gcol = (GraduatedColor) gstyle;
1102 setting.setColour(gcol.getMaxColor().getRGB());
1103 setting.setMincolour(gcol.getMinColor().getRGB());
1104 setting.setMin(gcol.getMin());
1105 setting.setMax(gcol.getMax());
1106 setting.setColourByLabel(gcol.isColourByLabel());
1107 setting.setAutoScale(gcol.isAutoScale());
1108 setting.setThreshold(gcol.getThresh());
1109 setting.setThreshstate(gcol.getThreshType());
1113 setting.setColour(ap.seqPanel.seqCanvas.getFeatureRenderer()
1114 .getColour(renderOrder[ro]).getRGB());
1117 setting.setDisplay(av.featuresDisplayed
1118 .containsKey(renderOrder[ro]));
1119 float rorder = ap.seqPanel.seqCanvas.getFeatureRenderer()
1120 .getOrder(renderOrder[ro]);
1123 setting.setOrder(rorder);
1125 fs.addSetting(setting);
1126 settingsAdded.addElement(renderOrder[ro]);
1130 // Make sure we save none displayed feature settings
1131 Iterator en = ap.seqPanel.seqCanvas.getFeatureRenderer().featureColours
1132 .keySet().iterator();
1133 while (en.hasNext())
1135 String key = en.next().toString();
1136 if (settingsAdded.contains(key))
1141 Setting setting = new Setting();
1142 setting.setType(key);
1143 setting.setColour(ap.seqPanel.seqCanvas.getFeatureRenderer()
1144 .getColour(key).getRGB());
1146 setting.setDisplay(false);
1147 float rorder = ap.seqPanel.seqCanvas.getFeatureRenderer()
1151 setting.setOrder(rorder);
1153 fs.addSetting(setting);
1154 settingsAdded.addElement(key);
1156 en = ap.seqPanel.seqCanvas.getFeatureRenderer().featureGroups
1157 .keySet().iterator();
1158 Vector groupsAdded = new Vector();
1159 while (en.hasNext())
1161 String grp = en.next().toString();
1162 if (groupsAdded.contains(grp))
1166 Group g = new Group();
1168 g.setDisplay(((Boolean) ap.seqPanel.seqCanvas
1169 .getFeatureRenderer().featureGroups.get(grp))
1172 groupsAdded.addElement(grp);
1174 jms.setFeatureSettings(fs);
1178 if (av.hasHiddenColumns())
1180 if (av.getColumnSelection() == null
1181 || av.getColumnSelection().getHiddenColumns() == null)
1183 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1187 for (int c = 0; c < av.getColumnSelection().getHiddenColumns()
1190 int[] region = (int[]) av.getColumnSelection()
1191 .getHiddenColumns().elementAt(c);
1192 HiddenColumns hc = new HiddenColumns();
1193 hc.setStart(region[0]);
1194 hc.setEnd(region[1]);
1195 view.addHiddenColumns(hc);
1199 if (calcIdSet.size() > 0)
1201 for (String calcId : calcIdSet)
1203 if (calcId.trim().length() > 0)
1205 CalcIdParam cidp = createCalcIdParam(calcId, av);
1206 // Some calcIds have no parameters.
1209 view.addCalcIdParam(cidp);
1215 jms.addViewport(view);
1217 object.setJalviewModelSequence(jms);
1218 object.getVamsasModel().addSequenceSet(vamsasSet);
1220 if (jout != null && fileName != null)
1222 // We may not want to write the object to disk,
1223 // eg we can copy the alignViewport to a new view object
1224 // using save and then load
1227 JarEntry entry = new JarEntry(fileName);
1228 jout.putNextEntry(entry);
1229 PrintWriter pout = new PrintWriter(new OutputStreamWriter(jout,
1231 org.exolab.castor.xml.Marshaller marshaller = new org.exolab.castor.xml.Marshaller(
1233 marshaller.marshal(object);
1236 } catch (Exception ex)
1238 // TODO: raise error in GUI if marshalling failed.
1239 ex.printStackTrace();
1245 private AnnotationColours constructAnnotationColours(
1246 AnnotationColourGradient acg, Vector userColours,
1247 JalviewModelSequence jms)
1249 AnnotationColours ac = new AnnotationColours();
1250 ac.setAboveThreshold(acg.getAboveThreshold());
1251 ac.setThreshold(acg.getAnnotationThreshold());
1252 ac.setAnnotation(acg.getAnnotation());
1253 if (acg.getBaseColour() instanceof jalview.schemes.UserColourScheme)
1255 ac.setColourScheme(SetUserColourScheme(acg.getBaseColour(),
1260 ac.setColourScheme(ColourSchemeProperty.getColourName(acg
1264 ac.setMaxColour(acg.getMaxColour().getRGB());
1265 ac.setMinColour(acg.getMinColour().getRGB());
1266 ac.setPerSequence(acg.isSeqAssociated());
1267 ac.setPredefinedColours(acg.isPredefinedColours());
1271 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
1272 IdentityHashMap groupRefs, AlignmentViewport av,
1273 Set<String> calcIdSet, boolean storeDS, SequenceSet vamsasSet)
1276 for (int i = 0; i < aa.length; i++)
1278 Annotation an = new Annotation();
1280 if (aa[i].annotationId != null)
1282 annotationIds.put(aa[i].annotationId, aa[i]);
1285 an.setId(aa[i].annotationId);
1287 an.setVisible(aa[i].visible);
1289 an.setDescription(aa[i].description);
1291 if (aa[i].sequenceRef != null)
1293 // TODO later annotation sequenceRef should be the XML ID of the
1294 // sequence rather than its display name
1295 an.setSequenceRef(aa[i].sequenceRef.getName());
1297 if (aa[i].groupRef != null)
1299 Object groupIdr = groupRefs.get(aa[i].groupRef);
1300 if (groupIdr == null)
1302 // make a locally unique String
1303 groupRefs.put(aa[i].groupRef,
1304 groupIdr = ("" + System.currentTimeMillis()
1305 + aa[i].groupRef.getName() + groupRefs.size()));
1307 an.setGroupRef(groupIdr.toString());
1310 // store all visualization attributes for annotation
1311 an.setGraphHeight(aa[i].graphHeight);
1312 an.setCentreColLabels(aa[i].centreColLabels);
1313 an.setScaleColLabels(aa[i].scaleColLabel);
1314 an.setShowAllColLabels(aa[i].showAllColLabels);
1315 an.setBelowAlignment(aa[i].belowAlignment);
1317 if (aa[i].graph > 0)
1320 an.setGraphType(aa[i].graph);
1321 an.setGraphGroup(aa[i].graphGroup);
1322 if (aa[i].getThreshold() != null)
1324 ThresholdLine line = new ThresholdLine();
1325 line.setLabel(aa[i].getThreshold().label);
1326 line.setValue(aa[i].getThreshold().value);
1327 line.setColour(aa[i].getThreshold().colour.getRGB());
1328 an.setThresholdLine(line);
1336 an.setLabel(aa[i].label);
1338 if (aa[i] == av.getAlignmentQualityAnnot()
1339 || aa[i] == av.getAlignmentConservationAnnotation()
1340 || aa[i] == av.getAlignmentConsensusAnnotation()
1341 || aa[i].autoCalculated)
1343 // new way of indicating autocalculated annotation -
1344 an.setAutoCalculated(aa[i].autoCalculated);
1346 if (aa[i].hasScore())
1348 an.setScore(aa[i].getScore());
1351 if (aa[i].getCalcId() != null)
1353 calcIdSet.add(aa[i].getCalcId());
1354 an.setCalcId(aa[i].getCalcId());
1357 AnnotationElement ae;
1358 if (aa[i].annotations != null)
1360 an.setScoreOnly(false);
1361 for (int a = 0; a < aa[i].annotations.length; a++)
1363 if ((aa[i] == null) || (aa[i].annotations[a] == null))
1368 ae = new AnnotationElement();
1369 if (aa[i].annotations[a].description != null)
1370 ae.setDescription(aa[i].annotations[a].description);
1371 if (aa[i].annotations[a].displayCharacter != null)
1372 ae.setDisplayCharacter(aa[i].annotations[a].displayCharacter);
1374 if (!Float.isNaN(aa[i].annotations[a].value))
1375 ae.setValue(aa[i].annotations[a].value);
1378 if (aa[i].annotations[a].secondaryStructure != ' '
1379 && aa[i].annotations[a].secondaryStructure != '\0')
1380 ae.setSecondaryStructure(aa[i].annotations[a].secondaryStructure
1383 if (aa[i].annotations[a].colour != null
1384 && aa[i].annotations[a].colour != java.awt.Color.black)
1386 ae.setColour(aa[i].annotations[a].colour.getRGB());
1389 an.addAnnotationElement(ae);
1390 if (aa[i].autoCalculated)
1392 // only write one non-null entry into the annotation row -
1393 // sufficient to get the visualization attributes necessary to
1401 an.setScoreOnly(true);
1403 if (!storeDS || (storeDS && !aa[i].autoCalculated))
1405 // skip autocalculated annotation - these are only provided for
1407 vamsasSet.addAnnotation(an);
1413 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
1415 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
1416 if (settings != null)
1418 CalcIdParam vCalcIdParam = new CalcIdParam();
1419 vCalcIdParam.setCalcId(calcId);
1420 vCalcIdParam.addServiceURL(settings.getServiceURI());
1421 // generic URI allowing a third party to resolve another instance of the
1422 // service used for this calculation
1423 for (String urls : settings.getServiceURLs())
1425 vCalcIdParam.addServiceURL(urls);
1427 vCalcIdParam.setVersion("1.0");
1428 if (settings.getPreset() != null)
1430 WsParamSetI setting = settings.getPreset();
1431 vCalcIdParam.setName(setting.getName());
1432 vCalcIdParam.setDescription(setting.getDescription());
1436 vCalcIdParam.setName("");
1437 vCalcIdParam.setDescription("Last used parameters");
1439 // need to be able to recover 1) settings 2) user-defined presets or
1440 // recreate settings from preset 3) predefined settings provided by
1441 // service - or settings that can be transferred (or discarded)
1442 vCalcIdParam.setParameters(settings.getWsParamFile().replace("\n",
1444 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
1445 // todo - decide if updateImmediately is needed for any projects.
1447 return vCalcIdParam;
1452 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
1455 if (calcIdParam.getVersion().equals("1.0"))
1457 Jws2Instance service = Jws2Discoverer.getDiscoverer()
1458 .getPreferredServiceFor(calcIdParam.getServiceURL());
1459 if (service != null)
1461 WsParamSetI parmSet = null;
1464 parmSet = service.getParamStore().parseServiceParameterFile(
1465 calcIdParam.getName(), calcIdParam.getDescription(),
1466 calcIdParam.getServiceURL(),
1467 calcIdParam.getParameters().replace("|\\n|", "\n"));
1468 } catch (IOException x)
1470 warn("Couldn't parse parameter data for "
1471 + calcIdParam.getCalcId(), x);
1474 List<ArgumentI> argList = null;
1475 if (calcIdParam.getName().length() > 0)
1477 parmSet = service.getParamStore()
1478 .getPreset(calcIdParam.getName());
1479 if (parmSet != null)
1481 // TODO : check we have a good match with settings in AACon -
1482 // otherwise we'll need to create a new preset
1487 argList = parmSet.getArguments();
1490 AAConSettings settings = new AAConSettings(
1491 calcIdParam.isAutoUpdate(), service, parmSet, argList);
1492 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
1493 calcIdParam.isNeedsUpdate());
1498 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
1502 throw new Error("Unsupported Version for calcIdparam "
1503 + calcIdParam.toString());
1507 * External mapping between jalview objects and objects yielding a valid and
1508 * unique object ID string. This is null for normal Jalview project IO, but
1509 * non-null when a jalview project is being read or written as part of a
1512 IdentityHashMap jv2vobj = null;
1515 * Construct a unique ID for jvobj using either existing bindings or if none
1516 * exist, the result of the hashcode call for the object.
1519 * jalview data object
1520 * @return unique ID for referring to jvobj
1522 private String makeHashCode(Object jvobj, String altCode)
1524 if (jv2vobj != null)
1526 Object id = jv2vobj.get(jvobj);
1529 return id.toString();
1531 // check string ID mappings
1532 if (jvids2vobj != null && jvobj instanceof String)
1534 id = jvids2vobj.get(jvobj);
1538 return id.toString();
1540 // give up and warn that something has gone wrong
1541 warn("Cannot find ID for object in external mapping : " + jvobj);
1547 * return local jalview object mapped to ID, if it exists
1551 * @return null or object bound to idcode
1553 private Object retrieveExistingObj(String idcode)
1555 if (idcode != null && vobj2jv != null)
1557 return vobj2jv.get(idcode);
1563 * binding from ID strings from external mapping table to jalview data model
1566 private Hashtable vobj2jv;
1568 private Sequence createVamsasSequence(String id, SequenceI jds)
1570 return createVamsasSequence(true, id, jds, null);
1573 private Sequence createVamsasSequence(boolean recurse, String id,
1574 SequenceI jds, SequenceI parentseq)
1576 Sequence vamsasSeq = new Sequence();
1577 vamsasSeq.setId(id);
1578 vamsasSeq.setName(jds.getName());
1579 vamsasSeq.setSequence(jds.getSequenceAsString());
1580 vamsasSeq.setDescription(jds.getDescription());
1581 jalview.datamodel.DBRefEntry[] dbrefs = null;
1582 if (jds.getDatasetSequence() != null)
1584 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
1585 if (jds.getDatasetSequence().getDBRef() != null)
1587 dbrefs = jds.getDatasetSequence().getDBRef();
1592 vamsasSeq.setDsseqid(id); // so we can tell which sequences really are
1593 // dataset sequences only
1594 dbrefs = jds.getDBRef();
1598 for (int d = 0; d < dbrefs.length; d++)
1600 DBRef dbref = new DBRef();
1601 dbref.setSource(dbrefs[d].getSource());
1602 dbref.setVersion(dbrefs[d].getVersion());
1603 dbref.setAccessionId(dbrefs[d].getAccessionId());
1604 if (dbrefs[d].hasMap())
1606 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
1608 dbref.setMapping(mp);
1610 vamsasSeq.addDBRef(dbref);
1616 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
1617 SequenceI parentseq, SequenceI jds, boolean recurse)
1620 if (jmp.getMap() != null)
1624 jalview.util.MapList mlst = jmp.getMap();
1625 int r[] = mlst.getFromRanges();
1626 for (int s = 0; s < r.length; s += 2)
1628 MapListFrom mfrom = new MapListFrom();
1629 mfrom.setStart(r[s]);
1630 mfrom.setEnd(r[s + 1]);
1631 mp.addMapListFrom(mfrom);
1633 r = mlst.getToRanges();
1634 for (int s = 0; s < r.length; s += 2)
1636 MapListTo mto = new MapListTo();
1638 mto.setEnd(r[s + 1]);
1639 mp.addMapListTo(mto);
1641 mp.setMapFromUnit(mlst.getFromRatio());
1642 mp.setMapToUnit(mlst.getToRatio());
1643 if (jmp.getTo() != null)
1645 MappingChoice mpc = new MappingChoice();
1647 && (parentseq != jmp.getTo() || parentseq
1648 .getDatasetSequence() != jmp.getTo()))
1650 mpc.setSequence(createVamsasSequence(false, seqHash(jmp.getTo()),
1656 SequenceI ps = null;
1657 if (parentseq != jmp.getTo()
1658 && parentseq.getDatasetSequence() != jmp.getTo())
1660 // chaining dbref rather than a handshaking one
1661 jmpid = seqHash(ps = jmp.getTo());
1665 jmpid = seqHash(ps = parentseq);
1667 mpc.setDseqFor(jmpid);
1668 if (!seqRefIds.containsKey(mpc.getDseqFor()))
1670 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
1671 seqRefIds.put(mpc.getDseqFor(), ps);
1675 jalview.bin.Cache.log.debug("reusing DseqFor ID");
1678 mp.setMappingChoice(mpc);
1684 String SetUserColourScheme(jalview.schemes.ColourSchemeI cs,
1685 Vector userColours, JalviewModelSequence jms)
1688 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
1689 boolean newucs = false;
1690 if (!userColours.contains(ucs))
1692 userColours.add(ucs);
1695 id = "ucs" + userColours.indexOf(ucs);
1698 // actually create the scheme's entry in the XML model
1699 java.awt.Color[] colours = ucs.getColours();
1700 jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
1701 jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
1703 for (int i = 0; i < colours.length; i++)
1705 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
1706 col.setName(ResidueProperties.aa[i]);
1707 col.setRGB(jalview.util.Format.getHexString(colours[i]));
1708 jbucs.addColour(col);
1710 if (ucs.getLowerCaseColours() != null)
1712 colours = ucs.getLowerCaseColours();
1713 for (int i = 0; i < colours.length; i++)
1715 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
1716 col.setName(ResidueProperties.aa[i].toLowerCase());
1717 col.setRGB(jalview.util.Format.getHexString(colours[i]));
1718 jbucs.addColour(col);
1723 uc.setUserColourScheme(jbucs);
1724 jms.addUserColours(uc);
1730 jalview.schemes.UserColourScheme GetUserColourScheme(
1731 JalviewModelSequence jms, String id)
1733 UserColours[] uc = jms.getUserColours();
1734 UserColours colours = null;
1736 for (int i = 0; i < uc.length; i++)
1738 if (uc[i].getId().equals(id))
1746 java.awt.Color[] newColours = new java.awt.Color[24];
1748 for (int i = 0; i < 24; i++)
1750 newColours[i] = new java.awt.Color(Integer.parseInt(colours
1751 .getUserColourScheme().getColour(i).getRGB(), 16));
1754 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
1757 if (colours.getUserColourScheme().getColourCount() > 24)
1759 newColours = new java.awt.Color[23];
1760 for (int i = 0; i < 23; i++)
1762 newColours[i] = new java.awt.Color(Integer.parseInt(colours
1763 .getUserColourScheme().getColour(i + 24).getRGB(), 16));
1765 ucs.setLowerCaseColours(newColours);
1772 * contains last error message (if any) encountered by XML loader.
1774 String errorMessage = null;
1777 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
1778 * exceptions are raised during project XML parsing
1780 public boolean attemptversion1parse = true;
1783 * Load a jalview project archive from a jar file
1786 * - HTTP URL or filename
1788 public AlignFrame LoadJalviewAlign(final String file)
1791 jalview.gui.AlignFrame af = null;
1795 // create list to store references for any new Jmol viewers created
1796 newStructureViewers = new Vector<AppJmol>();
1797 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
1798 // Workaround is to make sure caller implements the JarInputStreamProvider
1800 // so we can re-open the jar input stream for each entry.
1802 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
1803 af = LoadJalviewAlign(jprovider);
1805 } catch (MalformedURLException e)
1807 errorMessage = "Invalid URL format for '" + file + "'";
1813 SwingUtilities.invokeAndWait(new Runnable()
1817 setLoadingFinishedForNewStructureViewers();
1820 } catch (Exception x)
1828 private jarInputStreamProvider createjarInputStreamProvider(
1829 final String file) throws MalformedURLException
1832 errorMessage = null;
1833 uniqueSetSuffix = null;
1835 viewportsAdded = null;
1836 frefedSequence = null;
1838 if (file.startsWith("http://"))
1840 url = new URL(file);
1842 final URL _url = url;
1843 return new jarInputStreamProvider()
1847 public JarInputStream getJarInputStream() throws IOException
1851 return new JarInputStream(_url.openStream());
1855 return new JarInputStream(new FileInputStream(file));
1860 public String getFilename()
1868 * Recover jalview session from a jalview project archive. Caller may
1869 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
1870 * themselves. Any null fields will be initialised with default values,
1871 * non-null fields are left alone.
1876 public AlignFrame LoadJalviewAlign(final jarInputStreamProvider jprovider)
1878 errorMessage = null;
1879 if (uniqueSetSuffix == null)
1881 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
1883 if (seqRefIds == null)
1885 seqRefIds = new Hashtable();
1887 if (viewportsAdded == null)
1889 viewportsAdded = new Hashtable();
1891 if (frefedSequence == null)
1893 frefedSequence = new Vector();
1896 jalview.gui.AlignFrame af = null, _af = null;
1897 Hashtable gatherToThisFrame = new Hashtable();
1898 final String file = jprovider.getFilename();
1901 JarInputStream jin = null;
1902 JarEntry jarentry = null;
1907 jin = jprovider.getJarInputStream();
1908 for (int i = 0; i < entryCount; i++)
1910 jarentry = jin.getNextJarEntry();
1913 if (jarentry != null && jarentry.getName().endsWith(".xml"))
1915 InputStreamReader in = new InputStreamReader(jin, "UTF-8");
1916 JalviewModel object = new JalviewModel();
1918 Unmarshaller unmar = new Unmarshaller(object);
1919 unmar.setValidation(false);
1920 object = (JalviewModel) unmar.unmarshal(in);
1921 if (true) // !skipViewport(object))
1923 _af = LoadFromObject(object, file, true, jprovider);
1924 if (object.getJalviewModelSequence().getViewportCount() > 0)
1927 if (af.viewport.gatherViewsHere)
1929 gatherToThisFrame.put(af.viewport.getSequenceSetId(), af);
1935 else if (jarentry != null)
1937 // Some other file here.
1940 } while (jarentry != null);
1941 resolveFrefedSequences();
1942 } catch (java.io.FileNotFoundException ex)
1944 ex.printStackTrace();
1945 errorMessage = "Couldn't locate Jalview XML file : " + file;
1946 System.err.println("Exception whilst loading jalview XML file : "
1948 } catch (java.net.UnknownHostException ex)
1950 ex.printStackTrace();
1951 errorMessage = "Couldn't locate Jalview XML file : " + file;
1952 System.err.println("Exception whilst loading jalview XML file : "
1954 } catch (Exception ex)
1956 System.err.println("Parsing as Jalview Version 2 file failed.");
1957 ex.printStackTrace(System.err);
1958 if (attemptversion1parse)
1960 // Is Version 1 Jar file?
1963 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
1964 } catch (Exception ex2)
1966 System.err.println("Exception whilst loading as jalviewXMLV1:");
1967 ex2.printStackTrace();
1971 if (Desktop.instance != null)
1973 Desktop.instance.stopLoading();
1977 System.out.println("Successfully loaded archive file");
1980 ex.printStackTrace();
1982 System.err.println("Exception whilst loading jalview XML file : "
1984 } catch (OutOfMemoryError e)
1986 // Don't use the OOM Window here
1987 errorMessage = "Out of memory loading jalview XML file";
1988 System.err.println("Out of memory whilst loading jalview XML file");
1989 e.printStackTrace();
1992 if (Desktop.instance != null)
1994 Desktop.instance.stopLoading();
1997 Enumeration en = gatherToThisFrame.elements();
1998 while (en.hasMoreElements())
2000 Desktop.instance.gatherViews((AlignFrame) en.nextElement());
2002 if (errorMessage != null)
2010 * check errorMessage for a valid error message and raise an error box in the
2011 * GUI or write the current errorMessage to stderr and then clear the error
2014 protected void reportErrors()
2016 reportErrors(false);
2019 protected void reportErrors(final boolean saving)
2021 if (errorMessage != null)
2023 final String finalErrorMessage = errorMessage;
2026 javax.swing.SwingUtilities.invokeLater(new Runnable()
2031 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2032 finalErrorMessage, "Error "
2033 + (saving ? "saving" : "loading")
2034 + " Jalview file", JOptionPane.WARNING_MESSAGE);
2040 System.err.println("Problem loading Jalview file: " + errorMessage);
2043 errorMessage = null;
2046 Hashtable alreadyLoadedPDB;
2049 * when set, local views will be updated from view stored in JalviewXML
2050 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2051 * sync if this is set to true.
2053 private final boolean updateLocalViews = false;
2055 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId)
2057 if (alreadyLoadedPDB == null)
2058 alreadyLoadedPDB = new Hashtable();
2060 if (alreadyLoadedPDB.containsKey(pdbId))
2061 return alreadyLoadedPDB.get(pdbId).toString();
2065 JarInputStream jin = jprovider.getJarInputStream();
2067 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2068 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2069 * FileInputStream(jprovider)); }
2072 JarEntry entry = null;
2075 entry = jin.getNextJarEntry();
2076 } while (entry != null && !entry.getName().equals(pdbId));
2079 BufferedReader in = new BufferedReader(new InputStreamReader(jin));
2080 File outFile = File.createTempFile("jalview_pdb", ".txt");
2081 outFile.deleteOnExit();
2082 PrintWriter out = new PrintWriter(new FileOutputStream(outFile));
2085 while ((data = in.readLine()) != null)
2092 } catch (Exception foo)
2097 String t = outFile.getAbsolutePath();
2098 alreadyLoadedPDB.put(pdbId, t);
2103 warn("Couldn't find PDB file entry in Jalview Jar for " + pdbId);
2105 } catch (Exception ex)
2107 ex.printStackTrace();
2113 private class JvAnnotRow
2115 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2122 * persisted version of annotation row from which to take vis properties
2124 public jalview.datamodel.AlignmentAnnotation template;
2127 * original position of the annotation row in the alignment
2133 * Load alignment frame from jalview XML DOM object
2138 * filename source string
2139 * @param loadTreesAndStructures
2140 * when false only create Viewport
2142 * data source provider
2143 * @return alignment frame created from view stored in DOM
2145 AlignFrame LoadFromObject(JalviewModel object, String file,
2146 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
2148 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
2149 Sequence[] vamsasSeq = vamsasSet.getSequence();
2151 JalviewModelSequence jms = object.getJalviewModelSequence();
2153 Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
2156 // ////////////////////////////////
2159 Vector hiddenSeqs = null;
2160 jalview.datamodel.Sequence jseq;
2162 ArrayList tmpseqs = new ArrayList();
2164 boolean multipleView = false;
2166 JSeq[] JSEQ = object.getJalviewModelSequence().getJSeq();
2167 int vi = 0; // counter in vamsasSeq array
2168 for (int i = 0; i < JSEQ.length; i++)
2170 String seqId = JSEQ[i].getId();
2172 if (seqRefIds.get(seqId) != null)
2174 tmpseqs.add(seqRefIds.get(seqId));
2175 multipleView = true;
2179 jseq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
2180 vamsasSeq[vi].getSequence());
2181 jseq.setDescription(vamsasSeq[vi].getDescription());
2182 jseq.setStart(JSEQ[i].getStart());
2183 jseq.setEnd(JSEQ[i].getEnd());
2184 jseq.setVamsasId(uniqueSetSuffix + seqId);
2185 seqRefIds.put(vamsasSeq[vi].getId(), jseq);
2190 if (JSEQ[i].getHidden())
2192 if (hiddenSeqs == null)
2194 hiddenSeqs = new Vector();
2197 hiddenSeqs.addElement(seqRefIds.get(seqId));
2203 // Create the alignment object from the sequence set
2204 // ///////////////////////////////
2205 jalview.datamodel.Sequence[] orderedSeqs = new jalview.datamodel.Sequence[tmpseqs
2208 tmpseqs.toArray(orderedSeqs);
2210 jalview.datamodel.Alignment al = new jalview.datamodel.Alignment(
2213 // / Add the alignment properties
2214 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
2216 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
2217 al.setProperty(ssp.getKey(), ssp.getValue());
2221 // SequenceFeatures are added to the DatasetSequence,
2222 // so we must create or recover the dataset before loading features
2223 // ///////////////////////////////
2224 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
2226 // older jalview projects do not have a dataset id.
2227 al.setDataset(null);
2231 recoverDatasetFor(vamsasSet, al);
2233 // ///////////////////////////////
2235 Hashtable pdbloaded = new Hashtable();
2238 // load sequence features, database references and any associated PDB
2239 // structures for the alignment
2240 for (int i = 0; i < vamsasSeq.length; i++)
2242 if (JSEQ[i].getFeaturesCount() > 0)
2244 Features[] features = JSEQ[i].getFeatures();
2245 for (int f = 0; f < features.length; f++)
2247 jalview.datamodel.SequenceFeature sf = new jalview.datamodel.SequenceFeature(
2248 features[f].getType(), features[f].getDescription(),
2249 features[f].getStatus(), features[f].getBegin(),
2250 features[f].getEnd(), features[f].getFeatureGroup());
2252 sf.setScore(features[f].getScore());
2253 for (int od = 0; od < features[f].getOtherDataCount(); od++)
2255 OtherData keyValue = features[f].getOtherData(od);
2256 if (keyValue.getKey().startsWith("LINK"))
2258 sf.addLink(keyValue.getValue());
2262 sf.setValue(keyValue.getKey(), keyValue.getValue());
2267 al.getSequenceAt(i).getDatasetSequence().addSequenceFeature(sf);
2270 if (vamsasSeq[i].getDBRefCount() > 0)
2272 addDBRefs(al.getSequenceAt(i).getDatasetSequence(), vamsasSeq[i]);
2274 if (JSEQ[i].getPdbidsCount() > 0)
2276 Pdbids[] ids = JSEQ[i].getPdbids();
2277 for (int p = 0; p < ids.length; p++)
2279 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
2280 entry.setId(ids[p].getId());
2281 entry.setType(ids[p].getType());
2282 if (ids[p].getFile() != null)
2284 if (!pdbloaded.containsKey(ids[p].getFile()))
2286 entry.setFile(loadPDBFile(jprovider, ids[p].getId()));
2290 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
2294 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
2298 } // end !multipleview
2300 // ///////////////////////////////
2301 // LOAD SEQUENCE MAPPINGS
2303 if (vamsasSet.getAlcodonFrameCount() > 0)
2305 // TODO Potentially this should only be done once for all views of an
2307 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
2308 for (int i = 0; i < alc.length; i++)
2310 jalview.datamodel.AlignedCodonFrame cf = new jalview.datamodel.AlignedCodonFrame(
2311 alc[i].getAlcodonCount());
2312 if (alc[i].getAlcodonCount() > 0)
2314 Alcodon[] alcods = alc[i].getAlcodon();
2315 for (int p = 0; p < cf.codons.length; p++)
2317 if (alcods[p].hasPos1() && alcods[p].hasPos2()
2318 && alcods[p].hasPos3())
2320 // translated codons require three valid positions
2321 cf.codons[p] = new int[3];
2322 cf.codons[p][0] = (int) alcods[p].getPos1();
2323 cf.codons[p][1] = (int) alcods[p].getPos2();
2324 cf.codons[p][2] = (int) alcods[p].getPos3();
2328 cf.codons[p] = null;
2332 if (alc[i].getAlcodMapCount() > 0)
2334 AlcodMap[] maps = alc[i].getAlcodMap();
2335 for (int m = 0; m < maps.length; m++)
2337 SequenceI dnaseq = (SequenceI) seqRefIds
2338 .get(maps[m].getDnasq());
2340 jalview.datamodel.Mapping mapping = null;
2341 // attach to dna sequence reference.
2342 if (maps[m].getMapping() != null)
2344 mapping = addMapping(maps[m].getMapping());
2348 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
2353 frefedSequence.add(new Object[]
2354 { maps[m].getDnasq(), cf, mapping });
2358 al.addCodonFrame(cf);
2363 // ////////////////////////////////
2365 ArrayList<JvAnnotRow> autoAlan = new ArrayList<JvAnnotRow>();
2367 * store any annotations which forward reference a group's ID
2369 Hashtable<String, ArrayList<jalview.datamodel.AlignmentAnnotation>> groupAnnotRefs = new Hashtable<String, ArrayList<jalview.datamodel.AlignmentAnnotation>>();
2371 if (vamsasSet.getAnnotationCount() > 0)
2373 Annotation[] an = vamsasSet.getAnnotation();
2375 for (int i = 0; i < an.length; i++)
2378 * test if annotation is automatically calculated for this view only
2380 boolean autoForView = false;
2381 if (an[i].getLabel().equals("Quality")
2382 || an[i].getLabel().equals("Conservation")
2383 || an[i].getLabel().equals("Consensus"))
2385 // Kludge for pre 2.5 projects which lacked the autocalculated flag
2387 if (!an[i].hasAutoCalculated())
2389 an[i].setAutoCalculated(true);
2393 || (an[i].hasAutoCalculated() && an[i].isAutoCalculated()))
2395 // remove ID - we don't recover annotation from other views for
2396 // view-specific annotation
2400 // set visiblity for other annotation in this view
2401 if (an[i].getId() != null
2402 && annotationIds.containsKey(an[i].getId()))
2404 jalview.datamodel.AlignmentAnnotation jda = (jalview.datamodel.AlignmentAnnotation) annotationIds
2405 .get(an[i].getId());
2406 // in principle Visible should always be true for annotation displayed
2407 // in multiple views
2408 if (an[i].hasVisible())
2409 jda.visible = an[i].getVisible();
2411 al.addAnnotation(jda);
2415 // Construct new annotation from model.
2416 AnnotationElement[] ae = an[i].getAnnotationElement();
2417 jalview.datamodel.Annotation[] anot = null;
2418 java.awt.Color firstColour = null;
2420 if (!an[i].getScoreOnly())
2422 anot = new jalview.datamodel.Annotation[al.getWidth()];
2423 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
2425 anpos = ae[aa].getPosition();
2427 if (anpos >= anot.length)
2430 anot[anpos] = new jalview.datamodel.Annotation(
2432 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
2433 (ae[aa].getSecondaryStructure() == null || ae[aa]
2434 .getSecondaryStructure().length() == 0) ? ' '
2435 : ae[aa].getSecondaryStructure().charAt(0),
2439 // JBPNote: Consider verifying dataflow for IO of secondary
2440 // structure annotation read from Stockholm files
2441 // this was added to try to ensure that
2442 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
2444 // anot[ae[aa].getPosition()].displayCharacter = "";
2446 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
2447 if (firstColour == null)
2449 firstColour = anot[anpos].colour;
2453 jalview.datamodel.AlignmentAnnotation jaa = null;
2455 if (an[i].getGraph())
2457 float llim = 0, hlim = 0;
2458 // if (autoForView || an[i].isAutoCalculated()) {
2461 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
2462 an[i].getDescription(), anot, llim, hlim,
2463 an[i].getGraphType());
2465 jaa.graphGroup = an[i].getGraphGroup();
2466 jaa._linecolour = firstColour;
2467 if (an[i].getThresholdLine() != null)
2469 jaa.setThreshold(new jalview.datamodel.GraphLine(an[i]
2470 .getThresholdLine().getValue(), an[i]
2471 .getThresholdLine().getLabel(), new java.awt.Color(
2472 an[i].getThresholdLine().getColour())));
2475 if (autoForView || an[i].isAutoCalculated())
2477 // Hardwire the symbol display line to ensure that labels for
2478 // histograms are displayed
2484 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
2485 an[i].getDescription(), anot);
2486 jaa._linecolour = firstColour;
2488 // register new annotation
2489 if (an[i].getId() != null)
2491 annotationIds.put(an[i].getId(), jaa);
2492 jaa.annotationId = an[i].getId();
2494 // recover sequence association
2495 if (an[i].getSequenceRef() != null)
2497 if (al.findName(an[i].getSequenceRef()) != null)
2499 jaa.createSequenceMapping(al.findName(an[i].getSequenceRef()),
2501 al.findName(an[i].getSequenceRef()).addAlignmentAnnotation(jaa);
2504 // and make a note of any group association
2505 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
2507 ArrayList<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
2508 .get(an[i].getGroupRef());
2511 aal = new ArrayList<jalview.datamodel.AlignmentAnnotation>();
2512 groupAnnotRefs.put(an[i].getGroupRef(), aal);
2517 if (an[i].hasScore())
2519 jaa.setScore(an[i].getScore());
2521 if (an[i].hasVisible())
2522 jaa.visible = an[i].getVisible();
2524 if (an[i].hasCentreColLabels())
2525 jaa.centreColLabels = an[i].getCentreColLabels();
2527 if (an[i].hasScaleColLabels())
2529 jaa.scaleColLabel = an[i].getScaleColLabels();
2531 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
2533 // newer files have an 'autoCalculated' flag and store calculation
2534 // state in viewport properties
2535 jaa.autoCalculated = true; // means annotation will be marked for
2536 // update at end of load.
2538 if (an[i].hasGraphHeight())
2540 jaa.graphHeight = an[i].getGraphHeight();
2542 if (an[i].hasBelowAlignment())
2544 jaa.belowAlignment = an[i].isBelowAlignment();
2546 jaa.setCalcId(an[i].getCalcId());
2548 if (jaa.autoCalculated)
2550 autoAlan.add(new JvAnnotRow(i, jaa));
2553 // if (!autoForView)
2555 // add autocalculated group annotation and any user created annotation
2557 al.addAnnotation(jaa);
2561 // ///////////////////////
2563 // Create alignment markup and styles for this view
2564 if (jms.getJGroupCount() > 0)
2566 JGroup[] groups = jms.getJGroup();
2567 boolean addAnnotSchemeGroup = false;
2568 for (int i = 0; i < groups.length; i++)
2570 ColourSchemeI cs = null;
2572 if (groups[i].getColour() != null)
2574 if (groups[i].getColour().startsWith("ucs"))
2576 cs = GetUserColourScheme(jms, groups[i].getColour());
2578 else if (groups[i].getColour().equals("AnnotationColourGradient")
2579 && groups[i].getAnnotationColours() != null)
2581 addAnnotSchemeGroup = true;
2586 cs = ColourSchemeProperty.getColour(al, groups[i].getColour());
2591 cs.setThreshold(groups[i].getPidThreshold(), true);
2595 Vector seqs = new Vector();
2597 for (int s = 0; s < groups[i].getSeqCount(); s++)
2599 String seqId = groups[i].getSeq(s) + "";
2600 jalview.datamodel.SequenceI ts = (jalview.datamodel.SequenceI) seqRefIds
2605 seqs.addElement(ts);
2609 if (seqs.size() < 1)
2614 jalview.datamodel.SequenceGroup sg = new jalview.datamodel.SequenceGroup(
2615 seqs, groups[i].getName(), cs, groups[i].getDisplayBoxes(),
2616 groups[i].getDisplayText(), groups[i].getColourText(),
2617 groups[i].getStart(), groups[i].getEnd());
2619 sg.setOutlineColour(new java.awt.Color(groups[i].getOutlineColour()));
2621 sg.textColour = new java.awt.Color(groups[i].getTextCol1());
2622 sg.textColour2 = new java.awt.Color(groups[i].getTextCol2());
2623 sg.setShowNonconserved(groups[i].hasShowUnconserved() ? groups[i]
2624 .isShowUnconserved() : false);
2625 sg.thresholdTextColour = groups[i].getTextColThreshold();
2626 if (groups[i].hasShowConsensusHistogram())
2628 sg.setShowConsensusHistogram(groups[i].isShowConsensusHistogram());
2631 if (groups[i].hasShowSequenceLogo())
2633 sg.setshowSequenceLogo(groups[i].isShowSequenceLogo());
2635 if (groups[i].hasNormaliseSequenceLogo())
2637 sg.setNormaliseSequenceLogo(groups[i].isNormaliseSequenceLogo());
2639 if (groups[i].hasIgnoreGapsinConsensus())
2641 sg.setIgnoreGapsConsensus(groups[i].getIgnoreGapsinConsensus());
2643 if (groups[i].getConsThreshold() != 0)
2645 jalview.analysis.Conservation c = new jalview.analysis.Conservation(
2646 "All", ResidueProperties.propHash, 3,
2647 sg.getSequences(null), 0, sg.getWidth() - 1);
2649 c.verdict(false, 25);
2650 sg.cs.setConservation(c);
2653 if (groups[i].getId() != null && groupAnnotRefs.size() > 0)
2655 // re-instate unique group/annotation row reference
2656 ArrayList<jalview.datamodel.AlignmentAnnotation> jaal = groupAnnotRefs
2657 .get(groups[i].getId());
2660 for (jalview.datamodel.AlignmentAnnotation jaa : jaal)
2663 if (jaa.autoCalculated)
2665 // match up and try to set group autocalc alignment row for this
2667 if (jaa.label.startsWith("Consensus for "))
2669 sg.setConsensus(jaa);
2671 // match up and try to set group autocalc alignment row for this
2673 if (jaa.label.startsWith("Conservation for "))
2675 sg.setConservationRow(jaa);
2682 if (addAnnotSchemeGroup)
2684 // reconstruct the annotation colourscheme
2685 sg.cs = constructAnnotationColour(
2686 groups[i].getAnnotationColours(), null, al, jms, false);
2692 // only dataset in this model, so just return.
2695 // ///////////////////////////////
2698 // If we just load in the same jar file again, the sequenceSetId
2699 // will be the same, and we end up with multiple references
2700 // to the same sequenceSet. We must modify this id on load
2701 // so that each load of the file gives a unique id
2702 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
2703 String viewId = (view.getId() == null ? null : view.getId()
2705 AlignFrame af = null;
2706 AlignViewport av = null;
2707 // now check to see if we really need to create a new viewport.
2708 if (multipleView && viewportsAdded.size() == 0)
2710 // We recovered an alignment for which a viewport already exists.
2711 // TODO: fix up any settings necessary for overlaying stored state onto
2712 // state recovered from another document. (may not be necessary).
2713 // we may need a binding from a viewport in memory to one recovered from
2715 // and then recover its containing af to allow the settings to be applied.
2716 // TODO: fix for vamsas demo
2718 .println("About to recover a viewport for existing alignment: Sequence set ID is "
2720 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
2721 if (seqsetobj != null)
2723 if (seqsetobj instanceof String)
2725 uniqueSeqSetId = (String) seqsetobj;
2727 .println("Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
2733 .println("Warning : Collision between sequence set ID string and existing jalview object mapping.");
2739 * indicate that annotation colours are applied across all groups (pre
2740 * Jalview 2.8.1 behaviour)
2742 boolean doGroupAnnColour = isVersionStringLaterThan("2.8.1",
2743 object.getVersion());
2745 AlignmentPanel ap = null;
2746 boolean isnewview = true;
2749 // Check to see if this alignment already has a view id == viewId
2750 jalview.gui.AlignmentPanel views[] = Desktop
2751 .getAlignmentPanels(uniqueSeqSetId);
2752 if (views != null && views.length > 0)
2754 for (int v = 0; v < views.length; v++)
2756 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
2758 // recover the existing alignpanel, alignframe, viewport
2759 af = views[v].alignFrame;
2762 // TODO: could even skip resetting view settings if we don't want to
2763 // change the local settings from other jalview processes
2772 af = loadViewport(file, JSEQ, hiddenSeqs, al, jms, view,
2773 uniqueSeqSetId, viewId, autoAlan);
2778 // /////////////////////////////////////
2779 if (loadTreesAndStructures && jms.getTreeCount() > 0)
2783 for (int t = 0; t < jms.getTreeCount(); t++)
2786 Tree tree = jms.getTree(t);
2788 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
2791 tp = af.ShowNewickTree(
2792 new jalview.io.NewickFile(tree.getNewick()),
2793 tree.getTitle(), tree.getWidth(), tree.getHeight(),
2794 tree.getXpos(), tree.getYpos());
2795 if (tree.getId() != null)
2797 // perhaps bind the tree id to something ?
2802 // update local tree attributes ?
2803 // TODO: should check if tp has been manipulated by user - if so its
2804 // settings shouldn't be modified
2805 tp.setTitle(tree.getTitle());
2806 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(), tree
2807 .getWidth(), tree.getHeight()));
2808 tp.av = av; // af.viewport; // TODO: verify 'associate with all
2811 tp.treeCanvas.av = av; // af.viewport;
2812 tp.treeCanvas.ap = ap; // af.alignPanel;
2817 warn("There was a problem recovering stored Newick tree: \n"
2818 + tree.getNewick());
2822 tp.fitToWindow.setState(tree.getFitToWindow());
2823 tp.fitToWindow_actionPerformed(null);
2825 if (tree.getFontName() != null)
2827 tp.setTreeFont(new java.awt.Font(tree.getFontName(), tree
2828 .getFontStyle(), tree.getFontSize()));
2832 tp.setTreeFont(new java.awt.Font(view.getFontName(), view
2833 .getFontStyle(), tree.getFontSize()));
2836 tp.showPlaceholders(tree.getMarkUnlinked());
2837 tp.showBootstrap(tree.getShowBootstrap());
2838 tp.showDistances(tree.getShowDistances());
2840 tp.treeCanvas.threshold = tree.getThreshold();
2842 if (tree.getCurrentTree())
2844 af.viewport.setCurrentTree(tp.getTree());
2848 } catch (Exception ex)
2850 ex.printStackTrace();
2854 // //LOAD STRUCTURES
2855 if (loadTreesAndStructures)
2857 // run through all PDB ids on the alignment, and collect mappings between
2858 // jmol view ids and all sequences referring to it
2859 Hashtable<String, Object[]> jmolViewIds = new Hashtable();
2861 for (int i = 0; i < JSEQ.length; i++)
2863 if (JSEQ[i].getPdbidsCount() > 0)
2865 Pdbids[] ids = JSEQ[i].getPdbids();
2866 for (int p = 0; p < ids.length; p++)
2868 for (int s = 0; s < ids[p].getStructureStateCount(); s++)
2870 // check to see if we haven't already created this structure view
2871 String sviewid = (ids[p].getStructureState(s).getViewId() == null) ? null
2872 : ids[p].getStructureState(s).getViewId()
2874 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
2875 // Originally : ids[p].getFile()
2876 // : TODO: verify external PDB file recovery still works in normal
2877 // jalview project load
2878 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId()));
2879 jpdb.setId(ids[p].getId());
2881 int x = ids[p].getStructureState(s).getXpos();
2882 int y = ids[p].getStructureState(s).getYpos();
2883 int width = ids[p].getStructureState(s).getWidth();
2884 int height = ids[p].getStructureState(s).getHeight();
2886 // Probably don't need to do this anymore...
2887 // Desktop.desktop.getComponentAt(x, y);
2888 // TODO: NOW: check that this recovers the PDB file correctly.
2889 String pdbFile = loadPDBFile(jprovider, ids[p].getId());
2890 jalview.datamodel.SequenceI seq = (jalview.datamodel.SequenceI) seqRefIds
2891 .get(JSEQ[i].getId() + "");
2892 if (sviewid == null)
2894 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width
2897 if (!jmolViewIds.containsKey(sviewid))
2899 jmolViewIds.put(sviewid, new Object[]
2901 { x, y, width, height }, "",
2902 new Hashtable<String, Object[]>(), new boolean[]
2903 { false, false, true } });
2904 // Legacy pre-2.7 conversion JAL-823 :
2905 // do not assume any view has to be linked for colour by
2909 // assemble String[] { pdb files }, String[] { id for each
2910 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
2911 // seqs_file 2}, boolean[] {
2912 // linkAlignPanel,superposeWithAlignpanel}} from hash
2913 Object[] jmoldat = jmolViewIds.get(sviewid);
2914 ((boolean[]) jmoldat[3])[0] |= ids[p].getStructureState(s)
2915 .hasAlignwithAlignPanel() ? ids[p].getStructureState(
2916 s).getAlignwithAlignPanel() : false;
2917 // never colour by linked panel if not specified
2918 ((boolean[]) jmoldat[3])[1] |= ids[p].getStructureState(s)
2919 .hasColourwithAlignPanel() ? ids[p]
2920 .getStructureState(s).getColourwithAlignPanel()
2922 // default for pre-2.7 projects is that Jmol colouring is enabled
2923 ((boolean[]) jmoldat[3])[2] &= ids[p].getStructureState(s)
2924 .hasColourByJmol() ? ids[p].getStructureState(s)
2925 .getColourByJmol() : true;
2927 if (((String) jmoldat[1]).length() < ids[p]
2928 .getStructureState(s).getContent().length())
2931 jmoldat[1] = ids[p].getStructureState(s).getContent();
2934 if (ids[p].getFile() != null)
2936 File mapkey = new File(ids[p].getFile());
2937 Object[] seqstrmaps = (Object[]) ((Hashtable) jmoldat[2])
2939 if (seqstrmaps == null)
2941 ((Hashtable) jmoldat[2]).put(mapkey,
2942 seqstrmaps = new Object[]
2943 { pdbFile, ids[p].getId(), new Vector(),
2946 if (!((Vector) seqstrmaps[2]).contains(seq))
2948 ((Vector) seqstrmaps[2]).addElement(seq);
2949 // ((Vector)seqstrmaps[3]).addElement(n) :
2950 // in principle, chains
2951 // should be stored here : do we need to
2952 // TODO: store and recover seq/pdb_id :
2958 errorMessage = ("The Jmol views in this project were imported\nfrom an older version of Jalview.\nPlease review the sequence colour associations\nin the Colour by section of the Jmol View menu.\n\nIn the case of problems, see note at\nhttp://issues.jalview.org/browse/JAL-747");
2967 // Instantiate the associated Jmol views
2968 for (Entry<String, Object[]> entry : jmolViewIds.entrySet())
2970 String sviewid = entry.getKey();
2971 Object[] svattrib = entry.getValue();
2972 int[] geom = (int[]) svattrib[0];
2973 String state = (String) svattrib[1];
2974 Hashtable<File, Object[]> oldFiles = (Hashtable<File, Object[]>) svattrib[2];
2975 final boolean useinJmolsuperpos = ((boolean[]) svattrib[3])[0], usetoColourbyseq = ((boolean[]) svattrib[3])[1], jmolColouring = ((boolean[]) svattrib[3])[2];
2976 int x = geom[0], y = geom[1], width = geom[2], height = geom[3];
2977 // collate the pdbfile -> sequence mappings from this view
2978 Vector<String> pdbfilenames = new Vector<String>();
2979 Vector<SequenceI[]> seqmaps = new Vector<SequenceI[]>();
2980 Vector<String> pdbids = new Vector<String>();
2982 // Search to see if we've already created this Jmol view
2983 AppJmol comp = null;
2984 JInternalFrame[] frames = null;
2989 frames = Desktop.desktop.getAllFrames();
2990 } catch (ArrayIndexOutOfBoundsException e)
2992 // occasional No such child exceptions are thrown here...
2997 } catch (Exception f)
3002 } while (frames == null);
3003 // search for any Jmol windows already open from other
3004 // alignment views that exactly match the stored structure state
3005 for (int f = 0; comp == null && f < frames.length; f++)
3007 if (frames[f] instanceof AppJmol)
3010 && ((AppJmol) frames[f]).getViewId().equals(sviewid))
3012 // post jalview 2.4 schema includes structure view id
3013 comp = (AppJmol) frames[f];
3015 else if (frames[f].getX() == x && frames[f].getY() == y
3016 && frames[f].getHeight() == height
3017 && frames[f].getWidth() == width)
3019 comp = (AppJmol) frames[f];
3026 // create a new Jmol window.
3027 // First parse the Jmol state to translate filenames loaded into the
3028 // view, and record the order in which files are shown in the Jmol
3029 // view, so we can add the sequence mappings in same order.
3030 StringBuffer newFileLoc = null;
3031 int cp = 0, ncp, ecp;
3032 while ((ncp = state.indexOf("load ", cp)) > -1)
3034 if (newFileLoc == null)
3036 newFileLoc = new StringBuffer();
3040 // look for next filename in load statement
3041 newFileLoc.append(state.substring(cp,
3042 ncp = (state.indexOf("\"", ncp + 1) + 1)));
3043 String oldfilenam = state.substring(ncp,
3044 ecp = state.indexOf("\"", ncp));
3045 // recover the new mapping data for this old filename
3046 // have to normalize filename - since Jmol and jalview do
3048 // translation differently.
3049 Object[] filedat = oldFiles.get(new File(oldfilenam));
3050 newFileLoc.append(Platform
3051 .escapeString((String) filedat[0]));
3052 pdbfilenames.addElement((String) filedat[0]);
3053 pdbids.addElement((String) filedat[1]);
3054 seqmaps.addElement(((Vector<SequenceI>) filedat[2])
3055 .toArray(new SequenceI[0]));
3056 newFileLoc.append("\"");
3057 cp = ecp + 1; // advance beyond last \" and set cursor so we can
3058 // look for next file statement.
3059 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
3063 // just append rest of state
3064 newFileLoc.append(state.substring(cp));
3069 .print("Ignoring incomplete Jmol state for PDB ids: ");
3070 newFileLoc = new StringBuffer(state);
3071 newFileLoc.append("; load append ");
3072 for (File id : oldFiles.keySet())
3074 // add this and any other pdb files that should be present in
3076 Object[] filedat = oldFiles.get(id);
3078 newFileLoc.append(((String) filedat[0]));
3079 pdbfilenames.addElement((String) filedat[0]);
3080 pdbids.addElement((String) filedat[1]);
3081 seqmaps.addElement(((Vector<SequenceI>) filedat[2])
3082 .toArray(new SequenceI[0]));
3083 newFileLoc.append(" \"");
3084 newFileLoc.append((String) filedat[0]);
3085 newFileLoc.append("\"");
3088 newFileLoc.append(";");
3091 if (newFileLoc != null)
3093 int histbug = newFileLoc.indexOf("history = ");
3095 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";",
3097 String val = (diff == -1) ? null : newFileLoc.substring(
3099 if (val != null && val.length() >= 4)
3101 if (val.contains("e"))
3103 if (val.trim().equals("true"))
3111 newFileLoc.replace(histbug, diff, val);
3114 // TODO: assemble String[] { pdb files }, String[] { id for each
3115 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3116 // seqs_file 2}} from hash
3117 final String[] pdbf = pdbfilenames
3118 .toArray(new String[pdbfilenames.size()]), id = pdbids
3119 .toArray(new String[pdbids.size()]);
3120 final SequenceI[][] sq = seqmaps
3121 .toArray(new SequenceI[seqmaps.size()][]);
3122 final String fileloc = newFileLoc.toString(), vid = sviewid;
3123 final AlignFrame alf = af;
3124 final java.awt.Rectangle rect = new java.awt.Rectangle(x, y,
3128 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
3133 AppJmol sview = null;
3136 sview = new AppJmol(pdbf, id, sq, alf.alignPanel,
3137 useinJmolsuperpos, usetoColourbyseq,
3138 jmolColouring, fileloc, rect, vid);
3139 addNewStructureViewer(sview);
3140 } catch (OutOfMemoryError ex)
3142 new OOMWarning("restoring structure view for PDB id "
3143 + id, (OutOfMemoryError) ex.getCause());
3144 if (sview != null && sview.isVisible())
3146 sview.closeViewer();
3147 sview.setVisible(false);
3153 } catch (InvocationTargetException ex)
3155 warn("Unexpected error when opening Jmol view.", ex);
3157 } catch (InterruptedException e)
3159 // e.printStackTrace();
3165 // if (comp != null)
3167 // NOTE: if the jalview project is part of a shared session then
3168 // view synchronization should/could be done here.
3170 // add mapping for sequences in this view to an already open Jmol
3172 for (File id : oldFiles.keySet())
3174 // add this and any other pdb files that should be present in the
3176 Object[] filedat = oldFiles.get(id);
3177 String pdbFile = (String) filedat[0];
3178 SequenceI[] seq = ((Vector<SequenceI>) filedat[2])
3179 .toArray(new SequenceI[0]);
3180 comp.jmb.ssm.setMapping(seq, null, pdbFile,
3181 jalview.io.AppletFormatAdapter.FILE);
3182 comp.jmb.addSequenceForStructFile(pdbFile, seq);
3184 // and add the AlignmentPanel's reference to the Jmol view
3185 comp.addAlignmentPanel(ap);
3186 if (useinJmolsuperpos)
3188 comp.useAlignmentPanelForSuperposition(ap);
3192 comp.excludeAlignmentPanelForSuperposition(ap);
3194 if (usetoColourbyseq)
3196 comp.useAlignmentPanelForColourbyseq(ap, !jmolColouring);
3200 comp.excludeAlignmentPanelForColourbyseq(ap);
3206 // and finally return.
3212 * @param supported - minimum version we are comparing against
3213 * @param version - version of data being processsed.
3214 * @return true if version is development/null or evaluates to the same or
3215 * later X.Y.Z (where X,Y,Z are like [0-9]+b?[0-9]*)
3217 private boolean isVersionStringLaterThan(String supported, String version)
3219 if (version == null || version.equalsIgnoreCase("DEVELOPMENT BUILD")
3220 || version.equalsIgnoreCase("Test") || version.equalsIgnoreCase("AUTOMATED BUILD"))
3222 System.err.println("Assuming project file with "
3223 + (version == null ? "null" : version)
3224 + " is compatible with Jalview version " + supported);
3229 StringTokenizer currentV = new StringTokenizer(supported, "."), fileV = new StringTokenizer(
3231 while (currentV.hasMoreTokens() && fileV.hasMoreTokens())
3233 // convert b to decimal to catch bugfix releases within a series
3234 String curT = currentV.nextToken().toLowerCase().replace('b', '.');
3235 String fileT = fileV.nextToken().toLowerCase().replace('b', '.');
3238 if (Float.valueOf(curT) > Float.valueOf(fileT))
3240 // current version is newer than the version that wrote the file
3243 } catch (NumberFormatException nfe)
3246 .println("** WARNING: Version comparison failed for tokens ("
3250 + ")\n** Current: '"
3251 + supported + "' and Version: '" + version + "'");
3254 if (currentV.hasMoreElements())
3256 // fileV has no minor version but identical series to current
3263 Vector<AppJmol> newStructureViewers = null;
3265 protected void addNewStructureViewer(AppJmol sview)
3267 if (newStructureViewers != null)
3269 sview.jmb.setFinishedLoadingFromArchive(false);
3270 newStructureViewers.add(sview);
3274 protected void setLoadingFinishedForNewStructureViewers()
3276 if (newStructureViewers != null)
3278 for (AppJmol sview : newStructureViewers)
3280 sview.jmb.setFinishedLoadingFromArchive(true);
3282 newStructureViewers.clear();
3283 newStructureViewers = null;
3287 AlignFrame loadViewport(String file, JSeq[] JSEQ, Vector hiddenSeqs,
3288 Alignment al, JalviewModelSequence jms, Viewport view,
3289 String uniqueSeqSetId, String viewId,
3290 ArrayList<JvAnnotRow> autoAlan)
3292 AlignFrame af = null;
3293 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
3294 uniqueSeqSetId, viewId);
3296 af.setFileName(file, "Jalview");
3298 for (int i = 0; i < JSEQ.length; i++)
3300 af.viewport.setSequenceColour(af.viewport.getAlignment()
3301 .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour()));
3304 af.viewport.gatherViewsHere = view.getGatheredViews();
3306 if (view.getSequenceSetId() != null)
3308 jalview.gui.AlignViewport av = (jalview.gui.AlignViewport) viewportsAdded
3309 .get(uniqueSeqSetId);
3311 af.viewport.setSequenceSetId(uniqueSeqSetId);
3314 // propagate shared settings to this new view
3315 af.viewport.historyList = av.historyList;
3316 af.viewport.redoList = av.redoList;
3320 viewportsAdded.put(uniqueSeqSetId, af.viewport);
3322 // TODO: check if this method can be called repeatedly without
3323 // side-effects if alignpanel already registered.
3324 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
3326 // apply Hidden regions to view.
3327 if (hiddenSeqs != null)
3329 for (int s = 0; s < JSEQ.length; s++)
3331 jalview.datamodel.SequenceGroup hidden = new jalview.datamodel.SequenceGroup();
3333 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
3336 al.getSequenceAt(JSEQ[s].getHiddenSequences(r)), false);
3338 af.viewport.hideRepSequences(al.getSequenceAt(s), hidden);
3341 jalview.datamodel.SequenceI[] hseqs = new jalview.datamodel.SequenceI[hiddenSeqs
3344 for (int s = 0; s < hiddenSeqs.size(); s++)
3346 hseqs[s] = (jalview.datamodel.SequenceI) hiddenSeqs.elementAt(s);
3349 af.viewport.hideSequence(hseqs);
3352 // recover view properties and display parameters
3353 if (view.getViewName() != null)
3355 af.viewport.viewName = view.getViewName();
3356 af.setInitialTabVisible();
3358 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
3361 af.viewport.setShowAnnotation(view.getShowAnnotation());
3362 af.viewport.setAbovePIDThreshold(view.getPidSelected());
3364 af.viewport.setColourText(view.getShowColourText());
3366 af.viewport.setConservationSelected(view.getConservationSelected());
3367 af.viewport.setShowJVSuffix(view.getShowFullId());
3368 af.viewport.rightAlignIds = view.getRightAlignIds();
3369 af.viewport.setFont(new java.awt.Font(view.getFontName(), view
3370 .getFontStyle(), view.getFontSize()));
3371 af.alignPanel.fontChanged();
3372 af.viewport.setRenderGaps(view.getRenderGaps());
3373 af.viewport.setWrapAlignment(view.getWrapAlignment());
3374 af.alignPanel.setWrapAlignment(view.getWrapAlignment());
3375 af.viewport.setShowAnnotation(view.getShowAnnotation());
3376 af.alignPanel.setAnnotationVisible(view.getShowAnnotation());
3378 af.viewport.setShowBoxes(view.getShowBoxes());
3380 af.viewport.setShowText(view.getShowText());
3382 af.viewport.textColour = new java.awt.Color(view.getTextCol1());
3383 af.viewport.textColour2 = new java.awt.Color(view.getTextCol2());
3384 af.viewport.thresholdTextColour = view.getTextColThreshold();
3385 af.viewport.setShowUnconserved(view.hasShowUnconserved() ? view
3386 .isShowUnconserved() : false);
3387 af.viewport.setStartRes(view.getStartRes());
3388 af.viewport.setStartSeq(view.getStartSeq());
3390 ColourSchemeI cs = null;
3391 // apply colourschemes
3392 if (view.getBgColour() != null)
3394 if (view.getBgColour().startsWith("ucs"))
3396 cs = GetUserColourScheme(jms, view.getBgColour());
3398 else if (view.getBgColour().startsWith("Annotation"))
3400 AnnotationColours viewAnnColour = view.getAnnotationColours();
3401 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
3408 cs = ColourSchemeProperty.getColour(al, view.getBgColour());
3413 cs.setThreshold(view.getPidThreshold(), true);
3414 cs.setConsensus(af.viewport.getSequenceConsensusHash());
3418 af.viewport.setGlobalColourScheme(cs);
3419 af.viewport.setColourAppliesToAllGroups(false);
3421 if (view.getConservationSelected() && cs != null)
3423 cs.setConservationInc(view.getConsThreshold());
3426 af.changeColour(cs);
3428 af.viewport.setColourAppliesToAllGroups(true);
3430 if (view.getShowSequenceFeatures())
3432 af.viewport.showSequenceFeatures = true;
3434 if (view.hasCentreColumnLabels())
3436 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
3438 if (view.hasIgnoreGapsinConsensus())
3440 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
3443 if (view.hasFollowHighlight())
3445 af.viewport.followHighlight = view.getFollowHighlight();
3447 if (view.hasFollowSelection())
3449 af.viewport.followSelection = view.getFollowSelection();
3451 if (view.hasShowConsensusHistogram())
3453 af.viewport.setShowConsensusHistogram(view
3454 .getShowConsensusHistogram());
3458 af.viewport.setShowConsensusHistogram(true);
3460 if (view.hasShowSequenceLogo())
3462 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
3466 af.viewport.setShowSequenceLogo(false);
3468 if (view.hasNormaliseSequenceLogo())
3470 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
3472 if (view.hasShowDbRefTooltip())
3474 af.viewport.setShowDbRefs(view.getShowDbRefTooltip());
3476 if (view.hasShowNPfeatureTooltip())
3478 af.viewport.setShowNpFeats(view.hasShowNPfeatureTooltip());
3480 if (view.hasShowGroupConsensus())
3482 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
3486 af.viewport.setShowGroupConsensus(false);
3488 if (view.hasShowGroupConservation())
3490 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
3494 af.viewport.setShowGroupConservation(false);
3497 // recover featre settings
3498 if (jms.getFeatureSettings() != null)
3500 af.viewport.featuresDisplayed = new Hashtable();
3501 String[] renderOrder = new String[jms.getFeatureSettings()
3502 .getSettingCount()];
3503 for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
3505 Setting setting = jms.getFeatureSettings().getSetting(fs);
3506 if (setting.hasMincolour())
3508 GraduatedColor gc = setting.hasMin() ? new GraduatedColor(
3509 new java.awt.Color(setting.getMincolour()),
3510 new java.awt.Color(setting.getColour()),
3511 setting.getMin(), setting.getMax()) : new GraduatedColor(
3512 new java.awt.Color(setting.getMincolour()),
3513 new java.awt.Color(setting.getColour()), 0, 1);
3514 if (setting.hasThreshold())
3516 gc.setThresh(setting.getThreshold());
3517 gc.setThreshType(setting.getThreshstate());
3519 gc.setAutoScaled(true); // default
3520 if (setting.hasAutoScale())
3522 gc.setAutoScaled(setting.getAutoScale());
3524 if (setting.hasColourByLabel())
3526 gc.setColourByLabel(setting.getColourByLabel());
3528 // and put in the feature colour table.
3529 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setColour(
3530 setting.getType(), gc);
3534 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setColour(
3536 new java.awt.Color(setting.getColour()));
3538 renderOrder[fs] = setting.getType();
3539 if (setting.hasOrder())
3540 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setOrder(
3541 setting.getType(), setting.getOrder());
3543 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setOrder(
3545 fs / jms.getFeatureSettings().getSettingCount());
3546 if (setting.getDisplay())
3548 af.viewport.featuresDisplayed.put(setting.getType(), new Integer(
3549 setting.getColour()));
3552 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().renderOrder = renderOrder;
3554 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().featureGroups = fgtable = new Hashtable();
3555 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
3557 Group grp = jms.getFeatureSettings().getGroup(gs);
3558 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
3562 if (view.getHiddenColumnsCount() > 0)
3564 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
3566 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(), view
3567 .getHiddenColumns(c).getEnd() // +1
3571 if (view.getCalcIdParam() != null)
3573 for (CalcIdParam calcIdParam : view.getCalcIdParam())
3575 if (calcIdParam != null)
3577 if (recoverCalcIdParam(calcIdParam, af.viewport))
3582 warn("Couldn't recover parameters for "
3583 + calcIdParam.getCalcId());
3588 af.setMenusFromViewport(af.viewport);
3589 // TODO: we don't need to do this if the viewport is aready visible.
3590 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
3592 af.alignPanel.updateAnnotation(false, true); // recompute any autoannotation
3593 reorderAutoannotation(af, al, autoAlan);
3594 af.alignPanel.alignmentChanged();
3598 private ColourSchemeI constructAnnotationColour(
3599 AnnotationColours viewAnnColour, AlignFrame af, Alignment al,
3600 JalviewModelSequence jms, boolean checkGroupAnnColour)
3602 boolean propagateAnnColour = false;
3603 ColourSchemeI cs = null;
3604 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
3605 if (checkGroupAnnColour && al.getGroups() != null
3606 && al.getGroups().size() > 0)
3608 // pre 2.8.1 behaviour
3609 // check to see if we should transfer annotation colours
3610 propagateAnnColour = true;
3611 for (jalview.datamodel.SequenceGroup sg : al.getGroups())
3613 if (sg.cs instanceof AnnotationColourGradient)
3615 propagateAnnColour = false;
3619 // int find annotation
3620 if (annAlignment.getAlignmentAnnotation() != null)
3622 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
3624 if (annAlignment.getAlignmentAnnotation()[i].label
3625 .equals(viewAnnColour.getAnnotation()))
3627 if (annAlignment.getAlignmentAnnotation()[i].getThreshold() == null)
3629 annAlignment.getAlignmentAnnotation()[i]
3630 .setThreshold(new jalview.datamodel.GraphLine(
3631 viewAnnColour.getThreshold(), "Threshold",
3632 java.awt.Color.black)
3637 if (viewAnnColour.getColourScheme().equals("None"))
3639 cs = new AnnotationColourGradient(
3640 annAlignment.getAlignmentAnnotation()[i],
3641 new java.awt.Color(viewAnnColour.getMinColour()),
3642 new java.awt.Color(viewAnnColour.getMaxColour()),
3643 viewAnnColour.getAboveThreshold());
3645 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
3647 cs = new AnnotationColourGradient(
3648 annAlignment.getAlignmentAnnotation()[i],
3649 GetUserColourScheme(jms,
3650 viewAnnColour.getColourScheme()),
3651 viewAnnColour.getAboveThreshold());
3655 cs = new AnnotationColourGradient(
3656 annAlignment.getAlignmentAnnotation()[i],
3657 ColourSchemeProperty.getColour(al,
3658 viewAnnColour.getColourScheme()),
3659 viewAnnColour.getAboveThreshold());
3661 if (viewAnnColour.hasPerSequence())
3663 ((AnnotationColourGradient) cs).setSeqAssociated(viewAnnColour
3666 if (viewAnnColour.hasPredefinedColours())
3668 ((AnnotationColourGradient) cs)
3669 .setPredefinedColours(viewAnnColour
3670 .isPredefinedColours());
3672 if (propagateAnnColour && al.getGroups() != null)
3674 // Also use these settings for all the groups
3675 for (int g = 0; g < al.getGroups().size(); g++)
3677 jalview.datamodel.SequenceGroup sg = al.getGroups().get(g);
3685 * if (viewAnnColour.getColourScheme().equals("None" )) { sg.cs =
3686 * new AnnotationColourGradient(
3687 * annAlignment.getAlignmentAnnotation()[i], new
3688 * java.awt.Color(viewAnnColour. getMinColour()), new
3689 * java.awt.Color(viewAnnColour. getMaxColour()),
3690 * viewAnnColour.getAboveThreshold()); } else
3693 sg.cs = new AnnotationColourGradient(
3694 annAlignment.getAlignmentAnnotation()[i], sg.cs,
3695 viewAnnColour.getAboveThreshold());
3696 if (cs instanceof AnnotationColourGradient)
3698 if (viewAnnColour.hasPerSequence())
3700 ((AnnotationColourGradient) cs)
3701 .setSeqAssociated(viewAnnColour.isPerSequence());
3703 if (viewAnnColour.hasPredefinedColours())
3705 ((AnnotationColourGradient) cs)
3706 .setPredefinedColours(viewAnnColour
3707 .isPredefinedColours());
3723 private void reorderAutoannotation(AlignFrame af, Alignment al,
3724 ArrayList<JvAnnotRow> autoAlan)
3726 // copy over visualization settings for autocalculated annotation in the
3728 if (al.getAlignmentAnnotation() != null)
3731 * Kludge for magic autoannotation names (see JAL-811)
3733 String[] magicNames = new String[]
3734 { "Consensus", "Quality", "Conservation" };
3735 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
3736 Hashtable<String, JvAnnotRow> visan = new Hashtable<String, JvAnnotRow>();
3737 for (String nm : magicNames)
3739 visan.put(nm, nullAnnot);
3741 for (JvAnnotRow auan : autoAlan)
3743 visan.put(auan.template.label
3744 + (auan.template.getCalcId() == null ? "" : "\t"
3745 + auan.template.getCalcId()), auan);
3747 int hSize = al.getAlignmentAnnotation().length;
3748 ArrayList<JvAnnotRow> reorder = new ArrayList<JvAnnotRow>();
3749 // work through any autoCalculated annotation already on the view
3750 // removing it if it should be placed in a different location on the
3751 // annotation panel.
3752 List<String> remains = new ArrayList(visan.keySet());
3753 for (int h = 0; h < hSize; h++)
3755 jalview.datamodel.AlignmentAnnotation jalan = al
3756 .getAlignmentAnnotation()[h];
3757 if (jalan.autoCalculated)
3760 JvAnnotRow valan = visan.get(k = jalan.label);
3761 if (jalan.getCalcId() != null)
3763 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
3768 // delete the auto calculated row from the alignment
3769 al.deleteAnnotation(jalan, false);
3773 if (valan != nullAnnot)
3775 if (jalan != valan.template)
3777 // newly created autoannotation row instance
3778 // so keep a reference to the visible annotation row
3779 // and copy over all relevant attributes
3780 if (valan.template.graphHeight >= 0)
3783 jalan.graphHeight = valan.template.graphHeight;
3785 jalan.visible = valan.template.visible;
3787 reorder.add(new JvAnnotRow(valan.order, jalan));
3792 // Add any (possibly stale) autocalculated rows that were not appended to
3793 // the view during construction
3794 for (String other : remains)
3796 JvAnnotRow othera = visan.get(other);
3797 if (othera != nullAnnot && othera.template.getCalcId() != null
3798 && othera.template.getCalcId().length() > 0)
3800 reorder.add(othera);
3803 // now put the automatic annotation in its correct place
3804 int s = 0, srt[] = new int[reorder.size()];
3805 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
3806 for (JvAnnotRow jvar : reorder)
3809 srt[s++] = jvar.order;
3812 jalview.util.QuickSort.sort(srt, rws);
3813 // and re-insert the annotation at its correct position
3814 for (JvAnnotRow jvar : rws)
3816 al.addAnnotation(jvar.template, jvar.order);
3818 af.alignPanel.adjustAnnotationHeight();
3822 Hashtable skipList = null;
3825 * TODO remove this method
3828 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
3829 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
3830 * throw new Error("Implementation Error. No skipList defined for this
3831 * Jalview2XML instance."); } return (AlignFrame)
3832 * skipList.get(view.getSequenceSetId()); }
3836 * Check if the Jalview view contained in object should be skipped or not.
3839 * @return true if view's sequenceSetId is a key in skipList
3841 private boolean skipViewport(JalviewModel object)
3843 if (skipList == null)
3848 if (skipList.containsKey(id = object.getJalviewModelSequence()
3849 .getViewport()[0].getSequenceSetId()))
3851 if (Cache.log != null && Cache.log.isDebugEnabled())
3853 Cache.log.debug("Skipping seuqence set id " + id);
3860 public void AddToSkipList(AlignFrame af)
3862 if (skipList == null)
3864 skipList = new Hashtable();
3866 skipList.put(af.getViewport().getSequenceSetId(), af);
3869 public void clearSkipList()
3871 if (skipList != null)
3878 private void recoverDatasetFor(SequenceSet vamsasSet, Alignment al)
3880 jalview.datamodel.Alignment ds = getDatasetFor(vamsasSet.getDatasetId());
3881 Vector dseqs = null;
3884 // create a list of new dataset sequences
3885 dseqs = new Vector();
3887 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
3889 Sequence vamsasSeq = vamsasSet.getSequence(i);
3890 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs);
3892 // create a new dataset
3895 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
3896 dseqs.copyInto(dsseqs);
3897 ds = new jalview.datamodel.Alignment(dsseqs);
3898 debug("Created new dataset " + vamsasSet.getDatasetId()
3899 + " for alignment " + System.identityHashCode(al));
3900 addDatasetRef(vamsasSet.getDatasetId(), ds);
3902 // set the dataset for the newly imported alignment.
3903 if (al.getDataset() == null)
3912 * sequence definition to create/merge dataset sequence for
3916 * vector to add new dataset sequence to
3918 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
3919 AlignmentI ds, Vector dseqs)
3921 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
3923 jalview.datamodel.Sequence sq = (jalview.datamodel.Sequence) seqRefIds
3924 .get(vamsasSeq.getId());
3925 jalview.datamodel.SequenceI dsq = null;
3926 if (sq != null && sq.getDatasetSequence() != null)
3928 dsq = sq.getDatasetSequence();
3931 String sqid = vamsasSeq.getDsseqid();
3934 // need to create or add a new dataset sequence reference to this sequence
3937 dsq = (jalview.datamodel.SequenceI) seqRefIds.get(sqid);
3942 // make a new dataset sequence
3943 dsq = sq.createDatasetSequence();
3946 // make up a new dataset reference for this sequence
3947 sqid = seqHash(dsq);
3949 dsq.setVamsasId(uniqueSetSuffix + sqid);
3950 seqRefIds.put(sqid, dsq);
3955 dseqs.addElement(dsq);
3960 ds.addSequence(dsq);
3966 { // make this dataset sequence sq's dataset sequence
3967 sq.setDatasetSequence(dsq);
3968 // and update the current dataset alignment
3973 if (!dseqs.contains(dsq))
3980 if (ds.findIndex(dsq) < 0)
3982 ds.addSequence(dsq);
3989 // TODO: refactor this as a merge dataset sequence function
3990 // now check that sq (the dataset sequence) sequence really is the union of
3991 // all references to it
3992 // boolean pre = sq.getStart() < dsq.getStart();
3993 // boolean post = sq.getEnd() > dsq.getEnd();
3997 StringBuffer sb = new StringBuffer();
3998 String newres = jalview.analysis.AlignSeq.extractGaps(
3999 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
4000 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
4001 && newres.length() > dsq.getLength())
4003 // Update with the longer sequence.
4007 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
4008 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
4009 * sb.append(newres.substring(newres.length() - sq.getEnd() -
4010 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
4012 dsq.setSequence(newres);
4014 // TODO: merges will never happen if we 'know' we have the real dataset
4015 // sequence - this should be detected when id==dssid
4017 .println("DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
4018 // + (pre ? "prepended" : "") + " "
4019 // + (post ? "appended" : ""));
4024 java.util.Hashtable datasetIds = null;
4026 java.util.IdentityHashMap dataset2Ids = null;
4028 private Alignment getDatasetFor(String datasetId)
4030 if (datasetIds == null)
4032 datasetIds = new Hashtable();
4035 if (datasetIds.containsKey(datasetId))
4037 return (Alignment) datasetIds.get(datasetId);
4042 private void addDatasetRef(String datasetId, Alignment dataset)
4044 if (datasetIds == null)
4046 datasetIds = new Hashtable();
4048 datasetIds.put(datasetId, dataset);
4052 * make a new dataset ID for this jalview dataset alignment
4057 private String getDatasetIdRef(jalview.datamodel.Alignment dataset)
4059 if (dataset.getDataset() != null)
4061 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
4063 String datasetId = makeHashCode(dataset, null);
4064 if (datasetId == null)
4066 // make a new datasetId and record it
4067 if (dataset2Ids == null)
4069 dataset2Ids = new IdentityHashMap();
4073 datasetId = (String) dataset2Ids.get(dataset);
4075 if (datasetId == null)
4077 datasetId = "ds" + dataset2Ids.size() + 1;
4078 dataset2Ids.put(dataset, datasetId);
4084 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
4086 for (int d = 0; d < sequence.getDBRefCount(); d++)
4088 DBRef dr = sequence.getDBRef(d);
4089 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
4090 sequence.getDBRef(d).getSource(), sequence.getDBRef(d)
4091 .getVersion(), sequence.getDBRef(d).getAccessionId());
4092 if (dr.getMapping() != null)
4094 entry.setMap(addMapping(dr.getMapping()));
4096 datasetSequence.addDBRef(entry);
4100 private jalview.datamodel.Mapping addMapping(Mapping m)
4102 SequenceI dsto = null;
4103 // Mapping m = dr.getMapping();
4104 int fr[] = new int[m.getMapListFromCount() * 2];
4105 Enumeration f = m.enumerateMapListFrom();
4106 for (int _i = 0; f.hasMoreElements(); _i += 2)
4108 MapListFrom mf = (MapListFrom) f.nextElement();
4109 fr[_i] = mf.getStart();
4110 fr[_i + 1] = mf.getEnd();
4112 int fto[] = new int[m.getMapListToCount() * 2];
4113 f = m.enumerateMapListTo();
4114 for (int _i = 0; f.hasMoreElements(); _i += 2)
4116 MapListTo mf = (MapListTo) f.nextElement();
4117 fto[_i] = mf.getStart();
4118 fto[_i + 1] = mf.getEnd();
4120 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto,
4121 fr, fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
4122 if (m.getMappingChoice() != null)
4124 MappingChoice mc = m.getMappingChoice();
4125 if (mc.getDseqFor() != null)
4127 String dsfor = "" + mc.getDseqFor();
4128 if (seqRefIds.containsKey(dsfor))
4133 jmap.setTo((SequenceI) seqRefIds.get(dsfor));
4137 frefedSequence.add(new Object[]
4144 * local sequence definition
4146 Sequence ms = mc.getSequence();
4147 jalview.datamodel.Sequence djs = null;
4148 String sqid = ms.getDsseqid();
4149 if (sqid != null && sqid.length() > 0)
4152 * recover dataset sequence
4154 djs = (jalview.datamodel.Sequence) seqRefIds.get(sqid);
4159 .println("Warning - making up dataset sequence id for DbRef sequence map reference");
4160 sqid = ((Object) ms).toString(); // make up a new hascode for
4161 // undefined dataset sequence hash
4162 // (unlikely to happen)
4168 * make a new dataset sequence and add it to refIds hash
4170 djs = new jalview.datamodel.Sequence(ms.getName(),
4172 djs.setStart(jmap.getMap().getToLowest());
4173 djs.setEnd(jmap.getMap().getToHighest());
4174 djs.setVamsasId(uniqueSetSuffix + sqid);
4176 seqRefIds.put(sqid, djs);
4179 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
4188 public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
4189 boolean keepSeqRefs)
4192 jalview.schemabinding.version2.JalviewModel jm = SaveState(ap, null,
4198 jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
4202 uniqueSetSuffix = "";
4203 jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
4208 if (this.frefedSequence == null)
4210 frefedSequence = new Vector();
4213 viewportsAdded = new Hashtable();
4215 AlignFrame af = LoadFromObject(jm, null, false, null);
4216 af.alignPanels.clear();
4217 af.closeMenuItem_actionPerformed(true);
4220 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
4221 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
4222 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
4223 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
4224 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
4227 return af.alignPanel;
4231 * flag indicating if hashtables should be cleared on finalization TODO this
4232 * flag may not be necessary
4234 private final boolean _cleartables = true;
4236 private Hashtable jvids2vobj;
4241 * @see java.lang.Object#finalize()
4244 protected void finalize() throws Throwable
4246 // really make sure we have no buried refs left.
4251 this.seqRefIds = null;
4252 this.seqsToIds = null;
4256 private void warn(String msg)
4261 private void warn(String msg, Exception e)
4263 if (Cache.log != null)
4267 Cache.log.warn(msg, e);
4271 Cache.log.warn(msg);
4276 System.err.println("Warning: " + msg);
4279 e.printStackTrace();
4284 private void debug(String string)
4286 debug(string, null);
4289 private void debug(String msg, Exception e)
4291 if (Cache.log != null)
4295 Cache.log.debug(msg, e);
4299 Cache.log.debug(msg);
4304 System.err.println("Warning: " + msg);
4307 e.printStackTrace();
4313 * set the object to ID mapping tables used to write/recover objects and XML
4314 * ID strings for the jalview project. If external tables are provided then
4315 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
4316 * object goes out of scope. - also populates the datasetIds hashtable with
4317 * alignment objects containing dataset sequences
4320 * Map from ID strings to jalview datamodel
4322 * Map from jalview datamodel to ID strings
4326 public void setObjectMappingTables(Hashtable vobj2jv,
4327 IdentityHashMap jv2vobj)
4329 this.jv2vobj = jv2vobj;
4330 this.vobj2jv = vobj2jv;
4331 Iterator ds = jv2vobj.keySet().iterator();
4333 while (ds.hasNext())
4335 Object jvobj = ds.next();
4336 id = jv2vobj.get(jvobj).toString();
4337 if (jvobj instanceof jalview.datamodel.Alignment)
4339 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
4341 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
4344 else if (jvobj instanceof jalview.datamodel.Sequence)
4346 // register sequence object so the XML parser can recover it.
4347 if (seqRefIds == null)
4349 seqRefIds = new Hashtable();
4351 if (seqsToIds == null)
4353 seqsToIds = new IdentityHashMap();
4355 seqRefIds.put(jv2vobj.get(jvobj).toString(), jvobj);
4356 seqsToIds.put(jvobj, id);
4358 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
4360 if (annotationIds == null)
4362 annotationIds = new Hashtable();
4365 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvobj);
4366 jalview.datamodel.AlignmentAnnotation jvann = (jalview.datamodel.AlignmentAnnotation) jvobj;
4367 if (jvann.annotationId == null)
4369 jvann.annotationId = anid;
4371 if (!jvann.annotationId.equals(anid))
4373 // TODO verify that this is the correct behaviour
4374 this.warn("Overriding Annotation ID for " + anid
4375 + " from different id : " + jvann.annotationId);
4376 jvann.annotationId = anid;
4379 else if (jvobj instanceof String)
4381 if (jvids2vobj == null)
4383 jvids2vobj = new Hashtable();
4384 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
4388 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
4393 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
4394 * objects created from the project archive. If string is null (default for
4395 * construction) then suffix will be set automatically.
4399 public void setUniqueSetSuffix(String string)
4401 uniqueSetSuffix = string;
4406 * uses skipList2 as the skipList for skipping views on sequence sets
4407 * associated with keys in the skipList
4411 public void setSkipList(Hashtable skipList2)
4413 skipList = skipList2;