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.showSequenceFeatures);
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 if (view.getShowSequenceFeatures())
3437 af.viewport.showSequenceFeatures = true;
3439 if (view.hasCentreColumnLabels())
3441 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
3443 if (view.hasIgnoreGapsinConsensus())
3445 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
3448 if (view.hasFollowHighlight())
3450 af.viewport.followHighlight = view.getFollowHighlight();
3452 if (view.hasFollowSelection())
3454 af.viewport.followSelection = view.getFollowSelection();
3456 if (view.hasShowConsensusHistogram())
3458 af.viewport.setShowConsensusHistogram(view
3459 .getShowConsensusHistogram());
3463 af.viewport.setShowConsensusHistogram(true);
3465 if (view.hasShowSequenceLogo())
3467 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
3471 af.viewport.setShowSequenceLogo(false);
3473 if (view.hasNormaliseSequenceLogo())
3475 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
3477 if (view.hasShowDbRefTooltip())
3479 af.viewport.setShowDbRefs(view.getShowDbRefTooltip());
3481 if (view.hasShowNPfeatureTooltip())
3483 af.viewport.setShowNpFeats(view.hasShowNPfeatureTooltip());
3485 if (view.hasShowGroupConsensus())
3487 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
3491 af.viewport.setShowGroupConsensus(false);
3493 if (view.hasShowGroupConservation())
3495 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
3499 af.viewport.setShowGroupConservation(false);
3502 // recover featre settings
3503 if (jms.getFeatureSettings() != null)
3505 af.viewport.featuresDisplayed = new Hashtable();
3506 String[] renderOrder = new String[jms.getFeatureSettings()
3507 .getSettingCount()];
3508 for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
3510 Setting setting = jms.getFeatureSettings().getSetting(fs);
3511 if (setting.hasMincolour())
3513 GraduatedColor gc = setting.hasMin() ? new GraduatedColor(
3514 new java.awt.Color(setting.getMincolour()),
3515 new java.awt.Color(setting.getColour()),
3516 setting.getMin(), setting.getMax()) : new GraduatedColor(
3517 new java.awt.Color(setting.getMincolour()),
3518 new java.awt.Color(setting.getColour()), 0, 1);
3519 if (setting.hasThreshold())
3521 gc.setThresh(setting.getThreshold());
3522 gc.setThreshType(setting.getThreshstate());
3524 gc.setAutoScaled(true); // default
3525 if (setting.hasAutoScale())
3527 gc.setAutoScaled(setting.getAutoScale());
3529 if (setting.hasColourByLabel())
3531 gc.setColourByLabel(setting.getColourByLabel());
3533 // and put in the feature colour table.
3534 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setColour(
3535 setting.getType(), gc);
3539 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setColour(
3541 new java.awt.Color(setting.getColour()));
3543 renderOrder[fs] = setting.getType();
3544 if (setting.hasOrder())
3545 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setOrder(
3546 setting.getType(), setting.getOrder());
3548 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setOrder(
3550 fs / jms.getFeatureSettings().getSettingCount());
3551 if (setting.getDisplay())
3553 af.viewport.featuresDisplayed.put(setting.getType(), new Integer(
3554 setting.getColour()));
3557 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().renderOrder = renderOrder;
3559 af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().featureGroups = fgtable = new Hashtable();
3560 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
3562 Group grp = jms.getFeatureSettings().getGroup(gs);
3563 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
3567 if (view.getHiddenColumnsCount() > 0)
3569 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
3571 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(), view
3572 .getHiddenColumns(c).getEnd() // +1
3576 if (view.getCalcIdParam() != null)
3578 for (CalcIdParam calcIdParam : view.getCalcIdParam())
3580 if (calcIdParam != null)
3582 if (recoverCalcIdParam(calcIdParam, af.viewport))
3587 warn("Couldn't recover parameters for "
3588 + calcIdParam.getCalcId());
3593 af.setMenusFromViewport(af.viewport);
3594 // TODO: we don't need to do this if the viewport is aready visible.
3595 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
3597 af.alignPanel.updateAnnotation(false, true); // recompute any autoannotation
3598 reorderAutoannotation(af, al, autoAlan);
3599 af.alignPanel.alignmentChanged();
3603 private ColourSchemeI constructAnnotationColour(
3604 AnnotationColours viewAnnColour, AlignFrame af, Alignment al,
3605 JalviewModelSequence jms, boolean checkGroupAnnColour)
3607 boolean propagateAnnColour = false;
3608 ColourSchemeI cs = null;
3609 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
3610 if (checkGroupAnnColour && al.getGroups() != null
3611 && al.getGroups().size() > 0)
3613 // pre 2.8.1 behaviour
3614 // check to see if we should transfer annotation colours
3615 propagateAnnColour = true;
3616 for (jalview.datamodel.SequenceGroup sg : al.getGroups())
3618 if (sg.cs instanceof AnnotationColourGradient)
3620 propagateAnnColour = false;
3624 // int find annotation
3625 if (annAlignment.getAlignmentAnnotation() != null)
3627 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
3629 if (annAlignment.getAlignmentAnnotation()[i].label
3630 .equals(viewAnnColour.getAnnotation()))
3632 if (annAlignment.getAlignmentAnnotation()[i].getThreshold() == null)
3634 annAlignment.getAlignmentAnnotation()[i]
3635 .setThreshold(new jalview.datamodel.GraphLine(
3636 viewAnnColour.getThreshold(), "Threshold",
3637 java.awt.Color.black)
3642 if (viewAnnColour.getColourScheme().equals("None"))
3644 cs = new AnnotationColourGradient(
3645 annAlignment.getAlignmentAnnotation()[i],
3646 new java.awt.Color(viewAnnColour.getMinColour()),
3647 new java.awt.Color(viewAnnColour.getMaxColour()),
3648 viewAnnColour.getAboveThreshold());
3650 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
3652 cs = new AnnotationColourGradient(
3653 annAlignment.getAlignmentAnnotation()[i],
3654 GetUserColourScheme(jms,
3655 viewAnnColour.getColourScheme()),
3656 viewAnnColour.getAboveThreshold());
3660 cs = new AnnotationColourGradient(
3661 annAlignment.getAlignmentAnnotation()[i],
3662 ColourSchemeProperty.getColour(al,
3663 viewAnnColour.getColourScheme()),
3664 viewAnnColour.getAboveThreshold());
3666 if (viewAnnColour.hasPerSequence())
3668 ((AnnotationColourGradient) cs).setSeqAssociated(viewAnnColour
3671 if (viewAnnColour.hasPredefinedColours())
3673 ((AnnotationColourGradient) cs)
3674 .setPredefinedColours(viewAnnColour
3675 .isPredefinedColours());
3677 if (propagateAnnColour && al.getGroups() != null)
3679 // Also use these settings for all the groups
3680 for (int g = 0; g < al.getGroups().size(); g++)
3682 jalview.datamodel.SequenceGroup sg = al.getGroups().get(g);
3690 * if (viewAnnColour.getColourScheme().equals("None" )) { sg.cs =
3691 * new AnnotationColourGradient(
3692 * annAlignment.getAlignmentAnnotation()[i], new
3693 * java.awt.Color(viewAnnColour. getMinColour()), new
3694 * java.awt.Color(viewAnnColour. getMaxColour()),
3695 * viewAnnColour.getAboveThreshold()); } else
3698 sg.cs = new AnnotationColourGradient(
3699 annAlignment.getAlignmentAnnotation()[i], sg.cs,
3700 viewAnnColour.getAboveThreshold());
3701 if (cs instanceof AnnotationColourGradient)
3703 if (viewAnnColour.hasPerSequence())
3705 ((AnnotationColourGradient) cs)
3706 .setSeqAssociated(viewAnnColour.isPerSequence());
3708 if (viewAnnColour.hasPredefinedColours())
3710 ((AnnotationColourGradient) cs)
3711 .setPredefinedColours(viewAnnColour
3712 .isPredefinedColours());
3728 private void reorderAutoannotation(AlignFrame af, Alignment al,
3729 ArrayList<JvAnnotRow> autoAlan)
3731 // copy over visualization settings for autocalculated annotation in the
3733 if (al.getAlignmentAnnotation() != null)
3736 * Kludge for magic autoannotation names (see JAL-811)
3738 String[] magicNames = new String[]
3739 { "Consensus", "Quality", "Conservation" };
3740 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
3741 Hashtable<String, JvAnnotRow> visan = new Hashtable<String, JvAnnotRow>();
3742 for (String nm : magicNames)
3744 visan.put(nm, nullAnnot);
3746 for (JvAnnotRow auan : autoAlan)
3748 visan.put(auan.template.label
3749 + (auan.template.getCalcId() == null ? "" : "\t"
3750 + auan.template.getCalcId()), auan);
3752 int hSize = al.getAlignmentAnnotation().length;
3753 ArrayList<JvAnnotRow> reorder = new ArrayList<JvAnnotRow>();
3754 // work through any autoCalculated annotation already on the view
3755 // removing it if it should be placed in a different location on the
3756 // annotation panel.
3757 List<String> remains = new ArrayList(visan.keySet());
3758 for (int h = 0; h < hSize; h++)
3760 jalview.datamodel.AlignmentAnnotation jalan = al
3761 .getAlignmentAnnotation()[h];
3762 if (jalan.autoCalculated)
3765 JvAnnotRow valan = visan.get(k = jalan.label);
3766 if (jalan.getCalcId() != null)
3768 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
3773 // delete the auto calculated row from the alignment
3774 al.deleteAnnotation(jalan, false);
3778 if (valan != nullAnnot)
3780 if (jalan != valan.template)
3782 // newly created autoannotation row instance
3783 // so keep a reference to the visible annotation row
3784 // and copy over all relevant attributes
3785 if (valan.template.graphHeight >= 0)
3788 jalan.graphHeight = valan.template.graphHeight;
3790 jalan.visible = valan.template.visible;
3792 reorder.add(new JvAnnotRow(valan.order, jalan));
3797 // Add any (possibly stale) autocalculated rows that were not appended to
3798 // the view during construction
3799 for (String other : remains)
3801 JvAnnotRow othera = visan.get(other);
3802 if (othera != nullAnnot && othera.template.getCalcId() != null
3803 && othera.template.getCalcId().length() > 0)
3805 reorder.add(othera);
3808 // now put the automatic annotation in its correct place
3809 int s = 0, srt[] = new int[reorder.size()];
3810 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
3811 for (JvAnnotRow jvar : reorder)
3814 srt[s++] = jvar.order;
3817 jalview.util.QuickSort.sort(srt, rws);
3818 // and re-insert the annotation at its correct position
3819 for (JvAnnotRow jvar : rws)
3821 al.addAnnotation(jvar.template, jvar.order);
3823 af.alignPanel.adjustAnnotationHeight();
3827 Hashtable skipList = null;
3830 * TODO remove this method
3833 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
3834 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
3835 * throw new Error("Implementation Error. No skipList defined for this
3836 * Jalview2XML instance."); } return (AlignFrame)
3837 * skipList.get(view.getSequenceSetId()); }
3841 * Check if the Jalview view contained in object should be skipped or not.
3844 * @return true if view's sequenceSetId is a key in skipList
3846 private boolean skipViewport(JalviewModel object)
3848 if (skipList == null)
3853 if (skipList.containsKey(id = object.getJalviewModelSequence()
3854 .getViewport()[0].getSequenceSetId()))
3856 if (Cache.log != null && Cache.log.isDebugEnabled())
3858 Cache.log.debug("Skipping seuqence set id " + id);
3865 public void AddToSkipList(AlignFrame af)
3867 if (skipList == null)
3869 skipList = new Hashtable();
3871 skipList.put(af.getViewport().getSequenceSetId(), af);
3874 public void clearSkipList()
3876 if (skipList != null)
3883 private void recoverDatasetFor(SequenceSet vamsasSet, Alignment al)
3885 jalview.datamodel.Alignment ds = getDatasetFor(vamsasSet.getDatasetId());
3886 Vector dseqs = null;
3889 // create a list of new dataset sequences
3890 dseqs = new Vector();
3892 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
3894 Sequence vamsasSeq = vamsasSet.getSequence(i);
3895 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs);
3897 // create a new dataset
3900 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
3901 dseqs.copyInto(dsseqs);
3902 ds = new jalview.datamodel.Alignment(dsseqs);
3903 debug("Created new dataset " + vamsasSet.getDatasetId()
3904 + " for alignment " + System.identityHashCode(al));
3905 addDatasetRef(vamsasSet.getDatasetId(), ds);
3907 // set the dataset for the newly imported alignment.
3908 if (al.getDataset() == null)
3917 * sequence definition to create/merge dataset sequence for
3921 * vector to add new dataset sequence to
3923 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
3924 AlignmentI ds, Vector dseqs)
3926 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
3928 jalview.datamodel.Sequence sq = (jalview.datamodel.Sequence) seqRefIds
3929 .get(vamsasSeq.getId());
3930 jalview.datamodel.SequenceI dsq = null;
3931 if (sq != null && sq.getDatasetSequence() != null)
3933 dsq = sq.getDatasetSequence();
3936 String sqid = vamsasSeq.getDsseqid();
3939 // need to create or add a new dataset sequence reference to this sequence
3942 dsq = (jalview.datamodel.SequenceI) seqRefIds.get(sqid);
3947 // make a new dataset sequence
3948 dsq = sq.createDatasetSequence();
3951 // make up a new dataset reference for this sequence
3952 sqid = seqHash(dsq);
3954 dsq.setVamsasId(uniqueSetSuffix + sqid);
3955 seqRefIds.put(sqid, dsq);
3960 dseqs.addElement(dsq);
3965 ds.addSequence(dsq);
3971 { // make this dataset sequence sq's dataset sequence
3972 sq.setDatasetSequence(dsq);
3973 // and update the current dataset alignment
3978 if (!dseqs.contains(dsq))
3985 if (ds.findIndex(dsq) < 0)
3987 ds.addSequence(dsq);
3994 // TODO: refactor this as a merge dataset sequence function
3995 // now check that sq (the dataset sequence) sequence really is the union of
3996 // all references to it
3997 // boolean pre = sq.getStart() < dsq.getStart();
3998 // boolean post = sq.getEnd() > dsq.getEnd();
4002 StringBuffer sb = new StringBuffer();
4003 String newres = jalview.analysis.AlignSeq.extractGaps(
4004 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
4005 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
4006 && newres.length() > dsq.getLength())
4008 // Update with the longer sequence.
4012 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
4013 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
4014 * sb.append(newres.substring(newres.length() - sq.getEnd() -
4015 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
4017 dsq.setSequence(newres);
4019 // TODO: merges will never happen if we 'know' we have the real dataset
4020 // sequence - this should be detected when id==dssid
4022 .println("DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
4023 // + (pre ? "prepended" : "") + " "
4024 // + (post ? "appended" : ""));
4029 java.util.Hashtable datasetIds = null;
4031 java.util.IdentityHashMap dataset2Ids = null;
4033 private Alignment getDatasetFor(String datasetId)
4035 if (datasetIds == null)
4037 datasetIds = new Hashtable();
4040 if (datasetIds.containsKey(datasetId))
4042 return (Alignment) datasetIds.get(datasetId);
4047 private void addDatasetRef(String datasetId, Alignment dataset)
4049 if (datasetIds == null)
4051 datasetIds = new Hashtable();
4053 datasetIds.put(datasetId, dataset);
4057 * make a new dataset ID for this jalview dataset alignment
4062 private String getDatasetIdRef(jalview.datamodel.Alignment dataset)
4064 if (dataset.getDataset() != null)
4066 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
4068 String datasetId = makeHashCode(dataset, null);
4069 if (datasetId == null)
4071 // make a new datasetId and record it
4072 if (dataset2Ids == null)
4074 dataset2Ids = new IdentityHashMap();
4078 datasetId = (String) dataset2Ids.get(dataset);
4080 if (datasetId == null)
4082 datasetId = "ds" + dataset2Ids.size() + 1;
4083 dataset2Ids.put(dataset, datasetId);
4089 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
4091 for (int d = 0; d < sequence.getDBRefCount(); d++)
4093 DBRef dr = sequence.getDBRef(d);
4094 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
4095 sequence.getDBRef(d).getSource(), sequence.getDBRef(d)
4096 .getVersion(), sequence.getDBRef(d).getAccessionId());
4097 if (dr.getMapping() != null)
4099 entry.setMap(addMapping(dr.getMapping()));
4101 datasetSequence.addDBRef(entry);
4105 private jalview.datamodel.Mapping addMapping(Mapping m)
4107 SequenceI dsto = null;
4108 // Mapping m = dr.getMapping();
4109 int fr[] = new int[m.getMapListFromCount() * 2];
4110 Enumeration f = m.enumerateMapListFrom();
4111 for (int _i = 0; f.hasMoreElements(); _i += 2)
4113 MapListFrom mf = (MapListFrom) f.nextElement();
4114 fr[_i] = mf.getStart();
4115 fr[_i + 1] = mf.getEnd();
4117 int fto[] = new int[m.getMapListToCount() * 2];
4118 f = m.enumerateMapListTo();
4119 for (int _i = 0; f.hasMoreElements(); _i += 2)
4121 MapListTo mf = (MapListTo) f.nextElement();
4122 fto[_i] = mf.getStart();
4123 fto[_i + 1] = mf.getEnd();
4125 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto,
4126 fr, fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
4127 if (m.getMappingChoice() != null)
4129 MappingChoice mc = m.getMappingChoice();
4130 if (mc.getDseqFor() != null)
4132 String dsfor = "" + mc.getDseqFor();
4133 if (seqRefIds.containsKey(dsfor))
4138 jmap.setTo((SequenceI) seqRefIds.get(dsfor));
4142 frefedSequence.add(new Object[]
4149 * local sequence definition
4151 Sequence ms = mc.getSequence();
4152 jalview.datamodel.Sequence djs = null;
4153 String sqid = ms.getDsseqid();
4154 if (sqid != null && sqid.length() > 0)
4157 * recover dataset sequence
4159 djs = (jalview.datamodel.Sequence) seqRefIds.get(sqid);
4164 .println("Warning - making up dataset sequence id for DbRef sequence map reference");
4165 sqid = ((Object) ms).toString(); // make up a new hascode for
4166 // undefined dataset sequence hash
4167 // (unlikely to happen)
4173 * make a new dataset sequence and add it to refIds hash
4175 djs = new jalview.datamodel.Sequence(ms.getName(),
4177 djs.setStart(jmap.getMap().getToLowest());
4178 djs.setEnd(jmap.getMap().getToHighest());
4179 djs.setVamsasId(uniqueSetSuffix + sqid);
4181 seqRefIds.put(sqid, djs);
4184 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
4193 public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
4194 boolean keepSeqRefs)
4197 jalview.schemabinding.version2.JalviewModel jm = SaveState(ap, null,
4203 jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
4207 uniqueSetSuffix = "";
4208 jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
4213 if (this.frefedSequence == null)
4215 frefedSequence = new Vector();
4218 viewportsAdded = new Hashtable();
4220 AlignFrame af = LoadFromObject(jm, null, false, null);
4221 af.alignPanels.clear();
4222 af.closeMenuItem_actionPerformed(true);
4225 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
4226 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
4227 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
4228 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
4229 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
4232 return af.alignPanel;
4236 * flag indicating if hashtables should be cleared on finalization TODO this
4237 * flag may not be necessary
4239 private final boolean _cleartables = true;
4241 private Hashtable jvids2vobj;
4246 * @see java.lang.Object#finalize()
4249 protected void finalize() throws Throwable
4251 // really make sure we have no buried refs left.
4256 this.seqRefIds = null;
4257 this.seqsToIds = null;
4261 private void warn(String msg)
4266 private void warn(String msg, Exception e)
4268 if (Cache.log != null)
4272 Cache.log.warn(msg, e);
4276 Cache.log.warn(msg);
4281 System.err.println("Warning: " + msg);
4284 e.printStackTrace();
4289 private void debug(String string)
4291 debug(string, null);
4294 private void debug(String msg, Exception e)
4296 if (Cache.log != null)
4300 Cache.log.debug(msg, e);
4304 Cache.log.debug(msg);
4309 System.err.println("Warning: " + msg);
4312 e.printStackTrace();
4318 * set the object to ID mapping tables used to write/recover objects and XML
4319 * ID strings for the jalview project. If external tables are provided then
4320 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
4321 * object goes out of scope. - also populates the datasetIds hashtable with
4322 * alignment objects containing dataset sequences
4325 * Map from ID strings to jalview datamodel
4327 * Map from jalview datamodel to ID strings
4331 public void setObjectMappingTables(Hashtable vobj2jv,
4332 IdentityHashMap jv2vobj)
4334 this.jv2vobj = jv2vobj;
4335 this.vobj2jv = vobj2jv;
4336 Iterator ds = jv2vobj.keySet().iterator();
4338 while (ds.hasNext())
4340 Object jvobj = ds.next();
4341 id = jv2vobj.get(jvobj).toString();
4342 if (jvobj instanceof jalview.datamodel.Alignment)
4344 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
4346 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
4349 else if (jvobj instanceof jalview.datamodel.Sequence)
4351 // register sequence object so the XML parser can recover it.
4352 if (seqRefIds == null)
4354 seqRefIds = new Hashtable();
4356 if (seqsToIds == null)
4358 seqsToIds = new IdentityHashMap();
4360 seqRefIds.put(jv2vobj.get(jvobj).toString(), jvobj);
4361 seqsToIds.put(jvobj, id);
4363 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
4365 if (annotationIds == null)
4367 annotationIds = new Hashtable();
4370 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvobj);
4371 jalview.datamodel.AlignmentAnnotation jvann = (jalview.datamodel.AlignmentAnnotation) jvobj;
4372 if (jvann.annotationId == null)
4374 jvann.annotationId = anid;
4376 if (!jvann.annotationId.equals(anid))
4378 // TODO verify that this is the correct behaviour
4379 this.warn("Overriding Annotation ID for " + anid
4380 + " from different id : " + jvann.annotationId);
4381 jvann.annotationId = anid;
4384 else if (jvobj instanceof String)
4386 if (jvids2vobj == null)
4388 jvids2vobj = new Hashtable();
4389 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
4393 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
4398 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
4399 * objects created from the project archive. If string is null (default for
4400 * construction) then suffix will be set automatically.
4404 public void setUniqueSetSuffix(String string)
4406 uniqueSetSuffix = string;
4411 * uses skipList2 as the skipList for skipping views on sequence sets
4412 * associated with keys in the skipList
4416 public void setSkipList(Hashtable skipList2)
4418 skipList = skipList2;