2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.0b1)
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 (object.getJalviewModelSequence().getViewportCount() > 1
1928 && af.viewport.gatherViewsHere)
1930 gatherToThisFrame.put(af.viewport.getSequenceSetId(), af);
1936 else if (jarentry != null)
1938 // Some other file here.
1941 } while (jarentry != null);
1942 resolveFrefedSequences();
1943 } catch (java.io.FileNotFoundException ex)
1945 ex.printStackTrace();
1946 errorMessage = "Couldn't locate Jalview XML file : " + file;
1947 System.err.println("Exception whilst loading jalview XML file : "
1949 } catch (java.net.UnknownHostException ex)
1951 ex.printStackTrace();
1952 errorMessage = "Couldn't locate Jalview XML file : " + file;
1953 System.err.println("Exception whilst loading jalview XML file : "
1955 } catch (Exception ex)
1957 System.err.println("Parsing as Jalview Version 2 file failed.");
1958 ex.printStackTrace(System.err);
1959 if (attemptversion1parse)
1961 // Is Version 1 Jar file?
1964 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
1965 } catch (Exception ex2)
1967 System.err.println("Exception whilst loading as jalviewXMLV1:");
1968 ex2.printStackTrace();
1972 if (Desktop.instance != null)
1974 Desktop.instance.stopLoading();
1978 System.out.println("Successfully loaded archive file");
1981 ex.printStackTrace();
1983 System.err.println("Exception whilst loading jalview XML file : "
1985 } catch (OutOfMemoryError e)
1987 // Don't use the OOM Window here
1988 errorMessage = "Out of memory loading jalview XML file";
1989 System.err.println("Out of memory whilst loading jalview XML file");
1990 e.printStackTrace();
1993 if (Desktop.instance != null)
1995 Desktop.instance.stopLoading();
1998 Enumeration en = gatherToThisFrame.elements();
1999 while (en.hasMoreElements())
2001 Desktop.instance.gatherViews((AlignFrame) en.nextElement());
2003 if (errorMessage != null)
2011 * check errorMessage for a valid error message and raise an error box in the
2012 * GUI or write the current errorMessage to stderr and then clear the error
2015 protected void reportErrors()
2017 reportErrors(false);
2020 protected void reportErrors(final boolean saving)
2022 if (errorMessage != null)
2024 final String finalErrorMessage = errorMessage;
2027 javax.swing.SwingUtilities.invokeLater(new Runnable()
2032 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2033 finalErrorMessage, "Error "
2034 + (saving ? "saving" : "loading")
2035 + " Jalview file", JOptionPane.WARNING_MESSAGE);
2041 System.err.println("Problem loading Jalview file: " + errorMessage);
2044 errorMessage = null;
2047 Hashtable alreadyLoadedPDB;
2050 * when set, local views will be updated from view stored in JalviewXML
2051 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2052 * sync if this is set to true.
2054 private final boolean updateLocalViews = false;
2056 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId)
2058 if (alreadyLoadedPDB == null)
2059 alreadyLoadedPDB = new Hashtable();
2061 if (alreadyLoadedPDB.containsKey(pdbId))
2062 return alreadyLoadedPDB.get(pdbId).toString();
2066 JarInputStream jin = jprovider.getJarInputStream();
2068 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2069 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2070 * FileInputStream(jprovider)); }
2073 JarEntry entry = null;
2076 entry = jin.getNextJarEntry();
2077 } while (entry != null && !entry.getName().equals(pdbId));
2080 BufferedReader in = new BufferedReader(new InputStreamReader(jin));
2081 File outFile = File.createTempFile("jalview_pdb", ".txt");
2082 outFile.deleteOnExit();
2083 PrintWriter out = new PrintWriter(new FileOutputStream(outFile));
2086 while ((data = in.readLine()) != null)
2093 } catch (Exception foo)
2098 String t = outFile.getAbsolutePath();
2099 alreadyLoadedPDB.put(pdbId, t);
2104 warn("Couldn't find PDB file entry in Jalview Jar for " + pdbId);
2106 } catch (Exception ex)
2108 ex.printStackTrace();
2114 private class JvAnnotRow
2116 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2123 * persisted version of annotation row from which to take vis properties
2125 public jalview.datamodel.AlignmentAnnotation template;
2128 * original position of the annotation row in the alignment
2134 * Load alignment frame from jalview XML DOM object
2139 * filename source string
2140 * @param loadTreesAndStructures
2141 * when false only create Viewport
2143 * data source provider
2144 * @return alignment frame created from view stored in DOM
2146 AlignFrame LoadFromObject(JalviewModel object, String file,
2147 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
2149 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
2150 Sequence[] vamsasSeq = vamsasSet.getSequence();
2152 JalviewModelSequence jms = object.getJalviewModelSequence();
2154 Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
2157 // ////////////////////////////////
2160 Vector hiddenSeqs = null;
2161 jalview.datamodel.Sequence jseq;
2163 ArrayList tmpseqs = new ArrayList();
2165 boolean multipleView = false;
2167 JSeq[] JSEQ = object.getJalviewModelSequence().getJSeq();
2168 int vi = 0; // counter in vamsasSeq array
2169 for (int i = 0; i < JSEQ.length; i++)
2171 String seqId = JSEQ[i].getId();
2173 if (seqRefIds.get(seqId) != null)
2175 tmpseqs.add(seqRefIds.get(seqId));
2176 multipleView = true;
2180 jseq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
2181 vamsasSeq[vi].getSequence());
2182 jseq.setDescription(vamsasSeq[vi].getDescription());
2183 jseq.setStart(JSEQ[i].getStart());
2184 jseq.setEnd(JSEQ[i].getEnd());
2185 jseq.setVamsasId(uniqueSetSuffix + seqId);
2186 seqRefIds.put(vamsasSeq[vi].getId(), jseq);
2191 if (JSEQ[i].getHidden())
2193 if (hiddenSeqs == null)
2195 hiddenSeqs = new Vector();
2198 hiddenSeqs.addElement(seqRefIds.get(seqId));
2204 // Create the alignment object from the sequence set
2205 // ///////////////////////////////
2206 jalview.datamodel.Sequence[] orderedSeqs = new jalview.datamodel.Sequence[tmpseqs
2209 tmpseqs.toArray(orderedSeqs);
2211 jalview.datamodel.Alignment al = new jalview.datamodel.Alignment(
2214 // / Add the alignment properties
2215 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
2217 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
2218 al.setProperty(ssp.getKey(), ssp.getValue());
2222 // SequenceFeatures are added to the DatasetSequence,
2223 // so we must create or recover the dataset before loading features
2224 // ///////////////////////////////
2225 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
2227 // older jalview projects do not have a dataset id.
2228 al.setDataset(null);
2232 recoverDatasetFor(vamsasSet, al);
2234 // ///////////////////////////////
2236 Hashtable pdbloaded = new Hashtable();
2239 // load sequence features, database references and any associated PDB
2240 // structures for the alignment
2241 for (int i = 0; i < vamsasSeq.length; i++)
2243 if (JSEQ[i].getFeaturesCount() > 0)
2245 Features[] features = JSEQ[i].getFeatures();
2246 for (int f = 0; f < features.length; f++)
2248 jalview.datamodel.SequenceFeature sf = new jalview.datamodel.SequenceFeature(
2249 features[f].getType(), features[f].getDescription(),
2250 features[f].getStatus(), features[f].getBegin(),
2251 features[f].getEnd(), features[f].getFeatureGroup());
2253 sf.setScore(features[f].getScore());
2254 for (int od = 0; od < features[f].getOtherDataCount(); od++)
2256 OtherData keyValue = features[f].getOtherData(od);
2257 if (keyValue.getKey().startsWith("LINK"))
2259 sf.addLink(keyValue.getValue());
2263 sf.setValue(keyValue.getKey(), keyValue.getValue());
2268 al.getSequenceAt(i).getDatasetSequence().addSequenceFeature(sf);
2271 if (vamsasSeq[i].getDBRefCount() > 0)
2273 addDBRefs(al.getSequenceAt(i).getDatasetSequence(), vamsasSeq[i]);
2275 if (JSEQ[i].getPdbidsCount() > 0)
2277 Pdbids[] ids = JSEQ[i].getPdbids();
2278 for (int p = 0; p < ids.length; p++)
2280 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
2281 entry.setId(ids[p].getId());
2282 entry.setType(ids[p].getType());
2283 if (ids[p].getFile() != null)
2285 if (!pdbloaded.containsKey(ids[p].getFile()))
2287 entry.setFile(loadPDBFile(jprovider, ids[p].getId()));
2291 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
2295 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
2299 } // end !multipleview
2301 // ///////////////////////////////
2302 // LOAD SEQUENCE MAPPINGS
2304 if (vamsasSet.getAlcodonFrameCount() > 0)
2306 // TODO Potentially this should only be done once for all views of an
2308 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
2309 for (int i = 0; i < alc.length; i++)
2311 jalview.datamodel.AlignedCodonFrame cf = new jalview.datamodel.AlignedCodonFrame(
2312 alc[i].getAlcodonCount());
2313 if (alc[i].getAlcodonCount() > 0)
2315 Alcodon[] alcods = alc[i].getAlcodon();
2316 for (int p = 0; p < cf.codons.length; p++)
2318 if (alcods[p].hasPos1() && alcods[p].hasPos2()
2319 && alcods[p].hasPos3())
2321 // translated codons require three valid positions
2322 cf.codons[p] = new int[3];
2323 cf.codons[p][0] = (int) alcods[p].getPos1();
2324 cf.codons[p][1] = (int) alcods[p].getPos2();
2325 cf.codons[p][2] = (int) alcods[p].getPos3();
2329 cf.codons[p] = null;
2333 if (alc[i].getAlcodMapCount() > 0)
2335 AlcodMap[] maps = alc[i].getAlcodMap();
2336 for (int m = 0; m < maps.length; m++)
2338 SequenceI dnaseq = (SequenceI) seqRefIds
2339 .get(maps[m].getDnasq());
2341 jalview.datamodel.Mapping mapping = null;
2342 // attach to dna sequence reference.
2343 if (maps[m].getMapping() != null)
2345 mapping = addMapping(maps[m].getMapping());
2349 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
2354 frefedSequence.add(new Object[]
2355 { maps[m].getDnasq(), cf, mapping });
2359 al.addCodonFrame(cf);
2364 // ////////////////////////////////
2366 ArrayList<JvAnnotRow> autoAlan = new ArrayList<JvAnnotRow>();
2368 * store any annotations which forward reference a group's ID
2370 Hashtable<String, ArrayList<jalview.datamodel.AlignmentAnnotation>> groupAnnotRefs = new Hashtable<String, ArrayList<jalview.datamodel.AlignmentAnnotation>>();
2372 if (vamsasSet.getAnnotationCount() > 0)
2374 Annotation[] an = vamsasSet.getAnnotation();
2376 for (int i = 0; i < an.length; i++)
2379 * test if annotation is automatically calculated for this view only
2381 boolean autoForView = false;
2382 if (an[i].getLabel().equals("Quality")
2383 || an[i].getLabel().equals("Conservation")
2384 || an[i].getLabel().equals("Consensus"))
2386 // Kludge for pre 2.5 projects which lacked the autocalculated flag
2388 if (!an[i].hasAutoCalculated())
2390 an[i].setAutoCalculated(true);
2394 || (an[i].hasAutoCalculated() && an[i].isAutoCalculated()))
2396 // remove ID - we don't recover annotation from other views for
2397 // view-specific annotation
2401 // set visiblity for other annotation in this view
2402 if (an[i].getId() != null
2403 && annotationIds.containsKey(an[i].getId()))
2405 jalview.datamodel.AlignmentAnnotation jda = (jalview.datamodel.AlignmentAnnotation) annotationIds
2406 .get(an[i].getId());
2407 // in principle Visible should always be true for annotation displayed
2408 // in multiple views
2409 if (an[i].hasVisible())
2410 jda.visible = an[i].getVisible();
2412 al.addAnnotation(jda);
2416 // Construct new annotation from model.
2417 AnnotationElement[] ae = an[i].getAnnotationElement();
2418 jalview.datamodel.Annotation[] anot = null;
2419 java.awt.Color firstColour = null;
2421 if (!an[i].getScoreOnly())
2423 anot = new jalview.datamodel.Annotation[al.getWidth()];
2424 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
2426 anpos = ae[aa].getPosition();
2428 if (anpos >= anot.length)
2431 anot[anpos] = new jalview.datamodel.Annotation(
2433 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
2434 (ae[aa].getSecondaryStructure() == null || ae[aa]
2435 .getSecondaryStructure().length() == 0) ? ' '
2436 : ae[aa].getSecondaryStructure().charAt(0),
2440 // JBPNote: Consider verifying dataflow for IO of secondary
2441 // structure annotation read from Stockholm files
2442 // this was added to try to ensure that
2443 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
2445 // anot[ae[aa].getPosition()].displayCharacter = "";
2447 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
2448 if (firstColour == null)
2450 firstColour = anot[anpos].colour;
2454 jalview.datamodel.AlignmentAnnotation jaa = null;
2456 if (an[i].getGraph())
2458 float llim = 0, hlim = 0;
2459 // if (autoForView || an[i].isAutoCalculated()) {
2462 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
2463 an[i].getDescription(), anot, llim, hlim,
2464 an[i].getGraphType());
2466 jaa.graphGroup = an[i].getGraphGroup();
2467 jaa._linecolour = firstColour;
2468 if (an[i].getThresholdLine() != null)
2470 jaa.setThreshold(new jalview.datamodel.GraphLine(an[i]
2471 .getThresholdLine().getValue(), an[i]
2472 .getThresholdLine().getLabel(), new java.awt.Color(
2473 an[i].getThresholdLine().getColour())));
2476 if (autoForView || an[i].isAutoCalculated())
2478 // Hardwire the symbol display line to ensure that labels for
2479 // histograms are displayed
2485 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
2486 an[i].getDescription(), anot);
2487 jaa._linecolour = firstColour;
2489 // register new annotation
2490 if (an[i].getId() != null)
2492 annotationIds.put(an[i].getId(), jaa);
2493 jaa.annotationId = an[i].getId();
2495 // recover sequence association
2496 if (an[i].getSequenceRef() != null)
2498 if (al.findName(an[i].getSequenceRef()) != null)
2500 jaa.createSequenceMapping(al.findName(an[i].getSequenceRef()),
2502 al.findName(an[i].getSequenceRef()).addAlignmentAnnotation(jaa);
2505 // and make a note of any group association
2506 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
2508 ArrayList<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
2509 .get(an[i].getGroupRef());
2512 aal = new ArrayList<jalview.datamodel.AlignmentAnnotation>();
2513 groupAnnotRefs.put(an[i].getGroupRef(), aal);
2518 if (an[i].hasScore())
2520 jaa.setScore(an[i].getScore());
2522 if (an[i].hasVisible())
2523 jaa.visible = an[i].getVisible();
2525 if (an[i].hasCentreColLabels())
2526 jaa.centreColLabels = an[i].getCentreColLabels();
2528 if (an[i].hasScaleColLabels())
2530 jaa.scaleColLabel = an[i].getScaleColLabels();
2532 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
2534 // newer files have an 'autoCalculated' flag and store calculation
2535 // state in viewport properties
2536 jaa.autoCalculated = true; // means annotation will be marked for
2537 // update at end of load.
2539 if (an[i].hasGraphHeight())
2541 jaa.graphHeight = an[i].getGraphHeight();
2543 if (an[i].hasBelowAlignment())
2545 jaa.belowAlignment = an[i].isBelowAlignment();
2547 jaa.setCalcId(an[i].getCalcId());
2549 if (jaa.autoCalculated)
2551 autoAlan.add(new JvAnnotRow(i, jaa));
2554 // if (!autoForView)
2556 // add autocalculated group annotation and any user created annotation
2558 al.addAnnotation(jaa);
2562 // ///////////////////////
2564 // Create alignment markup and styles for this view
2565 if (jms.getJGroupCount() > 0)
2567 JGroup[] groups = jms.getJGroup();
2568 boolean addAnnotSchemeGroup = false;
2569 for (int i = 0; i < groups.length; i++)
2571 ColourSchemeI cs = null;
2573 if (groups[i].getColour() != null)
2575 if (groups[i].getColour().startsWith("ucs"))
2577 cs = GetUserColourScheme(jms, groups[i].getColour());
2579 else if (groups[i].getColour().equals("AnnotationColourGradient")
2580 && groups[i].getAnnotationColours() != null)
2582 addAnnotSchemeGroup = true;
2587 cs = ColourSchemeProperty.getColour(al, groups[i].getColour());
2592 cs.setThreshold(groups[i].getPidThreshold(), true);
2596 Vector seqs = new Vector();
2598 for (int s = 0; s < groups[i].getSeqCount(); s++)
2600 String seqId = groups[i].getSeq(s) + "";
2601 jalview.datamodel.SequenceI ts = (jalview.datamodel.SequenceI) seqRefIds
2606 seqs.addElement(ts);
2610 if (seqs.size() < 1)
2615 jalview.datamodel.SequenceGroup sg = new jalview.datamodel.SequenceGroup(
2616 seqs, groups[i].getName(), cs, groups[i].getDisplayBoxes(),
2617 groups[i].getDisplayText(), groups[i].getColourText(),
2618 groups[i].getStart(), groups[i].getEnd());
2620 sg.setOutlineColour(new java.awt.Color(groups[i].getOutlineColour()));
2622 sg.textColour = new java.awt.Color(groups[i].getTextCol1());
2623 sg.textColour2 = new java.awt.Color(groups[i].getTextCol2());
2624 sg.setShowNonconserved(groups[i].hasShowUnconserved() ? groups[i]
2625 .isShowUnconserved() : false);
2626 sg.thresholdTextColour = groups[i].getTextColThreshold();
2627 if (groups[i].hasShowConsensusHistogram())
2629 sg.setShowConsensusHistogram(groups[i].isShowConsensusHistogram());
2632 if (groups[i].hasShowSequenceLogo())
2634 sg.setshowSequenceLogo(groups[i].isShowSequenceLogo());
2636 if (groups[i].hasNormaliseSequenceLogo())
2638 sg.setNormaliseSequenceLogo(groups[i].isNormaliseSequenceLogo());
2640 if (groups[i].hasIgnoreGapsinConsensus())
2642 sg.setIgnoreGapsConsensus(groups[i].getIgnoreGapsinConsensus());
2644 if (groups[i].getConsThreshold() != 0)
2646 jalview.analysis.Conservation c = new jalview.analysis.Conservation(
2647 "All", ResidueProperties.propHash, 3,
2648 sg.getSequences(null), 0, sg.getWidth() - 1);
2650 c.verdict(false, 25);
2651 sg.cs.setConservation(c);
2654 if (groups[i].getId() != null && groupAnnotRefs.size() > 0)
2656 // re-instate unique group/annotation row reference
2657 ArrayList<jalview.datamodel.AlignmentAnnotation> jaal = groupAnnotRefs
2658 .get(groups[i].getId());
2661 for (jalview.datamodel.AlignmentAnnotation jaa : jaal)
2664 if (jaa.autoCalculated)
2666 // match up and try to set group autocalc alignment row for this
2668 if (jaa.label.startsWith("Consensus for "))
2670 sg.setConsensus(jaa);
2672 // match up and try to set group autocalc alignment row for this
2674 if (jaa.label.startsWith("Conservation for "))
2676 sg.setConservationRow(jaa);
2683 if (addAnnotSchemeGroup)
2685 // reconstruct the annotation colourscheme
2686 sg.cs = constructAnnotationColour(
2687 groups[i].getAnnotationColours(), null, al, jms, false);
2693 // only dataset in this model, so just return.
2696 // ///////////////////////////////
2699 // If we just load in the same jar file again, the sequenceSetId
2700 // will be the same, and we end up with multiple references
2701 // to the same sequenceSet. We must modify this id on load
2702 // so that each load of the file gives a unique id
2703 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
2704 String viewId = (view.getId() == null ? null : view.getId()
2706 AlignFrame af = null;
2707 AlignViewport av = null;
2708 // now check to see if we really need to create a new viewport.
2709 if (multipleView && viewportsAdded.size() == 0)
2711 // We recovered an alignment for which a viewport already exists.
2712 // TODO: fix up any settings necessary for overlaying stored state onto
2713 // state recovered from another document. (may not be necessary).
2714 // we may need a binding from a viewport in memory to one recovered from
2716 // and then recover its containing af to allow the settings to be applied.
2717 // TODO: fix for vamsas demo
2719 .println("About to recover a viewport for existing alignment: Sequence set ID is "
2721 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
2722 if (seqsetobj != null)
2724 if (seqsetobj instanceof String)
2726 uniqueSeqSetId = (String) seqsetobj;
2728 .println("Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
2734 .println("Warning : Collision between sequence set ID string and existing jalview object mapping.");
2740 * indicate that annotation colours are applied across all groups (pre
2741 * Jalview 2.8.1 behaviour)
2743 boolean doGroupAnnColour = isVersionStringLaterThan("2.8.1",
2744 object.getVersion());
2746 AlignmentPanel ap = null;
2747 boolean isnewview = true;
2750 // Check to see if this alignment already has a view id == viewId
2751 jalview.gui.AlignmentPanel views[] = Desktop
2752 .getAlignmentPanels(uniqueSeqSetId);
2753 if (views != null && views.length > 0)
2755 for (int v = 0; v < views.length; v++)
2757 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
2759 // recover the existing alignpanel, alignframe, viewport
2760 af = views[v].alignFrame;
2763 // TODO: could even skip resetting view settings if we don't want to
2764 // change the local settings from other jalview processes
2773 af = loadViewport(file, JSEQ, hiddenSeqs, al, jms, view,
2774 uniqueSeqSetId, viewId, autoAlan);
2779 // /////////////////////////////////////
2780 if (loadTreesAndStructures && jms.getTreeCount() > 0)
2784 for (int t = 0; t < jms.getTreeCount(); t++)
2787 Tree tree = jms.getTree(t);
2789 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
2792 tp = af.ShowNewickTree(
2793 new jalview.io.NewickFile(tree.getNewick()),
2794 tree.getTitle(), tree.getWidth(), tree.getHeight(),
2795 tree.getXpos(), tree.getYpos());
2796 if (tree.getId() != null)
2798 // perhaps bind the tree id to something ?
2803 // update local tree attributes ?
2804 // TODO: should check if tp has been manipulated by user - if so its
2805 // settings shouldn't be modified
2806 tp.setTitle(tree.getTitle());
2807 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(), tree
2808 .getWidth(), tree.getHeight()));
2809 tp.av = av; // af.viewport; // TODO: verify 'associate with all
2812 tp.treeCanvas.av = av; // af.viewport;
2813 tp.treeCanvas.ap = ap; // af.alignPanel;
2818 warn("There was a problem recovering stored Newick tree: \n"
2819 + tree.getNewick());
2823 tp.fitToWindow.setState(tree.getFitToWindow());
2824 tp.fitToWindow_actionPerformed(null);
2826 if (tree.getFontName() != null)
2828 tp.setTreeFont(new java.awt.Font(tree.getFontName(), tree
2829 .getFontStyle(), tree.getFontSize()));
2833 tp.setTreeFont(new java.awt.Font(view.getFontName(), view
2834 .getFontStyle(), tree.getFontSize()));
2837 tp.showPlaceholders(tree.getMarkUnlinked());
2838 tp.showBootstrap(tree.getShowBootstrap());
2839 tp.showDistances(tree.getShowDistances());
2841 tp.treeCanvas.threshold = tree.getThreshold();
2843 if (tree.getCurrentTree())
2845 af.viewport.setCurrentTree(tp.getTree());
2849 } catch (Exception ex)
2851 ex.printStackTrace();
2855 // //LOAD STRUCTURES
2856 if (loadTreesAndStructures)
2858 // run through all PDB ids on the alignment, and collect mappings between
2859 // jmol view ids and all sequences referring to it
2860 Hashtable<String, Object[]> jmolViewIds = new Hashtable();
2862 for (int i = 0; i < JSEQ.length; i++)
2864 if (JSEQ[i].getPdbidsCount() > 0)
2866 Pdbids[] ids = JSEQ[i].getPdbids();
2867 for (int p = 0; p < ids.length; p++)
2869 for (int s = 0; s < ids[p].getStructureStateCount(); s++)
2871 // check to see if we haven't already created this structure view
2872 String sviewid = (ids[p].getStructureState(s).getViewId() == null) ? null
2873 : ids[p].getStructureState(s).getViewId()
2875 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
2876 // Originally : ids[p].getFile()
2877 // : TODO: verify external PDB file recovery still works in normal
2878 // jalview project load
2879 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId()));
2880 jpdb.setId(ids[p].getId());
2882 int x = ids[p].getStructureState(s).getXpos();
2883 int y = ids[p].getStructureState(s).getYpos();
2884 int width = ids[p].getStructureState(s).getWidth();
2885 int height = ids[p].getStructureState(s).getHeight();
2887 // Probably don't need to do this anymore...
2888 // Desktop.desktop.getComponentAt(x, y);
2889 // TODO: NOW: check that this recovers the PDB file correctly.
2890 String pdbFile = loadPDBFile(jprovider, ids[p].getId());
2891 jalview.datamodel.SequenceI seq = (jalview.datamodel.SequenceI) seqRefIds
2892 .get(JSEQ[i].getId() + "");
2893 if (sviewid == null)
2895 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width
2898 if (!jmolViewIds.containsKey(sviewid))
2900 jmolViewIds.put(sviewid, new Object[]
2902 { x, y, width, height }, "",
2903 new Hashtable<String, Object[]>(), new boolean[]
2904 { false, false, true } });
2905 // Legacy pre-2.7 conversion JAL-823 :
2906 // do not assume any view has to be linked for colour by
2910 // assemble String[] { pdb files }, String[] { id for each
2911 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
2912 // seqs_file 2}, boolean[] {
2913 // linkAlignPanel,superposeWithAlignpanel}} from hash
2914 Object[] jmoldat = jmolViewIds.get(sviewid);
2915 ((boolean[]) jmoldat[3])[0] |= ids[p].getStructureState(s)
2916 .hasAlignwithAlignPanel() ? ids[p].getStructureState(
2917 s).getAlignwithAlignPanel() : false;
2918 // never colour by linked panel if not specified
2919 ((boolean[]) jmoldat[3])[1] |= ids[p].getStructureState(s)
2920 .hasColourwithAlignPanel() ? ids[p]
2921 .getStructureState(s).getColourwithAlignPanel()
2923 // default for pre-2.7 projects is that Jmol colouring is enabled
2924 ((boolean[]) jmoldat[3])[2] &= ids[p].getStructureState(s)
2925 .hasColourByJmol() ? ids[p].getStructureState(s)
2926 .getColourByJmol() : true;
2928 if (((String) jmoldat[1]).length() < ids[p]
2929 .getStructureState(s).getContent().length())
2932 jmoldat[1] = ids[p].getStructureState(s).getContent();
2935 if (ids[p].getFile() != null)
2937 File mapkey = new File(ids[p].getFile());
2938 Object[] seqstrmaps = (Object[]) ((Hashtable) jmoldat[2])
2940 if (seqstrmaps == null)
2942 ((Hashtable) jmoldat[2]).put(mapkey,
2943 seqstrmaps = new Object[]
2944 { pdbFile, ids[p].getId(), new Vector(),
2947 if (!((Vector) seqstrmaps[2]).contains(seq))
2949 ((Vector) seqstrmaps[2]).addElement(seq);
2950 // ((Vector)seqstrmaps[3]).addElement(n) :
2951 // in principle, chains
2952 // should be stored here : do we need to
2953 // TODO: store and recover seq/pdb_id :
2959 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");
2968 // Instantiate the associated Jmol views
2969 for (Entry<String, Object[]> entry : jmolViewIds.entrySet())
2971 String sviewid = entry.getKey();
2972 Object[] svattrib = entry.getValue();
2973 int[] geom = (int[]) svattrib[0];
2974 String state = (String) svattrib[1];
2975 Hashtable<File, Object[]> oldFiles = (Hashtable<File, Object[]>) svattrib[2];
2976 final boolean useinJmolsuperpos = ((boolean[]) svattrib[3])[0], usetoColourbyseq = ((boolean[]) svattrib[3])[1], jmolColouring = ((boolean[]) svattrib[3])[2];
2977 int x = geom[0], y = geom[1], width = geom[2], height = geom[3];
2978 // collate the pdbfile -> sequence mappings from this view
2979 Vector<String> pdbfilenames = new Vector<String>();
2980 Vector<SequenceI[]> seqmaps = new Vector<SequenceI[]>();
2981 Vector<String> pdbids = new Vector<String>();
2983 // Search to see if we've already created this Jmol view
2984 AppJmol comp = null;
2985 JInternalFrame[] frames = null;
2990 frames = Desktop.desktop.getAllFrames();
2991 } catch (ArrayIndexOutOfBoundsException e)
2993 // occasional No such child exceptions are thrown here...
2998 } catch (Exception f)
3003 } while (frames == null);
3004 // search for any Jmol windows already open from other
3005 // alignment views that exactly match the stored structure state
3006 for (int f = 0; comp == null && f < frames.length; f++)
3008 if (frames[f] instanceof AppJmol)
3011 && ((AppJmol) frames[f]).getViewId().equals(sviewid))
3013 // post jalview 2.4 schema includes structure view id
3014 comp = (AppJmol) frames[f];
3016 else if (frames[f].getX() == x && frames[f].getY() == y
3017 && frames[f].getHeight() == height
3018 && frames[f].getWidth() == width)
3020 comp = (AppJmol) frames[f];
3027 // create a new Jmol window.
3028 // First parse the Jmol state to translate filenames loaded into the
3029 // view, and record the order in which files are shown in the Jmol
3030 // view, so we can add the sequence mappings in same order.
3031 StringBuffer newFileLoc = null;
3032 int cp = 0, ncp, ecp;
3033 while ((ncp = state.indexOf("load ", cp)) > -1)
3035 if (newFileLoc == null)
3037 newFileLoc = new StringBuffer();
3041 // look for next filename in load statement
3042 newFileLoc.append(state.substring(cp,
3043 ncp = (state.indexOf("\"", ncp + 1) + 1)));
3044 String oldfilenam = state.substring(ncp,
3045 ecp = state.indexOf("\"", ncp));
3046 // recover the new mapping data for this old filename
3047 // have to normalize filename - since Jmol and jalview do
3049 // translation differently.
3050 Object[] filedat = oldFiles.get(new File(oldfilenam));
3051 newFileLoc.append(Platform
3052 .escapeString((String) filedat[0]));
3053 pdbfilenames.addElement((String) filedat[0]);
3054 pdbids.addElement((String) filedat[1]);
3055 seqmaps.addElement(((Vector<SequenceI>) filedat[2])
3056 .toArray(new SequenceI[0]));
3057 newFileLoc.append("\"");
3058 cp = ecp + 1; // advance beyond last \" and set cursor so we can
3059 // look for next file statement.
3060 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
3064 // just append rest of state
3065 newFileLoc.append(state.substring(cp));
3070 .print("Ignoring incomplete Jmol state for PDB ids: ");
3071 newFileLoc = new StringBuffer(state);
3072 newFileLoc.append("; load append ");
3073 for (File id : oldFiles.keySet())
3075 // add this and any other pdb files that should be present in
3077 Object[] filedat = oldFiles.get(id);
3079 newFileLoc.append(((String) filedat[0]));
3080 pdbfilenames.addElement((String) filedat[0]);
3081 pdbids.addElement((String) filedat[1]);
3082 seqmaps.addElement(((Vector<SequenceI>) filedat[2])
3083 .toArray(new SequenceI[0]));
3084 newFileLoc.append(" \"");
3085 newFileLoc.append((String) filedat[0]);
3086 newFileLoc.append("\"");
3089 newFileLoc.append(";");
3092 if (newFileLoc != null)
3094 int histbug = newFileLoc.indexOf("history = ");
3096 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";",
3098 String val = (diff == -1) ? null : newFileLoc.substring(
3100 if (val != null && val.length() >= 4)
3102 if (val.contains("e"))
3104 if (val.trim().equals("true"))
3112 newFileLoc.replace(histbug, diff, val);
3115 // TODO: assemble String[] { pdb files }, String[] { id for each
3116 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3117 // seqs_file 2}} from hash
3118 final String[] pdbf = pdbfilenames
3119 .toArray(new String[pdbfilenames.size()]), id = pdbids
3120 .toArray(new String[pdbids.size()]);
3121 final SequenceI[][] sq = seqmaps
3122 .toArray(new SequenceI[seqmaps.size()][]);
3123 final String fileloc = newFileLoc.toString(), vid = sviewid;
3124 final AlignFrame alf = af;
3125 final java.awt.Rectangle rect = new java.awt.Rectangle(x, y,
3129 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
3134 AppJmol sview = null;
3137 sview = new AppJmol(pdbf, id, sq, alf.alignPanel,
3138 useinJmolsuperpos, usetoColourbyseq,
3139 jmolColouring, fileloc, rect, vid);
3140 addNewStructureViewer(sview);
3141 } catch (OutOfMemoryError ex)
3143 new OOMWarning("restoring structure view for PDB id "
3144 + id, (OutOfMemoryError) ex.getCause());
3145 if (sview != null && sview.isVisible())
3147 sview.closeViewer();
3148 sview.setVisible(false);
3154 } catch (InvocationTargetException ex)
3156 warn("Unexpected error when opening Jmol view.", ex);
3158 } catch (InterruptedException e)
3160 // e.printStackTrace();
3166 // if (comp != null)
3168 // NOTE: if the jalview project is part of a shared session then
3169 // view synchronization should/could be done here.
3171 // add mapping for sequences in this view to an already open Jmol
3173 for (File id : oldFiles.keySet())
3175 // add this and any other pdb files that should be present in the
3177 Object[] filedat = oldFiles.get(id);
3178 String pdbFile = (String) filedat[0];
3179 SequenceI[] seq = ((Vector<SequenceI>) filedat[2])
3180 .toArray(new SequenceI[0]);
3181 comp.jmb.ssm.setMapping(seq, null, pdbFile,
3182 jalview.io.AppletFormatAdapter.FILE);
3183 comp.jmb.addSequenceForStructFile(pdbFile, seq);
3185 // and add the AlignmentPanel's reference to the Jmol view
3186 comp.addAlignmentPanel(ap);
3187 if (useinJmolsuperpos)
3189 comp.useAlignmentPanelForSuperposition(ap);
3193 comp.excludeAlignmentPanelForSuperposition(ap);
3195 if (usetoColourbyseq)
3197 comp.useAlignmentPanelForColourbyseq(ap, !jmolColouring);
3201 comp.excludeAlignmentPanelForColourbyseq(ap);
3207 // and finally return.
3213 * @param supported - minimum version we are comparing against
3214 * @param version - version of data being processsed.
3215 * @return true if version is development/null or evaluates to the same or
3216 * later X.Y.Z (where X,Y,Z are like [0-9]+b?[0-9]*)
3218 private boolean isVersionStringLaterThan(String supported, String version)
3220 if (version == null || version.equalsIgnoreCase("DEVELOPMENT BUILD")
3221 || version.equalsIgnoreCase("Test"))
3223 System.err.println("Assuming project file with "
3224 + (version == null ? "null" : version)
3225 + " is compatible with Jalview version " + supported);
3230 StringTokenizer currentV = new StringTokenizer(supported, "."), fileV = new StringTokenizer(
3232 while (currentV.hasMoreTokens() && fileV.hasMoreTokens())
3234 // convert b to decimal to catch bugfix releases within a series
3235 String curT = currentV.nextToken().toLowerCase().replace('b', '.');
3236 String fileT = fileV.nextToken().toLowerCase().replace('b', '.');
3239 if (Float.valueOf(curT) > Float.valueOf(fileT))
3241 // current version is newer than the version that wrote the file
3244 } catch (NumberFormatException nfe)
3247 .println("** WARNING: Version comparison failed for tokens ("
3251 + ")\n** Current: '"
3252 + supported + "' and Version: '" + version + "'");
3255 if (currentV.hasMoreElements())
3257 // fileV has no minor version but identical series to current
3264 Vector<AppJmol> newStructureViewers = null;
3266 protected void addNewStructureViewer(AppJmol sview)
3268 if (newStructureViewers != null)
3270 sview.jmb.setFinishedLoadingFromArchive(false);
3271 newStructureViewers.add(sview);
3275 protected void setLoadingFinishedForNewStructureViewers()
3277 if (newStructureViewers != null)
3279 for (AppJmol sview : newStructureViewers)
3281 sview.jmb.setFinishedLoadingFromArchive(true);
3283 newStructureViewers.clear();
3284 newStructureViewers = null;
3288 AlignFrame loadViewport(String file, JSeq[] JSEQ, Vector hiddenSeqs,
3289 Alignment al, JalviewModelSequence jms, Viewport view,
3290 String uniqueSeqSetId, String viewId,
3291 ArrayList<JvAnnotRow> autoAlan)
3293 AlignFrame af = null;
3294 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
3295 uniqueSeqSetId, viewId);
3297 af.setFileName(file, "Jalview");
3299 for (int i = 0; i < JSEQ.length; i++)
3301 af.viewport.setSequenceColour(af.viewport.getAlignment()
3302 .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour()));
3305 af.viewport.gatherViewsHere = view.getGatheredViews();
3307 if (view.getSequenceSetId() != null)
3309 jalview.gui.AlignViewport av = (jalview.gui.AlignViewport) viewportsAdded
3310 .get(uniqueSeqSetId);
3312 af.viewport.setSequenceSetId(uniqueSeqSetId);
3315 // propagate shared settings to this new view
3316 af.viewport.historyList = av.historyList;
3317 af.viewport.redoList = av.redoList;
3321 viewportsAdded.put(uniqueSeqSetId, af.viewport);
3323 // TODO: check if this method can be called repeatedly without
3324 // side-effects if alignpanel already registered.
3325 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
3327 // apply Hidden regions to view.
3328 if (hiddenSeqs != null)
3330 for (int s = 0; s < JSEQ.length; s++)
3332 jalview.datamodel.SequenceGroup hidden = new jalview.datamodel.SequenceGroup();
3334 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
3337 al.getSequenceAt(JSEQ[s].getHiddenSequences(r)), false);
3339 af.viewport.hideRepSequences(al.getSequenceAt(s), hidden);
3342 jalview.datamodel.SequenceI[] hseqs = new jalview.datamodel.SequenceI[hiddenSeqs
3345 for (int s = 0; s < hiddenSeqs.size(); s++)
3347 hseqs[s] = (jalview.datamodel.SequenceI) hiddenSeqs.elementAt(s);
3350 af.viewport.hideSequence(hseqs);
3353 // recover view properties and display parameters
3354 if (view.getViewName() != null)
3356 af.viewport.viewName = view.getViewName();
3357 af.setInitialTabVisible();
3359 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
3362 af.viewport.setShowAnnotation(view.getShowAnnotation());
3363 af.viewport.setAbovePIDThreshold(view.getPidSelected());
3365 af.viewport.setColourText(view.getShowColourText());
3367 af.viewport.setConservationSelected(view.getConservationSelected());
3368 af.viewport.setShowJVSuffix(view.getShowFullId());
3369 af.viewport.rightAlignIds = view.getRightAlignIds();
3370 af.viewport.setFont(new java.awt.Font(view.getFontName(), view
3371 .getFontStyle(), view.getFontSize()));
3372 af.alignPanel.fontChanged();
3373 af.viewport.setRenderGaps(view.getRenderGaps());
3374 af.viewport.setWrapAlignment(view.getWrapAlignment());
3375 af.alignPanel.setWrapAlignment(view.getWrapAlignment());
3376 af.viewport.setShowAnnotation(view.getShowAnnotation());
3377 af.alignPanel.setAnnotationVisible(view.getShowAnnotation());
3379 af.viewport.setShowBoxes(view.getShowBoxes());
3381 af.viewport.setShowText(view.getShowText());
3383 af.viewport.textColour = new java.awt.Color(view.getTextCol1());
3384 af.viewport.textColour2 = new java.awt.Color(view.getTextCol2());
3385 af.viewport.thresholdTextColour = view.getTextColThreshold();
3386 af.viewport.setShowUnconserved(view.hasShowUnconserved() ? view
3387 .isShowUnconserved() : false);
3388 af.viewport.setStartRes(view.getStartRes());
3389 af.viewport.setStartSeq(view.getStartSeq());
3391 ColourSchemeI cs = null;
3392 // apply colourschemes
3393 if (view.getBgColour() != null)
3395 if (view.getBgColour().startsWith("ucs"))
3397 cs = GetUserColourScheme(jms, view.getBgColour());
3399 else if (view.getBgColour().startsWith("Annotation"))
3401 AnnotationColours viewAnnColour = view.getAnnotationColours();
3402 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
3409 cs = ColourSchemeProperty.getColour(al, view.getBgColour());
3414 cs.setThreshold(view.getPidThreshold(), true);
3415 cs.setConsensus(af.viewport.getSequenceConsensusHash());
3419 af.viewport.setGlobalColourScheme(cs);
3420 af.viewport.setColourAppliesToAllGroups(false);
3422 if (view.getConservationSelected() && cs != null)
3424 cs.setConservationInc(view.getConsThreshold());
3427 af.changeColour(cs);
3429 af.viewport.setColourAppliesToAllGroups(true);
3431 if (view.getShowSequenceFeatures())
3433 af.viewport.showSequenceFeatures = true;
3435 if (view.hasCentreColumnLabels())
3437 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
3439 if (view.hasIgnoreGapsinConsensus())
3441 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
3444 if (view.hasFollowHighlight())
3446 af.viewport.followHighlight = view.getFollowHighlight();
3448 if (view.hasFollowSelection())
3450 af.viewport.followSelection = view.getFollowSelection();
3452 if (view.hasShowConsensusHistogram())
3454 af.viewport.setShowConsensusHistogram(view
3455 .getShowConsensusHistogram());
3459 af.viewport.setShowConsensusHistogram(true);
3461 if (view.hasShowSequenceLogo())
3463 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
3467 af.viewport.setShowSequenceLogo(false);
3469 if (view.hasNormaliseSequenceLogo())
3471 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
3473 if (view.hasShowDbRefTooltip())
3475 af.viewport.setShowDbRefs(view.getShowDbRefTooltip());
3477 if (view.hasShowNPfeatureTooltip())
3479 af.viewport.setShowNpFeats(view.hasShowNPfeatureTooltip());
3481 if (view.hasShowGroupConsensus())
3483 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
3487 af.viewport.setShowGroupConsensus(false);
3489 if (view.hasShowGroupConservation())
3491 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
3495 af.viewport.setShowGroupConservation(false);
3498 // recover featre settings
3499 if (jms.getFeatureSettings() != null)
3501 af.viewport.featuresDisplayed = new Hashtable();
3502 String[] renderOrder = new String[jms.getFeatureSettings()
3503 .getSettingCount()];
3504 for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
3506 Setting setting = jms.getFeatureSettings().getSetting(fs);
3507 if (setting.hasMincolour())
3509 GraduatedColor gc = setting.hasMin() ? new GraduatedColor(
3510 new java.awt.Color(setting.getMincolour()),
3511 new java.awt.Color(setting.getColour()),
3512 setting.getMin(), setting.getMax()) : new GraduatedColor(
3513 new java.awt.Color(setting.getMincolour()),
3514 new java.awt.Color(setting.getColour()), 0, 1);
3515 if (setting.hasThreshold())
3517 gc.setThresh(setting.getThreshold());
3518 gc.setThreshType(setting.getThreshstate());
3520 gc.setAutoScaled(true); // default
3521 if (setting.hasAutoScale())
3523 gc.setAutoScaled(setting.getAutoScale());
3525 if (setting.hasColourByLabel())
3527 gc.setColourByLabel(setting.getColourByLabel());
3529 // and put in the feature colour table.
3530 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setColour(
3531 setting.getType(), gc);
3535 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setColour(
3537 new java.awt.Color(setting.getColour()));
3539 renderOrder[fs] = setting.getType();
3540 if (setting.hasOrder())
3541 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setOrder(
3542 setting.getType(), setting.getOrder());
3544 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setOrder(
3546 fs / jms.getFeatureSettings().getSettingCount());
3547 if (setting.getDisplay())
3549 af.viewport.featuresDisplayed.put(setting.getType(), new Integer(
3550 setting.getColour()));
3553 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().renderOrder = renderOrder;
3555 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().featureGroups = fgtable = new Hashtable();
3556 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
3558 Group grp = jms.getFeatureSettings().getGroup(gs);
3559 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
3563 if (view.getHiddenColumnsCount() > 0)
3565 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
3567 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(), view
3568 .getHiddenColumns(c).getEnd() // +1
3572 if (view.getCalcIdParam() != null)
3574 for (CalcIdParam calcIdParam : view.getCalcIdParam())
3576 if (calcIdParam != null)
3578 if (recoverCalcIdParam(calcIdParam, af.viewport))
3583 warn("Couldn't recover parameters for "
3584 + calcIdParam.getCalcId());
3589 af.setMenusFromViewport(af.viewport);
3590 // TODO: we don't need to do this if the viewport is aready visible.
3591 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
3593 af.alignPanel.updateAnnotation(false, true); // recompute any autoannotation
3594 reorderAutoannotation(af, al, autoAlan);
3595 af.alignPanel.alignmentChanged();
3599 private ColourSchemeI constructAnnotationColour(
3600 AnnotationColours viewAnnColour, AlignFrame af, Alignment al,
3601 JalviewModelSequence jms, boolean checkGroupAnnColour)
3603 boolean propagateAnnColour = false;
3604 ColourSchemeI cs = null;
3605 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
3606 if (checkGroupAnnColour && al.getGroups() != null
3607 && al.getGroups().size() > 0)
3609 // pre 2.8.1 behaviour
3610 // check to see if we should transfer annotation colours
3611 propagateAnnColour = true;
3612 for (jalview.datamodel.SequenceGroup sg : al.getGroups())
3614 if (sg.cs instanceof AnnotationColourGradient)
3616 propagateAnnColour = false;
3620 // int find annotation
3621 if (annAlignment.getAlignmentAnnotation() != null)
3623 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
3625 if (annAlignment.getAlignmentAnnotation()[i].label
3626 .equals(viewAnnColour.getAnnotation()))
3628 if (annAlignment.getAlignmentAnnotation()[i].getThreshold() == null)
3630 annAlignment.getAlignmentAnnotation()[i]
3631 .setThreshold(new jalview.datamodel.GraphLine(
3632 viewAnnColour.getThreshold(), "Threshold",
3633 java.awt.Color.black)
3638 if (viewAnnColour.getColourScheme().equals("None"))
3640 cs = new AnnotationColourGradient(
3641 annAlignment.getAlignmentAnnotation()[i],
3642 new java.awt.Color(viewAnnColour.getMinColour()),
3643 new java.awt.Color(viewAnnColour.getMaxColour()),
3644 viewAnnColour.getAboveThreshold());
3646 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
3648 cs = new AnnotationColourGradient(
3649 annAlignment.getAlignmentAnnotation()[i],
3650 GetUserColourScheme(jms,
3651 viewAnnColour.getColourScheme()),
3652 viewAnnColour.getAboveThreshold());
3656 cs = new AnnotationColourGradient(
3657 annAlignment.getAlignmentAnnotation()[i],
3658 ColourSchemeProperty.getColour(al,
3659 viewAnnColour.getColourScheme()),
3660 viewAnnColour.getAboveThreshold());
3662 if (viewAnnColour.hasPerSequence())
3664 ((AnnotationColourGradient) cs).setSeqAssociated(viewAnnColour
3667 if (viewAnnColour.hasPredefinedColours())
3669 ((AnnotationColourGradient) cs)
3670 .setPredefinedColours(viewAnnColour
3671 .isPredefinedColours());
3673 if (propagateAnnColour && al.getGroups() != null)
3675 // Also use these settings for all the groups
3676 for (int g = 0; g < al.getGroups().size(); g++)
3678 jalview.datamodel.SequenceGroup sg = al.getGroups().get(g);
3686 * if (viewAnnColour.getColourScheme().equals("None" )) { sg.cs =
3687 * new AnnotationColourGradient(
3688 * annAlignment.getAlignmentAnnotation()[i], new
3689 * java.awt.Color(viewAnnColour. getMinColour()), new
3690 * java.awt.Color(viewAnnColour. getMaxColour()),
3691 * viewAnnColour.getAboveThreshold()); } else
3694 sg.cs = new AnnotationColourGradient(
3695 annAlignment.getAlignmentAnnotation()[i], sg.cs,
3696 viewAnnColour.getAboveThreshold());
3697 if (cs instanceof AnnotationColourGradient)
3699 if (viewAnnColour.hasPerSequence())
3701 ((AnnotationColourGradient) cs)
3702 .setSeqAssociated(viewAnnColour.isPerSequence());
3704 if (viewAnnColour.hasPredefinedColours())
3706 ((AnnotationColourGradient) cs)
3707 .setPredefinedColours(viewAnnColour
3708 .isPredefinedColours());
3724 private void reorderAutoannotation(AlignFrame af, Alignment al,
3725 ArrayList<JvAnnotRow> autoAlan)
3727 // copy over visualization settings for autocalculated annotation in the
3729 if (al.getAlignmentAnnotation() != null)
3732 * Kludge for magic autoannotation names (see JAL-811)
3734 String[] magicNames = new String[]
3735 { "Consensus", "Quality", "Conservation" };
3736 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
3737 Hashtable<String, JvAnnotRow> visan = new Hashtable<String, JvAnnotRow>();
3738 for (String nm : magicNames)
3740 visan.put(nm, nullAnnot);
3742 for (JvAnnotRow auan : autoAlan)
3744 visan.put(auan.template.label
3745 + (auan.template.getCalcId() == null ? "" : "\t"
3746 + auan.template.getCalcId()), auan);
3748 int hSize = al.getAlignmentAnnotation().length;
3749 ArrayList<JvAnnotRow> reorder = new ArrayList<JvAnnotRow>();
3750 // work through any autoCalculated annotation already on the view
3751 // removing it if it should be placed in a different location on the
3752 // annotation panel.
3753 List<String> remains = new ArrayList(visan.keySet());
3754 for (int h = 0; h < hSize; h++)
3756 jalview.datamodel.AlignmentAnnotation jalan = al
3757 .getAlignmentAnnotation()[h];
3758 if (jalan.autoCalculated)
3761 JvAnnotRow valan = visan.get(k = jalan.label);
3762 if (jalan.getCalcId() != null)
3764 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
3769 // delete the auto calculated row from the alignment
3770 al.deleteAnnotation(jalan, false);
3774 if (valan != nullAnnot)
3776 if (jalan != valan.template)
3778 // newly created autoannotation row instance
3779 // so keep a reference to the visible annotation row
3780 // and copy over all relevant attributes
3781 if (valan.template.graphHeight >= 0)
3784 jalan.graphHeight = valan.template.graphHeight;
3786 jalan.visible = valan.template.visible;
3788 reorder.add(new JvAnnotRow(valan.order, jalan));
3793 // Add any (possibly stale) autocalculated rows that were not appended to
3794 // the view during construction
3795 for (String other : remains)
3797 JvAnnotRow othera = visan.get(other);
3798 if (othera != nullAnnot && othera.template.getCalcId() != null
3799 && othera.template.getCalcId().length() > 0)
3801 reorder.add(othera);
3804 // now put the automatic annotation in its correct place
3805 int s = 0, srt[] = new int[reorder.size()];
3806 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
3807 for (JvAnnotRow jvar : reorder)
3810 srt[s++] = jvar.order;
3813 jalview.util.QuickSort.sort(srt, rws);
3814 // and re-insert the annotation at its correct position
3815 for (JvAnnotRow jvar : rws)
3817 al.addAnnotation(jvar.template, jvar.order);
3819 af.alignPanel.adjustAnnotationHeight();
3823 Hashtable skipList = null;
3826 * TODO remove this method
3829 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
3830 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
3831 * throw new Error("Implementation Error. No skipList defined for this
3832 * Jalview2XML instance."); } return (AlignFrame)
3833 * skipList.get(view.getSequenceSetId()); }
3837 * Check if the Jalview view contained in object should be skipped or not.
3840 * @return true if view's sequenceSetId is a key in skipList
3842 private boolean skipViewport(JalviewModel object)
3844 if (skipList == null)
3849 if (skipList.containsKey(id = object.getJalviewModelSequence()
3850 .getViewport()[0].getSequenceSetId()))
3852 if (Cache.log != null && Cache.log.isDebugEnabled())
3854 Cache.log.debug("Skipping seuqence set id " + id);
3861 public void AddToSkipList(AlignFrame af)
3863 if (skipList == null)
3865 skipList = new Hashtable();
3867 skipList.put(af.getViewport().getSequenceSetId(), af);
3870 public void clearSkipList()
3872 if (skipList != null)
3879 private void recoverDatasetFor(SequenceSet vamsasSet, Alignment al)
3881 jalview.datamodel.Alignment ds = getDatasetFor(vamsasSet.getDatasetId());
3882 Vector dseqs = null;
3885 // create a list of new dataset sequences
3886 dseqs = new Vector();
3888 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
3890 Sequence vamsasSeq = vamsasSet.getSequence(i);
3891 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs);
3893 // create a new dataset
3896 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
3897 dseqs.copyInto(dsseqs);
3898 ds = new jalview.datamodel.Alignment(dsseqs);
3899 debug("Created new dataset " + vamsasSet.getDatasetId()
3900 + " for alignment " + System.identityHashCode(al));
3901 addDatasetRef(vamsasSet.getDatasetId(), ds);
3903 // set the dataset for the newly imported alignment.
3904 if (al.getDataset() == null)
3913 * sequence definition to create/merge dataset sequence for
3917 * vector to add new dataset sequence to
3919 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
3920 AlignmentI ds, Vector dseqs)
3922 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
3924 jalview.datamodel.Sequence sq = (jalview.datamodel.Sequence) seqRefIds
3925 .get(vamsasSeq.getId());
3926 jalview.datamodel.SequenceI dsq = null;
3927 if (sq != null && sq.getDatasetSequence() != null)
3929 dsq = sq.getDatasetSequence();
3932 String sqid = vamsasSeq.getDsseqid();
3935 // need to create or add a new dataset sequence reference to this sequence
3938 dsq = (jalview.datamodel.SequenceI) seqRefIds.get(sqid);
3943 // make a new dataset sequence
3944 dsq = sq.createDatasetSequence();
3947 // make up a new dataset reference for this sequence
3948 sqid = seqHash(dsq);
3950 dsq.setVamsasId(uniqueSetSuffix + sqid);
3951 seqRefIds.put(sqid, dsq);
3956 dseqs.addElement(dsq);
3961 ds.addSequence(dsq);
3967 { // make this dataset sequence sq's dataset sequence
3968 sq.setDatasetSequence(dsq);
3969 // and update the current dataset alignment
3974 if (!dseqs.contains(dsq))
3981 if (ds.findIndex(dsq) < 0)
3983 ds.addSequence(dsq);
3990 // TODO: refactor this as a merge dataset sequence function
3991 // now check that sq (the dataset sequence) sequence really is the union of
3992 // all references to it
3993 // boolean pre = sq.getStart() < dsq.getStart();
3994 // boolean post = sq.getEnd() > dsq.getEnd();
3998 StringBuffer sb = new StringBuffer();
3999 String newres = jalview.analysis.AlignSeq.extractGaps(
4000 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
4001 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
4002 && newres.length() > dsq.getLength())
4004 // Update with the longer sequence.
4008 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
4009 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
4010 * sb.append(newres.substring(newres.length() - sq.getEnd() -
4011 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
4013 dsq.setSequence(newres);
4015 // TODO: merges will never happen if we 'know' we have the real dataset
4016 // sequence - this should be detected when id==dssid
4018 .println("DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
4019 // + (pre ? "prepended" : "") + " "
4020 // + (post ? "appended" : ""));
4025 java.util.Hashtable datasetIds = null;
4027 java.util.IdentityHashMap dataset2Ids = null;
4029 private Alignment getDatasetFor(String datasetId)
4031 if (datasetIds == null)
4033 datasetIds = new Hashtable();
4036 if (datasetIds.containsKey(datasetId))
4038 return (Alignment) datasetIds.get(datasetId);
4043 private void addDatasetRef(String datasetId, Alignment dataset)
4045 if (datasetIds == null)
4047 datasetIds = new Hashtable();
4049 datasetIds.put(datasetId, dataset);
4053 * make a new dataset ID for this jalview dataset alignment
4058 private String getDatasetIdRef(jalview.datamodel.Alignment dataset)
4060 if (dataset.getDataset() != null)
4062 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
4064 String datasetId = makeHashCode(dataset, null);
4065 if (datasetId == null)
4067 // make a new datasetId and record it
4068 if (dataset2Ids == null)
4070 dataset2Ids = new IdentityHashMap();
4074 datasetId = (String) dataset2Ids.get(dataset);
4076 if (datasetId == null)
4078 datasetId = "ds" + dataset2Ids.size() + 1;
4079 dataset2Ids.put(dataset, datasetId);
4085 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
4087 for (int d = 0; d < sequence.getDBRefCount(); d++)
4089 DBRef dr = sequence.getDBRef(d);
4090 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
4091 sequence.getDBRef(d).getSource(), sequence.getDBRef(d)
4092 .getVersion(), sequence.getDBRef(d).getAccessionId());
4093 if (dr.getMapping() != null)
4095 entry.setMap(addMapping(dr.getMapping()));
4097 datasetSequence.addDBRef(entry);
4101 private jalview.datamodel.Mapping addMapping(Mapping m)
4103 SequenceI dsto = null;
4104 // Mapping m = dr.getMapping();
4105 int fr[] = new int[m.getMapListFromCount() * 2];
4106 Enumeration f = m.enumerateMapListFrom();
4107 for (int _i = 0; f.hasMoreElements(); _i += 2)
4109 MapListFrom mf = (MapListFrom) f.nextElement();
4110 fr[_i] = mf.getStart();
4111 fr[_i + 1] = mf.getEnd();
4113 int fto[] = new int[m.getMapListToCount() * 2];
4114 f = m.enumerateMapListTo();
4115 for (int _i = 0; f.hasMoreElements(); _i += 2)
4117 MapListTo mf = (MapListTo) f.nextElement();
4118 fto[_i] = mf.getStart();
4119 fto[_i + 1] = mf.getEnd();
4121 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto,
4122 fr, fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
4123 if (m.getMappingChoice() != null)
4125 MappingChoice mc = m.getMappingChoice();
4126 if (mc.getDseqFor() != null)
4128 String dsfor = "" + mc.getDseqFor();
4129 if (seqRefIds.containsKey(dsfor))
4134 jmap.setTo((SequenceI) seqRefIds.get(dsfor));
4138 frefedSequence.add(new Object[]
4145 * local sequence definition
4147 Sequence ms = mc.getSequence();
4148 jalview.datamodel.Sequence djs = null;
4149 String sqid = ms.getDsseqid();
4150 if (sqid != null && sqid.length() > 0)
4153 * recover dataset sequence
4155 djs = (jalview.datamodel.Sequence) seqRefIds.get(sqid);
4160 .println("Warning - making up dataset sequence id for DbRef sequence map reference");
4161 sqid = ((Object) ms).toString(); // make up a new hascode for
4162 // undefined dataset sequence hash
4163 // (unlikely to happen)
4169 * make a new dataset sequence and add it to refIds hash
4171 djs = new jalview.datamodel.Sequence(ms.getName(),
4173 djs.setStart(jmap.getMap().getToLowest());
4174 djs.setEnd(jmap.getMap().getToHighest());
4175 djs.setVamsasId(uniqueSetSuffix + sqid);
4177 seqRefIds.put(sqid, djs);
4180 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
4189 public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
4190 boolean keepSeqRefs)
4193 jalview.schemabinding.version2.JalviewModel jm = SaveState(ap, null,
4199 jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
4203 uniqueSetSuffix = "";
4204 jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
4209 if (this.frefedSequence == null)
4211 frefedSequence = new Vector();
4214 viewportsAdded = new Hashtable();
4216 AlignFrame af = LoadFromObject(jm, null, false, null);
4217 af.alignPanels.clear();
4218 af.closeMenuItem_actionPerformed(true);
4221 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
4222 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
4223 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
4224 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
4225 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
4228 return af.alignPanel;
4232 * flag indicating if hashtables should be cleared on finalization TODO this
4233 * flag may not be necessary
4235 private final boolean _cleartables = true;
4237 private Hashtable jvids2vobj;
4242 * @see java.lang.Object#finalize()
4245 protected void finalize() throws Throwable
4247 // really make sure we have no buried refs left.
4252 this.seqRefIds = null;
4253 this.seqsToIds = null;
4257 private void warn(String msg)
4262 private void warn(String msg, Exception e)
4264 if (Cache.log != null)
4268 Cache.log.warn(msg, e);
4272 Cache.log.warn(msg);
4277 System.err.println("Warning: " + msg);
4280 e.printStackTrace();
4285 private void debug(String string)
4287 debug(string, null);
4290 private void debug(String msg, Exception e)
4292 if (Cache.log != null)
4296 Cache.log.debug(msg, e);
4300 Cache.log.debug(msg);
4305 System.err.println("Warning: " + msg);
4308 e.printStackTrace();
4314 * set the object to ID mapping tables used to write/recover objects and XML
4315 * ID strings for the jalview project. If external tables are provided then
4316 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
4317 * object goes out of scope. - also populates the datasetIds hashtable with
4318 * alignment objects containing dataset sequences
4321 * Map from ID strings to jalview datamodel
4323 * Map from jalview datamodel to ID strings
4327 public void setObjectMappingTables(Hashtable vobj2jv,
4328 IdentityHashMap jv2vobj)
4330 this.jv2vobj = jv2vobj;
4331 this.vobj2jv = vobj2jv;
4332 Iterator ds = jv2vobj.keySet().iterator();
4334 while (ds.hasNext())
4336 Object jvobj = ds.next();
4337 id = jv2vobj.get(jvobj).toString();
4338 if (jvobj instanceof jalview.datamodel.Alignment)
4340 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
4342 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
4345 else if (jvobj instanceof jalview.datamodel.Sequence)
4347 // register sequence object so the XML parser can recover it.
4348 if (seqRefIds == null)
4350 seqRefIds = new Hashtable();
4352 if (seqsToIds == null)
4354 seqsToIds = new IdentityHashMap();
4356 seqRefIds.put(jv2vobj.get(jvobj).toString(), jvobj);
4357 seqsToIds.put(jvobj, id);
4359 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
4361 if (annotationIds == null)
4363 annotationIds = new Hashtable();
4366 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvobj);
4367 jalview.datamodel.AlignmentAnnotation jvann = (jalview.datamodel.AlignmentAnnotation) jvobj;
4368 if (jvann.annotationId == null)
4370 jvann.annotationId = anid;
4372 if (!jvann.annotationId.equals(anid))
4374 // TODO verify that this is the correct behaviour
4375 this.warn("Overriding Annotation ID for " + anid
4376 + " from different id : " + jvann.annotationId);
4377 jvann.annotationId = anid;
4380 else if (jvobj instanceof String)
4382 if (jvids2vobj == null)
4384 jvids2vobj = new Hashtable();
4385 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
4389 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
4394 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
4395 * objects created from the project archive. If string is null (default for
4396 * construction) then suffix will be set automatically.
4400 public void setUniqueSetSuffix(String string)
4402 uniqueSetSuffix = string;
4407 * uses skipList2 as the skipList for skipping views on sequence sets
4408 * associated with keys in the skipList
4412 public void setSkipList(Hashtable skipList2)
4414 skipList = skipList2;