2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
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
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import java.awt.Rectangle;
25 import java.lang.reflect.InvocationTargetException;
28 import java.util.Map.Entry;
29 import java.util.jar.*;
33 import org.exolab.castor.xml.*;
35 import jalview.bin.Cache;
36 import jalview.datamodel.Alignment;
37 import jalview.datamodel.AlignmentAnnotation;
38 import jalview.datamodel.AlignmentI;
39 import jalview.datamodel.SequenceI;
40 import jalview.schemabinding.version2.*;
41 import jalview.schemes.*;
42 import jalview.util.Platform;
43 import jalview.util.jarInputStreamProvider;
44 import jalview.viewmodel.AlignmentViewport;
45 import jalview.ws.jws2.Jws2Discoverer;
46 import jalview.ws.jws2.dm.AAConSettings;
47 import jalview.ws.jws2.jabaws2.Jws2Instance;
48 import jalview.ws.params.ArgumentI;
49 import jalview.ws.params.AutoCalcSetting;
50 import jalview.ws.params.WsParamSetI;
53 * Write out the current jalview desktop state as a Jalview XML stream.
55 * Note: the vamsas objects referred to here are primitive versions of the
56 * VAMSAS project schema elements - they are not the same and most likely never
60 * @version $Revision: 1.134 $
62 public class Jalview2XML
65 * create/return unique hash string for sq
68 * @return new or existing unique string for sq
70 String seqHash(SequenceI sq)
72 if (seqsToIds == null)
76 if (seqsToIds.containsKey(sq))
78 return (String) seqsToIds.get(sq);
82 // create sequential key
83 String key = "sq" + (seqsToIds.size() + 1);
84 key = makeHashCode(sq, key); // check we don't have an external reference
86 seqsToIds.put(sq, key);
95 if (seqRefIds != null)
99 if (seqsToIds != null)
109 warn("clearSeqRefs called when _cleartables was not set. Doing nothing.");
110 // seqRefIds = new Hashtable();
111 // seqsToIds = new IdentityHashMap();
117 if (seqsToIds == null)
119 seqsToIds = new IdentityHashMap();
121 if (seqRefIds == null)
123 seqRefIds = new Hashtable();
128 * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
129 * of sequence objects are created.
131 java.util.IdentityHashMap seqsToIds = null;
134 * jalview XML Sequence ID to jalview sequence object reference (both dataset
135 * and alignment sequences. Populated as XML reps of sequence objects are
138 java.util.Hashtable seqRefIds = null; // key->SequenceI resolution
140 Vector frefedSequence = null;
142 boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
148 public Jalview2XML(boolean raiseGUI)
150 this.raiseGUI = raiseGUI;
153 public void resolveFrefedSequences()
155 if (frefedSequence.size() > 0)
157 int r = 0, rSize = frefedSequence.size();
160 Object[] ref = (Object[]) frefedSequence.elementAt(r);
163 String sref = (String) ref[0];
164 if (seqRefIds.containsKey(sref))
166 if (ref[1] instanceof jalview.datamodel.Mapping)
168 SequenceI seq = (SequenceI) seqRefIds.get(sref);
169 while (seq.getDatasetSequence() != null)
171 seq = seq.getDatasetSequence();
173 ((jalview.datamodel.Mapping) ref[1]).setTo(seq);
177 if (ref[1] instanceof jalview.datamodel.AlignedCodonFrame)
179 SequenceI seq = (SequenceI) seqRefIds.get(sref);
180 while (seq.getDatasetSequence() != null)
182 seq = seq.getDatasetSequence();
185 && ref[2] instanceof jalview.datamodel.Mapping)
187 jalview.datamodel.Mapping mp = (jalview.datamodel.Mapping) ref[2];
188 ((jalview.datamodel.AlignedCodonFrame) ref[1]).addMap(
189 seq, mp.getTo(), mp.getMap());
194 .println("IMPLEMENTATION ERROR: Unimplemented forward sequence references for AlcodonFrames involving "
195 + ref[2].getClass() + " type objects.");
201 .println("IMPLEMENTATION ERROR: Unimplemented forward sequence references for "
202 + ref[1].getClass() + " type objects.");
205 frefedSequence.remove(r);
211 .println("IMPLEMENTATION WARNING: Unresolved forward reference for hash string "
213 + " with objecttype "
214 + ref[1].getClass());
221 frefedSequence.remove(r);
229 * This maintains a list of viewports, the key being the seqSetId. Important
230 * to set historyItem and redoList for multiple views
232 Hashtable viewportsAdded;
234 Hashtable annotationIds = new Hashtable();
236 String uniqueSetSuffix = "";
239 * List of pdbfiles added to Jar
241 Vector pdbfiles = null;
243 // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
244 public void SaveState(File statefile)
248 FileOutputStream fos = new FileOutputStream(statefile);
249 JarOutputStream jout = new JarOutputStream(fos);
252 } catch (Exception e)
254 // TODO: inform user of the problem - they need to know if their data was
256 if (errorMessage == null)
258 errorMessage = "Couldn't write Jalview Archive to output file '"
259 + statefile + "' - See console error log for details";
263 errorMessage += "(output file was '" + statefile + "')";
271 * Writes a jalview project archive to the given Jar output stream.
275 public void SaveState(JarOutputStream jout)
277 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
284 Hashtable<String, AlignFrame> dsses = new Hashtable<String, AlignFrame>();
289 // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
290 // //////////////////////////////////////////////////
291 // NOTE ALSO new PrintWriter must be used for each new JarEntry
292 PrintWriter out = null;
294 Vector shortNames = new Vector();
297 for (int i = frames.length - 1; i > -1; i--)
299 if (frames[i] instanceof AlignFrame)
301 AlignFrame af = (AlignFrame) frames[i];
304 && skipList.containsKey(af.getViewport()
305 .getSequenceSetId()))
310 String shortName = af.getTitle();
312 if (shortName.indexOf(File.separatorChar) > -1)
314 shortName = shortName.substring(shortName
315 .lastIndexOf(File.separatorChar) + 1);
320 while (shortNames.contains(shortName))
322 if (shortName.endsWith("_" + (count - 1)))
324 shortName = shortName
325 .substring(0, shortName.lastIndexOf("_"));
328 shortName = shortName.concat("_" + count);
332 shortNames.addElement(shortName);
334 if (!shortName.endsWith(".xml"))
336 shortName = shortName + ".xml";
339 int ap, apSize = af.alignPanels.size();
341 for (ap = 0; ap < apSize; ap++)
343 AlignmentPanel apanel = (AlignmentPanel) af.alignPanels
345 String fileName = apSize == 1 ? shortName : ap + shortName;
346 if (!fileName.endsWith(".xml"))
348 fileName = fileName + ".xml";
351 SaveState(apanel, fileName, jout);
353 String dssid = getDatasetIdRef(af.getViewport().getAlignment()
355 if (!dsses.containsKey(dssid))
357 dsses.put(dssid, af);
364 writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix,
370 } catch (Exception foo)
375 } catch (Exception ex)
377 // TODO: inform user of the problem - they need to know if their data was
379 if (errorMessage == null)
381 errorMessage = "Couldn't write Jalview Archive - see error output for details";
383 ex.printStackTrace();
387 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
388 public boolean SaveAlignment(AlignFrame af, String jarFile,
393 int ap, apSize = af.alignPanels.size();
394 FileOutputStream fos = new FileOutputStream(jarFile);
395 JarOutputStream jout = new JarOutputStream(fos);
396 Hashtable<String, AlignFrame> dsses = new Hashtable<String, AlignFrame>();
397 for (ap = 0; ap < apSize; ap++)
399 AlignmentPanel apanel = (AlignmentPanel) af.alignPanels
401 String jfileName = apSize == 1 ? fileName : fileName + ap;
402 if (!jfileName.endsWith(".xml"))
404 jfileName = jfileName + ".xml";
406 SaveState(apanel, jfileName, jout);
407 String dssid = getDatasetIdRef(af.getViewport().getAlignment()
409 if (!dsses.containsKey(dssid))
411 dsses.put(dssid, af);
414 writeDatasetFor(dsses, fileName, jout);
418 } catch (Exception foo)
424 } catch (Exception ex)
426 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
427 ex.printStackTrace();
432 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
433 String fileName, JarOutputStream jout)
436 for (String dssids : dsses.keySet())
438 AlignFrame _af = dsses.get(dssids);
439 String jfileName = fileName + " Dataset for " + _af.getTitle();
440 if (!jfileName.endsWith(".xml"))
442 jfileName = jfileName + ".xml";
444 SaveState(_af.alignPanel, jfileName, true, jout);
449 * create a JalviewModel from an algnment view and marshall it to a
453 * panel to create jalview model for
455 * name of alignment panel written to output stream
461 public JalviewModel SaveState(AlignmentPanel ap, String fileName,
462 JarOutputStream jout)
464 return SaveState(ap, fileName, false, jout);
468 * create a JalviewModel from an algnment view and marshall it to a
472 * panel to create jalview model for
474 * name of alignment panel written to output stream
476 * when true, only write the dataset for the alignment, not the data
477 * associated with the view.
483 public JalviewModel SaveState(AlignmentPanel ap, String fileName,
484 boolean storeDS, JarOutputStream jout)
487 Vector jmolViewIds = new Vector(); //
488 Vector userColours = new Vector();
490 AlignViewport av = ap.av;
492 JalviewModel object = new JalviewModel();
493 object.setVamsasModel(new jalview.schemabinding.version2.VamsasModel());
495 object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
496 object.setVersion(jalview.bin.Cache.getDefault("VERSION",
497 "Development Build"));
499 jalview.datamodel.AlignmentI jal = av.getAlignment();
501 if (av.hasHiddenRows())
503 jal = jal.getHiddenSequences().getFullAlignment();
506 SequenceSet vamsasSet = new SequenceSet();
508 JalviewModelSequence jms = new JalviewModelSequence();
510 vamsasSet.setGapChar(jal.getGapCharacter() + "");
512 if (jal.getDataset() != null)
514 // dataset id is the dataset's hashcode
515 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
518 // switch jal and the dataset
519 jal = jal.getDataset();
522 if (jal.getProperties() != null)
524 Enumeration en = jal.getProperties().keys();
525 while (en.hasMoreElements())
527 String key = en.nextElement().toString();
528 SequenceSetProperties ssp = new SequenceSetProperties();
530 ssp.setValue(jal.getProperties().get(key).toString());
531 vamsasSet.addSequenceSetProperties(ssp);
536 Set<String> calcIdSet = new HashSet<String>();
540 jalview.datamodel.SequenceI jds, jdatasq;
541 for (int i = 0; i < jal.getHeight(); i++)
543 jds = jal.getSequenceAt(i);
544 jdatasq = jds.getDatasetSequence() == null ? jds : jds
545 .getDatasetSequence();
548 if (seqRefIds.get(id) != null)
550 // This happens for two reasons: 1. multiple views are being serialised.
551 // 2. the hashCode has collided with another sequence's code. This DOES
552 // HAPPEN! (PF00072.15.stk does this)
553 // JBPNote: Uncomment to debug writing out of files that do not read
554 // back in due to ArrayOutOfBoundExceptions.
555 // System.err.println("vamsasSeq backref: "+id+"");
556 // System.err.println(jds.getName()+"
557 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
558 // System.err.println("Hashcode: "+seqHash(jds));
559 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
560 // System.err.println(rsq.getName()+"
561 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
562 // System.err.println("Hashcode: "+seqHash(rsq));
566 vamsasSeq = createVamsasSequence(id, jds);
567 vamsasSet.addSequence(vamsasSeq);
568 seqRefIds.put(id, jds);
572 jseq.setStart(jds.getStart());
573 jseq.setEnd(jds.getEnd());
574 jseq.setColour(av.getSequenceColour(jds).getRGB());
576 jseq.setId(id); // jseq id should be a string not a number
579 // Store any sequences this sequence represents
580 if (av.hasHiddenRows())
582 jseq.setHidden(av.getAlignment().getHiddenSequences()
585 if (av.isHiddenRepSequence(jal.getSequenceAt(i)))
587 jalview.datamodel.SequenceI[] reps = av
588 .getRepresentedSequences(jal.getSequenceAt(i))
589 .getSequencesInOrder(jal);
591 for (int h = 0; h < reps.length; h++)
593 if (reps[h] != jal.getSequenceAt(i))
595 jseq.addHiddenSequences(jal.findIndex(reps[h]));
602 if (jdatasq.getSequenceFeatures() != null)
604 jalview.datamodel.SequenceFeature[] sf = jdatasq
605 .getSequenceFeatures();
607 while (index < sf.length)
609 Features features = new Features();
611 features.setBegin(sf[index].getBegin());
612 features.setEnd(sf[index].getEnd());
613 features.setDescription(sf[index].getDescription());
614 features.setType(sf[index].getType());
615 features.setFeatureGroup(sf[index].getFeatureGroup());
616 features.setScore(sf[index].getScore());
617 if (sf[index].links != null)
619 for (int l = 0; l < sf[index].links.size(); l++)
621 OtherData keyValue = new OtherData();
622 keyValue.setKey("LINK_" + l);
623 keyValue.setValue(sf[index].links.elementAt(l).toString());
624 features.addOtherData(keyValue);
627 if (sf[index].otherDetails != null)
630 Enumeration keys = sf[index].otherDetails.keys();
631 while (keys.hasMoreElements())
633 key = keys.nextElement().toString();
634 OtherData keyValue = new OtherData();
635 keyValue.setKey(key);
636 keyValue.setValue(sf[index].otherDetails.get(key).toString());
637 features.addOtherData(keyValue);
641 jseq.addFeatures(features);
646 if (jdatasq.getPDBId() != null)
648 Enumeration en = jdatasq.getPDBId().elements();
649 while (en.hasMoreElements())
651 Pdbids pdb = new Pdbids();
652 jalview.datamodel.PDBEntry entry = (jalview.datamodel.PDBEntry) en
655 pdb.setId(entry.getId());
656 pdb.setType(entry.getType());
658 // store any JMol views associated with this seqeunce
659 // this section copes with duplicate entries in the project, so a
660 // dataset only view *should* be coped with sensibly
662 // This must have been loaded, is it still visible?
663 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
664 String matchedFile = null;
665 for (int f = frames.length - 1; f > -1; f--)
667 if (frames[f] instanceof AppJmol)
669 jmol = (AppJmol) frames[f];
670 for (int peid = 0; peid < jmol.jmb.pdbentry.length; peid++)
672 if (!jmol.jmb.pdbentry[peid].getId().equals(entry.getId())
673 && !(entry.getId().length() > 4 && entry
677 jmol.jmb.pdbentry[peid].getId()
680 if (matchedFile == null)
682 matchedFile = jmol.jmb.pdbentry[peid].getFile();
684 else if (!matchedFile.equals(jmol.jmb.pdbentry[peid]
688 .warn("Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
689 + jmol.jmb.pdbentry[peid].getFile());
693 // can get at it if the ID
694 // match is ambiguous (e.g.
696 String statestring = jmol.jmb.viewer.getStateInfo();
698 for (int smap = 0; smap < jmol.jmb.sequence[peid].length; smap++)
700 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
701 if (jds == jmol.jmb.sequence[peid][smap])
703 StructureState state = new StructureState();
704 state.setVisible(true);
705 state.setXpos(jmol.getX());
706 state.setYpos(jmol.getY());
707 state.setWidth(jmol.getWidth());
708 state.setHeight(jmol.getHeight());
709 state.setViewId(jmol.getViewId());
710 state.setAlignwithAlignPanel(jmol.isUsedforaligment(ap));
711 state.setColourwithAlignPanel(jmol
712 .isUsedforcolourby(ap));
713 state.setColourByJmol(jmol.isColouredByJmol());
714 if (!jmolViewIds.contains(state.getViewId()))
716 // Make sure we only store a Jmol state once in each XML
718 jmolViewIds.addElement(state.getViewId());
719 state.setContent(statestring.replaceAll("\n", ""));
723 state.setContent("# duplicate state");
725 pdb.addStructureState(state);
733 if (matchedFile != null || entry.getFile() != null)
735 if (entry.getFile() != null)
738 matchedFile = entry.getFile();
740 pdb.setFile(matchedFile); // entry.getFile());
741 if (pdbfiles == null)
743 pdbfiles = new Vector();
746 if (!pdbfiles.contains(entry.getId()))
748 pdbfiles.addElement(entry.getId());
751 File file = new File(matchedFile);
752 if (file.exists() && jout != null)
754 byte[] data = new byte[(int) file.length()];
755 jout.putNextEntry(new JarEntry(entry.getId()));
756 DataInputStream dis = new DataInputStream(
757 new FileInputStream(file));
760 DataOutputStream dout = new DataOutputStream(jout);
761 dout.write(data, 0, data.length);
765 } catch (Exception ex)
767 ex.printStackTrace();
773 if (entry.getProperty() != null)
775 PdbentryItem item = new PdbentryItem();
776 Hashtable properties = entry.getProperty();
777 Enumeration en2 = properties.keys();
778 while (en2.hasMoreElements())
780 Property prop = new Property();
781 String key = en2.nextElement().toString();
783 prop.setValue(properties.get(key).toString());
784 item.addProperty(prop);
786 pdb.addPdbentryItem(item);
796 if (!storeDS && av.hasHiddenRows())
798 jal = av.getAlignment();
801 if (jal.getCodonFrames() != null && jal.getCodonFrames().length > 0)
803 jalview.datamodel.AlignedCodonFrame[] jac = jal.getCodonFrames();
804 for (int i = 0; i < jac.length; i++)
806 AlcodonFrame alc = new AlcodonFrame();
807 vamsasSet.addAlcodonFrame(alc);
808 for (int p = 0; p < jac[i].aaWidth; p++)
810 Alcodon cmap = new Alcodon();
811 if (jac[i].codons[p] != null)
813 // Null codons indicate a gapped column in the translated peptide
815 cmap.setPos1(jac[i].codons[p][0]);
816 cmap.setPos2(jac[i].codons[p][1]);
817 cmap.setPos3(jac[i].codons[p][2]);
819 alc.addAlcodon(cmap);
821 if (jac[i].getProtMappings() != null
822 && jac[i].getProtMappings().length > 0)
824 SequenceI[] dnas = jac[i].getdnaSeqs();
825 jalview.datamodel.Mapping[] pmaps = jac[i].getProtMappings();
826 for (int m = 0; m < pmaps.length; m++)
828 AlcodMap alcmap = new AlcodMap();
829 alcmap.setDnasq(seqHash(dnas[m]));
830 alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
832 alc.addAlcodMap(alcmap);
839 // /////////////////////////////////
840 if (!storeDS && av.currentTree != null)
842 // FIND ANY ASSOCIATED TREES
843 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
844 if (Desktop.desktop != null)
846 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
848 for (int t = 0; t < frames.length; t++)
850 if (frames[t] instanceof TreePanel)
852 TreePanel tp = (TreePanel) frames[t];
854 if (tp.treeCanvas.av.getAlignment() == jal)
856 Tree tree = new Tree();
857 tree.setTitle(tp.getTitle());
858 tree.setCurrentTree((av.currentTree == tp.getTree()));
859 tree.setNewick(tp.getTree().toString());
860 tree.setThreshold(tp.treeCanvas.threshold);
862 tree.setFitToWindow(tp.fitToWindow.getState());
863 tree.setFontName(tp.getTreeFont().getName());
864 tree.setFontSize(tp.getTreeFont().getSize());
865 tree.setFontStyle(tp.getTreeFont().getStyle());
866 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
868 tree.setShowBootstrap(tp.bootstrapMenu.getState());
869 tree.setShowDistances(tp.distanceMenu.getState());
871 tree.setHeight(tp.getHeight());
872 tree.setWidth(tp.getWidth());
873 tree.setXpos(tp.getX());
874 tree.setYpos(tp.getY());
875 tree.setId(makeHashCode(tp, null));
884 * store forward refs from an annotationRow to any groups
886 IdentityHashMap groupRefs = new IdentityHashMap();
889 for (SequenceI sq : jal.getSequences())
891 // Store annotation on dataset sequences only
892 jalview.datamodel.AlignmentAnnotation[] aa = sq.getAnnotation();
893 if (aa != null && aa.length > 0)
895 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
902 if (jal.getAlignmentAnnotation() != null)
904 // Store the annotation shown on the alignment.
905 jalview.datamodel.AlignmentAnnotation[] aa = jal
906 .getAlignmentAnnotation();
907 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
912 if (jal.getGroups() != null)
914 JGroup[] groups = new JGroup[jal.getGroups().size()];
916 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
918 groups[++i] = new JGroup();
920 groups[i].setStart(sg.getStartRes());
921 groups[i].setEnd(sg.getEndRes());
922 groups[i].setName(sg.getName());
923 if (groupRefs.containsKey(sg))
925 // group has references so set it's ID field
926 groups[i].setId(groupRefs.get(sg).toString());
930 if (sg.cs.conservationApplied())
932 groups[i].setConsThreshold(sg.cs.getConservationInc());
934 if (sg.cs instanceof jalview.schemes.UserColourScheme)
936 groups[i].setColour(SetUserColourScheme(sg.cs, userColours,
942 .setColour(ColourSchemeProperty.getColourName(sg.cs));
945 else if (sg.cs instanceof jalview.schemes.AnnotationColourGradient)
947 groups[i].setColour("AnnotationColourGradient");
948 groups[i].setAnnotationColours(constructAnnotationColours(
949 (jalview.schemes.AnnotationColourGradient) sg.cs,
952 else if (sg.cs instanceof jalview.schemes.UserColourScheme)
955 .setColour(SetUserColourScheme(sg.cs, userColours, jms));
959 groups[i].setColour(ColourSchemeProperty.getColourName(sg.cs));
962 groups[i].setPidThreshold(sg.cs.getThreshold());
965 groups[i].setOutlineColour(sg.getOutlineColour().getRGB());
966 groups[i].setDisplayBoxes(sg.getDisplayBoxes());
967 groups[i].setDisplayText(sg.getDisplayText());
968 groups[i].setColourText(sg.getColourText());
969 groups[i].setTextCol1(sg.textColour.getRGB());
970 groups[i].setTextCol2(sg.textColour2.getRGB());
971 groups[i].setTextColThreshold(sg.thresholdTextColour);
972 groups[i].setShowUnconserved(sg.getShowNonconserved());
973 groups[i].setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
974 groups[i].setShowConsensusHistogram(sg.isShowConsensusHistogram());
975 groups[i].setShowSequenceLogo(sg.isShowSequenceLogo());
976 groups[i].setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
977 for (int s = 0; s < sg.getSize(); s++)
979 jalview.datamodel.Sequence seq = (jalview.datamodel.Sequence) sg
981 groups[i].addSeq(seqHash(seq));
985 jms.setJGroup(groups);
989 // /////////SAVE VIEWPORT
990 Viewport view = new Viewport();
991 view.setTitle(ap.alignFrame.getTitle());
992 view.setSequenceSetId(makeHashCode(av.getSequenceSetId(),
993 av.getSequenceSetId()));
994 view.setId(av.getViewId());
995 view.setViewName(av.viewName);
996 view.setGatheredViews(av.gatherViewsHere);
998 if (ap.av.explodedPosition != null)
1000 view.setXpos(av.explodedPosition.x);
1001 view.setYpos(av.explodedPosition.y);
1002 view.setWidth(av.explodedPosition.width);
1003 view.setHeight(av.explodedPosition.height);
1007 view.setXpos(ap.alignFrame.getBounds().x);
1008 view.setYpos(ap.alignFrame.getBounds().y);
1009 view.setWidth(ap.alignFrame.getBounds().width);
1010 view.setHeight(ap.alignFrame.getBounds().height);
1013 view.setStartRes(av.startRes);
1014 view.setStartSeq(av.startSeq);
1016 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1018 view.setBgColour(SetUserColourScheme(av.getGlobalColourScheme(),
1021 else if (av.getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1023 AnnotationColours ac = constructAnnotationColours(
1024 (jalview.schemes.AnnotationColourGradient) av
1025 .getGlobalColourScheme(),
1028 view.setAnnotationColours(ac);
1029 view.setBgColour("AnnotationColourGradient");
1033 view.setBgColour(ColourSchemeProperty.getColourName(av
1034 .getGlobalColourScheme()));
1037 ColourSchemeI cs = av.getGlobalColourScheme();
1041 if (cs.conservationApplied())
1043 view.setConsThreshold(cs.getConservationInc());
1044 if (cs instanceof jalview.schemes.UserColourScheme)
1046 view.setBgColour(SetUserColourScheme(cs, userColours, jms));
1050 if (cs instanceof ResidueColourScheme)
1052 view.setPidThreshold(cs.getThreshold());
1056 view.setConservationSelected(av.getConservationSelected());
1057 view.setPidSelected(av.getAbovePIDThreshold());
1058 view.setFontName(av.font.getName());
1059 view.setFontSize(av.font.getSize());
1060 view.setFontStyle(av.font.getStyle());
1061 view.setRenderGaps(av.renderGaps);
1062 view.setShowAnnotation(av.getShowAnnotation());
1063 view.setShowBoxes(av.getShowBoxes());
1064 view.setShowColourText(av.getColourText());
1065 view.setShowFullId(av.getShowJVSuffix());
1066 view.setRightAlignIds(av.rightAlignIds);
1067 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1068 view.setShowText(av.getShowText());
1069 view.setShowUnconserved(av.getShowUnconserved());
1070 view.setWrapAlignment(av.getWrapAlignment());
1071 view.setTextCol1(av.textColour.getRGB());
1072 view.setTextCol2(av.textColour2.getRGB());
1073 view.setTextColThreshold(av.thresholdTextColour);
1074 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1075 view.setShowSequenceLogo(av.isShowSequenceLogo());
1076 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1077 view.setShowGroupConsensus(av.isShowGroupConsensus());
1078 view.setShowGroupConservation(av.isShowGroupConservation());
1079 view.setShowNPfeatureTooltip(av.isShowNpFeats());
1080 view.setShowDbRefTooltip(av.isShowDbRefs());
1081 view.setFollowHighlight(av.followHighlight);
1082 view.setFollowSelection(av.followSelection);
1083 view.setIgnoreGapsinConsensus(av.getIgnoreGapsConsensus());
1084 if (av.featuresDisplayed != null)
1086 jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
1088 String[] renderOrder = ap.seqPanel.seqCanvas.getFeatureRenderer().renderOrder;
1090 Vector settingsAdded = new Vector();
1091 Object gstyle = null;
1092 GraduatedColor gcol = null;
1093 if (renderOrder != null)
1095 for (int ro = 0; ro < renderOrder.length; ro++)
1097 gstyle = ap.seqPanel.seqCanvas.getFeatureRenderer()
1098 .getFeatureStyle(renderOrder[ro]);
1099 Setting setting = new Setting();
1100 setting.setType(renderOrder[ro]);
1101 if (gstyle instanceof GraduatedColor)
1103 gcol = (GraduatedColor) gstyle;
1104 setting.setColour(gcol.getMaxColor().getRGB());
1105 setting.setMincolour(gcol.getMinColor().getRGB());
1106 setting.setMin(gcol.getMin());
1107 setting.setMax(gcol.getMax());
1108 setting.setColourByLabel(gcol.isColourByLabel());
1109 setting.setAutoScale(gcol.isAutoScale());
1110 setting.setThreshold(gcol.getThresh());
1111 setting.setThreshstate(gcol.getThreshType());
1115 setting.setColour(ap.seqPanel.seqCanvas.getFeatureRenderer()
1116 .getColour(renderOrder[ro]).getRGB());
1119 setting.setDisplay(av.featuresDisplayed
1120 .containsKey(renderOrder[ro]));
1121 float rorder = ap.seqPanel.seqCanvas.getFeatureRenderer()
1122 .getOrder(renderOrder[ro]);
1125 setting.setOrder(rorder);
1127 fs.addSetting(setting);
1128 settingsAdded.addElement(renderOrder[ro]);
1132 // Make sure we save none displayed feature settings
1133 Iterator en = ap.seqPanel.seqCanvas.getFeatureRenderer().featureColours
1134 .keySet().iterator();
1135 while (en.hasNext())
1137 String key = en.next().toString();
1138 if (settingsAdded.contains(key))
1143 Setting setting = new Setting();
1144 setting.setType(key);
1145 setting.setColour(ap.seqPanel.seqCanvas.getFeatureRenderer()
1146 .getColour(key).getRGB());
1148 setting.setDisplay(false);
1149 float rorder = ap.seqPanel.seqCanvas.getFeatureRenderer()
1153 setting.setOrder(rorder);
1155 fs.addSetting(setting);
1156 settingsAdded.addElement(key);
1158 en = ap.seqPanel.seqCanvas.getFeatureRenderer().featureGroups
1159 .keySet().iterator();
1160 Vector groupsAdded = new Vector();
1161 while (en.hasNext())
1163 String grp = en.next().toString();
1164 if (groupsAdded.contains(grp))
1168 Group g = new Group();
1170 g.setDisplay(((Boolean) ap.seqPanel.seqCanvas
1171 .getFeatureRenderer().featureGroups.get(grp))
1174 groupsAdded.addElement(grp);
1176 jms.setFeatureSettings(fs);
1180 if (av.hasHiddenColumns())
1182 if (av.getColumnSelection() == null
1183 || av.getColumnSelection().getHiddenColumns() == null)
1185 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1189 for (int c = 0; c < av.getColumnSelection().getHiddenColumns()
1192 int[] region = (int[]) av.getColumnSelection()
1193 .getHiddenColumns().elementAt(c);
1194 HiddenColumns hc = new HiddenColumns();
1195 hc.setStart(region[0]);
1196 hc.setEnd(region[1]);
1197 view.addHiddenColumns(hc);
1201 if (calcIdSet.size() > 0)
1203 for (String calcId : calcIdSet)
1205 if (calcId.trim().length() > 0)
1207 CalcIdParam cidp = createCalcIdParam(calcId, av);
1208 // Some calcIds have no parameters.
1211 view.addCalcIdParam(cidp);
1217 jms.addViewport(view);
1219 object.setJalviewModelSequence(jms);
1220 object.getVamsasModel().addSequenceSet(vamsasSet);
1222 if (jout != null && fileName != null)
1224 // We may not want to write the object to disk,
1225 // eg we can copy the alignViewport to a new view object
1226 // using save and then load
1229 JarEntry entry = new JarEntry(fileName);
1230 jout.putNextEntry(entry);
1231 PrintWriter pout = new PrintWriter(new OutputStreamWriter(jout,
1233 org.exolab.castor.xml.Marshaller marshaller = new org.exolab.castor.xml.Marshaller(
1235 marshaller.marshal(object);
1238 } catch (Exception ex)
1240 // TODO: raise error in GUI if marshalling failed.
1241 ex.printStackTrace();
1247 private AnnotationColours constructAnnotationColours(
1248 AnnotationColourGradient acg, Vector userColours,
1249 JalviewModelSequence jms)
1251 AnnotationColours ac = new AnnotationColours();
1252 ac.setAboveThreshold(acg.getAboveThreshold());
1253 ac.setThreshold(acg.getAnnotationThreshold());
1254 ac.setAnnotation(acg.getAnnotation());
1255 if (acg.getBaseColour() instanceof jalview.schemes.UserColourScheme)
1257 ac.setColourScheme(SetUserColourScheme(acg.getBaseColour(),
1262 ac.setColourScheme(ColourSchemeProperty.getColourName(acg
1266 ac.setMaxColour(acg.getMaxColour().getRGB());
1267 ac.setMinColour(acg.getMinColour().getRGB());
1268 ac.setPerSequence(acg.isSeqAssociated());
1269 ac.setPredefinedColours(acg.isPredefinedColours());
1273 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
1274 IdentityHashMap groupRefs, AlignmentViewport av,
1275 Set<String> calcIdSet, boolean storeDS, SequenceSet vamsasSet)
1278 for (int i = 0; i < aa.length; i++)
1280 Annotation an = new Annotation();
1282 if (aa[i].annotationId != null)
1284 annotationIds.put(aa[i].annotationId, aa[i]);
1287 an.setId(aa[i].annotationId);
1289 an.setVisible(aa[i].visible);
1291 an.setDescription(aa[i].description);
1293 if (aa[i].sequenceRef != null)
1295 // TODO later annotation sequenceRef should be the XML ID of the
1296 // sequence rather than its display name
1297 an.setSequenceRef(aa[i].sequenceRef.getName());
1299 if (aa[i].groupRef != null)
1301 Object groupIdr = groupRefs.get(aa[i].groupRef);
1302 if (groupIdr == null)
1304 // make a locally unique String
1305 groupRefs.put(aa[i].groupRef,
1306 groupIdr = ("" + System.currentTimeMillis()
1307 + aa[i].groupRef.getName() + groupRefs.size()));
1309 an.setGroupRef(groupIdr.toString());
1312 // store all visualization attributes for annotation
1313 an.setGraphHeight(aa[i].graphHeight);
1314 an.setCentreColLabels(aa[i].centreColLabels);
1315 an.setScaleColLabels(aa[i].scaleColLabel);
1316 an.setShowAllColLabels(aa[i].showAllColLabels);
1317 an.setBelowAlignment(aa[i].belowAlignment);
1319 if (aa[i].graph > 0)
1322 an.setGraphType(aa[i].graph);
1323 an.setGraphGroup(aa[i].graphGroup);
1324 if (aa[i].getThreshold() != null)
1326 ThresholdLine line = new ThresholdLine();
1327 line.setLabel(aa[i].getThreshold().label);
1328 line.setValue(aa[i].getThreshold().value);
1329 line.setColour(aa[i].getThreshold().colour.getRGB());
1330 an.setThresholdLine(line);
1338 an.setLabel(aa[i].label);
1340 if (aa[i] == av.getAlignmentQualityAnnot()
1341 || aa[i] == av.getAlignmentConservationAnnotation()
1342 || aa[i] == av.getAlignmentConsensusAnnotation()
1343 || aa[i].autoCalculated)
1345 // new way of indicating autocalculated annotation -
1346 an.setAutoCalculated(aa[i].autoCalculated);
1348 if (aa[i].hasScore())
1350 an.setScore(aa[i].getScore());
1353 if (aa[i].getCalcId() != null)
1355 calcIdSet.add(aa[i].getCalcId());
1356 an.setCalcId(aa[i].getCalcId());
1359 AnnotationElement ae;
1360 if (aa[i].annotations != null)
1362 an.setScoreOnly(false);
1363 for (int a = 0; a < aa[i].annotations.length; a++)
1365 if ((aa[i] == null) || (aa[i].annotations[a] == null))
1370 ae = new AnnotationElement();
1371 if (aa[i].annotations[a].description != null)
1372 ae.setDescription(aa[i].annotations[a].description);
1373 if (aa[i].annotations[a].displayCharacter != null)
1374 ae.setDisplayCharacter(aa[i].annotations[a].displayCharacter);
1376 if (!Float.isNaN(aa[i].annotations[a].value))
1377 ae.setValue(aa[i].annotations[a].value);
1380 if (aa[i].annotations[a].secondaryStructure != ' '
1381 && aa[i].annotations[a].secondaryStructure != '\0')
1382 ae.setSecondaryStructure(aa[i].annotations[a].secondaryStructure
1385 if (aa[i].annotations[a].colour != null
1386 && aa[i].annotations[a].colour != java.awt.Color.black)
1388 ae.setColour(aa[i].annotations[a].colour.getRGB());
1391 an.addAnnotationElement(ae);
1392 if (aa[i].autoCalculated)
1394 // only write one non-null entry into the annotation row -
1395 // sufficient to get the visualization attributes necessary to
1403 an.setScoreOnly(true);
1405 if (!storeDS || (storeDS && !aa[i].autoCalculated))
1407 // skip autocalculated annotation - these are only provided for
1409 vamsasSet.addAnnotation(an);
1415 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
1417 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
1418 if (settings != null)
1420 CalcIdParam vCalcIdParam = new CalcIdParam();
1421 vCalcIdParam.setCalcId(calcId);
1422 vCalcIdParam.addServiceURL(settings.getServiceURI());
1423 // generic URI allowing a third party to resolve another instance of the
1424 // service used for this calculation
1425 for (String urls : settings.getServiceURLs())
1427 vCalcIdParam.addServiceURL(urls);
1429 vCalcIdParam.setVersion("1.0");
1430 if (settings.getPreset() != null)
1432 WsParamSetI setting = settings.getPreset();
1433 vCalcIdParam.setName(setting.getName());
1434 vCalcIdParam.setDescription(setting.getDescription());
1438 vCalcIdParam.setName("");
1439 vCalcIdParam.setDescription("Last used parameters");
1441 // need to be able to recover 1) settings 2) user-defined presets or
1442 // recreate settings from preset 3) predefined settings provided by
1443 // service - or settings that can be transferred (or discarded)
1444 vCalcIdParam.setParameters(settings.getWsParamFile().replace("\n",
1446 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
1447 // todo - decide if updateImmediately is needed for any projects.
1449 return vCalcIdParam;
1454 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
1457 if (calcIdParam.getVersion().equals("1.0"))
1459 Jws2Instance service = Jws2Discoverer.getDiscoverer()
1460 .getPreferredServiceFor(calcIdParam.getServiceURL());
1461 if (service != null)
1463 WsParamSetI parmSet = null;
1466 parmSet = service.getParamStore().parseServiceParameterFile(
1467 calcIdParam.getName(), calcIdParam.getDescription(),
1468 calcIdParam.getServiceURL(),
1469 calcIdParam.getParameters().replace("|\\n|", "\n"));
1470 } catch (IOException x)
1472 warn("Couldn't parse parameter data for "
1473 + calcIdParam.getCalcId(), x);
1476 List<ArgumentI> argList = null;
1477 if (calcIdParam.getName().length() > 0)
1479 parmSet = service.getParamStore()
1480 .getPreset(calcIdParam.getName());
1481 if (parmSet != null)
1483 // TODO : check we have a good match with settings in AACon -
1484 // otherwise we'll need to create a new preset
1489 argList = parmSet.getArguments();
1492 AAConSettings settings = new AAConSettings(
1493 calcIdParam.isAutoUpdate(), service, parmSet, argList);
1494 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
1495 calcIdParam.isNeedsUpdate());
1500 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
1504 throw new Error("Unsupported Version for calcIdparam "
1505 + calcIdParam.toString());
1509 * External mapping between jalview objects and objects yielding a valid and
1510 * unique object ID string. This is null for normal Jalview project IO, but
1511 * non-null when a jalview project is being read or written as part of a
1514 IdentityHashMap jv2vobj = null;
1517 * Construct a unique ID for jvobj using either existing bindings or if none
1518 * exist, the result of the hashcode call for the object.
1521 * jalview data object
1522 * @return unique ID for referring to jvobj
1524 private String makeHashCode(Object jvobj, String altCode)
1526 if (jv2vobj != null)
1528 Object id = jv2vobj.get(jvobj);
1531 return id.toString();
1533 // check string ID mappings
1534 if (jvids2vobj != null && jvobj instanceof String)
1536 id = jvids2vobj.get(jvobj);
1540 return id.toString();
1542 // give up and warn that something has gone wrong
1543 warn("Cannot find ID for object in external mapping : " + jvobj);
1549 * return local jalview object mapped to ID, if it exists
1553 * @return null or object bound to idcode
1555 private Object retrieveExistingObj(String idcode)
1557 if (idcode != null && vobj2jv != null)
1559 return vobj2jv.get(idcode);
1565 * binding from ID strings from external mapping table to jalview data model
1568 private Hashtable vobj2jv;
1570 private Sequence createVamsasSequence(String id, SequenceI jds)
1572 return createVamsasSequence(true, id, jds, null);
1575 private Sequence createVamsasSequence(boolean recurse, String id,
1576 SequenceI jds, SequenceI parentseq)
1578 Sequence vamsasSeq = new Sequence();
1579 vamsasSeq.setId(id);
1580 vamsasSeq.setName(jds.getName());
1581 vamsasSeq.setSequence(jds.getSequenceAsString());
1582 vamsasSeq.setDescription(jds.getDescription());
1583 jalview.datamodel.DBRefEntry[] dbrefs = null;
1584 if (jds.getDatasetSequence() != null)
1586 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
1587 if (jds.getDatasetSequence().getDBRef() != null)
1589 dbrefs = jds.getDatasetSequence().getDBRef();
1594 vamsasSeq.setDsseqid(id); // so we can tell which sequences really are
1595 // dataset sequences only
1596 dbrefs = jds.getDBRef();
1600 for (int d = 0; d < dbrefs.length; d++)
1602 DBRef dbref = new DBRef();
1603 dbref.setSource(dbrefs[d].getSource());
1604 dbref.setVersion(dbrefs[d].getVersion());
1605 dbref.setAccessionId(dbrefs[d].getAccessionId());
1606 if (dbrefs[d].hasMap())
1608 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
1610 dbref.setMapping(mp);
1612 vamsasSeq.addDBRef(dbref);
1618 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
1619 SequenceI parentseq, SequenceI jds, boolean recurse)
1622 if (jmp.getMap() != null)
1626 jalview.util.MapList mlst = jmp.getMap();
1627 int r[] = mlst.getFromRanges();
1628 for (int s = 0; s < r.length; s += 2)
1630 MapListFrom mfrom = new MapListFrom();
1631 mfrom.setStart(r[s]);
1632 mfrom.setEnd(r[s + 1]);
1633 mp.addMapListFrom(mfrom);
1635 r = mlst.getToRanges();
1636 for (int s = 0; s < r.length; s += 2)
1638 MapListTo mto = new MapListTo();
1640 mto.setEnd(r[s + 1]);
1641 mp.addMapListTo(mto);
1643 mp.setMapFromUnit(mlst.getFromRatio());
1644 mp.setMapToUnit(mlst.getToRatio());
1645 if (jmp.getTo() != null)
1647 MappingChoice mpc = new MappingChoice();
1649 && (parentseq != jmp.getTo() || parentseq
1650 .getDatasetSequence() != jmp.getTo()))
1652 mpc.setSequence(createVamsasSequence(false, seqHash(jmp.getTo()),
1658 SequenceI ps = null;
1659 if (parentseq != jmp.getTo()
1660 && parentseq.getDatasetSequence() != jmp.getTo())
1662 // chaining dbref rather than a handshaking one
1663 jmpid = seqHash(ps = jmp.getTo());
1667 jmpid = seqHash(ps = parentseq);
1669 mpc.setDseqFor(jmpid);
1670 if (!seqRefIds.containsKey(mpc.getDseqFor()))
1672 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
1673 seqRefIds.put(mpc.getDseqFor(), ps);
1677 jalview.bin.Cache.log.debug("reusing DseqFor ID");
1680 mp.setMappingChoice(mpc);
1686 String SetUserColourScheme(jalview.schemes.ColourSchemeI cs,
1687 Vector userColours, JalviewModelSequence jms)
1690 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
1691 boolean newucs = false;
1692 if (!userColours.contains(ucs))
1694 userColours.add(ucs);
1697 id = "ucs" + userColours.indexOf(ucs);
1700 // actually create the scheme's entry in the XML model
1701 java.awt.Color[] colours = ucs.getColours();
1702 jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
1703 jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
1705 for (int i = 0; i < colours.length; i++)
1707 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
1708 col.setName(ResidueProperties.aa[i]);
1709 col.setRGB(jalview.util.Format.getHexString(colours[i]));
1710 jbucs.addColour(col);
1712 if (ucs.getLowerCaseColours() != null)
1714 colours = ucs.getLowerCaseColours();
1715 for (int i = 0; i < colours.length; i++)
1717 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
1718 col.setName(ResidueProperties.aa[i].toLowerCase());
1719 col.setRGB(jalview.util.Format.getHexString(colours[i]));
1720 jbucs.addColour(col);
1725 uc.setUserColourScheme(jbucs);
1726 jms.addUserColours(uc);
1732 jalview.schemes.UserColourScheme GetUserColourScheme(
1733 JalviewModelSequence jms, String id)
1735 UserColours[] uc = jms.getUserColours();
1736 UserColours colours = null;
1738 for (int i = 0; i < uc.length; i++)
1740 if (uc[i].getId().equals(id))
1748 java.awt.Color[] newColours = new java.awt.Color[24];
1750 for (int i = 0; i < 24; i++)
1752 newColours[i] = new java.awt.Color(Integer.parseInt(colours
1753 .getUserColourScheme().getColour(i).getRGB(), 16));
1756 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
1759 if (colours.getUserColourScheme().getColourCount() > 24)
1761 newColours = new java.awt.Color[23];
1762 for (int i = 0; i < 23; i++)
1764 newColours[i] = new java.awt.Color(Integer.parseInt(colours
1765 .getUserColourScheme().getColour(i + 24).getRGB(), 16));
1767 ucs.setLowerCaseColours(newColours);
1774 * contains last error message (if any) encountered by XML loader.
1776 String errorMessage = null;
1779 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
1780 * exceptions are raised during project XML parsing
1782 public boolean attemptversion1parse = true;
1785 * Load a jalview project archive from a jar file
1788 * - HTTP URL or filename
1790 public AlignFrame LoadJalviewAlign(final String file)
1793 jalview.gui.AlignFrame af = null;
1797 // create list to store references for any new Jmol viewers created
1798 newStructureViewers = new Vector<AppJmol>();
1799 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
1800 // Workaround is to make sure caller implements the JarInputStreamProvider
1802 // so we can re-open the jar input stream for each entry.
1804 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
1805 af = LoadJalviewAlign(jprovider);
1807 } catch (MalformedURLException e)
1809 errorMessage = "Invalid URL format for '" + file + "'";
1815 SwingUtilities.invokeAndWait(new Runnable()
1819 setLoadingFinishedForNewStructureViewers();
1822 } catch (Exception x)
1830 private jarInputStreamProvider createjarInputStreamProvider(
1831 final String file) throws MalformedURLException
1834 errorMessage = null;
1835 uniqueSetSuffix = null;
1837 viewportsAdded = null;
1838 frefedSequence = null;
1840 if (file.startsWith("http://"))
1842 url = new URL(file);
1844 final URL _url = url;
1845 return new jarInputStreamProvider()
1849 public JarInputStream getJarInputStream() throws IOException
1853 return new JarInputStream(_url.openStream());
1857 return new JarInputStream(new FileInputStream(file));
1862 public String getFilename()
1870 * Recover jalview session from a jalview project archive. Caller may
1871 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
1872 * themselves. Any null fields will be initialised with default values,
1873 * non-null fields are left alone.
1878 public AlignFrame LoadJalviewAlign(final jarInputStreamProvider jprovider)
1880 errorMessage = null;
1881 if (uniqueSetSuffix == null)
1883 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
1885 if (seqRefIds == null)
1887 seqRefIds = new Hashtable();
1889 if (viewportsAdded == null)
1891 viewportsAdded = new Hashtable();
1893 if (frefedSequence == null)
1895 frefedSequence = new Vector();
1898 jalview.gui.AlignFrame af = null, _af = null;
1899 Hashtable gatherToThisFrame = new Hashtable();
1900 final String file = jprovider.getFilename();
1903 JarInputStream jin = null;
1904 JarEntry jarentry = null;
1909 jin = jprovider.getJarInputStream();
1910 for (int i = 0; i < entryCount; i++)
1912 jarentry = jin.getNextJarEntry();
1915 if (jarentry != null && jarentry.getName().endsWith(".xml"))
1917 InputStreamReader in = new InputStreamReader(jin, "UTF-8");
1918 JalviewModel object = new JalviewModel();
1920 Unmarshaller unmar = new Unmarshaller(object);
1921 unmar.setValidation(false);
1922 object = (JalviewModel) unmar.unmarshal(in);
1923 if (true) // !skipViewport(object))
1925 _af = LoadFromObject(object, file, true, jprovider);
1926 if (object.getJalviewModelSequence().getViewportCount() > 0)
1929 if (af.viewport.gatherViewsHere)
1931 gatherToThisFrame.put(af.viewport.getSequenceSetId(), af);
1937 else if (jarentry != null)
1939 // Some other file here.
1942 } while (jarentry != null);
1943 resolveFrefedSequences();
1944 } catch (java.io.FileNotFoundException ex)
1946 ex.printStackTrace();
1947 errorMessage = "Couldn't locate Jalview XML file : " + file;
1948 System.err.println("Exception whilst loading jalview XML file : "
1950 } catch (java.net.UnknownHostException ex)
1952 ex.printStackTrace();
1953 errorMessage = "Couldn't locate Jalview XML file : " + file;
1954 System.err.println("Exception whilst loading jalview XML file : "
1956 } catch (Exception ex)
1958 System.err.println("Parsing as Jalview Version 2 file failed.");
1959 ex.printStackTrace(System.err);
1960 if (attemptversion1parse)
1962 // Is Version 1 Jar file?
1965 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
1966 } catch (Exception ex2)
1968 System.err.println("Exception whilst loading as jalviewXMLV1:");
1969 ex2.printStackTrace();
1973 if (Desktop.instance != null)
1975 Desktop.instance.stopLoading();
1979 System.out.println("Successfully loaded archive file");
1982 ex.printStackTrace();
1984 System.err.println("Exception whilst loading jalview XML file : "
1986 } catch (OutOfMemoryError e)
1988 // Don't use the OOM Window here
1989 errorMessage = "Out of memory loading jalview XML file";
1990 System.err.println("Out of memory whilst loading jalview XML file");
1991 e.printStackTrace();
1994 if (Desktop.instance != null)
1996 Desktop.instance.stopLoading();
1999 Enumeration en = gatherToThisFrame.elements();
2000 while (en.hasMoreElements())
2002 Desktop.instance.gatherViews((AlignFrame) en.nextElement());
2004 if (errorMessage != null)
2012 * check errorMessage for a valid error message and raise an error box in the
2013 * GUI or write the current errorMessage to stderr and then clear the error
2016 protected void reportErrors()
2018 reportErrors(false);
2021 protected void reportErrors(final boolean saving)
2023 if (errorMessage != null)
2025 final String finalErrorMessage = errorMessage;
2028 javax.swing.SwingUtilities.invokeLater(new Runnable()
2033 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2034 finalErrorMessage, "Error "
2035 + (saving ? "saving" : "loading")
2036 + " Jalview file", JOptionPane.WARNING_MESSAGE);
2042 System.err.println("Problem loading Jalview file: " + errorMessage);
2045 errorMessage = null;
2048 Hashtable alreadyLoadedPDB;
2051 * when set, local views will be updated from view stored in JalviewXML
2052 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2053 * sync if this is set to true.
2055 private final boolean updateLocalViews = false;
2057 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId)
2059 if (alreadyLoadedPDB == null)
2060 alreadyLoadedPDB = new Hashtable();
2062 if (alreadyLoadedPDB.containsKey(pdbId))
2063 return alreadyLoadedPDB.get(pdbId).toString();
2067 JarInputStream jin = jprovider.getJarInputStream();
2069 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2070 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2071 * FileInputStream(jprovider)); }
2074 JarEntry entry = null;
2077 entry = jin.getNextJarEntry();
2078 } while (entry != null && !entry.getName().equals(pdbId));
2081 BufferedReader in = new BufferedReader(new InputStreamReader(jin));
2082 File outFile = File.createTempFile("jalview_pdb", ".txt");
2083 outFile.deleteOnExit();
2084 PrintWriter out = new PrintWriter(new FileOutputStream(outFile));
2087 while ((data = in.readLine()) != null)
2094 } catch (Exception foo)
2099 String t = outFile.getAbsolutePath();
2100 alreadyLoadedPDB.put(pdbId, t);
2105 warn("Couldn't find PDB file entry in Jalview Jar for " + pdbId);
2107 } catch (Exception ex)
2109 ex.printStackTrace();
2115 private class JvAnnotRow
2117 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2124 * persisted version of annotation row from which to take vis properties
2126 public jalview.datamodel.AlignmentAnnotation template;
2129 * original position of the annotation row in the alignment
2135 * Load alignment frame from jalview XML DOM object
2140 * filename source string
2141 * @param loadTreesAndStructures
2142 * when false only create Viewport
2144 * data source provider
2145 * @return alignment frame created from view stored in DOM
2147 AlignFrame LoadFromObject(JalviewModel object, String file,
2148 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
2150 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
2151 Sequence[] vamsasSeq = vamsasSet.getSequence();
2153 JalviewModelSequence jms = object.getJalviewModelSequence();
2155 Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
2158 // ////////////////////////////////
2161 Vector hiddenSeqs = null;
2162 jalview.datamodel.Sequence jseq;
2164 ArrayList tmpseqs = new ArrayList();
2166 boolean multipleView = false;
2168 JSeq[] JSEQ = object.getJalviewModelSequence().getJSeq();
2169 int vi = 0; // counter in vamsasSeq array
2170 for (int i = 0; i < JSEQ.length; i++)
2172 String seqId = JSEQ[i].getId();
2174 if (seqRefIds.get(seqId) != null)
2176 tmpseqs.add(seqRefIds.get(seqId));
2177 multipleView = true;
2181 jseq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
2182 vamsasSeq[vi].getSequence());
2183 jseq.setDescription(vamsasSeq[vi].getDescription());
2184 jseq.setStart(JSEQ[i].getStart());
2185 jseq.setEnd(JSEQ[i].getEnd());
2186 jseq.setVamsasId(uniqueSetSuffix + seqId);
2187 seqRefIds.put(vamsasSeq[vi].getId(), jseq);
2192 if (JSEQ[i].getHidden())
2194 if (hiddenSeqs == null)
2196 hiddenSeqs = new Vector();
2199 hiddenSeqs.addElement(seqRefIds.get(seqId));
2205 // Create the alignment object from the sequence set
2206 // ///////////////////////////////
2207 jalview.datamodel.Sequence[] orderedSeqs = new jalview.datamodel.Sequence[tmpseqs
2210 tmpseqs.toArray(orderedSeqs);
2212 jalview.datamodel.Alignment al = new jalview.datamodel.Alignment(
2215 // / Add the alignment properties
2216 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
2218 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
2219 al.setProperty(ssp.getKey(), ssp.getValue());
2223 // SequenceFeatures are added to the DatasetSequence,
2224 // so we must create or recover the dataset before loading features
2225 // ///////////////////////////////
2226 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
2228 // older jalview projects do not have a dataset id.
2229 al.setDataset(null);
2233 recoverDatasetFor(vamsasSet, al);
2235 // ///////////////////////////////
2237 Hashtable pdbloaded = new Hashtable();
2240 // load sequence features, database references and any associated PDB
2241 // structures for the alignment
2242 for (int i = 0; i < vamsasSeq.length; i++)
2244 if (JSEQ[i].getFeaturesCount() > 0)
2246 Features[] features = JSEQ[i].getFeatures();
2247 for (int f = 0; f < features.length; f++)
2249 jalview.datamodel.SequenceFeature sf = new jalview.datamodel.SequenceFeature(
2250 features[f].getType(), features[f].getDescription(),
2251 features[f].getStatus(), features[f].getBegin(),
2252 features[f].getEnd(), features[f].getFeatureGroup());
2254 sf.setScore(features[f].getScore());
2255 for (int od = 0; od < features[f].getOtherDataCount(); od++)
2257 OtherData keyValue = features[f].getOtherData(od);
2258 if (keyValue.getKey().startsWith("LINK"))
2260 sf.addLink(keyValue.getValue());
2264 sf.setValue(keyValue.getKey(), keyValue.getValue());
2269 al.getSequenceAt(i).getDatasetSequence().addSequenceFeature(sf);
2272 if (vamsasSeq[i].getDBRefCount() > 0)
2274 addDBRefs(al.getSequenceAt(i).getDatasetSequence(), vamsasSeq[i]);
2276 if (JSEQ[i].getPdbidsCount() > 0)
2278 Pdbids[] ids = JSEQ[i].getPdbids();
2279 for (int p = 0; p < ids.length; p++)
2281 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
2282 entry.setId(ids[p].getId());
2283 entry.setType(ids[p].getType());
2284 if (ids[p].getFile() != null)
2286 if (!pdbloaded.containsKey(ids[p].getFile()))
2288 entry.setFile(loadPDBFile(jprovider, ids[p].getId()));
2292 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
2296 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
2300 } // end !multipleview
2302 // ///////////////////////////////
2303 // LOAD SEQUENCE MAPPINGS
2305 if (vamsasSet.getAlcodonFrameCount() > 0)
2307 // TODO Potentially this should only be done once for all views of an
2309 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
2310 for (int i = 0; i < alc.length; i++)
2312 jalview.datamodel.AlignedCodonFrame cf = new jalview.datamodel.AlignedCodonFrame(
2313 alc[i].getAlcodonCount());
2314 if (alc[i].getAlcodonCount() > 0)
2316 Alcodon[] alcods = alc[i].getAlcodon();
2317 for (int p = 0; p < cf.codons.length; p++)
2319 if (alcods[p].hasPos1() && alcods[p].hasPos2()
2320 && alcods[p].hasPos3())
2322 // translated codons require three valid positions
2323 cf.codons[p] = new int[3];
2324 cf.codons[p][0] = (int) alcods[p].getPos1();
2325 cf.codons[p][1] = (int) alcods[p].getPos2();
2326 cf.codons[p][2] = (int) alcods[p].getPos3();
2330 cf.codons[p] = null;
2334 if (alc[i].getAlcodMapCount() > 0)
2336 AlcodMap[] maps = alc[i].getAlcodMap();
2337 for (int m = 0; m < maps.length; m++)
2339 SequenceI dnaseq = (SequenceI) seqRefIds
2340 .get(maps[m].getDnasq());
2342 jalview.datamodel.Mapping mapping = null;
2343 // attach to dna sequence reference.
2344 if (maps[m].getMapping() != null)
2346 mapping = addMapping(maps[m].getMapping());
2350 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
2355 frefedSequence.add(new Object[]
2356 { maps[m].getDnasq(), cf, mapping });
2360 al.addCodonFrame(cf);
2365 // ////////////////////////////////
2367 ArrayList<JvAnnotRow> autoAlan = new ArrayList<JvAnnotRow>();
2369 * store any annotations which forward reference a group's ID
2371 Hashtable<String, ArrayList<jalview.datamodel.AlignmentAnnotation>> groupAnnotRefs = new Hashtable<String, ArrayList<jalview.datamodel.AlignmentAnnotation>>();
2373 if (vamsasSet.getAnnotationCount() > 0)
2375 Annotation[] an = vamsasSet.getAnnotation();
2377 for (int i = 0; i < an.length; i++)
2380 * test if annotation is automatically calculated for this view only
2382 boolean autoForView = false;
2383 if (an[i].getLabel().equals("Quality")
2384 || an[i].getLabel().equals("Conservation")
2385 || an[i].getLabel().equals("Consensus"))
2387 // Kludge for pre 2.5 projects which lacked the autocalculated flag
2389 if (!an[i].hasAutoCalculated())
2391 an[i].setAutoCalculated(true);
2395 || (an[i].hasAutoCalculated() && an[i].isAutoCalculated()))
2397 // remove ID - we don't recover annotation from other views for
2398 // view-specific annotation
2402 // set visiblity for other annotation in this view
2403 if (an[i].getId() != null
2404 && annotationIds.containsKey(an[i].getId()))
2406 jalview.datamodel.AlignmentAnnotation jda = (jalview.datamodel.AlignmentAnnotation) annotationIds
2407 .get(an[i].getId());
2408 // in principle Visible should always be true for annotation displayed
2409 // in multiple views
2410 if (an[i].hasVisible())
2411 jda.visible = an[i].getVisible();
2413 al.addAnnotation(jda);
2417 // Construct new annotation from model.
2418 AnnotationElement[] ae = an[i].getAnnotationElement();
2419 jalview.datamodel.Annotation[] anot = null;
2420 java.awt.Color firstColour = null;
2422 if (!an[i].getScoreOnly())
2424 anot = new jalview.datamodel.Annotation[al.getWidth()];
2425 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
2427 anpos = ae[aa].getPosition();
2429 if (anpos >= anot.length)
2432 anot[anpos] = new jalview.datamodel.Annotation(
2434 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
2435 (ae[aa].getSecondaryStructure() == null || ae[aa]
2436 .getSecondaryStructure().length() == 0) ? ' '
2437 : ae[aa].getSecondaryStructure().charAt(0),
2441 // JBPNote: Consider verifying dataflow for IO of secondary
2442 // structure annotation read from Stockholm files
2443 // this was added to try to ensure that
2444 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
2446 // anot[ae[aa].getPosition()].displayCharacter = "";
2448 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
2449 if (firstColour == null)
2451 firstColour = anot[anpos].colour;
2455 jalview.datamodel.AlignmentAnnotation jaa = null;
2457 if (an[i].getGraph())
2459 float llim = 0, hlim = 0;
2460 // if (autoForView || an[i].isAutoCalculated()) {
2463 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
2464 an[i].getDescription(), anot, llim, hlim,
2465 an[i].getGraphType());
2467 jaa.graphGroup = an[i].getGraphGroup();
2468 jaa._linecolour = firstColour;
2469 if (an[i].getThresholdLine() != null)
2471 jaa.setThreshold(new jalview.datamodel.GraphLine(an[i]
2472 .getThresholdLine().getValue(), an[i]
2473 .getThresholdLine().getLabel(), new java.awt.Color(
2474 an[i].getThresholdLine().getColour())));
2477 if (autoForView || an[i].isAutoCalculated())
2479 // Hardwire the symbol display line to ensure that labels for
2480 // histograms are displayed
2486 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
2487 an[i].getDescription(), anot);
2488 jaa._linecolour = firstColour;
2490 // register new annotation
2491 if (an[i].getId() != null)
2493 annotationIds.put(an[i].getId(), jaa);
2494 jaa.annotationId = an[i].getId();
2496 // recover sequence association
2497 if (an[i].getSequenceRef() != null)
2499 if (al.findName(an[i].getSequenceRef()) != null)
2501 jaa.createSequenceMapping(al.findName(an[i].getSequenceRef()),
2503 al.findName(an[i].getSequenceRef()).addAlignmentAnnotation(jaa);
2506 // and make a note of any group association
2507 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
2509 ArrayList<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
2510 .get(an[i].getGroupRef());
2513 aal = new ArrayList<jalview.datamodel.AlignmentAnnotation>();
2514 groupAnnotRefs.put(an[i].getGroupRef(), aal);
2519 if (an[i].hasScore())
2521 jaa.setScore(an[i].getScore());
2523 if (an[i].hasVisible())
2524 jaa.visible = an[i].getVisible();
2526 if (an[i].hasCentreColLabels())
2527 jaa.centreColLabels = an[i].getCentreColLabels();
2529 if (an[i].hasScaleColLabels())
2531 jaa.scaleColLabel = an[i].getScaleColLabels();
2533 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
2535 // newer files have an 'autoCalculated' flag and store calculation
2536 // state in viewport properties
2537 jaa.autoCalculated = true; // means annotation will be marked for
2538 // update at end of load.
2540 if (an[i].hasGraphHeight())
2542 jaa.graphHeight = an[i].getGraphHeight();
2544 if (an[i].hasBelowAlignment())
2546 jaa.belowAlignment = an[i].isBelowAlignment();
2548 jaa.setCalcId(an[i].getCalcId());
2550 if (jaa.autoCalculated)
2552 autoAlan.add(new JvAnnotRow(i, jaa));
2555 // if (!autoForView)
2557 // add autocalculated group annotation and any user created annotation
2559 al.addAnnotation(jaa);
2563 // ///////////////////////
2565 // Create alignment markup and styles for this view
2566 if (jms.getJGroupCount() > 0)
2568 JGroup[] groups = jms.getJGroup();
2569 boolean addAnnotSchemeGroup = false;
2570 for (int i = 0; i < groups.length; i++)
2572 ColourSchemeI cs = null;
2574 if (groups[i].getColour() != null)
2576 if (groups[i].getColour().startsWith("ucs"))
2578 cs = GetUserColourScheme(jms, groups[i].getColour());
2580 else if (groups[i].getColour().equals("AnnotationColourGradient")
2581 && groups[i].getAnnotationColours() != null)
2583 addAnnotSchemeGroup = true;
2588 cs = ColourSchemeProperty.getColour(al, groups[i].getColour());
2593 cs.setThreshold(groups[i].getPidThreshold(), true);
2597 Vector seqs = new Vector();
2599 for (int s = 0; s < groups[i].getSeqCount(); s++)
2601 String seqId = groups[i].getSeq(s) + "";
2602 jalview.datamodel.SequenceI ts = (jalview.datamodel.SequenceI) seqRefIds
2607 seqs.addElement(ts);
2611 if (seqs.size() < 1)
2616 jalview.datamodel.SequenceGroup sg = new jalview.datamodel.SequenceGroup(
2617 seqs, groups[i].getName(), cs, groups[i].getDisplayBoxes(),
2618 groups[i].getDisplayText(), groups[i].getColourText(),
2619 groups[i].getStart(), groups[i].getEnd());
2621 sg.setOutlineColour(new java.awt.Color(groups[i].getOutlineColour()));
2623 sg.textColour = new java.awt.Color(groups[i].getTextCol1());
2624 sg.textColour2 = new java.awt.Color(groups[i].getTextCol2());
2625 sg.setShowNonconserved(groups[i].hasShowUnconserved() ? groups[i]
2626 .isShowUnconserved() : false);
2627 sg.thresholdTextColour = groups[i].getTextColThreshold();
2628 if (groups[i].hasShowConsensusHistogram())
2630 sg.setShowConsensusHistogram(groups[i].isShowConsensusHistogram());
2633 if (groups[i].hasShowSequenceLogo())
2635 sg.setshowSequenceLogo(groups[i].isShowSequenceLogo());
2637 if (groups[i].hasNormaliseSequenceLogo())
2639 sg.setNormaliseSequenceLogo(groups[i].isNormaliseSequenceLogo());
2641 if (groups[i].hasIgnoreGapsinConsensus())
2643 sg.setIgnoreGapsConsensus(groups[i].getIgnoreGapsinConsensus());
2645 if (groups[i].getConsThreshold() != 0)
2647 jalview.analysis.Conservation c = new jalview.analysis.Conservation(
2648 "All", ResidueProperties.propHash, 3,
2649 sg.getSequences(null), 0, sg.getWidth() - 1);
2651 c.verdict(false, 25);
2652 sg.cs.setConservation(c);
2655 if (groups[i].getId() != null && groupAnnotRefs.size() > 0)
2657 // re-instate unique group/annotation row reference
2658 ArrayList<jalview.datamodel.AlignmentAnnotation> jaal = groupAnnotRefs
2659 .get(groups[i].getId());
2662 for (jalview.datamodel.AlignmentAnnotation jaa : jaal)
2665 if (jaa.autoCalculated)
2667 // match up and try to set group autocalc alignment row for this
2669 if (jaa.label.startsWith("Consensus for "))
2671 sg.setConsensus(jaa);
2673 // match up and try to set group autocalc alignment row for this
2675 if (jaa.label.startsWith("Conservation for "))
2677 sg.setConservationRow(jaa);
2684 if (addAnnotSchemeGroup)
2686 // reconstruct the annotation colourscheme
2687 sg.cs = constructAnnotationColour(
2688 groups[i].getAnnotationColours(), null, al, jms, false);
2694 // only dataset in this model, so just return.
2697 // ///////////////////////////////
2700 // If we just load in the same jar file again, the sequenceSetId
2701 // will be the same, and we end up with multiple references
2702 // to the same sequenceSet. We must modify this id on load
2703 // so that each load of the file gives a unique id
2704 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
2705 String viewId = (view.getId() == null ? null : view.getId()
2707 AlignFrame af = null;
2708 AlignViewport av = null;
2709 // now check to see if we really need to create a new viewport.
2710 if (multipleView && viewportsAdded.size() == 0)
2712 // We recovered an alignment for which a viewport already exists.
2713 // TODO: fix up any settings necessary for overlaying stored state onto
2714 // state recovered from another document. (may not be necessary).
2715 // we may need a binding from a viewport in memory to one recovered from
2717 // and then recover its containing af to allow the settings to be applied.
2718 // TODO: fix for vamsas demo
2720 .println("About to recover a viewport for existing alignment: Sequence set ID is "
2722 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
2723 if (seqsetobj != null)
2725 if (seqsetobj instanceof String)
2727 uniqueSeqSetId = (String) seqsetobj;
2729 .println("Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
2735 .println("Warning : Collision between sequence set ID string and existing jalview object mapping.");
2741 * indicate that annotation colours are applied across all groups (pre
2742 * Jalview 2.8.1 behaviour)
2744 boolean doGroupAnnColour = isVersionStringLaterThan("2.8.1",
2745 object.getVersion());
2747 AlignmentPanel ap = null;
2748 boolean isnewview = true;
2751 // Check to see if this alignment already has a view id == viewId
2752 jalview.gui.AlignmentPanel views[] = Desktop
2753 .getAlignmentPanels(uniqueSeqSetId);
2754 if (views != null && views.length > 0)
2756 for (int v = 0; v < views.length; v++)
2758 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
2760 // recover the existing alignpanel, alignframe, viewport
2761 af = views[v].alignFrame;
2764 // TODO: could even skip resetting view settings if we don't want to
2765 // change the local settings from other jalview processes
2774 af = loadViewport(file, JSEQ, hiddenSeqs, al, jms, view,
2775 uniqueSeqSetId, viewId, autoAlan);
2780 // /////////////////////////////////////
2781 if (loadTreesAndStructures && jms.getTreeCount() > 0)
2785 for (int t = 0; t < jms.getTreeCount(); t++)
2788 Tree tree = jms.getTree(t);
2790 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
2793 tp = af.ShowNewickTree(
2794 new jalview.io.NewickFile(tree.getNewick()),
2795 tree.getTitle(), tree.getWidth(), tree.getHeight(),
2796 tree.getXpos(), tree.getYpos());
2797 if (tree.getId() != null)
2799 // perhaps bind the tree id to something ?
2804 // update local tree attributes ?
2805 // TODO: should check if tp has been manipulated by user - if so its
2806 // settings shouldn't be modified
2807 tp.setTitle(tree.getTitle());
2808 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(), tree
2809 .getWidth(), tree.getHeight()));
2810 tp.av = av; // af.viewport; // TODO: verify 'associate with all
2813 tp.treeCanvas.av = av; // af.viewport;
2814 tp.treeCanvas.ap = ap; // af.alignPanel;
2819 warn("There was a problem recovering stored Newick tree: \n"
2820 + tree.getNewick());
2824 tp.fitToWindow.setState(tree.getFitToWindow());
2825 tp.fitToWindow_actionPerformed(null);
2827 if (tree.getFontName() != null)
2829 tp.setTreeFont(new java.awt.Font(tree.getFontName(), tree
2830 .getFontStyle(), tree.getFontSize()));
2834 tp.setTreeFont(new java.awt.Font(view.getFontName(), view
2835 .getFontStyle(), tree.getFontSize()));
2838 tp.showPlaceholders(tree.getMarkUnlinked());
2839 tp.showBootstrap(tree.getShowBootstrap());
2840 tp.showDistances(tree.getShowDistances());
2842 tp.treeCanvas.threshold = tree.getThreshold();
2844 if (tree.getCurrentTree())
2846 af.viewport.setCurrentTree(tp.getTree());
2850 } catch (Exception ex)
2852 ex.printStackTrace();
2856 // //LOAD STRUCTURES
2857 if (loadTreesAndStructures)
2859 // run through all PDB ids on the alignment, and collect mappings between
2860 // jmol view ids and all sequences referring to it
2861 Hashtable<String, Object[]> jmolViewIds = new Hashtable();
2863 for (int i = 0; i < JSEQ.length; i++)
2865 if (JSEQ[i].getPdbidsCount() > 0)
2867 Pdbids[] ids = JSEQ[i].getPdbids();
2868 for (int p = 0; p < ids.length; p++)
2870 for (int s = 0; s < ids[p].getStructureStateCount(); s++)
2872 // check to see if we haven't already created this structure view
2873 String sviewid = (ids[p].getStructureState(s).getViewId() == null) ? null
2874 : ids[p].getStructureState(s).getViewId()
2876 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
2877 // Originally : ids[p].getFile()
2878 // : TODO: verify external PDB file recovery still works in normal
2879 // jalview project load
2880 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId()));
2881 jpdb.setId(ids[p].getId());
2883 int x = ids[p].getStructureState(s).getXpos();
2884 int y = ids[p].getStructureState(s).getYpos();
2885 int width = ids[p].getStructureState(s).getWidth();
2886 int height = ids[p].getStructureState(s).getHeight();
2888 // Probably don't need to do this anymore...
2889 // Desktop.desktop.getComponentAt(x, y);
2890 // TODO: NOW: check that this recovers the PDB file correctly.
2891 String pdbFile = loadPDBFile(jprovider, ids[p].getId());
2892 jalview.datamodel.SequenceI seq = (jalview.datamodel.SequenceI) seqRefIds
2893 .get(JSEQ[i].getId() + "");
2894 if (sviewid == null)
2896 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width
2899 if (!jmolViewIds.containsKey(sviewid))
2901 jmolViewIds.put(sviewid, new Object[]
2903 { x, y, width, height }, "",
2904 new Hashtable<String, Object[]>(), new boolean[]
2905 { false, false, true } });
2906 // Legacy pre-2.7 conversion JAL-823 :
2907 // do not assume any view has to be linked for colour by
2911 // assemble String[] { pdb files }, String[] { id for each
2912 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
2913 // seqs_file 2}, boolean[] {
2914 // linkAlignPanel,superposeWithAlignpanel}} from hash
2915 Object[] jmoldat = jmolViewIds.get(sviewid);
2916 ((boolean[]) jmoldat[3])[0] |= ids[p].getStructureState(s)
2917 .hasAlignwithAlignPanel() ? ids[p].getStructureState(
2918 s).getAlignwithAlignPanel() : false;
2919 // never colour by linked panel if not specified
2920 ((boolean[]) jmoldat[3])[1] |= ids[p].getStructureState(s)
2921 .hasColourwithAlignPanel() ? ids[p]
2922 .getStructureState(s).getColourwithAlignPanel()
2924 // default for pre-2.7 projects is that Jmol colouring is enabled
2925 ((boolean[]) jmoldat[3])[2] &= ids[p].getStructureState(s)
2926 .hasColourByJmol() ? ids[p].getStructureState(s)
2927 .getColourByJmol() : true;
2929 if (((String) jmoldat[1]).length() < ids[p]
2930 .getStructureState(s).getContent().length())
2933 jmoldat[1] = ids[p].getStructureState(s).getContent();
2936 if (ids[p].getFile() != null)
2938 File mapkey = new File(ids[p].getFile());
2939 Object[] seqstrmaps = (Object[]) ((Hashtable) jmoldat[2])
2941 if (seqstrmaps == null)
2943 ((Hashtable) jmoldat[2]).put(mapkey,
2944 seqstrmaps = new Object[]
2945 { pdbFile, ids[p].getId(), new Vector(),
2948 if (!((Vector) seqstrmaps[2]).contains(seq))
2950 ((Vector) seqstrmaps[2]).addElement(seq);
2951 // ((Vector)seqstrmaps[3]).addElement(n) :
2952 // in principle, chains
2953 // should be stored here : do we need to
2954 // TODO: store and recover seq/pdb_id :
2960 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");
2969 // Instantiate the associated Jmol views
2970 for (Entry<String, Object[]> entry : jmolViewIds.entrySet())
2972 String sviewid = entry.getKey();
2973 Object[] svattrib = entry.getValue();
2974 int[] geom = (int[]) svattrib[0];
2975 String state = (String) svattrib[1];
2976 Hashtable<File, Object[]> oldFiles = (Hashtable<File, Object[]>) svattrib[2];
2977 final boolean useinJmolsuperpos = ((boolean[]) svattrib[3])[0], usetoColourbyseq = ((boolean[]) svattrib[3])[1], jmolColouring = ((boolean[]) svattrib[3])[2];
2978 int x = geom[0], y = geom[1], width = geom[2], height = geom[3];
2979 // collate the pdbfile -> sequence mappings from this view
2980 Vector<String> pdbfilenames = new Vector<String>();
2981 Vector<SequenceI[]> seqmaps = new Vector<SequenceI[]>();
2982 Vector<String> pdbids = new Vector<String>();
2984 // Search to see if we've already created this Jmol view
2985 AppJmol comp = null;
2986 JInternalFrame[] frames = null;
2991 frames = Desktop.desktop.getAllFrames();
2992 } catch (ArrayIndexOutOfBoundsException e)
2994 // occasional No such child exceptions are thrown here...
2999 } catch (Exception f)
3004 } while (frames == null);
3005 // search for any Jmol windows already open from other
3006 // alignment views that exactly match the stored structure state
3007 for (int f = 0; comp == null && f < frames.length; f++)
3009 if (frames[f] instanceof AppJmol)
3012 && ((AppJmol) frames[f]).getViewId().equals(sviewid))
3014 // post jalview 2.4 schema includes structure view id
3015 comp = (AppJmol) frames[f];
3017 else if (frames[f].getX() == x && frames[f].getY() == y
3018 && frames[f].getHeight() == height
3019 && frames[f].getWidth() == width)
3021 comp = (AppJmol) frames[f];
3028 // create a new Jmol window.
3029 // First parse the Jmol state to translate filenames loaded into the
3030 // view, and record the order in which files are shown in the Jmol
3031 // view, so we can add the sequence mappings in same order.
3032 StringBuffer newFileLoc = null;
3033 int cp = 0, ncp, ecp;
3034 while ((ncp = state.indexOf("load ", cp)) > -1)
3036 if (newFileLoc == null)
3038 newFileLoc = new StringBuffer();
3042 // look for next filename in load statement
3043 newFileLoc.append(state.substring(cp,
3044 ncp = (state.indexOf("\"", ncp + 1) + 1)));
3045 String oldfilenam = state.substring(ncp,
3046 ecp = state.indexOf("\"", ncp));
3047 // recover the new mapping data for this old filename
3048 // have to normalize filename - since Jmol and jalview do
3050 // translation differently.
3051 Object[] filedat = oldFiles.get(new File(oldfilenam));
3052 newFileLoc.append(Platform
3053 .escapeString((String) filedat[0]));
3054 pdbfilenames.addElement((String) filedat[0]);
3055 pdbids.addElement((String) filedat[1]);
3056 seqmaps.addElement(((Vector<SequenceI>) filedat[2])
3057 .toArray(new SequenceI[0]));
3058 newFileLoc.append("\"");
3059 cp = ecp + 1; // advance beyond last \" and set cursor so we can
3060 // look for next file statement.
3061 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
3065 // just append rest of state
3066 newFileLoc.append(state.substring(cp));
3071 .print("Ignoring incomplete Jmol state for PDB ids: ");
3072 newFileLoc = new StringBuffer(state);
3073 newFileLoc.append("; load append ");
3074 for (File id : oldFiles.keySet())
3076 // add this and any other pdb files that should be present in
3078 Object[] filedat = oldFiles.get(id);
3080 newFileLoc.append(((String) filedat[0]));
3081 pdbfilenames.addElement((String) filedat[0]);
3082 pdbids.addElement((String) filedat[1]);
3083 seqmaps.addElement(((Vector<SequenceI>) filedat[2])
3084 .toArray(new SequenceI[0]));
3085 newFileLoc.append(" \"");
3086 newFileLoc.append((String) filedat[0]);
3087 newFileLoc.append("\"");
3090 newFileLoc.append(";");
3093 if (newFileLoc != null)
3095 int histbug = newFileLoc.indexOf("history = ");
3097 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";",
3099 String val = (diff == -1) ? null : newFileLoc.substring(
3101 if (val != null && val.length() >= 4)
3103 if (val.contains("e"))
3105 if (val.trim().equals("true"))
3113 newFileLoc.replace(histbug, diff, val);
3116 // TODO: assemble String[] { pdb files }, String[] { id for each
3117 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3118 // seqs_file 2}} from hash
3119 final String[] pdbf = pdbfilenames
3120 .toArray(new String[pdbfilenames.size()]), id = pdbids
3121 .toArray(new String[pdbids.size()]);
3122 final SequenceI[][] sq = seqmaps
3123 .toArray(new SequenceI[seqmaps.size()][]);
3124 final String fileloc = newFileLoc.toString(), vid = sviewid;
3125 final AlignFrame alf = af;
3126 final java.awt.Rectangle rect = new java.awt.Rectangle(x, y,
3130 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
3135 AppJmol sview = null;
3138 sview = new AppJmol(pdbf, id, sq, alf.alignPanel,
3139 useinJmolsuperpos, usetoColourbyseq,
3140 jmolColouring, fileloc, rect, vid);
3141 addNewStructureViewer(sview);
3142 } catch (OutOfMemoryError ex)
3144 new OOMWarning("restoring structure view for PDB id "
3145 + id, (OutOfMemoryError) ex.getCause());
3146 if (sview != null && sview.isVisible())
3148 sview.closeViewer();
3149 sview.setVisible(false);
3155 } catch (InvocationTargetException ex)
3157 warn("Unexpected error when opening Jmol view.", ex);
3159 } catch (InterruptedException e)
3161 // e.printStackTrace();
3167 // if (comp != null)
3169 // NOTE: if the jalview project is part of a shared session then
3170 // view synchronization should/could be done here.
3172 // add mapping for sequences in this view to an already open Jmol
3174 for (File id : oldFiles.keySet())
3176 // add this and any other pdb files that should be present in the
3178 Object[] filedat = oldFiles.get(id);
3179 String pdbFile = (String) filedat[0];
3180 SequenceI[] seq = ((Vector<SequenceI>) filedat[2])
3181 .toArray(new SequenceI[0]);
3182 comp.jmb.ssm.setMapping(seq, null, pdbFile,
3183 jalview.io.AppletFormatAdapter.FILE);
3184 comp.jmb.addSequenceForStructFile(pdbFile, seq);
3186 // and add the AlignmentPanel's reference to the Jmol view
3187 comp.addAlignmentPanel(ap);
3188 if (useinJmolsuperpos)
3190 comp.useAlignmentPanelForSuperposition(ap);
3194 comp.excludeAlignmentPanelForSuperposition(ap);
3196 if (usetoColourbyseq)
3198 comp.useAlignmentPanelForColourbyseq(ap, !jmolColouring);
3202 comp.excludeAlignmentPanelForColourbyseq(ap);
3208 // and finally return.
3215 * - minimum version we are comparing against
3217 * - version of data being processsed.
3218 * @return true if version is development/null or evaluates to the same or
3219 * later X.Y.Z (where X,Y,Z are like [0-9]+b?[0-9]*)
3221 private boolean isVersionStringLaterThan(String supported, String version)
3223 if (version == null || version.equalsIgnoreCase("DEVELOPMENT BUILD")
3224 || version.equalsIgnoreCase("Test")
3225 || version.equalsIgnoreCase("AUTOMATED BUILD"))
3227 System.err.println("Assuming project file with "
3228 + (version == null ? "null" : version)
3229 + " is compatible with Jalview version " + supported);
3234 StringTokenizer currentV = new StringTokenizer(supported, "."), fileV = new StringTokenizer(
3236 while (currentV.hasMoreTokens() && fileV.hasMoreTokens())
3238 // convert b to decimal to catch bugfix releases within a series
3239 String curT = currentV.nextToken().toLowerCase().replace('b', '.');
3240 String fileT = fileV.nextToken().toLowerCase().replace('b', '.');
3243 if (Float.valueOf(curT) > Float.valueOf(fileT))
3245 // current version is newer than the version that wrote the file
3248 } catch (NumberFormatException nfe)
3251 .println("** WARNING: Version comparison failed for tokens ("
3255 + ")\n** Current: '"
3256 + supported + "' and Version: '" + version + "'");
3259 if (currentV.hasMoreElements())
3261 // fileV has no minor version but identical series to current
3268 Vector<AppJmol> newStructureViewers = null;
3270 protected void addNewStructureViewer(AppJmol sview)
3272 if (newStructureViewers != null)
3274 sview.jmb.setFinishedLoadingFromArchive(false);
3275 newStructureViewers.add(sview);
3279 protected void setLoadingFinishedForNewStructureViewers()
3281 if (newStructureViewers != null)
3283 for (AppJmol sview : newStructureViewers)
3285 sview.jmb.setFinishedLoadingFromArchive(true);
3287 newStructureViewers.clear();
3288 newStructureViewers = null;
3292 AlignFrame loadViewport(String file, JSeq[] JSEQ, Vector hiddenSeqs,
3293 Alignment al, JalviewModelSequence jms, Viewport view,
3294 String uniqueSeqSetId, String viewId,
3295 ArrayList<JvAnnotRow> autoAlan)
3297 AlignFrame af = null;
3298 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
3299 uniqueSeqSetId, viewId);
3301 af.setFileName(file, "Jalview");
3303 for (int i = 0; i < JSEQ.length; i++)
3305 af.viewport.setSequenceColour(af.viewport.getAlignment()
3306 .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour()));
3309 af.viewport.gatherViewsHere = view.getGatheredViews();
3311 if (view.getSequenceSetId() != null)
3313 jalview.gui.AlignViewport av = (jalview.gui.AlignViewport) viewportsAdded
3314 .get(uniqueSeqSetId);
3316 af.viewport.setSequenceSetId(uniqueSeqSetId);
3319 // propagate shared settings to this new view
3320 af.viewport.historyList = av.historyList;
3321 af.viewport.redoList = av.redoList;
3325 viewportsAdded.put(uniqueSeqSetId, af.viewport);
3327 // TODO: check if this method can be called repeatedly without
3328 // side-effects if alignpanel already registered.
3329 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
3331 // apply Hidden regions to view.
3332 if (hiddenSeqs != null)
3334 for (int s = 0; s < JSEQ.length; s++)
3336 jalview.datamodel.SequenceGroup hidden = new jalview.datamodel.SequenceGroup();
3338 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
3341 al.getSequenceAt(JSEQ[s].getHiddenSequences(r)), false);
3343 af.viewport.hideRepSequences(al.getSequenceAt(s), hidden);
3346 jalview.datamodel.SequenceI[] hseqs = new jalview.datamodel.SequenceI[hiddenSeqs
3349 for (int s = 0; s < hiddenSeqs.size(); s++)
3351 hseqs[s] = (jalview.datamodel.SequenceI) hiddenSeqs.elementAt(s);
3354 af.viewport.hideSequence(hseqs);
3357 // recover view properties and display parameters
3358 if (view.getViewName() != null)
3360 af.viewport.viewName = view.getViewName();
3361 af.setInitialTabVisible();
3363 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
3366 af.viewport.setShowAnnotation(view.getShowAnnotation());
3367 af.viewport.setAbovePIDThreshold(view.getPidSelected());
3369 af.viewport.setColourText(view.getShowColourText());
3371 af.viewport.setConservationSelected(view.getConservationSelected());
3372 af.viewport.setShowJVSuffix(view.getShowFullId());
3373 af.viewport.rightAlignIds = view.getRightAlignIds();
3374 af.viewport.setFont(new java.awt.Font(view.getFontName(), view
3375 .getFontStyle(), view.getFontSize()));
3376 af.alignPanel.fontChanged();
3377 af.viewport.setRenderGaps(view.getRenderGaps());
3378 af.viewport.setWrapAlignment(view.getWrapAlignment());
3379 af.alignPanel.setWrapAlignment(view.getWrapAlignment());
3380 af.viewport.setShowAnnotation(view.getShowAnnotation());
3381 af.alignPanel.setAnnotationVisible(view.getShowAnnotation());
3383 af.viewport.setShowBoxes(view.getShowBoxes());
3385 af.viewport.setShowText(view.getShowText());
3387 af.viewport.textColour = new java.awt.Color(view.getTextCol1());
3388 af.viewport.textColour2 = new java.awt.Color(view.getTextCol2());
3389 af.viewport.thresholdTextColour = view.getTextColThreshold();
3390 af.viewport.setShowUnconserved(view.hasShowUnconserved() ? view
3391 .isShowUnconserved() : false);
3392 af.viewport.setStartRes(view.getStartRes());
3393 af.viewport.setStartSeq(view.getStartSeq());
3395 ColourSchemeI cs = null;
3396 // apply colourschemes
3397 if (view.getBgColour() != null)
3399 if (view.getBgColour().startsWith("ucs"))
3401 cs = GetUserColourScheme(jms, view.getBgColour());
3403 else if (view.getBgColour().startsWith("Annotation"))
3405 AnnotationColours viewAnnColour = view.getAnnotationColours();
3406 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
3413 cs = ColourSchemeProperty.getColour(al, view.getBgColour());
3418 cs.setThreshold(view.getPidThreshold(), true);
3419 cs.setConsensus(af.viewport.getSequenceConsensusHash());
3423 af.viewport.setGlobalColourScheme(cs);
3424 af.viewport.setColourAppliesToAllGroups(false);
3426 if (view.getConservationSelected() && cs != null)
3428 cs.setConservationInc(view.getConsThreshold());
3431 af.changeColour(cs);
3433 af.viewport.setColourAppliesToAllGroups(true);
3435 af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures());
3437 if (view.hasCentreColumnLabels())
3439 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
3441 if (view.hasIgnoreGapsinConsensus())
3443 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
3446 if (view.hasFollowHighlight())
3448 af.viewport.followHighlight = view.getFollowHighlight();
3450 if (view.hasFollowSelection())
3452 af.viewport.followSelection = view.getFollowSelection();
3454 if (view.hasShowConsensusHistogram())
3456 af.viewport.setShowConsensusHistogram(view
3457 .getShowConsensusHistogram());
3461 af.viewport.setShowConsensusHistogram(true);
3463 if (view.hasShowSequenceLogo())
3465 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
3469 af.viewport.setShowSequenceLogo(false);
3471 if (view.hasNormaliseSequenceLogo())
3473 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
3475 if (view.hasShowDbRefTooltip())
3477 af.viewport.setShowDbRefs(view.getShowDbRefTooltip());
3479 if (view.hasShowNPfeatureTooltip())
3481 af.viewport.setShowNpFeats(view.hasShowNPfeatureTooltip());
3483 if (view.hasShowGroupConsensus())
3485 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
3489 af.viewport.setShowGroupConsensus(false);
3491 if (view.hasShowGroupConservation())
3493 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
3497 af.viewport.setShowGroupConservation(false);
3500 // recover featre settings
3501 if (jms.getFeatureSettings() != null)
3503 af.viewport.featuresDisplayed = new Hashtable();
3504 String[] renderOrder = new String[jms.getFeatureSettings()
3505 .getSettingCount()];
3506 for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
3508 Setting setting = jms.getFeatureSettings().getSetting(fs);
3509 if (setting.hasMincolour())
3511 GraduatedColor gc = setting.hasMin() ? new GraduatedColor(
3512 new java.awt.Color(setting.getMincolour()),
3513 new java.awt.Color(setting.getColour()),
3514 setting.getMin(), setting.getMax()) : new GraduatedColor(
3515 new java.awt.Color(setting.getMincolour()),
3516 new java.awt.Color(setting.getColour()), 0, 1);
3517 if (setting.hasThreshold())
3519 gc.setThresh(setting.getThreshold());
3520 gc.setThreshType(setting.getThreshstate());
3522 gc.setAutoScaled(true); // default
3523 if (setting.hasAutoScale())
3525 gc.setAutoScaled(setting.getAutoScale());
3527 if (setting.hasColourByLabel())
3529 gc.setColourByLabel(setting.getColourByLabel());
3531 // and put in the feature colour table.
3532 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setColour(
3533 setting.getType(), gc);
3537 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setColour(
3539 new java.awt.Color(setting.getColour()));
3541 renderOrder[fs] = setting.getType();
3542 if (setting.hasOrder())
3543 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setOrder(
3544 setting.getType(), setting.getOrder());
3546 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setOrder(
3548 fs / jms.getFeatureSettings().getSettingCount());
3549 if (setting.getDisplay())
3551 af.viewport.featuresDisplayed.put(setting.getType(), new Integer(
3552 setting.getColour()));
3555 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().renderOrder = renderOrder;
3557 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().featureGroups = fgtable = new Hashtable();
3558 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
3560 Group grp = jms.getFeatureSettings().getGroup(gs);
3561 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
3565 if (view.getHiddenColumnsCount() > 0)
3567 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
3569 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(), view
3570 .getHiddenColumns(c).getEnd() // +1
3574 if (view.getCalcIdParam() != null)
3576 for (CalcIdParam calcIdParam : view.getCalcIdParam())
3578 if (calcIdParam != null)
3580 if (recoverCalcIdParam(calcIdParam, af.viewport))
3585 warn("Couldn't recover parameters for "
3586 + calcIdParam.getCalcId());
3591 af.setMenusFromViewport(af.viewport);
3592 // TODO: we don't need to do this if the viewport is aready visible.
3593 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
3595 af.alignPanel.updateAnnotation(false, true); // recompute any autoannotation
3596 reorderAutoannotation(af, al, autoAlan);
3597 af.alignPanel.alignmentChanged();
3601 private ColourSchemeI constructAnnotationColour(
3602 AnnotationColours viewAnnColour, AlignFrame af, Alignment al,
3603 JalviewModelSequence jms, boolean checkGroupAnnColour)
3605 boolean propagateAnnColour = false;
3606 ColourSchemeI cs = null;
3607 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
3608 if (checkGroupAnnColour && al.getGroups() != null
3609 && al.getGroups().size() > 0)
3611 // pre 2.8.1 behaviour
3612 // check to see if we should transfer annotation colours
3613 propagateAnnColour = true;
3614 for (jalview.datamodel.SequenceGroup sg : al.getGroups())
3616 if (sg.cs instanceof AnnotationColourGradient)
3618 propagateAnnColour = false;
3622 // int find annotation
3623 if (annAlignment.getAlignmentAnnotation() != null)
3625 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
3627 if (annAlignment.getAlignmentAnnotation()[i].label
3628 .equals(viewAnnColour.getAnnotation()))
3630 if (annAlignment.getAlignmentAnnotation()[i].getThreshold() == null)
3632 annAlignment.getAlignmentAnnotation()[i]
3633 .setThreshold(new jalview.datamodel.GraphLine(
3634 viewAnnColour.getThreshold(), "Threshold",
3635 java.awt.Color.black)
3640 if (viewAnnColour.getColourScheme().equals("None"))
3642 cs = new AnnotationColourGradient(
3643 annAlignment.getAlignmentAnnotation()[i],
3644 new java.awt.Color(viewAnnColour.getMinColour()),
3645 new java.awt.Color(viewAnnColour.getMaxColour()),
3646 viewAnnColour.getAboveThreshold());
3648 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
3650 cs = new AnnotationColourGradient(
3651 annAlignment.getAlignmentAnnotation()[i],
3652 GetUserColourScheme(jms,
3653 viewAnnColour.getColourScheme()),
3654 viewAnnColour.getAboveThreshold());
3658 cs = new AnnotationColourGradient(
3659 annAlignment.getAlignmentAnnotation()[i],
3660 ColourSchemeProperty.getColour(al,
3661 viewAnnColour.getColourScheme()),
3662 viewAnnColour.getAboveThreshold());
3664 if (viewAnnColour.hasPerSequence())
3666 ((AnnotationColourGradient) cs).setSeqAssociated(viewAnnColour
3669 if (viewAnnColour.hasPredefinedColours())
3671 ((AnnotationColourGradient) cs)
3672 .setPredefinedColours(viewAnnColour
3673 .isPredefinedColours());
3675 if (propagateAnnColour && al.getGroups() != null)
3677 // Also use these settings for all the groups
3678 for (int g = 0; g < al.getGroups().size(); g++)
3680 jalview.datamodel.SequenceGroup sg = al.getGroups().get(g);
3688 * if (viewAnnColour.getColourScheme().equals("None" )) { sg.cs =
3689 * new AnnotationColourGradient(
3690 * annAlignment.getAlignmentAnnotation()[i], new
3691 * java.awt.Color(viewAnnColour. getMinColour()), new
3692 * java.awt.Color(viewAnnColour. getMaxColour()),
3693 * viewAnnColour.getAboveThreshold()); } else
3696 sg.cs = new AnnotationColourGradient(
3697 annAlignment.getAlignmentAnnotation()[i], sg.cs,
3698 viewAnnColour.getAboveThreshold());
3699 if (cs instanceof AnnotationColourGradient)
3701 if (viewAnnColour.hasPerSequence())
3703 ((AnnotationColourGradient) cs)
3704 .setSeqAssociated(viewAnnColour.isPerSequence());
3706 if (viewAnnColour.hasPredefinedColours())
3708 ((AnnotationColourGradient) cs)
3709 .setPredefinedColours(viewAnnColour
3710 .isPredefinedColours());
3726 private void reorderAutoannotation(AlignFrame af, Alignment al,
3727 ArrayList<JvAnnotRow> autoAlan)
3729 // copy over visualization settings for autocalculated annotation in the
3731 if (al.getAlignmentAnnotation() != null)
3734 * Kludge for magic autoannotation names (see JAL-811)
3736 String[] magicNames = new String[]
3737 { "Consensus", "Quality", "Conservation" };
3738 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
3739 Hashtable<String, JvAnnotRow> visan = new Hashtable<String, JvAnnotRow>();
3740 for (String nm : magicNames)
3742 visan.put(nm, nullAnnot);
3744 for (JvAnnotRow auan : autoAlan)
3746 visan.put(auan.template.label
3747 + (auan.template.getCalcId() == null ? "" : "\t"
3748 + auan.template.getCalcId()), auan);
3750 int hSize = al.getAlignmentAnnotation().length;
3751 ArrayList<JvAnnotRow> reorder = new ArrayList<JvAnnotRow>();
3752 // work through any autoCalculated annotation already on the view
3753 // removing it if it should be placed in a different location on the
3754 // annotation panel.
3755 List<String> remains = new ArrayList(visan.keySet());
3756 for (int h = 0; h < hSize; h++)
3758 jalview.datamodel.AlignmentAnnotation jalan = al
3759 .getAlignmentAnnotation()[h];
3760 if (jalan.autoCalculated)
3763 JvAnnotRow valan = visan.get(k = jalan.label);
3764 if (jalan.getCalcId() != null)
3766 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
3771 // delete the auto calculated row from the alignment
3772 al.deleteAnnotation(jalan, false);
3776 if (valan != nullAnnot)
3778 if (jalan != valan.template)
3780 // newly created autoannotation row instance
3781 // so keep a reference to the visible annotation row
3782 // and copy over all relevant attributes
3783 if (valan.template.graphHeight >= 0)
3786 jalan.graphHeight = valan.template.graphHeight;
3788 jalan.visible = valan.template.visible;
3790 reorder.add(new JvAnnotRow(valan.order, jalan));
3795 // Add any (possibly stale) autocalculated rows that were not appended to
3796 // the view during construction
3797 for (String other : remains)
3799 JvAnnotRow othera = visan.get(other);
3800 if (othera != nullAnnot && othera.template.getCalcId() != null
3801 && othera.template.getCalcId().length() > 0)
3803 reorder.add(othera);
3806 // now put the automatic annotation in its correct place
3807 int s = 0, srt[] = new int[reorder.size()];
3808 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
3809 for (JvAnnotRow jvar : reorder)
3812 srt[s++] = jvar.order;
3815 jalview.util.QuickSort.sort(srt, rws);
3816 // and re-insert the annotation at its correct position
3817 for (JvAnnotRow jvar : rws)
3819 al.addAnnotation(jvar.template, jvar.order);
3821 af.alignPanel.adjustAnnotationHeight();
3825 Hashtable skipList = null;
3828 * TODO remove this method
3831 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
3832 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
3833 * throw new Error("Implementation Error. No skipList defined for this
3834 * Jalview2XML instance."); } return (AlignFrame)
3835 * skipList.get(view.getSequenceSetId()); }
3839 * Check if the Jalview view contained in object should be skipped or not.
3842 * @return true if view's sequenceSetId is a key in skipList
3844 private boolean skipViewport(JalviewModel object)
3846 if (skipList == null)
3851 if (skipList.containsKey(id = object.getJalviewModelSequence()
3852 .getViewport()[0].getSequenceSetId()))
3854 if (Cache.log != null && Cache.log.isDebugEnabled())
3856 Cache.log.debug("Skipping seuqence set id " + id);
3863 public void AddToSkipList(AlignFrame af)
3865 if (skipList == null)
3867 skipList = new Hashtable();
3869 skipList.put(af.getViewport().getSequenceSetId(), af);
3872 public void clearSkipList()
3874 if (skipList != null)
3881 private void recoverDatasetFor(SequenceSet vamsasSet, Alignment al)
3883 jalview.datamodel.Alignment ds = getDatasetFor(vamsasSet.getDatasetId());
3884 Vector dseqs = null;
3887 // create a list of new dataset sequences
3888 dseqs = new Vector();
3890 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
3892 Sequence vamsasSeq = vamsasSet.getSequence(i);
3893 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs);
3895 // create a new dataset
3898 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
3899 dseqs.copyInto(dsseqs);
3900 ds = new jalview.datamodel.Alignment(dsseqs);
3901 debug("Created new dataset " + vamsasSet.getDatasetId()
3902 + " for alignment " + System.identityHashCode(al));
3903 addDatasetRef(vamsasSet.getDatasetId(), ds);
3905 // set the dataset for the newly imported alignment.
3906 if (al.getDataset() == null)
3915 * sequence definition to create/merge dataset sequence for
3919 * vector to add new dataset sequence to
3921 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
3922 AlignmentI ds, Vector dseqs)
3924 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
3926 jalview.datamodel.Sequence sq = (jalview.datamodel.Sequence) seqRefIds
3927 .get(vamsasSeq.getId());
3928 jalview.datamodel.SequenceI dsq = null;
3929 if (sq != null && sq.getDatasetSequence() != null)
3931 dsq = sq.getDatasetSequence();
3934 String sqid = vamsasSeq.getDsseqid();
3937 // need to create or add a new dataset sequence reference to this sequence
3940 dsq = (jalview.datamodel.SequenceI) seqRefIds.get(sqid);
3945 // make a new dataset sequence
3946 dsq = sq.createDatasetSequence();
3949 // make up a new dataset reference for this sequence
3950 sqid = seqHash(dsq);
3952 dsq.setVamsasId(uniqueSetSuffix + sqid);
3953 seqRefIds.put(sqid, dsq);
3958 dseqs.addElement(dsq);
3963 ds.addSequence(dsq);
3969 { // make this dataset sequence sq's dataset sequence
3970 sq.setDatasetSequence(dsq);
3971 // and update the current dataset alignment
3976 if (!dseqs.contains(dsq))
3983 if (ds.findIndex(dsq) < 0)
3985 ds.addSequence(dsq);
3992 // TODO: refactor this as a merge dataset sequence function
3993 // now check that sq (the dataset sequence) sequence really is the union of
3994 // all references to it
3995 // boolean pre = sq.getStart() < dsq.getStart();
3996 // boolean post = sq.getEnd() > dsq.getEnd();
4000 StringBuffer sb = new StringBuffer();
4001 String newres = jalview.analysis.AlignSeq.extractGaps(
4002 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
4003 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
4004 && newres.length() > dsq.getLength())
4006 // Update with the longer sequence.
4010 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
4011 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
4012 * sb.append(newres.substring(newres.length() - sq.getEnd() -
4013 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
4015 dsq.setSequence(newres);
4017 // TODO: merges will never happen if we 'know' we have the real dataset
4018 // sequence - this should be detected when id==dssid
4020 .println("DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
4021 // + (pre ? "prepended" : "") + " "
4022 // + (post ? "appended" : ""));
4027 java.util.Hashtable datasetIds = null;
4029 java.util.IdentityHashMap dataset2Ids = null;
4031 private Alignment getDatasetFor(String datasetId)
4033 if (datasetIds == null)
4035 datasetIds = new Hashtable();
4038 if (datasetIds.containsKey(datasetId))
4040 return (Alignment) datasetIds.get(datasetId);
4045 private void addDatasetRef(String datasetId, Alignment dataset)
4047 if (datasetIds == null)
4049 datasetIds = new Hashtable();
4051 datasetIds.put(datasetId, dataset);
4055 * make a new dataset ID for this jalview dataset alignment
4060 private String getDatasetIdRef(jalview.datamodel.Alignment dataset)
4062 if (dataset.getDataset() != null)
4064 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
4066 String datasetId = makeHashCode(dataset, null);
4067 if (datasetId == null)
4069 // make a new datasetId and record it
4070 if (dataset2Ids == null)
4072 dataset2Ids = new IdentityHashMap();
4076 datasetId = (String) dataset2Ids.get(dataset);
4078 if (datasetId == null)
4080 datasetId = "ds" + dataset2Ids.size() + 1;
4081 dataset2Ids.put(dataset, datasetId);
4087 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
4089 for (int d = 0; d < sequence.getDBRefCount(); d++)
4091 DBRef dr = sequence.getDBRef(d);
4092 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
4093 sequence.getDBRef(d).getSource(), sequence.getDBRef(d)
4094 .getVersion(), sequence.getDBRef(d).getAccessionId());
4095 if (dr.getMapping() != null)
4097 entry.setMap(addMapping(dr.getMapping()));
4099 datasetSequence.addDBRef(entry);
4103 private jalview.datamodel.Mapping addMapping(Mapping m)
4105 SequenceI dsto = null;
4106 // Mapping m = dr.getMapping();
4107 int fr[] = new int[m.getMapListFromCount() * 2];
4108 Enumeration f = m.enumerateMapListFrom();
4109 for (int _i = 0; f.hasMoreElements(); _i += 2)
4111 MapListFrom mf = (MapListFrom) f.nextElement();
4112 fr[_i] = mf.getStart();
4113 fr[_i + 1] = mf.getEnd();
4115 int fto[] = new int[m.getMapListToCount() * 2];
4116 f = m.enumerateMapListTo();
4117 for (int _i = 0; f.hasMoreElements(); _i += 2)
4119 MapListTo mf = (MapListTo) f.nextElement();
4120 fto[_i] = mf.getStart();
4121 fto[_i + 1] = mf.getEnd();
4123 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto,
4124 fr, fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
4125 if (m.getMappingChoice() != null)
4127 MappingChoice mc = m.getMappingChoice();
4128 if (mc.getDseqFor() != null)
4130 String dsfor = "" + mc.getDseqFor();
4131 if (seqRefIds.containsKey(dsfor))
4136 jmap.setTo((SequenceI) seqRefIds.get(dsfor));
4140 frefedSequence.add(new Object[]
4147 * local sequence definition
4149 Sequence ms = mc.getSequence();
4150 jalview.datamodel.Sequence djs = null;
4151 String sqid = ms.getDsseqid();
4152 if (sqid != null && sqid.length() > 0)
4155 * recover dataset sequence
4157 djs = (jalview.datamodel.Sequence) seqRefIds.get(sqid);
4162 .println("Warning - making up dataset sequence id for DbRef sequence map reference");
4163 sqid = ((Object) ms).toString(); // make up a new hascode for
4164 // undefined dataset sequence hash
4165 // (unlikely to happen)
4171 * make a new dataset sequence and add it to refIds hash
4173 djs = new jalview.datamodel.Sequence(ms.getName(),
4175 djs.setStart(jmap.getMap().getToLowest());
4176 djs.setEnd(jmap.getMap().getToHighest());
4177 djs.setVamsasId(uniqueSetSuffix + sqid);
4179 seqRefIds.put(sqid, djs);
4182 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
4191 public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
4192 boolean keepSeqRefs)
4195 jalview.schemabinding.version2.JalviewModel jm = SaveState(ap, null,
4201 jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
4205 uniqueSetSuffix = "";
4206 jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
4211 if (this.frefedSequence == null)
4213 frefedSequence = new Vector();
4216 viewportsAdded = new Hashtable();
4218 AlignFrame af = LoadFromObject(jm, null, false, null);
4219 af.alignPanels.clear();
4220 af.closeMenuItem_actionPerformed(true);
4223 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
4224 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
4225 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
4226 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
4227 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
4230 return af.alignPanel;
4234 * flag indicating if hashtables should be cleared on finalization TODO this
4235 * flag may not be necessary
4237 private final boolean _cleartables = true;
4239 private Hashtable jvids2vobj;
4244 * @see java.lang.Object#finalize()
4247 protected void finalize() throws Throwable
4249 // really make sure we have no buried refs left.
4254 this.seqRefIds = null;
4255 this.seqsToIds = null;
4259 private void warn(String msg)
4264 private void warn(String msg, Exception e)
4266 if (Cache.log != null)
4270 Cache.log.warn(msg, e);
4274 Cache.log.warn(msg);
4279 System.err.println("Warning: " + msg);
4282 e.printStackTrace();
4287 private void debug(String string)
4289 debug(string, null);
4292 private void debug(String msg, Exception e)
4294 if (Cache.log != null)
4298 Cache.log.debug(msg, e);
4302 Cache.log.debug(msg);
4307 System.err.println("Warning: " + msg);
4310 e.printStackTrace();
4316 * set the object to ID mapping tables used to write/recover objects and XML
4317 * ID strings for the jalview project. If external tables are provided then
4318 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
4319 * object goes out of scope. - also populates the datasetIds hashtable with
4320 * alignment objects containing dataset sequences
4323 * Map from ID strings to jalview datamodel
4325 * Map from jalview datamodel to ID strings
4329 public void setObjectMappingTables(Hashtable vobj2jv,
4330 IdentityHashMap jv2vobj)
4332 this.jv2vobj = jv2vobj;
4333 this.vobj2jv = vobj2jv;
4334 Iterator ds = jv2vobj.keySet().iterator();
4336 while (ds.hasNext())
4338 Object jvobj = ds.next();
4339 id = jv2vobj.get(jvobj).toString();
4340 if (jvobj instanceof jalview.datamodel.Alignment)
4342 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
4344 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
4347 else if (jvobj instanceof jalview.datamodel.Sequence)
4349 // register sequence object so the XML parser can recover it.
4350 if (seqRefIds == null)
4352 seqRefIds = new Hashtable();
4354 if (seqsToIds == null)
4356 seqsToIds = new IdentityHashMap();
4358 seqRefIds.put(jv2vobj.get(jvobj).toString(), jvobj);
4359 seqsToIds.put(jvobj, id);
4361 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
4363 if (annotationIds == null)
4365 annotationIds = new Hashtable();
4368 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvobj);
4369 jalview.datamodel.AlignmentAnnotation jvann = (jalview.datamodel.AlignmentAnnotation) jvobj;
4370 if (jvann.annotationId == null)
4372 jvann.annotationId = anid;
4374 if (!jvann.annotationId.equals(anid))
4376 // TODO verify that this is the correct behaviour
4377 this.warn("Overriding Annotation ID for " + anid
4378 + " from different id : " + jvann.annotationId);
4379 jvann.annotationId = anid;
4382 else if (jvobj instanceof String)
4384 if (jvids2vobj == null)
4386 jvids2vobj = new Hashtable();
4387 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
4391 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
4396 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
4397 * objects created from the project archive. If string is null (default for
4398 * construction) then suffix will be set automatically.
4402 public void setUniqueSetSuffix(String string)
4404 uniqueSetSuffix = string;
4409 * uses skipList2 as the skipList for skipping views on sequence sets
4410 * associated with keys in the skipList
4414 public void setSkipList(Hashtable skipList2)
4416 skipList = skipList2;