2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ 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 jalview.api.structures.JalviewStructureDisplayI;
24 import jalview.bin.Cache;
25 import jalview.datamodel.AlignedCodonFrame;
26 import jalview.datamodel.Alignment;
27 import jalview.datamodel.AlignmentAnnotation;
28 import jalview.datamodel.AlignmentI;
29 import jalview.datamodel.PDBEntry;
30 import jalview.datamodel.RnaViewerModel;
31 import jalview.datamodel.SequenceGroup;
32 import jalview.datamodel.SequenceI;
33 import jalview.datamodel.StructureViewerModel;
34 import jalview.datamodel.StructureViewerModel.StructureData;
35 import jalview.ext.varna.RnaModel;
36 import jalview.gui.StructureViewer.ViewerType;
37 import jalview.schemabinding.version2.AlcodMap;
38 import jalview.schemabinding.version2.AlcodonFrame;
39 import jalview.schemabinding.version2.Annotation;
40 import jalview.schemabinding.version2.AnnotationColours;
41 import jalview.schemabinding.version2.AnnotationElement;
42 import jalview.schemabinding.version2.CalcIdParam;
43 import jalview.schemabinding.version2.DBRef;
44 import jalview.schemabinding.version2.Features;
45 import jalview.schemabinding.version2.Group;
46 import jalview.schemabinding.version2.HiddenColumns;
47 import jalview.schemabinding.version2.JGroup;
48 import jalview.schemabinding.version2.JSeq;
49 import jalview.schemabinding.version2.JalviewModel;
50 import jalview.schemabinding.version2.JalviewModelSequence;
51 import jalview.schemabinding.version2.MapListFrom;
52 import jalview.schemabinding.version2.MapListTo;
53 import jalview.schemabinding.version2.Mapping;
54 import jalview.schemabinding.version2.MappingChoice;
55 import jalview.schemabinding.version2.OtherData;
56 import jalview.schemabinding.version2.PdbentryItem;
57 import jalview.schemabinding.version2.Pdbids;
58 import jalview.schemabinding.version2.Property;
59 import jalview.schemabinding.version2.RnaViewer;
60 import jalview.schemabinding.version2.SecondaryStructure;
61 import jalview.schemabinding.version2.Sequence;
62 import jalview.schemabinding.version2.SequenceSet;
63 import jalview.schemabinding.version2.SequenceSetProperties;
64 import jalview.schemabinding.version2.Setting;
65 import jalview.schemabinding.version2.StructureState;
66 import jalview.schemabinding.version2.ThresholdLine;
67 import jalview.schemabinding.version2.Tree;
68 import jalview.schemabinding.version2.UserColours;
69 import jalview.schemabinding.version2.Viewport;
70 import jalview.schemes.AnnotationColourGradient;
71 import jalview.schemes.ColourSchemeI;
72 import jalview.schemes.ColourSchemeProperty;
73 import jalview.schemes.GraduatedColor;
74 import jalview.schemes.ResidueColourScheme;
75 import jalview.schemes.ResidueProperties;
76 import jalview.schemes.UserColourScheme;
77 import jalview.structure.StructureSelectionManager;
78 import jalview.structures.models.AAStructureBindingModel;
79 import jalview.util.MessageManager;
80 import jalview.util.Platform;
81 import jalview.util.jarInputStreamProvider;
82 import jalview.viewmodel.AlignmentViewport;
83 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
84 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
85 import jalview.ws.jws2.Jws2Discoverer;
86 import jalview.ws.jws2.dm.AAConSettings;
87 import jalview.ws.jws2.jabaws2.Jws2Instance;
88 import jalview.ws.params.ArgumentI;
89 import jalview.ws.params.AutoCalcSetting;
90 import jalview.ws.params.WsParamSetI;
92 import java.awt.Rectangle;
93 import java.io.BufferedReader;
94 import java.io.DataInputStream;
95 import java.io.DataOutputStream;
97 import java.io.FileInputStream;
98 import java.io.FileOutputStream;
99 import java.io.IOException;
100 import java.io.InputStreamReader;
101 import java.io.OutputStreamWriter;
102 import java.io.PrintWriter;
103 import java.lang.reflect.InvocationTargetException;
104 import java.net.MalformedURLException;
106 import java.util.ArrayList;
107 import java.util.Enumeration;
108 import java.util.HashMap;
109 import java.util.HashSet;
110 import java.util.Hashtable;
111 import java.util.IdentityHashMap;
112 import java.util.Iterator;
113 import java.util.LinkedHashMap;
114 import java.util.List;
115 import java.util.Map;
116 import java.util.Map.Entry;
117 import java.util.Set;
118 import java.util.StringTokenizer;
119 import java.util.Vector;
120 import java.util.jar.JarEntry;
121 import java.util.jar.JarInputStream;
122 import java.util.jar.JarOutputStream;
124 import javax.swing.JInternalFrame;
125 import javax.swing.JOptionPane;
126 import javax.swing.SwingUtilities;
128 import org.exolab.castor.xml.Marshaller;
129 import org.exolab.castor.xml.Unmarshaller;
132 * Write out the current jalview desktop state as a Jalview XML stream.
134 * Note: the vamsas objects referred to here are primitive versions of the
135 * VAMSAS project schema elements - they are not the same and most likely never
139 * @version $Revision: 1.134 $
141 public class Jalview2XML
143 private static final String VIEWER_PREFIX = "viewer_";
145 private static final String RNA_PREFIX = "rna_";
147 private static final String UTF_8 = "UTF-8";
149 // use this with nextCounter() to make unique names for entities
150 private int counter = 0;
153 * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
154 * of sequence objects are created.
156 IdentityHashMap<SequenceI, String> seqsToIds = null;
159 * jalview XML Sequence ID to jalview sequence object reference (both dataset
160 * and alignment sequences. Populated as XML reps of sequence objects are
163 Map<String, SequenceI> seqRefIds = null;
165 Vector frefedSequence = null;
167 boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
170 * Map of reconstructed AlignFrame objects that appear to have come from
171 * SplitFrame objects (have a dna/protein complement view).
173 private Map<Viewport, AlignFrame> splitFrameCandidates = new HashMap<Viewport, AlignFrame>();
176 * Map from displayed rna structure models to their saved session state jar
179 private Map<RnaModel, String> rnaSessions = new HashMap<RnaModel, String>();
182 * create/return unique hash string for sq
185 * @return new or existing unique string for sq
187 String seqHash(SequenceI sq)
189 if (seqsToIds == null)
193 if (seqsToIds.containsKey(sq))
195 return seqsToIds.get(sq);
199 // create sequential key
200 String key = "sq" + (seqsToIds.size() + 1);
201 key = makeHashCode(sq, key); // check we don't have an external reference
203 seqsToIds.put(sq, key);
212 if (seqRefIds != null)
216 if (seqsToIds != null)
226 warn("clearSeqRefs called when _cleartables was not set. Doing nothing.");
227 // seqRefIds = new Hashtable();
228 // seqsToIds = new IdentityHashMap();
234 if (seqsToIds == null)
236 seqsToIds = new IdentityHashMap<SequenceI, String>();
238 if (seqRefIds == null)
240 seqRefIds = new HashMap<String, SequenceI>();
248 public Jalview2XML(boolean raiseGUI)
250 this.raiseGUI = raiseGUI;
253 public void resolveFrefedSequences()
255 if (frefedSequence.size() > 0)
257 int r = 0, rSize = frefedSequence.size();
260 Object[] ref = (Object[]) frefedSequence.elementAt(r);
263 String sref = (String) ref[0];
264 if (seqRefIds.containsKey(sref))
266 if (ref[1] instanceof jalview.datamodel.Mapping)
268 SequenceI seq = seqRefIds.get(sref);
269 while (seq.getDatasetSequence() != null)
271 seq = seq.getDatasetSequence();
273 ((jalview.datamodel.Mapping) ref[1]).setTo(seq);
277 if (ref[1] instanceof jalview.datamodel.AlignedCodonFrame)
279 SequenceI seq = seqRefIds.get(sref);
280 while (seq.getDatasetSequence() != null)
282 seq = seq.getDatasetSequence();
285 && ref[2] instanceof jalview.datamodel.Mapping)
287 jalview.datamodel.Mapping mp = (jalview.datamodel.Mapping) ref[2];
288 ((jalview.datamodel.AlignedCodonFrame) ref[1]).addMap(
289 seq, mp.getTo(), mp.getMap());
294 .println("IMPLEMENTATION ERROR: Unimplemented forward sequence references for AlcodonFrames involving "
295 + ref[2].getClass() + " type objects.");
301 .println("IMPLEMENTATION ERROR: Unimplemented forward sequence references for "
302 + ref[1].getClass() + " type objects.");
305 frefedSequence.remove(r);
311 .println("IMPLEMENTATION WARNING: Unresolved forward reference for hash string "
313 + " with objecttype "
314 + ref[1].getClass());
321 frefedSequence.remove(r);
329 * This maintains a map of viewports, the key being the seqSetId. Important to
330 * set historyItem and redoList for multiple views
332 Map<String, AlignViewport> viewportsAdded = new HashMap<String, AlignViewport>();
334 Map<String, AlignmentAnnotation> annotationIds = new HashMap<String, AlignmentAnnotation>();
336 String uniqueSetSuffix = "";
339 * List of pdbfiles added to Jar
341 List<String> pdbfiles = null;
343 // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
344 public void saveState(File statefile)
346 FileOutputStream fos = null;
349 fos = new FileOutputStream(statefile);
350 JarOutputStream jout = new JarOutputStream(fos);
353 } catch (Exception e)
355 // TODO: inform user of the problem - they need to know if their data was
357 if (errorMessage == null)
359 errorMessage = "Couldn't write Jalview Archive to output file '"
360 + statefile + "' - See console error log for details";
364 errorMessage += "(output file was '" + statefile + "')";
374 } catch (IOException e)
384 * Writes a jalview project archive to the given Jar output stream.
388 public void saveState(JarOutputStream jout)
390 AlignFrame[] frames = Desktop.getAlignFrames();
397 Hashtable<String, AlignFrame> dsses = new Hashtable<String, AlignFrame>();
400 * ensure cached data is clear before starting
402 // todo tidy up seqRefIds, seqsToIds initialisation / reset
404 splitFrameCandidates.clear();
409 // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
410 // //////////////////////////////////////////////////
412 List<String> shortNames = new ArrayList<String>();
413 List<String> viewIds = new ArrayList<String>();
416 for (int i = frames.length - 1; i > -1; i--)
418 AlignFrame af = frames[i];
422 .containsKey(af.getViewport().getSequenceSetId()))
427 String shortName = makeFilename(af, shortNames);
429 int ap, apSize = af.alignPanels.size();
431 for (ap = 0; ap < apSize; ap++)
433 AlignmentPanel apanel = af.alignPanels.get(ap);
434 String fileName = apSize == 1 ? shortName : ap + shortName;
435 if (!fileName.endsWith(".xml"))
437 fileName = fileName + ".xml";
440 saveState(apanel, fileName, jout, viewIds);
442 String dssid = getDatasetIdRef(af.getViewport().getAlignment()
444 if (!dsses.containsKey(dssid))
446 dsses.put(dssid, af);
451 writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix,
457 } catch (Exception foo)
462 } catch (Exception ex)
464 // TODO: inform user of the problem - they need to know if their data was
466 if (errorMessage == null)
468 errorMessage = "Couldn't write Jalview Archive - see error output for details";
470 ex.printStackTrace();
475 * Generates a distinct file name, based on the title of the AlignFrame, by
476 * appending _n for increasing n until an unused name is generated. The new
477 * name (without its extension) is added to the list.
481 * @return the generated name, with .xml extension
483 protected String makeFilename(AlignFrame af, List<String> namesUsed)
485 String shortName = af.getTitle();
487 if (shortName.indexOf(File.separatorChar) > -1)
489 shortName = shortName.substring(shortName
490 .lastIndexOf(File.separatorChar) + 1);
495 while (namesUsed.contains(shortName))
497 if (shortName.endsWith("_" + (count - 1)))
499 shortName = shortName.substring(0, shortName.lastIndexOf("_"));
502 shortName = shortName.concat("_" + count);
506 namesUsed.add(shortName);
508 if (!shortName.endsWith(".xml"))
510 shortName = shortName + ".xml";
515 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
516 public boolean saveAlignment(AlignFrame af, String jarFile,
522 int apSize = af.alignPanels.size();
523 FileOutputStream fos = new FileOutputStream(jarFile);
524 JarOutputStream jout = new JarOutputStream(fos);
525 Hashtable<String, AlignFrame> dsses = new Hashtable<String, AlignFrame>();
526 List<String> viewIds = new ArrayList<String>();
528 for (AlignmentPanel apanel : af.alignPanels)
530 String jfileName = apSize == 1 ? fileName : fileName + ap;
532 if (!jfileName.endsWith(".xml"))
534 jfileName = jfileName + ".xml";
536 saveState(apanel, jfileName, jout, viewIds);
537 String dssid = getDatasetIdRef(af.getViewport().getAlignment()
539 if (!dsses.containsKey(dssid))
541 dsses.put(dssid, af);
544 writeDatasetFor(dsses, fileName, jout);
548 } catch (Exception foo)
554 } catch (Exception ex)
556 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
557 ex.printStackTrace();
562 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
563 String fileName, JarOutputStream jout)
566 for (String dssids : dsses.keySet())
568 AlignFrame _af = dsses.get(dssids);
569 String jfileName = fileName + " Dataset for " + _af.getTitle();
570 if (!jfileName.endsWith(".xml"))
572 jfileName = jfileName + ".xml";
574 saveState(_af.alignPanel, jfileName, true, jout, null);
579 * create a JalviewModel from an alignment view and marshall it to a
583 * panel to create jalview model for
585 * name of alignment panel written to output stream
592 public JalviewModel saveState(AlignmentPanel ap, String fileName,
593 JarOutputStream jout, List<String> viewIds)
595 return saveState(ap, fileName, false, jout, viewIds);
599 * create a JalviewModel from an alignment view and marshall it to a
603 * panel to create jalview model for
605 * name of alignment panel written to output stream
607 * when true, only write the dataset for the alignment, not the data
608 * associated with the view.
614 public JalviewModel saveState(AlignmentPanel ap, String fileName,
615 boolean storeDS, JarOutputStream jout, List<String> viewIds)
619 viewIds = new ArrayList<String>();
624 List<UserColourScheme> userColours = new ArrayList<UserColourScheme>();
626 AlignViewport av = ap.av;
628 JalviewModel object = new JalviewModel();
629 object.setVamsasModel(new jalview.schemabinding.version2.VamsasModel());
631 object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
632 object.setVersion(jalview.bin.Cache.getDefault("VERSION",
633 "Development Build"));
635 jalview.datamodel.AlignmentI jal = av.getAlignment();
637 if (av.hasHiddenRows())
639 jal = jal.getHiddenSequences().getFullAlignment();
642 SequenceSet vamsasSet = new SequenceSet();
644 JalviewModelSequence jms = new JalviewModelSequence();
646 vamsasSet.setGapChar(jal.getGapCharacter() + "");
648 if (jal.getDataset() != null)
650 // dataset id is the dataset's hashcode
651 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
654 // switch jal and the dataset
655 jal = jal.getDataset();
658 if (jal.getProperties() != null)
660 Enumeration en = jal.getProperties().keys();
661 while (en.hasMoreElements())
663 String key = en.nextElement().toString();
664 SequenceSetProperties ssp = new SequenceSetProperties();
666 ssp.setValue(jal.getProperties().get(key).toString());
667 vamsasSet.addSequenceSetProperties(ssp);
672 Set<String> calcIdSet = new HashSet<String>();
675 for (int i = 0; i < jal.getHeight(); i++)
677 final SequenceI jds = jal.getSequenceAt(i);
678 final SequenceI jdatasq = jds.getDatasetSequence() == null ? jds
680 .getDatasetSequence();
681 String id = seqHash(jds);
683 if (seqRefIds.get(id) != null)
685 // This happens for two reasons: 1. multiple views are being serialised.
686 // 2. the hashCode has collided with another sequence's code. This DOES
687 // HAPPEN! (PF00072.15.stk does this)
688 // JBPNote: Uncomment to debug writing out of files that do not read
689 // back in due to ArrayOutOfBoundExceptions.
690 // System.err.println("vamsasSeq backref: "+id+"");
691 // System.err.println(jds.getName()+"
692 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
693 // System.err.println("Hashcode: "+seqHash(jds));
694 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
695 // System.err.println(rsq.getName()+"
696 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
697 // System.err.println("Hashcode: "+seqHash(rsq));
701 vamsasSeq = createVamsasSequence(id, jds);
702 vamsasSet.addSequence(vamsasSeq);
703 seqRefIds.put(id, jds);
707 jseq.setStart(jds.getStart());
708 jseq.setEnd(jds.getEnd());
709 jseq.setColour(av.getSequenceColour(jds).getRGB());
711 jseq.setId(id); // jseq id should be a string not a number
714 // Store any sequences this sequence represents
715 if (av.hasHiddenRows())
717 jseq.setHidden(av.getAlignment().getHiddenSequences()
720 if (av.isHiddenRepSequence(jal.getSequenceAt(i)))
722 jalview.datamodel.SequenceI[] reps = av
723 .getRepresentedSequences(jal.getSequenceAt(i))
724 .getSequencesInOrder(jal);
726 for (int h = 0; h < reps.length; h++)
728 if (reps[h] != jal.getSequenceAt(i))
730 jseq.addHiddenSequences(jal.findIndex(reps[h]));
737 if (jds.getSequenceFeatures() != null)
739 jalview.datamodel.SequenceFeature[] sf = jds
740 .getSequenceFeatures();
742 while (index < sf.length)
744 Features features = new Features();
746 features.setBegin(sf[index].getBegin());
747 features.setEnd(sf[index].getEnd());
748 features.setDescription(sf[index].getDescription());
749 features.setType(sf[index].getType());
750 features.setFeatureGroup(sf[index].getFeatureGroup());
751 features.setScore(sf[index].getScore());
752 if (sf[index].links != null)
754 for (int l = 0; l < sf[index].links.size(); l++)
756 OtherData keyValue = new OtherData();
757 keyValue.setKey("LINK_" + l);
758 keyValue.setValue(sf[index].links.elementAt(l).toString());
759 features.addOtherData(keyValue);
762 if (sf[index].otherDetails != null)
765 Enumeration keys = sf[index].otherDetails.keys();
766 while (keys.hasMoreElements())
768 key = keys.nextElement().toString();
769 OtherData keyValue = new OtherData();
770 keyValue.setKey(key);
771 keyValue.setValue(sf[index].otherDetails.get(key).toString());
772 features.addOtherData(keyValue);
776 jseq.addFeatures(features);
781 if (jdatasq.getPDBId() != null)
783 Enumeration en = jdatasq.getPDBId().elements();
784 while (en.hasMoreElements())
786 Pdbids pdb = new Pdbids();
787 jalview.datamodel.PDBEntry entry = (jalview.datamodel.PDBEntry) en
790 String pdbId = entry.getId();
792 pdb.setType(entry.getType());
795 * Store any structure views associated with this sequence. This
796 * section copes with duplicate entries in the project, so a dataset
797 * only view *should* be coped with sensibly.
799 // This must have been loaded, is it still visible?
800 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
801 String matchedFile = null;
802 for (int f = frames.length - 1; f > -1; f--)
804 if (frames[f] instanceof StructureViewerBase)
806 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
807 matchedFile = saveStructureState(ap, jds, pdb, entry,
808 viewIds, matchedFile, viewFrame);
810 * Only store each structure viewer's state once in the project
811 * jar. First time through only (storeDS==false)
813 String viewId = viewFrame.getViewId();
814 if (!storeDS && !viewIds.contains(viewId))
819 String viewerState = viewFrame.getStateInfo();
820 writeJarEntry(jout, getViewerJarEntryName(viewId),
821 viewerState.getBytes());
822 } catch (IOException e)
824 System.err.println("Error saving viewer state: "
831 if (matchedFile != null || entry.getFile() != null)
833 if (entry.getFile() != null)
836 matchedFile = entry.getFile();
838 pdb.setFile(matchedFile); // entry.getFile());
839 if (pdbfiles == null)
841 pdbfiles = new ArrayList<String>();
844 if (!pdbfiles.contains(pdbId))
847 copyFileToJar(jout, matchedFile, pdbId);
851 if (entry.getProperty() != null && !entry.getProperty().isEmpty())
853 PdbentryItem item = new PdbentryItem();
854 Hashtable properties = entry.getProperty();
855 Enumeration en2 = properties.keys();
856 while (en2.hasMoreElements())
858 Property prop = new Property();
859 String key = en2.nextElement().toString();
861 prop.setValue(properties.get(key).toString());
862 item.addProperty(prop);
864 pdb.addPdbentryItem(item);
871 saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
876 if (!storeDS && av.hasHiddenRows())
878 jal = av.getAlignment();
881 if (jal.getCodonFrames() != null)
883 Set<AlignedCodonFrame> jac = jal.getCodonFrames();
884 for (AlignedCodonFrame acf : jac)
886 AlcodonFrame alc = new AlcodonFrame();
887 vamsasSet.addAlcodonFrame(alc);
888 if (acf.getProtMappings() != null
889 && acf.getProtMappings().length > 0)
891 SequenceI[] dnas = acf.getdnaSeqs();
892 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
893 for (int m = 0; m < pmaps.length; m++)
895 AlcodMap alcmap = new AlcodMap();
896 alcmap.setDnasq(seqHash(dnas[m]));
897 alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
899 alc.addAlcodMap(alcmap);
904 // AlcodonFrame alc = new AlcodonFrame();
905 // vamsasSet.addAlcodonFrame(alc);
906 // for (int p = 0; p < acf.aaWidth; p++)
908 // Alcodon cmap = new Alcodon();
909 // if (acf.codons[p] != null)
911 // // Null codons indicate a gapped column in the translated peptide
913 // cmap.setPos1(acf.codons[p][0]);
914 // cmap.setPos2(acf.codons[p][1]);
915 // cmap.setPos3(acf.codons[p][2]);
917 // alc.addAlcodon(cmap);
919 // if (acf.getProtMappings() != null
920 // && acf.getProtMappings().length > 0)
922 // SequenceI[] dnas = acf.getdnaSeqs();
923 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
924 // for (int m = 0; m < pmaps.length; m++)
926 // AlcodMap alcmap = new AlcodMap();
927 // alcmap.setDnasq(seqHash(dnas[m]));
928 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
930 // alc.addAlcodMap(alcmap);
937 // /////////////////////////////////
938 if (!storeDS && av.currentTree != null)
940 // FIND ANY ASSOCIATED TREES
941 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
942 if (Desktop.desktop != null)
944 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
946 for (int t = 0; t < frames.length; t++)
948 if (frames[t] instanceof TreePanel)
950 TreePanel tp = (TreePanel) frames[t];
952 if (tp.treeCanvas.av.getAlignment() == jal)
954 Tree tree = new Tree();
955 tree.setTitle(tp.getTitle());
956 tree.setCurrentTree((av.currentTree == tp.getTree()));
957 tree.setNewick(tp.getTree().toString());
958 tree.setThreshold(tp.treeCanvas.threshold);
960 tree.setFitToWindow(tp.fitToWindow.getState());
961 tree.setFontName(tp.getTreeFont().getName());
962 tree.setFontSize(tp.getTreeFont().getSize());
963 tree.setFontStyle(tp.getTreeFont().getStyle());
964 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
966 tree.setShowBootstrap(tp.bootstrapMenu.getState());
967 tree.setShowDistances(tp.distanceMenu.getState());
969 tree.setHeight(tp.getHeight());
970 tree.setWidth(tp.getWidth());
971 tree.setXpos(tp.getX());
972 tree.setYpos(tp.getY());
973 tree.setId(makeHashCode(tp, null));
983 * store forward refs from an annotationRow to any groups
985 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<SequenceGroup, String>();
988 for (SequenceI sq : jal.getSequences())
990 // Store annotation on dataset sequences only
991 AlignmentAnnotation[] aa = sq.getAnnotation();
992 if (aa != null && aa.length > 0)
994 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1001 if (jal.getAlignmentAnnotation() != null)
1003 // Store the annotation shown on the alignment.
1004 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1005 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1010 if (jal.getGroups() != null)
1012 JGroup[] groups = new JGroup[jal.getGroups().size()];
1014 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1016 JGroup jGroup = new JGroup();
1017 groups[++i] = jGroup;
1019 jGroup.setStart(sg.getStartRes());
1020 jGroup.setEnd(sg.getEndRes());
1021 jGroup.setName(sg.getName());
1022 if (groupRefs.containsKey(sg))
1024 // group has references so set its ID field
1025 jGroup.setId(groupRefs.get(sg));
1029 if (sg.cs.conservationApplied())
1031 jGroup.setConsThreshold(sg.cs.getConservationInc());
1033 if (sg.cs instanceof jalview.schemes.UserColourScheme)
1035 jGroup.setColour(setUserColourScheme(sg.cs, userColours,
1041 .setColour(ColourSchemeProperty.getColourName(sg.cs));
1044 else if (sg.cs instanceof jalview.schemes.AnnotationColourGradient)
1046 jGroup.setColour("AnnotationColourGradient");
1047 jGroup.setAnnotationColours(constructAnnotationColours(
1048 (jalview.schemes.AnnotationColourGradient) sg.cs,
1051 else if (sg.cs instanceof jalview.schemes.UserColourScheme)
1054 .setColour(setUserColourScheme(sg.cs, userColours, jms));
1058 jGroup.setColour(ColourSchemeProperty.getColourName(sg.cs));
1061 jGroup.setPidThreshold(sg.cs.getThreshold());
1064 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1065 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1066 jGroup.setDisplayText(sg.getDisplayText());
1067 jGroup.setColourText(sg.getColourText());
1068 jGroup.setTextCol1(sg.textColour.getRGB());
1069 jGroup.setTextCol2(sg.textColour2.getRGB());
1070 jGroup.setTextColThreshold(sg.thresholdTextColour);
1071 jGroup.setShowUnconserved(sg.getShowNonconserved());
1072 jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1073 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1074 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1075 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1076 for (SequenceI seq : sg.getSequences())
1078 jGroup.addSeq(seqHash(seq));
1082 jms.setJGroup(groups);
1086 // /////////SAVE VIEWPORT
1087 Viewport view = new Viewport();
1088 view.setTitle(ap.alignFrame.getTitle());
1089 view.setSequenceSetId(makeHashCode(av.getSequenceSetId(),
1090 av.getSequenceSetId()));
1091 view.setId(av.getViewId());
1092 if (av.getCodingComplement() != null)
1094 view.setComplementId(av.getCodingComplement().getViewId());
1096 view.setViewName(av.viewName);
1097 view.setGatheredViews(av.isGatherViewsHere());
1099 Rectangle position = ap.av.getExplodedGeometry();
1100 if (position == null)
1102 position = ap.alignFrame.getBounds();
1104 view.setXpos(position.x);
1105 view.setYpos(position.y);
1106 view.setWidth(position.width);
1107 view.setHeight(position.height);
1109 view.setStartRes(av.startRes);
1110 view.setStartSeq(av.startSeq);
1112 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1114 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1117 else if (av.getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1119 AnnotationColours ac = constructAnnotationColours(
1120 (jalview.schemes.AnnotationColourGradient) av
1121 .getGlobalColourScheme(),
1124 view.setAnnotationColours(ac);
1125 view.setBgColour("AnnotationColourGradient");
1129 view.setBgColour(ColourSchemeProperty.getColourName(av
1130 .getGlobalColourScheme()));
1133 ColourSchemeI cs = av.getGlobalColourScheme();
1137 if (cs.conservationApplied())
1139 view.setConsThreshold(cs.getConservationInc());
1140 if (cs instanceof jalview.schemes.UserColourScheme)
1142 view.setBgColour(setUserColourScheme(cs, userColours, jms));
1146 if (cs instanceof ResidueColourScheme)
1148 view.setPidThreshold(cs.getThreshold());
1152 view.setConservationSelected(av.getConservationSelected());
1153 view.setPidSelected(av.getAbovePIDThreshold());
1154 view.setFontName(av.font.getName());
1155 view.setFontSize(av.font.getSize());
1156 view.setFontStyle(av.font.getStyle());
1157 view.setRenderGaps(av.isRenderGaps());
1158 view.setShowAnnotation(av.isShowAnnotation());
1159 view.setShowBoxes(av.getShowBoxes());
1160 view.setShowColourText(av.getColourText());
1161 view.setShowFullId(av.getShowJVSuffix());
1162 view.setRightAlignIds(av.isRightAlignIds());
1163 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1164 view.setShowText(av.getShowText());
1165 view.setShowUnconserved(av.getShowUnconserved());
1166 view.setWrapAlignment(av.getWrapAlignment());
1167 view.setTextCol1(av.getTextColour().getRGB());
1168 view.setTextCol2(av.getTextColour2().getRGB());
1169 view.setTextColThreshold(av.getThresholdTextColour());
1170 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1171 view.setShowSequenceLogo(av.isShowSequenceLogo());
1172 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1173 view.setShowGroupConsensus(av.isShowGroupConsensus());
1174 view.setShowGroupConservation(av.isShowGroupConservation());
1175 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1176 view.setShowDbRefTooltip(av.isShowDBRefs());
1177 view.setFollowHighlight(av.isFollowHighlight());
1178 view.setFollowSelection(av.followSelection);
1179 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1180 if (av.getFeaturesDisplayed() != null)
1182 jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
1184 String[] renderOrder = ap.getSeqPanel().seqCanvas
1185 .getFeatureRenderer().getRenderOrder()
1186 .toArray(new String[0]);
1188 Vector settingsAdded = new Vector();
1189 Object gstyle = null;
1190 GraduatedColor gcol = null;
1191 if (renderOrder != null)
1193 for (int ro = 0; ro < renderOrder.length; ro++)
1195 gstyle = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1196 .getFeatureStyle(renderOrder[ro]);
1197 Setting setting = new Setting();
1198 setting.setType(renderOrder[ro]);
1199 if (gstyle instanceof GraduatedColor)
1201 gcol = (GraduatedColor) gstyle;
1202 setting.setColour(gcol.getMaxColor().getRGB());
1203 setting.setMincolour(gcol.getMinColor().getRGB());
1204 setting.setMin(gcol.getMin());
1205 setting.setMax(gcol.getMax());
1206 setting.setColourByLabel(gcol.isColourByLabel());
1207 setting.setAutoScale(gcol.isAutoScale());
1208 setting.setThreshold(gcol.getThresh());
1209 setting.setThreshstate(gcol.getThreshType());
1213 setting.setColour(ap.getSeqPanel().seqCanvas
1214 .getFeatureRenderer()
1215 .getColour(renderOrder[ro]).getRGB());
1218 setting.setDisplay(av.getFeaturesDisplayed().isVisible(
1220 float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1221 .getOrder(renderOrder[ro]);
1224 setting.setOrder(rorder);
1226 fs.addSetting(setting);
1227 settingsAdded.addElement(renderOrder[ro]);
1231 // Make sure we save none displayed feature settings
1232 Iterator en = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1233 .getFeatureColours().keySet().iterator();
1234 while (en.hasNext())
1236 String key = en.next().toString();
1237 if (settingsAdded.contains(key))
1242 Setting setting = new Setting();
1243 setting.setType(key);
1244 setting.setColour(ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1245 .getColour(key).getRGB());
1247 setting.setDisplay(false);
1248 float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1252 setting.setOrder(rorder);
1254 fs.addSetting(setting);
1255 settingsAdded.addElement(key);
1257 // is groups actually supposed to be a map here ?
1258 en = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1259 .getFeatureGroups().iterator();
1260 Vector groupsAdded = new Vector();
1261 while (en.hasNext())
1263 String grp = en.next().toString();
1264 if (groupsAdded.contains(grp))
1268 Group g = new Group();
1270 g.setDisplay(((Boolean) ap.getSeqPanel().seqCanvas
1271 .getFeatureRenderer().checkGroupVisibility(grp, false))
1274 groupsAdded.addElement(grp);
1276 jms.setFeatureSettings(fs);
1280 if (av.hasHiddenColumns())
1282 if (av.getColumnSelection() == null
1283 || av.getColumnSelection().getHiddenColumns() == null)
1285 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1289 for (int c = 0; c < av.getColumnSelection().getHiddenColumns()
1292 int[] region = av.getColumnSelection().getHiddenColumns()
1294 HiddenColumns hc = new HiddenColumns();
1295 hc.setStart(region[0]);
1296 hc.setEnd(region[1]);
1297 view.addHiddenColumns(hc);
1301 if (calcIdSet.size() > 0)
1303 for (String calcId : calcIdSet)
1305 if (calcId.trim().length() > 0)
1307 CalcIdParam cidp = createCalcIdParam(calcId, av);
1308 // Some calcIds have no parameters.
1311 view.addCalcIdParam(cidp);
1317 jms.addViewport(view);
1319 object.setJalviewModelSequence(jms);
1320 object.getVamsasModel().addSequenceSet(vamsasSet);
1322 if (jout != null && fileName != null)
1324 // We may not want to write the object to disk,
1325 // eg we can copy the alignViewport to a new view object
1326 // using save and then load
1329 System.out.println("Writing jar entry " + fileName);
1330 JarEntry entry = new JarEntry(fileName);
1331 jout.putNextEntry(entry);
1332 PrintWriter pout = new PrintWriter(new OutputStreamWriter(jout,
1334 Marshaller marshaller = new Marshaller(pout);
1335 marshaller.marshal(object);
1338 } catch (Exception ex)
1340 // TODO: raise error in GUI if marshalling failed.
1341 ex.printStackTrace();
1348 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1349 * for each viewer, with
1351 * <li>viewer geometry (position, size, split pane divider location)</li>
1352 * <li>index of the selected structure in the viewer (currently shows gapped
1354 * <li>the id of the annotation holding RNA secondary structure</li>
1355 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1357 * Varna viewer state is also written out (in native Varna XML) to separate
1358 * project jar entries. A separate entry is written for each RNA structure
1359 * displayed, with the naming convention
1361 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
1369 * @param storeDataset
1371 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
1372 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
1373 boolean storeDataset)
1375 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1376 for (int f = frames.length - 1; f > -1; f--)
1378 if (frames[f] instanceof AppVarna)
1380 AppVarna varna = (AppVarna) frames[f];
1382 * link the sequence to every viewer that is showing it and is linked to
1383 * its alignment panel
1385 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1387 String viewId = varna.getViewId();
1388 RnaViewer rna = new RnaViewer();
1389 rna.setViewId(viewId);
1390 rna.setTitle(varna.getTitle());
1391 rna.setXpos(varna.getX());
1392 rna.setYpos(varna.getY());
1393 rna.setWidth(varna.getWidth());
1394 rna.setHeight(varna.getHeight());
1395 rna.setDividerLocation(varna.getDividerLocation());
1396 rna.setSelectedRna(varna.getSelectedIndex());
1397 jseq.addRnaViewer(rna);
1400 * Store each Varna panel's state once in the project per sequence.
1401 * First time through only (storeDataset==false)
1403 // boolean storeSessions = false;
1404 // String sequenceViewId = viewId + seqsToIds.get(jds);
1405 // if (!storeDataset && !viewIds.contains(sequenceViewId))
1407 // viewIds.add(sequenceViewId);
1408 // storeSessions = true;
1410 for (RnaModel model : varna.getModels())
1412 if (model.seq == jds)
1415 * VARNA saves each view (sequence or alignment secondary
1416 * structure, gapped or trimmed) as a separate XML file
1418 String jarEntryName = rnaSessions.get(model);
1419 if (jarEntryName == null)
1422 String varnaStateFile = varna.getStateInfo(model.rna);
1423 jarEntryName = RNA_PREFIX + viewId + "_"
1425 copyFileToJar(jout, varnaStateFile, jarEntryName);
1426 rnaSessions.put(model, jarEntryName);
1428 SecondaryStructure ss = new SecondaryStructure();
1429 String annotationId = varna.getAnnotation(jds).annotationId;
1430 ss.setAnnotationId(annotationId);
1431 ss.setViewerState(jarEntryName);
1432 ss.setGapped(model.gapped);
1433 ss.setTitle(model.title);
1434 rna.addSecondaryStructure(ss);
1443 * Copy the contents of a file to a new entry added to the output jar
1447 * @param jarEntryName
1449 protected void copyFileToJar(JarOutputStream jout, String infilePath,
1450 String jarEntryName)
1452 DataInputStream dis = null;
1455 File file = new File(infilePath);
1456 if (file.exists() && jout != null)
1458 dis = new DataInputStream(new FileInputStream(file));
1459 byte[] data = new byte[(int) file.length()];
1460 dis.readFully(data);
1461 writeJarEntry(jout, jarEntryName, data);
1463 } catch (Exception ex)
1465 ex.printStackTrace();
1473 } catch (IOException e)
1482 * Write the data to a new entry of given name in the output jar file
1485 * @param jarEntryName
1487 * @throws IOException
1489 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
1490 byte[] data) throws IOException
1494 System.out.println("Writing jar entry " + jarEntryName);
1495 jout.putNextEntry(new JarEntry(jarEntryName));
1496 DataOutputStream dout = new DataOutputStream(jout);
1497 dout.write(data, 0, data.length);
1504 * Save the state of a structure viewer
1509 * the archive XML element under which to save the state
1512 * @param matchedFile
1516 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
1517 Pdbids pdb, PDBEntry entry, List<String> viewIds,
1518 String matchedFile, StructureViewerBase viewFrame)
1520 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
1523 * Look for any bindings for this viewer to the PDB file of interest
1524 * (including part matches excluding chain id)
1526 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
1528 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
1529 final String pdbId = pdbentry.getId();
1530 if (!pdbId.equals(entry.getId())
1531 && !(entry.getId().length() > 4 && entry.getId()
1532 .toLowerCase().startsWith(pdbId.toLowerCase())))
1535 * not interested in a binding to a different PDB entry here
1539 if (matchedFile == null)
1541 matchedFile = pdbentry.getFile();
1543 else if (!matchedFile.equals(pdbentry.getFile()))
1546 .warn("Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
1547 + pdbentry.getFile());
1551 // can get at it if the ID
1552 // match is ambiguous (e.g.
1555 for (int smap = 0; smap < viewFrame.getBinding().getSequence()[peid].length; smap++)
1557 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
1558 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
1560 StructureState state = new StructureState();
1561 state.setVisible(true);
1562 state.setXpos(viewFrame.getX());
1563 state.setYpos(viewFrame.getY());
1564 state.setWidth(viewFrame.getWidth());
1565 state.setHeight(viewFrame.getHeight());
1566 final String viewId = viewFrame.getViewId();
1567 state.setViewId(viewId);
1568 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
1569 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
1570 state.setColourByJmol(viewFrame.isColouredByViewer());
1571 state.setType(viewFrame.getViewerType().toString());
1572 pdb.addStructureState(state);
1579 private AnnotationColours constructAnnotationColours(
1580 AnnotationColourGradient acg, List<UserColourScheme> userColours,
1581 JalviewModelSequence jms)
1583 AnnotationColours ac = new AnnotationColours();
1584 ac.setAboveThreshold(acg.getAboveThreshold());
1585 ac.setThreshold(acg.getAnnotationThreshold());
1586 ac.setAnnotation(acg.getAnnotation());
1587 if (acg.getBaseColour() instanceof jalview.schemes.UserColourScheme)
1589 ac.setColourScheme(setUserColourScheme(acg.getBaseColour(),
1594 ac.setColourScheme(ColourSchemeProperty.getColourName(acg
1598 ac.setMaxColour(acg.getMaxColour().getRGB());
1599 ac.setMinColour(acg.getMinColour().getRGB());
1600 ac.setPerSequence(acg.isSeqAssociated());
1601 ac.setPredefinedColours(acg.isPredefinedColours());
1605 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
1606 IdentityHashMap<SequenceGroup, String> groupRefs,
1607 AlignmentViewport av,
1608 Set<String> calcIdSet, boolean storeDS, SequenceSet vamsasSet)
1611 for (int i = 0; i < aa.length; i++)
1613 Annotation an = new Annotation();
1615 AlignmentAnnotation annotation = aa[i];
1616 if (annotation.annotationId != null)
1618 annotationIds.put(annotation.annotationId, annotation);
1621 an.setId(annotation.annotationId);
1623 an.setVisible(annotation.visible);
1625 an.setDescription(annotation.description);
1627 if (annotation.sequenceRef != null)
1629 // 2.9 JAL-1781 xref on sequence id rather than name
1630 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
1632 if (annotation.groupRef != null)
1634 String groupIdr = groupRefs.get(annotation.groupRef);
1635 if (groupIdr == null)
1637 // make a locally unique String
1638 groupRefs.put(annotation.groupRef,
1639 groupIdr = ("" + System.currentTimeMillis()
1640 + annotation.groupRef.getName() + groupRefs.size()));
1642 an.setGroupRef(groupIdr.toString());
1645 // store all visualization attributes for annotation
1646 an.setGraphHeight(annotation.graphHeight);
1647 an.setCentreColLabels(annotation.centreColLabels);
1648 an.setScaleColLabels(annotation.scaleColLabel);
1649 an.setShowAllColLabels(annotation.showAllColLabels);
1650 an.setBelowAlignment(annotation.belowAlignment);
1652 if (annotation.graph > 0)
1655 an.setGraphType(annotation.graph);
1656 an.setGraphGroup(annotation.graphGroup);
1657 if (annotation.getThreshold() != null)
1659 ThresholdLine line = new ThresholdLine();
1660 line.setLabel(annotation.getThreshold().label);
1661 line.setValue(annotation.getThreshold().value);
1662 line.setColour(annotation.getThreshold().colour.getRGB());
1663 an.setThresholdLine(line);
1671 an.setLabel(annotation.label);
1673 if (annotation == av.getAlignmentQualityAnnot()
1674 || annotation == av.getAlignmentConservationAnnotation()
1675 || annotation == av.getAlignmentConsensusAnnotation()
1676 || annotation.autoCalculated)
1678 // new way of indicating autocalculated annotation -
1679 an.setAutoCalculated(annotation.autoCalculated);
1681 if (annotation.hasScore())
1683 an.setScore(annotation.getScore());
1686 if (annotation.getCalcId() != null)
1688 calcIdSet.add(annotation.getCalcId());
1689 an.setCalcId(annotation.getCalcId());
1691 if (annotation.hasProperties())
1693 for (String pr : annotation.getProperties())
1695 Property prop = new Property();
1697 prop.setValue(annotation.getProperty(pr));
1698 an.addProperty(prop);
1702 AnnotationElement ae;
1703 if (annotation.annotations != null)
1705 an.setScoreOnly(false);
1706 for (int a = 0; a < annotation.annotations.length; a++)
1708 if ((annotation == null) || (annotation.annotations[a] == null))
1713 ae = new AnnotationElement();
1714 if (annotation.annotations[a].description != null)
1716 ae.setDescription(annotation.annotations[a].description);
1718 if (annotation.annotations[a].displayCharacter != null)
1720 ae.setDisplayCharacter(annotation.annotations[a].displayCharacter);
1723 if (!Float.isNaN(annotation.annotations[a].value))
1725 ae.setValue(annotation.annotations[a].value);
1729 if (annotation.annotations[a].secondaryStructure > ' ')
1731 ae.setSecondaryStructure(annotation.annotations[a].secondaryStructure
1735 if (annotation.annotations[a].colour != null
1736 && annotation.annotations[a].colour != java.awt.Color.black)
1738 ae.setColour(annotation.annotations[a].colour.getRGB());
1741 an.addAnnotationElement(ae);
1742 if (annotation.autoCalculated)
1744 // only write one non-null entry into the annotation row -
1745 // sufficient to get the visualization attributes necessary to
1753 an.setScoreOnly(true);
1755 if (!storeDS || (storeDS && !annotation.autoCalculated))
1757 // skip autocalculated annotation - these are only provided for
1759 vamsasSet.addAnnotation(an);
1765 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
1767 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
1768 if (settings != null)
1770 CalcIdParam vCalcIdParam = new CalcIdParam();
1771 vCalcIdParam.setCalcId(calcId);
1772 vCalcIdParam.addServiceURL(settings.getServiceURI());
1773 // generic URI allowing a third party to resolve another instance of the
1774 // service used for this calculation
1775 for (String urls : settings.getServiceURLs())
1777 vCalcIdParam.addServiceURL(urls);
1779 vCalcIdParam.setVersion("1.0");
1780 if (settings.getPreset() != null)
1782 WsParamSetI setting = settings.getPreset();
1783 vCalcIdParam.setName(setting.getName());
1784 vCalcIdParam.setDescription(setting.getDescription());
1788 vCalcIdParam.setName("");
1789 vCalcIdParam.setDescription("Last used parameters");
1791 // need to be able to recover 1) settings 2) user-defined presets or
1792 // recreate settings from preset 3) predefined settings provided by
1793 // service - or settings that can be transferred (or discarded)
1794 vCalcIdParam.setParameters(settings.getWsParamFile().replace("\n",
1796 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
1797 // todo - decide if updateImmediately is needed for any projects.
1799 return vCalcIdParam;
1804 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
1807 if (calcIdParam.getVersion().equals("1.0"))
1809 Jws2Instance service = Jws2Discoverer.getDiscoverer()
1810 .getPreferredServiceFor(calcIdParam.getServiceURL());
1811 if (service != null)
1813 WsParamSetI parmSet = null;
1816 parmSet = service.getParamStore().parseServiceParameterFile(
1817 calcIdParam.getName(), calcIdParam.getDescription(),
1818 calcIdParam.getServiceURL(),
1819 calcIdParam.getParameters().replace("|\\n|", "\n"));
1820 } catch (IOException x)
1822 warn("Couldn't parse parameter data for "
1823 + calcIdParam.getCalcId(), x);
1826 List<ArgumentI> argList = null;
1827 if (calcIdParam.getName().length() > 0)
1829 parmSet = service.getParamStore()
1830 .getPreset(calcIdParam.getName());
1831 if (parmSet != null)
1833 // TODO : check we have a good match with settings in AACon -
1834 // otherwise we'll need to create a new preset
1839 argList = parmSet.getArguments();
1842 AAConSettings settings = new AAConSettings(
1843 calcIdParam.isAutoUpdate(), service, parmSet, argList);
1844 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
1845 calcIdParam.isNeedsUpdate());
1850 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
1854 throw new Error(MessageManager.formatMessage(
1855 "error.unsupported_version_calcIdparam", new Object[]
1856 { calcIdParam.toString() }));
1860 * External mapping between jalview objects and objects yielding a valid and
1861 * unique object ID string. This is null for normal Jalview project IO, but
1862 * non-null when a jalview project is being read or written as part of a
1865 IdentityHashMap jv2vobj = null;
1868 * Construct a unique ID for jvobj using either existing bindings or if none
1869 * exist, the result of the hashcode call for the object.
1872 * jalview data object
1873 * @return unique ID for referring to jvobj
1875 private String makeHashCode(Object jvobj, String altCode)
1877 if (jv2vobj != null)
1879 Object id = jv2vobj.get(jvobj);
1882 return id.toString();
1884 // check string ID mappings
1885 if (jvids2vobj != null && jvobj instanceof String)
1887 id = jvids2vobj.get(jvobj);
1891 return id.toString();
1893 // give up and warn that something has gone wrong
1894 warn("Cannot find ID for object in external mapping : " + jvobj);
1900 * return local jalview object mapped to ID, if it exists
1904 * @return null or object bound to idcode
1906 private Object retrieveExistingObj(String idcode)
1908 if (idcode != null && vobj2jv != null)
1910 return vobj2jv.get(idcode);
1916 * binding from ID strings from external mapping table to jalview data model
1919 private Hashtable vobj2jv;
1921 private Sequence createVamsasSequence(String id, SequenceI jds)
1923 return createVamsasSequence(true, id, jds, null);
1926 private Sequence createVamsasSequence(boolean recurse, String id,
1927 SequenceI jds, SequenceI parentseq)
1929 Sequence vamsasSeq = new Sequence();
1930 vamsasSeq.setId(id);
1931 vamsasSeq.setName(jds.getName());
1932 vamsasSeq.setSequence(jds.getSequenceAsString());
1933 vamsasSeq.setDescription(jds.getDescription());
1934 jalview.datamodel.DBRefEntry[] dbrefs = null;
1935 if (jds.getDatasetSequence() != null)
1937 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
1938 if (jds.getDatasetSequence().getDBRef() != null)
1940 dbrefs = jds.getDatasetSequence().getDBRef();
1945 vamsasSeq.setDsseqid(id); // so we can tell which sequences really are
1946 // dataset sequences only
1947 dbrefs = jds.getDBRef();
1951 for (int d = 0; d < dbrefs.length; d++)
1953 DBRef dbref = new DBRef();
1954 dbref.setSource(dbrefs[d].getSource());
1955 dbref.setVersion(dbrefs[d].getVersion());
1956 dbref.setAccessionId(dbrefs[d].getAccessionId());
1957 if (dbrefs[d].hasMap())
1959 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
1961 dbref.setMapping(mp);
1963 vamsasSeq.addDBRef(dbref);
1969 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
1970 SequenceI parentseq, SequenceI jds, boolean recurse)
1973 if (jmp.getMap() != null)
1977 jalview.util.MapList mlst = jmp.getMap();
1978 List<int[]> r = mlst.getFromRanges();
1979 for (int[] range : r)
1981 MapListFrom mfrom = new MapListFrom();
1982 mfrom.setStart(range[0]);
1983 mfrom.setEnd(range[1]);
1984 mp.addMapListFrom(mfrom);
1986 r = mlst.getToRanges();
1987 for (int[] range : r)
1989 MapListTo mto = new MapListTo();
1990 mto.setStart(range[0]);
1991 mto.setEnd(range[1]);
1992 mp.addMapListTo(mto);
1994 mp.setMapFromUnit(mlst.getFromRatio());
1995 mp.setMapToUnit(mlst.getToRatio());
1996 if (jmp.getTo() != null)
1998 MappingChoice mpc = new MappingChoice();
2000 && (parentseq != jmp.getTo() || parentseq
2001 .getDatasetSequence() != jmp.getTo()))
2003 mpc.setSequence(createVamsasSequence(false, seqHash(jmp.getTo()),
2009 SequenceI ps = null;
2010 if (parentseq != jmp.getTo()
2011 && parentseq.getDatasetSequence() != jmp.getTo())
2013 // chaining dbref rather than a handshaking one
2014 jmpid = seqHash(ps = jmp.getTo());
2018 jmpid = seqHash(ps = parentseq);
2020 mpc.setDseqFor(jmpid);
2021 if (!seqRefIds.containsKey(mpc.getDseqFor()))
2023 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2024 seqRefIds.put(mpc.getDseqFor(), ps);
2028 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2031 mp.setMappingChoice(mpc);
2037 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2038 List<UserColourScheme> userColours, JalviewModelSequence jms)
2041 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2042 boolean newucs = false;
2043 if (!userColours.contains(ucs))
2045 userColours.add(ucs);
2048 id = "ucs" + userColours.indexOf(ucs);
2051 // actually create the scheme's entry in the XML model
2052 java.awt.Color[] colours = ucs.getColours();
2053 jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
2054 jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
2056 for (int i = 0; i < colours.length; i++)
2058 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2059 col.setName(ResidueProperties.aa[i]);
2060 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2061 jbucs.addColour(col);
2063 if (ucs.getLowerCaseColours() != null)
2065 colours = ucs.getLowerCaseColours();
2066 for (int i = 0; i < colours.length; i++)
2068 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2069 col.setName(ResidueProperties.aa[i].toLowerCase());
2070 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2071 jbucs.addColour(col);
2076 uc.setUserColourScheme(jbucs);
2077 jms.addUserColours(uc);
2083 jalview.schemes.UserColourScheme getUserColourScheme(
2084 JalviewModelSequence jms, String id)
2086 UserColours[] uc = jms.getUserColours();
2087 UserColours colours = null;
2089 for (int i = 0; i < uc.length; i++)
2091 if (uc[i].getId().equals(id))
2099 java.awt.Color[] newColours = new java.awt.Color[24];
2101 for (int i = 0; i < 24; i++)
2103 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2104 .getUserColourScheme().getColour(i).getRGB(), 16));
2107 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2110 if (colours.getUserColourScheme().getColourCount() > 24)
2112 newColours = new java.awt.Color[23];
2113 for (int i = 0; i < 23; i++)
2115 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2116 .getUserColourScheme().getColour(i + 24).getRGB(), 16));
2118 ucs.setLowerCaseColours(newColours);
2125 * contains last error message (if any) encountered by XML loader.
2127 String errorMessage = null;
2130 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2131 * exceptions are raised during project XML parsing
2133 public boolean attemptversion1parse = true;
2136 * Load a jalview project archive from a jar file
2139 * - HTTP URL or filename
2141 public AlignFrame loadJalviewAlign(final String file)
2144 jalview.gui.AlignFrame af = null;
2148 // create list to store references for any new Jmol viewers created
2149 newStructureViewers = new Vector<JalviewStructureDisplayI>();
2150 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2151 // Workaround is to make sure caller implements the JarInputStreamProvider
2153 // so we can re-open the jar input stream for each entry.
2155 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2156 af = loadJalviewAlign(jprovider);
2158 } catch (MalformedURLException e)
2160 errorMessage = "Invalid URL format for '" + file + "'";
2166 SwingUtilities.invokeAndWait(new Runnable()
2170 setLoadingFinishedForNewStructureViewers();
2173 } catch (Exception x)
2175 System.err.println("Error loading alignment: " + x.getMessage());
2181 private jarInputStreamProvider createjarInputStreamProvider(
2182 final String file) throws MalformedURLException
2185 errorMessage = null;
2186 uniqueSetSuffix = null;
2188 viewportsAdded.clear();
2189 frefedSequence = null;
2191 if (file.startsWith("http://"))
2193 url = new URL(file);
2195 final URL _url = url;
2196 return new jarInputStreamProvider()
2200 public JarInputStream getJarInputStream() throws IOException
2204 return new JarInputStream(_url.openStream());
2208 return new JarInputStream(new FileInputStream(file));
2213 public String getFilename()
2221 * Recover jalview session from a jalview project archive. Caller may
2222 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2223 * themselves. Any null fields will be initialised with default values,
2224 * non-null fields are left alone.
2229 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2231 errorMessage = null;
2232 if (uniqueSetSuffix == null)
2234 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2236 if (seqRefIds == null)
2238 seqRefIds = new HashMap<String, SequenceI>();
2240 if (frefedSequence == null)
2242 frefedSequence = new Vector();
2245 AlignFrame af = null, _af = null;
2246 Map<String, AlignFrame> gatherToThisFrame = new HashMap<String, AlignFrame>();
2247 final String file = jprovider.getFilename();
2250 JarInputStream jin = null;
2251 JarEntry jarentry = null;
2256 jin = jprovider.getJarInputStream();
2257 for (int i = 0; i < entryCount; i++)
2259 jarentry = jin.getNextJarEntry();
2262 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2264 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2265 JalviewModel object = new JalviewModel();
2267 Unmarshaller unmar = new Unmarshaller(object);
2268 unmar.setValidation(false);
2269 object = (JalviewModel) unmar.unmarshal(in);
2270 if (true) // !skipViewport(object))
2272 _af = loadFromObject(object, file, true, jprovider);
2273 if (object.getJalviewModelSequence().getViewportCount() > 0)
2276 if (af.viewport.isGatherViewsHere())
2278 gatherToThisFrame.put(af.viewport.getSequenceSetId(), af);
2284 else if (jarentry != null)
2286 // Some other file here.
2289 } while (jarentry != null);
2290 resolveFrefedSequences();
2291 } catch (IOException ex)
2293 ex.printStackTrace();
2294 errorMessage = "Couldn't locate Jalview XML file : " + file;
2295 System.err.println("Exception whilst loading jalview XML file : "
2297 } catch (Exception ex)
2299 System.err.println("Parsing as Jalview Version 2 file failed.");
2300 ex.printStackTrace(System.err);
2301 if (attemptversion1parse)
2303 // Is Version 1 Jar file?
2306 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
2307 } catch (Exception ex2)
2309 System.err.println("Exception whilst loading as jalviewXMLV1:");
2310 ex2.printStackTrace();
2314 if (Desktop.instance != null)
2316 Desktop.instance.stopLoading();
2320 System.out.println("Successfully loaded archive file");
2323 ex.printStackTrace();
2325 System.err.println("Exception whilst loading jalview XML file : "
2327 } catch (OutOfMemoryError e)
2329 // Don't use the OOM Window here
2330 errorMessage = "Out of memory loading jalview XML file";
2331 System.err.println("Out of memory whilst loading jalview XML file");
2332 e.printStackTrace();
2335 if (Desktop.instance != null)
2337 Desktop.instance.stopLoading();
2341 * Regather multiple views (with the same sequence set id) to the frame (if
2342 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2343 * views instead of separate frames. Note this doesn't restore a state where
2344 * some expanded views in turn have tabbed views - the last "first tab" read
2345 * in will play the role of gatherer for all.
2347 for (AlignFrame fr : gatherToThisFrame.values())
2349 Desktop.instance.gatherViews(fr);
2352 restoreSplitFrames();
2354 if (errorMessage != null)
2362 * Try to reconstruct and display SplitFrame windows, where each contains
2363 * complementary dna and protein alignments. Done by pairing up AlignFrame
2364 * objects (created earlier) which have complementary viewport ids associated.
2366 protected void restoreSplitFrames()
2368 List<SplitFrame> gatherTo = new ArrayList<SplitFrame>();
2369 List<AlignFrame> addedToSplitFrames = new ArrayList<AlignFrame>();
2370 Map<String, AlignFrame> dna = new HashMap<String, AlignFrame>();
2373 * Identify the DNA alignments
2375 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2378 AlignFrame af = candidate.getValue();
2379 if (af.getViewport().getAlignment().isNucleotide())
2381 dna.put(candidate.getKey().getId(), af);
2386 * Try to match up the protein complements
2388 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2391 AlignFrame af = candidate.getValue();
2392 if (!af.getViewport().getAlignment().isNucleotide())
2394 String complementId = candidate.getKey().getComplementId();
2395 // only non-null complements should be in the Map
2396 if (complementId != null && dna.containsKey(complementId))
2398 final AlignFrame dnaFrame = dna.get(complementId);
2399 SplitFrame sf = createSplitFrame(dnaFrame, af);
2400 addedToSplitFrames.add(dnaFrame);
2401 addedToSplitFrames.add(af);
2402 if (af.viewport.isGatherViewsHere())
2411 * Open any that we failed to pair up (which shouldn't happen!) as
2412 * standalone AlignFrame's.
2414 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2417 AlignFrame af = candidate.getValue();
2418 if (!addedToSplitFrames.contains(af)) {
2419 Viewport view = candidate.getKey();
2420 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
2422 System.err.println("Failed to restore view " + view.getTitle()
2423 + " to split frame");
2428 * Gather back into tabbed views as flagged.
2430 for (SplitFrame sf : gatherTo)
2432 Desktop.instance.gatherViews(sf);
2435 splitFrameCandidates.clear();
2439 * Construct and display one SplitFrame holding DNA and protein alignments.
2442 * @param proteinFrame
2445 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
2446 AlignFrame proteinFrame)
2448 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
2449 String title = MessageManager.getString("label.linked_view_title");
2450 int width = (int) dnaFrame.getBounds().getWidth();
2451 int height = (int) (dnaFrame.getBounds().getHeight()
2452 + proteinFrame.getBounds().getHeight() + 50);
2453 Desktop.addInternalFrame(splitFrame, title, width, height);
2456 * And compute cDNA consensus (couldn't do earlier with consensus as
2457 * mappings were not yet present)
2459 proteinFrame.viewport.alignmentChanged(proteinFrame.alignPanel);
2465 * check errorMessage for a valid error message and raise an error box in the
2466 * GUI or write the current errorMessage to stderr and then clear the error
2469 protected void reportErrors()
2471 reportErrors(false);
2474 protected void reportErrors(final boolean saving)
2476 if (errorMessage != null)
2478 final String finalErrorMessage = errorMessage;
2481 javax.swing.SwingUtilities.invokeLater(new Runnable()
2486 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2487 finalErrorMessage, "Error "
2488 + (saving ? "saving" : "loading")
2489 + " Jalview file", JOptionPane.WARNING_MESSAGE);
2495 System.err.println("Problem loading Jalview file: " + errorMessage);
2498 errorMessage = null;
2501 Map<String, String> alreadyLoadedPDB = new HashMap<String, String>();
2504 * when set, local views will be updated from view stored in JalviewXML
2505 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2506 * sync if this is set to true.
2508 private final boolean updateLocalViews = false;
2511 * Returns the path to a temporary file holding the PDB file for the given PDB
2512 * id. The first time of asking, searches for a file of that name in the
2513 * Jalview project jar, and copies it to a new temporary file. Any repeat
2514 * requests just return the path to the file previously created.
2520 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId)
2522 if (alreadyLoadedPDB.containsKey(pdbId))
2524 return alreadyLoadedPDB.get(pdbId).toString();
2527 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb");
2528 if (tempFile != null)
2530 alreadyLoadedPDB.put(pdbId, tempFile);
2536 * Copies the jar entry of given name to a new temporary file and returns the
2537 * path to the file, or null if the entry is not found.
2540 * @param jarEntryName
2542 * a prefix for the temporary file name, must be at least three
2546 protected String copyJarEntry(jarInputStreamProvider jprovider,
2547 String jarEntryName, String prefix)
2549 BufferedReader in = null;
2550 PrintWriter out = null;
2554 JarInputStream jin = jprovider.getJarInputStream();
2556 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2557 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2558 * FileInputStream(jprovider)); }
2561 JarEntry entry = null;
2564 entry = jin.getNextJarEntry();
2565 } while (entry != null && !entry.getName().equals(jarEntryName));
2568 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
2569 File outFile = File.createTempFile(prefix, ".tmp");
2570 outFile.deleteOnExit();
2571 out = new PrintWriter(new FileOutputStream(outFile));
2574 while ((data = in.readLine()) != null)
2579 String t = outFile.getAbsolutePath();
2584 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
2586 } catch (Exception ex)
2588 ex.printStackTrace();
2596 } catch (IOException e)
2610 private class JvAnnotRow
2612 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2619 * persisted version of annotation row from which to take vis properties
2621 public jalview.datamodel.AlignmentAnnotation template;
2624 * original position of the annotation row in the alignment
2630 * Load alignment frame from jalview XML DOM object
2635 * filename source string
2636 * @param loadTreesAndStructures
2637 * when false only create Viewport
2639 * data source provider
2640 * @return alignment frame created from view stored in DOM
2642 AlignFrame loadFromObject(JalviewModel object, String file,
2643 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
2645 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
2646 Sequence[] vamsasSeq = vamsasSet.getSequence();
2648 JalviewModelSequence jms = object.getJalviewModelSequence();
2650 Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
2653 // ////////////////////////////////
2656 List<SequenceI> hiddenSeqs = null;
2657 jalview.datamodel.Sequence jseq;
2659 List<SequenceI> tmpseqs = new ArrayList<SequenceI>();
2661 boolean multipleView = false;
2663 JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
2664 int vi = 0; // counter in vamsasSeq array
2665 for (int i = 0; i < jseqs.length; i++)
2667 String seqId = jseqs[i].getId();
2669 if (seqRefIds.get(seqId) != null)
2671 tmpseqs.add(seqRefIds.get(seqId));
2672 multipleView = true;
2676 jseq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
2677 vamsasSeq[vi].getSequence());
2678 jseq.setDescription(vamsasSeq[vi].getDescription());
2679 jseq.setStart(jseqs[i].getStart());
2680 jseq.setEnd(jseqs[i].getEnd());
2681 jseq.setVamsasId(uniqueSetSuffix + seqId);
2682 seqRefIds.put(vamsasSeq[vi].getId(), jseq);
2687 if (jseqs[i].getHidden())
2689 if (hiddenSeqs == null)
2691 hiddenSeqs = new ArrayList<SequenceI>();
2694 hiddenSeqs.add(seqRefIds.get(seqId));
2700 // Create the alignment object from the sequence set
2701 // ///////////////////////////////
2702 SequenceI[] orderedSeqs = tmpseqs
2703 .toArray(new SequenceI[tmpseqs.size()]);
2705 Alignment al = new Alignment(orderedSeqs);
2707 // / Add the alignment properties
2708 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
2710 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
2711 al.setProperty(ssp.getKey(), ssp.getValue());
2715 // SequenceFeatures are added to the DatasetSequence,
2716 // so we must create or recover the dataset before loading features
2717 // ///////////////////////////////
2718 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
2720 // older jalview projects do not have a dataset id.
2721 al.setDataset(null);
2725 // recover dataset - passing on flag indicating if this a 'viewless'
2726 // sequence set (a.k.a. a stored dataset for the project)
2727 recoverDatasetFor(vamsasSet, al, object.getJalviewModelSequence()
2728 .getViewportCount() == 0);
2730 // ///////////////////////////////
2732 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
2735 // load sequence features, database references and any associated PDB
2736 // structures for the alignment
2737 for (int i = 0; i < vamsasSeq.length; i++)
2739 if (jseqs[i].getFeaturesCount() > 0)
2741 Features[] features = jseqs[i].getFeatures();
2742 for (int f = 0; f < features.length; f++)
2744 jalview.datamodel.SequenceFeature sf = new jalview.datamodel.SequenceFeature(
2745 features[f].getType(), features[f].getDescription(),
2746 features[f].getStatus(), features[f].getBegin(),
2747 features[f].getEnd(), features[f].getFeatureGroup());
2749 sf.setScore(features[f].getScore());
2750 for (int od = 0; od < features[f].getOtherDataCount(); od++)
2752 OtherData keyValue = features[f].getOtherData(od);
2753 if (keyValue.getKey().startsWith("LINK"))
2755 sf.addLink(keyValue.getValue());
2759 sf.setValue(keyValue.getKey(), keyValue.getValue());
2764 al.getSequenceAt(i).getDatasetSequence().addSequenceFeature(sf);
2767 if (vamsasSeq[i].getDBRefCount() > 0)
2769 addDBRefs(al.getSequenceAt(i).getDatasetSequence(), vamsasSeq[i]);
2771 if (jseqs[i].getPdbidsCount() > 0)
2773 Pdbids[] ids = jseqs[i].getPdbids();
2774 for (int p = 0; p < ids.length; p++)
2776 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
2777 entry.setId(ids[p].getId());
2778 if (ids[p].getType() != null)
2780 if (ids[p].getType().equalsIgnoreCase("PDB"))
2782 entry.setType(PDBEntry.Type.PDB);
2786 entry.setType(PDBEntry.Type.FILE);
2789 if (ids[p].getFile() != null)
2791 if (!pdbloaded.containsKey(ids[p].getFile()))
2793 entry.setFile(loadPDBFile(jprovider, ids[p].getId()));
2797 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
2800 StructureSelectionManager.getStructureSelectionManager(
2801 Desktop.instance).registerPDBEntry(entry);
2802 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
2806 } // end !multipleview
2808 // ///////////////////////////////
2809 // LOAD SEQUENCE MAPPINGS
2811 if (vamsasSet.getAlcodonFrameCount() > 0)
2813 // TODO Potentially this should only be done once for all views of an
2815 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
2816 for (int i = 0; i < alc.length; i++)
2818 AlignedCodonFrame cf = new AlignedCodonFrame();
2819 if (alc[i].getAlcodMapCount() > 0)
2821 AlcodMap[] maps = alc[i].getAlcodMap();
2822 for (int m = 0; m < maps.length; m++)
2824 SequenceI dnaseq = seqRefIds.get(maps[m].getDnasq());
2826 jalview.datamodel.Mapping mapping = null;
2827 // attach to dna sequence reference.
2828 if (maps[m].getMapping() != null)
2830 mapping = addMapping(maps[m].getMapping());
2834 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
2839 frefedSequence.add(new Object[]
2840 { maps[m].getDnasq(), cf, mapping });
2844 al.addCodonFrame(cf);
2848 // ////////////////////////////////
2850 List<JvAnnotRow> autoAlan = new ArrayList<JvAnnotRow>();
2853 * store any annotations which forward reference a group's ID
2855 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<String, List<AlignmentAnnotation>>();
2857 if (vamsasSet.getAnnotationCount() > 0)
2859 Annotation[] an = vamsasSet.getAnnotation();
2861 for (int i = 0; i < an.length; i++)
2863 Annotation annotation = an[i];
2866 * test if annotation is automatically calculated for this view only
2868 boolean autoForView = false;
2869 if (annotation.getLabel().equals("Quality")
2870 || annotation.getLabel().equals("Conservation")
2871 || annotation.getLabel().equals("Consensus"))
2873 // Kludge for pre 2.5 projects which lacked the autocalculated flag
2875 if (!annotation.hasAutoCalculated())
2877 annotation.setAutoCalculated(true);
2881 || (annotation.hasAutoCalculated() && annotation
2882 .isAutoCalculated()))
2884 // remove ID - we don't recover annotation from other views for
2885 // view-specific annotation
2886 annotation.setId(null);
2889 // set visiblity for other annotation in this view
2890 String annotationId = annotation.getId();
2891 if (annotationId != null
2892 && annotationIds.containsKey(annotationId))
2894 AlignmentAnnotation jda = annotationIds.get(annotationId);
2895 // in principle Visible should always be true for annotation displayed
2896 // in multiple views
2897 if (annotation.hasVisible())
2899 jda.visible = annotation.getVisible();
2902 al.addAnnotation(jda);
2906 // Construct new annotation from model.
2907 AnnotationElement[] ae = annotation.getAnnotationElement();
2908 jalview.datamodel.Annotation[] anot = null;
2909 java.awt.Color firstColour = null;
2911 if (!annotation.getScoreOnly())
2913 anot = new jalview.datamodel.Annotation[al.getWidth()];
2914 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
2916 anpos = ae[aa].getPosition();
2918 if (anpos >= anot.length)
2923 anot[anpos] = new jalview.datamodel.Annotation(
2925 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
2926 (ae[aa].getSecondaryStructure() == null || ae[aa]
2927 .getSecondaryStructure().length() == 0) ? ' '
2928 : ae[aa].getSecondaryStructure().charAt(0),
2932 // JBPNote: Consider verifying dataflow for IO of secondary
2933 // structure annotation read from Stockholm files
2934 // this was added to try to ensure that
2935 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
2937 // anot[ae[aa].getPosition()].displayCharacter = "";
2939 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
2940 if (firstColour == null)
2942 firstColour = anot[anpos].colour;
2946 jalview.datamodel.AlignmentAnnotation jaa = null;
2948 if (annotation.getGraph())
2950 float llim = 0, hlim = 0;
2951 // if (autoForView || an[i].isAutoCalculated()) {
2954 jaa = new jalview.datamodel.AlignmentAnnotation(
2955 annotation.getLabel(), annotation.getDescription(), anot,
2956 llim, hlim, annotation.getGraphType());
2958 jaa.graphGroup = annotation.getGraphGroup();
2959 jaa._linecolour = firstColour;
2960 if (annotation.getThresholdLine() != null)
2962 jaa.setThreshold(new jalview.datamodel.GraphLine(annotation
2963 .getThresholdLine().getValue(), annotation
2964 .getThresholdLine().getLabel(), new java.awt.Color(
2965 annotation.getThresholdLine().getColour())));
2968 if (autoForView || annotation.isAutoCalculated())
2970 // Hardwire the symbol display line to ensure that labels for
2971 // histograms are displayed
2977 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
2978 an[i].getDescription(), anot);
2979 jaa._linecolour = firstColour;
2981 // register new annotation
2982 if (an[i].getId() != null)
2984 annotationIds.put(an[i].getId(), jaa);
2985 jaa.annotationId = an[i].getId();
2987 // recover sequence association
2988 String sequenceRef = an[i].getSequenceRef();
2989 if (sequenceRef != null)
2991 // from 2.9 sequenceRef is to sequence id (JAL-1781)
2992 SequenceI sequence = seqRefIds.get(sequenceRef);
2993 if (sequence == null)
2995 // in pre-2.9 projects sequence ref is to sequence name
2996 sequence = al.findName(sequenceRef);
2998 if (sequence != null)
3000 jaa.createSequenceMapping(sequence, 1, true);
3001 sequence.addAlignmentAnnotation(jaa);
3004 // and make a note of any group association
3005 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
3007 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3008 .get(an[i].getGroupRef());
3011 aal = new ArrayList<jalview.datamodel.AlignmentAnnotation>();
3012 groupAnnotRefs.put(an[i].getGroupRef(), aal);
3017 if (an[i].hasScore())
3019 jaa.setScore(an[i].getScore());
3021 if (an[i].hasVisible())
3023 jaa.visible = an[i].getVisible();
3026 if (an[i].hasCentreColLabels())
3028 jaa.centreColLabels = an[i].getCentreColLabels();
3031 if (an[i].hasScaleColLabels())
3033 jaa.scaleColLabel = an[i].getScaleColLabels();
3035 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
3037 // newer files have an 'autoCalculated' flag and store calculation
3038 // state in viewport properties
3039 jaa.autoCalculated = true; // means annotation will be marked for
3040 // update at end of load.
3042 if (an[i].hasGraphHeight())
3044 jaa.graphHeight = an[i].getGraphHeight();
3046 if (an[i].hasBelowAlignment())
3048 jaa.belowAlignment = an[i].isBelowAlignment();
3050 jaa.setCalcId(an[i].getCalcId());
3051 if (an[i].getPropertyCount() > 0)
3053 for (jalview.schemabinding.version2.Property prop : an[i]
3056 jaa.setProperty(prop.getName(), prop.getValue());
3059 if (jaa.autoCalculated)
3061 autoAlan.add(new JvAnnotRow(i, jaa));
3064 // if (!autoForView)
3066 // add autocalculated group annotation and any user created annotation
3068 al.addAnnotation(jaa);
3072 // ///////////////////////
3074 // Create alignment markup and styles for this view
3075 if (jms.getJGroupCount() > 0)
3077 JGroup[] groups = jms.getJGroup();
3078 boolean addAnnotSchemeGroup = false;
3079 for (int i = 0; i < groups.length; i++)
3081 JGroup jGroup = groups[i];
3082 ColourSchemeI cs = null;
3083 if (jGroup.getColour() != null)
3085 if (jGroup.getColour().startsWith("ucs"))
3087 cs = getUserColourScheme(jms, jGroup.getColour());
3089 else if (jGroup.getColour().equals("AnnotationColourGradient")
3090 && jGroup.getAnnotationColours() != null)
3092 addAnnotSchemeGroup = true;
3097 cs = ColourSchemeProperty.getColour(al, jGroup.getColour());
3102 cs.setThreshold(jGroup.getPidThreshold(), true);
3106 Vector<SequenceI> seqs = new Vector<SequenceI>();
3108 for (int s = 0; s < jGroup.getSeqCount(); s++)
3110 String seqId = jGroup.getSeq(s) + "";
3111 SequenceI ts = seqRefIds.get(seqId);
3115 seqs.addElement(ts);
3119 if (seqs.size() < 1)
3124 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3125 jGroup.getDisplayBoxes(), jGroup.getDisplayText(),
3126 jGroup.getColourText(), jGroup.getStart(),
3129 sg.setOutlineColour(new java.awt.Color(jGroup.getOutlineColour()));
3131 sg.textColour = new java.awt.Color(jGroup.getTextCol1());
3132 sg.textColour2 = new java.awt.Color(jGroup.getTextCol2());
3133 sg.setShowNonconserved(jGroup.hasShowUnconserved() ? jGroup
3134 .isShowUnconserved() : false);
3135 sg.thresholdTextColour = jGroup.getTextColThreshold();
3136 if (jGroup.hasShowConsensusHistogram())
3138 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3141 if (jGroup.hasShowSequenceLogo())
3143 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3145 if (jGroup.hasNormaliseSequenceLogo())
3147 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3149 if (jGroup.hasIgnoreGapsinConsensus())
3151 sg.setIgnoreGapsConsensus(jGroup.getIgnoreGapsinConsensus());
3153 if (jGroup.getConsThreshold() != 0)
3155 jalview.analysis.Conservation c = new jalview.analysis.Conservation(
3156 "All", ResidueProperties.propHash, 3,
3157 sg.getSequences(null), 0, sg.getWidth() - 1);
3159 c.verdict(false, 25);
3160 sg.cs.setConservation(c);
3163 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3165 // re-instate unique group/annotation row reference
3166 List<AlignmentAnnotation> jaal = groupAnnotRefs
3167 .get(jGroup.getId());
3170 for (AlignmentAnnotation jaa : jaal)
3173 if (jaa.autoCalculated)
3175 // match up and try to set group autocalc alignment row for this
3177 if (jaa.label.startsWith("Consensus for "))
3179 sg.setConsensus(jaa);
3181 // match up and try to set group autocalc alignment row for this
3183 if (jaa.label.startsWith("Conservation for "))
3185 sg.setConservationRow(jaa);
3192 if (addAnnotSchemeGroup)
3194 // reconstruct the annotation colourscheme
3195 sg.cs = constructAnnotationColour(
3196 jGroup.getAnnotationColours(), null, al, jms, false);
3202 // only dataset in this model, so just return.
3205 // ///////////////////////////////
3208 // If we just load in the same jar file again, the sequenceSetId
3209 // will be the same, and we end up with multiple references
3210 // to the same sequenceSet. We must modify this id on load
3211 // so that each load of the file gives a unique id
3212 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3213 String viewId = (view.getId() == null ? null : view.getId()
3215 AlignFrame af = null;
3216 AlignViewport av = null;
3217 // now check to see if we really need to create a new viewport.
3218 if (multipleView && viewportsAdded.size() == 0)
3220 // We recovered an alignment for which a viewport already exists.
3221 // TODO: fix up any settings necessary for overlaying stored state onto
3222 // state recovered from another document. (may not be necessary).
3223 // we may need a binding from a viewport in memory to one recovered from
3225 // and then recover its containing af to allow the settings to be applied.
3226 // TODO: fix for vamsas demo
3228 .println("About to recover a viewport for existing alignment: Sequence set ID is "
3230 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3231 if (seqsetobj != null)
3233 if (seqsetobj instanceof String)
3235 uniqueSeqSetId = (String) seqsetobj;
3237 .println("Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
3243 .println("Warning : Collision between sequence set ID string and existing jalview object mapping.");
3249 * indicate that annotation colours are applied across all groups (pre
3250 * Jalview 2.8.1 behaviour)
3252 boolean doGroupAnnColour = isVersionStringLaterThan("2.8.1",
3253 object.getVersion());
3255 AlignmentPanel ap = null;
3256 boolean isnewview = true;
3259 // Check to see if this alignment already has a view id == viewId
3260 jalview.gui.AlignmentPanel views[] = Desktop
3261 .getAlignmentPanels(uniqueSeqSetId);
3262 if (views != null && views.length > 0)
3264 for (int v = 0; v < views.length; v++)
3266 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
3268 // recover the existing alignpanel, alignframe, viewport
3269 af = views[v].alignFrame;
3272 // TODO: could even skip resetting view settings if we don't want to
3273 // change the local settings from other jalview processes
3282 af = loadViewport(file, jseqs, hiddenSeqs, al, jms, view,
3283 uniqueSeqSetId, viewId, autoAlan);
3289 * Load any trees, PDB structures and viewers
3291 * Not done if flag is false (when this method is used for New View)
3293 if (loadTreesAndStructures)
3295 loadTrees(jms, view, af, av, ap);
3296 loadPDBStructures(jprovider, jseqs, af, ap);
3297 loadRnaViewers(jprovider, jseqs, ap);
3299 // and finally return.
3304 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
3305 * panel is restored from separate jar entries, two (gapped and trimmed) per
3306 * sequence and secondary structure.
3308 * Currently each viewer shows just one sequence and structure (gapped and
3309 * trimmed), however this method is designed to support multiple sequences or
3310 * structures in viewers if wanted in future.
3316 private void loadRnaViewers(jarInputStreamProvider jprovider,
3317 JSeq[] jseqs, AlignmentPanel ap)
3320 * scan the sequences for references to viewers; create each one the first
3321 * time it is referenced, add Rna models to existing viewers
3323 for (JSeq jseq : jseqs)
3325 for (int i = 0; i < jseq.getRnaViewerCount(); i++)
3327 RnaViewer viewer = jseq.getRnaViewer(i);
3328 AppVarna appVarna = findOrCreateVarnaViewer(viewer, uniqueSetSuffix,
3331 for (int j = 0; j < viewer.getSecondaryStructureCount(); j++)
3333 SecondaryStructure ss = viewer.getSecondaryStructure(j);
3334 SequenceI seq = seqRefIds.get(jseq.getId());
3335 AlignmentAnnotation ann = this.annotationIds.get(ss
3336 .getAnnotationId());
3339 * add the structure to the Varna display (with session state copied
3340 * from the jar to a temporary file)
3342 boolean gapped = ss.isGapped();
3343 String rnaTitle = ss.getTitle();
3344 String sessionState = ss.getViewerState();
3345 String tempStateFile = copyJarEntry(jprovider, sessionState,
3347 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
3348 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
3350 appVarna.setInitialSelection(viewer.getSelectedRna());
3356 * Locate and return an already instantiated matching AppVarna, or create one
3360 * @param viewIdSuffix
3364 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
3365 String viewIdSuffix, AlignmentPanel ap)
3368 * on each load a suffix is appended to the saved viewId, to avoid conflicts
3369 * if load is repeated
3371 String postLoadId = viewer.getViewId() + viewIdSuffix;
3372 for (JInternalFrame frame : getAllFrames())
3374 if (frame instanceof AppVarna)
3376 AppVarna varna = (AppVarna) frame;
3377 if (postLoadId.equals(varna.getViewId()))
3379 // this viewer is already instantiated
3380 // could in future here add ap as another 'parent' of the
3381 // AppVarna window; currently just 1-to-many
3388 * viewer not found - make it
3390 RnaViewerModel model = new RnaViewerModel(postLoadId,
3391 viewer.getTitle(), viewer.getXpos(),
3392 viewer.getYpos(), viewer.getWidth(), viewer.getHeight(),
3393 viewer.getDividerLocation());
3394 AppVarna varna = new AppVarna(model, ap);
3400 * Load any saved trees
3408 protected void loadTrees(JalviewModelSequence jms, Viewport view,
3409 AlignFrame af, AlignViewport av, AlignmentPanel ap)
3411 // TODO result of automated refactoring - are all these parameters needed?
3414 for (int t = 0; t < jms.getTreeCount(); t++)
3417 Tree tree = jms.getTree(t);
3419 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
3422 tp = af.ShowNewickTree(
3423 new jalview.io.NewickFile(tree.getNewick()),
3424 tree.getTitle(), tree.getWidth(), tree.getHeight(),
3425 tree.getXpos(), tree.getYpos());
3426 if (tree.getId() != null)
3428 // perhaps bind the tree id to something ?
3433 // update local tree attributes ?
3434 // TODO: should check if tp has been manipulated by user - if so its
3435 // settings shouldn't be modified
3436 tp.setTitle(tree.getTitle());
3437 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(), tree
3438 .getWidth(), tree.getHeight()));
3439 tp.av = av; // af.viewport; // TODO: verify 'associate with all
3442 tp.treeCanvas.av = av; // af.viewport;
3443 tp.treeCanvas.ap = ap; // af.alignPanel;
3448 warn("There was a problem recovering stored Newick tree: \n"
3449 + tree.getNewick());
3453 tp.fitToWindow.setState(tree.getFitToWindow());
3454 tp.fitToWindow_actionPerformed(null);
3456 if (tree.getFontName() != null)
3458 tp.setTreeFont(new java.awt.Font(tree.getFontName(), tree
3459 .getFontStyle(), tree.getFontSize()));
3463 tp.setTreeFont(new java.awt.Font(view.getFontName(), view
3464 .getFontStyle(), tree.getFontSize()));
3467 tp.showPlaceholders(tree.getMarkUnlinked());
3468 tp.showBootstrap(tree.getShowBootstrap());
3469 tp.showDistances(tree.getShowDistances());
3471 tp.treeCanvas.threshold = tree.getThreshold();
3473 if (tree.getCurrentTree())
3475 af.viewport.setCurrentTree(tp.getTree());
3479 } catch (Exception ex)
3481 ex.printStackTrace();
3486 * Load and link any saved structure viewers.
3493 protected void loadPDBStructures(jarInputStreamProvider jprovider,
3494 JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
3497 * Run through all PDB ids on the alignment, and collect mappings between
3498 * distinct view ids and all sequences referring to that view.
3500 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<String, StructureViewerModel>();
3502 for (int i = 0; i < jseqs.length; i++)
3504 if (jseqs[i].getPdbidsCount() > 0)
3506 Pdbids[] ids = jseqs[i].getPdbids();
3507 for (int p = 0; p < ids.length; p++)
3509 final int structureStateCount = ids[p].getStructureStateCount();
3510 for (int s = 0; s < structureStateCount; s++)
3512 // check to see if we haven't already created this structure view
3513 final StructureState structureState = ids[p]
3514 .getStructureState(s);
3515 String sviewid = (structureState.getViewId() == null) ? null
3516 : structureState.getViewId() + uniqueSetSuffix;
3517 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
3518 // Originally : ids[p].getFile()
3519 // : TODO: verify external PDB file recovery still works in normal
3520 // jalview project load
3521 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId()));
3522 jpdb.setId(ids[p].getId());
3524 int x = structureState.getXpos();
3525 int y = structureState.getYpos();
3526 int width = structureState.getWidth();
3527 int height = structureState.getHeight();
3529 // Probably don't need to do this anymore...
3530 // Desktop.desktop.getComponentAt(x, y);
3531 // TODO: NOW: check that this recovers the PDB file correctly.
3532 String pdbFile = loadPDBFile(jprovider, ids[p].getId());
3533 jalview.datamodel.SequenceI seq = seqRefIds.get(jseqs[i]
3535 if (sviewid == null)
3537 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width
3540 if (!structureViewers.containsKey(sviewid))
3542 structureViewers.put(sviewid,
3543 new StructureViewerModel(x, y, width, height, false,
3544 false, true, structureState.getViewId(),
3545 structureState.getType()));
3546 // Legacy pre-2.7 conversion JAL-823 :
3547 // do not assume any view has to be linked for colour by
3551 // assemble String[] { pdb files }, String[] { id for each
3552 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3553 // seqs_file 2}, boolean[] {
3554 // linkAlignPanel,superposeWithAlignpanel}} from hash
3555 StructureViewerModel jmoldat = structureViewers.get(sviewid);
3556 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
3557 | (structureState.hasAlignwithAlignPanel() ? structureState
3558 .getAlignwithAlignPanel() : false));
3561 * Default colour by linked panel to false if not specified (e.g.
3562 * for pre-2.7 projects)
3564 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
3565 colourWithAlignPanel |= (structureState
3566 .hasColourwithAlignPanel() ? structureState
3567 .getColourwithAlignPanel() : false);
3568 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
3571 * Default colour by viewer to true if not specified (e.g. for
3574 boolean colourByViewer = jmoldat.isColourByViewer();
3575 colourByViewer &= structureState.hasColourByJmol() ? structureState
3576 .getColourByJmol() : true;
3577 jmoldat.setColourByViewer(colourByViewer);
3579 if (jmoldat.getStateData().length() < structureState
3580 .getContent().length())
3583 jmoldat.setStateData(structureState.getContent());
3586 if (ids[p].getFile() != null)
3588 File mapkey = new File(ids[p].getFile());
3589 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
3590 if (seqstrmaps == null)
3592 jmoldat.getFileData().put(
3594 seqstrmaps = jmoldat.new StructureData(pdbFile,
3597 if (!seqstrmaps.getSeqList().contains(seq))
3599 seqstrmaps.getSeqList().add(seq);
3605 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");
3612 // Instantiate the associated structure views
3613 for (Entry<String, StructureViewerModel> entry : structureViewers
3618 createOrLinkStructureViewer(entry, af, ap, jprovider);
3619 } catch (Exception e)
3621 System.err.println("Error loading structure viewer: "
3623 // failed - try the next one
3635 protected void createOrLinkStructureViewer(
3636 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3637 AlignmentPanel ap, jarInputStreamProvider jprovider)
3639 final StructureViewerModel stateData = viewerData.getValue();
3642 * Search for any viewer windows already open from other alignment views
3643 * that exactly match the stored structure state
3645 StructureViewerBase comp = findMatchingViewer(viewerData);
3649 linkStructureViewer(ap, comp, stateData);
3654 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
3655 * "viewer_"+stateData.viewId
3657 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
3659 createChimeraViewer(viewerData, af, jprovider);
3664 * else Jmol (if pre-2.9, stateData contains JMOL state string)
3666 createJmolViewer(viewerData, af, jprovider);
3671 * Create a new Chimera viewer.
3677 protected void createChimeraViewer(Entry<String, StructureViewerModel> viewerData,
3679 jarInputStreamProvider jprovider)
3681 StructureViewerModel data = viewerData.getValue();
3682 String chimeraSessionFile = data.getStateData();
3685 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
3687 * NB this is the 'saved' viewId as in the project file XML, _not_ the
3688 * 'uniquified' sviewid used to reconstruct the viewer here
3690 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
3691 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
3694 Set<Entry<File, StructureData>> fileData = data.getFileData()
3696 List<PDBEntry> pdbs = new ArrayList<PDBEntry>();
3697 List<SequenceI[]> allseqs = new ArrayList<SequenceI[]>();
3698 for (Entry<File, StructureData> pdb : fileData)
3700 String filePath = pdb.getValue().getFilePath();
3701 String pdbId = pdb.getValue().getPdbId();
3702 // pdbs.add(new PDBEntry(filePath, pdbId));
3703 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
3704 final List<SequenceI> seqList = pdb.getValue().getSeqList();
3705 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
3709 boolean colourByChimera = data.isColourByViewer();
3710 boolean colourBySequence = data.isColourWithAlignPanel();
3712 // TODO use StructureViewer as a factory here, see JAL-1761
3713 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
3714 final SequenceI[][] seqsArray = allseqs.toArray(new SequenceI[allseqs
3716 String newViewId = viewerData.getKey();
3718 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
3719 af.alignPanel, pdbArray,
3720 seqsArray, colourByChimera, colourBySequence, newViewId);
3721 cvf.setSize(data.getWidth(), data.getHeight());
3722 cvf.setLocation(data.getX(), data.getY());
3726 * Create a new Jmol window. First parse the Jmol state to translate filenames
3727 * loaded into the view, and record the order in which files are shown in the
3728 * Jmol view, so we can add the sequence mappings in same order.
3734 protected void createJmolViewer(
3735 final Entry<String, StructureViewerModel> viewerData,
3736 AlignFrame af, jarInputStreamProvider jprovider)
3738 final StructureViewerModel svattrib = viewerData.getValue();
3739 String state = svattrib.getStateData();
3742 * Pre-2.9: state element value is the Jmol state string
3744 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
3747 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
3749 state = readJarEntry(jprovider,
3750 getViewerJarEntryName(svattrib.getViewId()));
3753 List<String> pdbfilenames = new ArrayList<String>();
3754 List<SequenceI[]> seqmaps = new ArrayList<SequenceI[]>();
3755 List<String> pdbids = new ArrayList<String>();
3756 StringBuilder newFileLoc = new StringBuilder(64);
3757 int cp = 0, ncp, ecp;
3758 Map<File, StructureData> oldFiles = svattrib.getFileData();
3759 while ((ncp = state.indexOf("load ", cp)) > -1)
3763 // look for next filename in load statement
3764 newFileLoc.append(state.substring(cp,
3765 ncp = (state.indexOf("\"", ncp + 1) + 1)));
3766 String oldfilenam = state.substring(ncp,
3767 ecp = state.indexOf("\"", ncp));
3768 // recover the new mapping data for this old filename
3769 // have to normalize filename - since Jmol and jalview do
3771 // translation differently.
3772 StructureData filedat = oldFiles.get(new File(oldfilenam));
3773 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
3774 pdbfilenames.add(filedat.getFilePath());
3775 pdbids.add(filedat.getPdbId());
3776 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
3777 newFileLoc.append("\"");
3778 cp = ecp + 1; // advance beyond last \" and set cursor so we can
3779 // look for next file statement.
3780 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
3784 // just append rest of state
3785 newFileLoc.append(state.substring(cp));
3789 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
3790 newFileLoc = new StringBuilder(state);
3791 newFileLoc.append("; load append ");
3792 for (File id : oldFiles.keySet())
3794 // add this and any other pdb files that should be present in
3796 StructureData filedat = oldFiles.get(id);
3797 newFileLoc.append(filedat.getFilePath());
3798 pdbfilenames.add(filedat.getFilePath());
3799 pdbids.add(filedat.getPdbId());
3800 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
3801 newFileLoc.append(" \"");
3802 newFileLoc.append(filedat.getFilePath());
3803 newFileLoc.append("\"");
3806 newFileLoc.append(";");
3809 if (newFileLoc.length() > 0)
3811 int histbug = newFileLoc.indexOf("history = ");
3813 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
3814 String val = (diff == -1) ? null : newFileLoc
3815 .substring(histbug, diff);
3816 if (val != null && val.length() >= 4)
3818 if (val.contains("e"))
3820 if (val.trim().equals("true"))
3828 newFileLoc.replace(histbug, diff, val);
3832 final String[] pdbf = pdbfilenames.toArray(new String[pdbfilenames
3834 final String[] id = pdbids.toArray(new String[pdbids.size()]);
3835 final SequenceI[][] sq = seqmaps
3836 .toArray(new SequenceI[seqmaps.size()][]);
3837 final String fileloc = newFileLoc.toString();
3838 final String sviewid = viewerData.getKey();
3839 final AlignFrame alf = af;
3840 final Rectangle rect = new Rectangle(svattrib.getX(),
3841 svattrib.getY(), svattrib.getWidth(), svattrib.getHeight());
3844 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
3849 JalviewStructureDisplayI sview = null;
3852 sview = new StructureViewer(alf.alignPanel
3853 .getStructureSelectionManager()).createView(
3854 StructureViewer.ViewerType.JMOL, pdbf, id, sq,
3855 alf.alignPanel, svattrib, fileloc, rect, sviewid);
3856 addNewStructureViewer(sview);
3857 } catch (OutOfMemoryError ex)
3859 new OOMWarning("restoring structure view for PDB id " + id,
3860 (OutOfMemoryError) ex.getCause());
3861 if (sview != null && sview.isVisible())
3863 sview.closeViewer(false);
3864 sview.setVisible(false);
3870 } catch (InvocationTargetException ex)
3872 warn("Unexpected error when opening Jmol view.", ex);
3874 } catch (InterruptedException e)
3876 // e.printStackTrace();
3882 * Generates a name for the entry in the project jar file to hold state
3883 * information for a structure viewer
3888 protected String getViewerJarEntryName(String viewId)
3890 return VIEWER_PREFIX + viewId;
3894 * Returns any open frame that matches given structure viewer data. The match
3895 * is based on the unique viewId, or (for older project versions) the frame's
3901 protected StructureViewerBase findMatchingViewer(
3902 Entry<String, StructureViewerModel> viewerData)
3904 final String sviewid = viewerData.getKey();
3905 final StructureViewerModel svattrib = viewerData.getValue();
3906 StructureViewerBase comp = null;
3907 JInternalFrame[] frames = getAllFrames();
3908 for (JInternalFrame frame : frames)
3910 if (frame instanceof StructureViewerBase)
3913 * Post jalview 2.4 schema includes structure view id
3916 && ((StructureViewerBase) frame).getViewId()
3919 comp = (StructureViewerBase) frame;
3920 break; // break added in 2.9
3923 * Otherwise test for matching position and size of viewer frame
3925 else if (frame.getX() == svattrib.getX()
3926 && frame.getY() == svattrib.getY()
3927 && frame.getHeight() == svattrib.getHeight()
3928 && frame.getWidth() == svattrib.getWidth())
3930 comp = (StructureViewerBase) frame;
3931 // no break in faint hope of an exact match on viewId
3939 * Link an AlignmentPanel to an existing structure viewer.
3944 * @param useinViewerSuperpos
3945 * @param usetoColourbyseq
3946 * @param viewerColouring
3948 protected void linkStructureViewer(AlignmentPanel ap,
3949 StructureViewerBase viewer, StructureViewerModel stateData)
3951 // NOTE: if the jalview project is part of a shared session then
3952 // view synchronization should/could be done here.
3954 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
3955 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
3956 final boolean viewerColouring = stateData.isColourByViewer();
3957 Map<File, StructureData> oldFiles = stateData.getFileData();
3960 * Add mapping for sequences in this view to an already open viewer
3962 final AAStructureBindingModel binding = viewer.getBinding();
3963 for (File id : oldFiles.keySet())
3965 // add this and any other pdb files that should be present in the
3967 StructureData filedat = oldFiles.get(id);
3968 String pdbFile = filedat.getFilePath();
3969 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
3970 binding.getSsm().setMapping(seq, null, pdbFile,
3971 jalview.io.AppletFormatAdapter.FILE);
3972 binding.addSequenceForStructFile(pdbFile, seq);
3974 // and add the AlignmentPanel's reference to the view panel
3975 viewer.addAlignmentPanel(ap);
3976 if (useinViewerSuperpos)
3978 viewer.useAlignmentPanelForSuperposition(ap);
3982 viewer.excludeAlignmentPanelForSuperposition(ap);
3984 if (usetoColourbyseq)
3986 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
3990 viewer.excludeAlignmentPanelForColourbyseq(ap);
3995 * Get all frames within the Desktop.
3999 protected JInternalFrame[] getAllFrames()
4001 JInternalFrame[] frames = null;
4002 // TODO is this necessary - is it safe - risk of hanging?
4007 frames = Desktop.desktop.getAllFrames();
4008 } catch (ArrayIndexOutOfBoundsException e)
4010 // occasional No such child exceptions are thrown here...
4014 } catch (InterruptedException f)
4018 } while (frames == null);
4025 * - minimum version we are comparing against
4027 * - version of data being processsed.
4028 * @return true if version is development/null or evaluates to the same or
4029 * later X.Y.Z (where X,Y,Z are like [0-9]+b?[0-9]*)
4031 protected boolean isVersionStringLaterThan(String supported,
4034 if (version == null || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4035 || version.equalsIgnoreCase("Test")
4036 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4038 System.err.println("Assuming project file with "
4039 + (version == null ? "null" : version)
4040 + " is compatible with Jalview version " + supported);
4045 StringTokenizer currentV = new StringTokenizer(supported, "."), fileV = new StringTokenizer(
4047 while (currentV.hasMoreTokens() && fileV.hasMoreTokens())
4049 // convert b to decimal to catch bugfix releases within a series
4050 String curT = currentV.nextToken().toLowerCase().replace('b', '.');
4051 String fileT = fileV.nextToken().toLowerCase().replace('b', '.');
4054 if (Float.valueOf(curT) > Float.valueOf(fileT))
4056 // current version is newer than the version that wrote the file
4059 } catch (NumberFormatException nfe)
4062 .println("** WARNING: Version comparison failed for tokens ("
4066 + ")\n** Current: '"
4067 + supported + "' and Version: '" + version + "'");
4070 if (currentV.hasMoreElements())
4072 // fileV has no minor version but identical series to current
4079 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4081 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4083 if (newStructureViewers != null)
4085 sview.getBinding().setFinishedLoadingFromArchive(false);
4086 newStructureViewers.add(sview);
4090 protected void setLoadingFinishedForNewStructureViewers()
4092 if (newStructureViewers != null)
4094 for (JalviewStructureDisplayI sview : newStructureViewers)
4096 sview.getBinding().setFinishedLoadingFromArchive(true);
4098 newStructureViewers.clear();
4099 newStructureViewers = null;
4103 AlignFrame loadViewport(String file, JSeq[] JSEQ,
4104 List<SequenceI> hiddenSeqs, Alignment al,
4105 JalviewModelSequence jms, Viewport view, String uniqueSeqSetId,
4106 String viewId, List<JvAnnotRow> autoAlan)
4108 AlignFrame af = null;
4109 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
4110 uniqueSeqSetId, viewId);
4112 af.setFileName(file, "Jalview");
4114 for (int i = 0; i < JSEQ.length; i++)
4116 af.viewport.setSequenceColour(af.viewport.getAlignment()
4117 .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour()));
4120 af.viewport.setGatherViewsHere(view.getGatheredViews());
4122 if (view.getSequenceSetId() != null)
4124 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4126 af.viewport.setSequenceSetId(uniqueSeqSetId);
4129 // propagate shared settings to this new view
4130 af.viewport.setHistoryList(av.getHistoryList());
4131 af.viewport.setRedoList(av.getRedoList());
4135 viewportsAdded.put(uniqueSeqSetId, af.viewport);
4137 // TODO: check if this method can be called repeatedly without
4138 // side-effects if alignpanel already registered.
4139 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4141 // apply Hidden regions to view.
4142 if (hiddenSeqs != null)
4144 for (int s = 0; s < JSEQ.length; s++)
4146 jalview.datamodel.SequenceGroup hidden = new jalview.datamodel.SequenceGroup();
4148 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
4151 al.getSequenceAt(JSEQ[s].getHiddenSequences(r)), false);
4153 af.viewport.hideRepSequences(al.getSequenceAt(s), hidden);
4156 // jalview.datamodel.SequenceI[] hseqs = new
4157 // jalview.datamodel.SequenceI[hiddenSeqs
4160 // for (int s = 0; s < hiddenSeqs.size(); s++)
4162 // hseqs[s] = (jalview.datamodel.SequenceI) hiddenSeqs.elementAt(s);
4165 SequenceI[] hseqs = hiddenSeqs.toArray(new SequenceI[hiddenSeqs
4167 af.viewport.hideSequence(hseqs);
4170 // recover view properties and display parameters
4171 if (view.getViewName() != null)
4173 af.viewport.viewName = view.getViewName();
4174 af.setInitialTabVisible();
4176 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
4179 af.viewport.setShowAnnotation(view.getShowAnnotation());
4180 af.viewport.setAbovePIDThreshold(view.getPidSelected());
4182 af.viewport.setColourText(view.getShowColourText());
4184 af.viewport.setConservationSelected(view.getConservationSelected());
4185 af.viewport.setShowJVSuffix(view.getShowFullId());
4186 af.viewport.setRightAlignIds(view.getRightAlignIds());
4187 af.viewport.setFont(
4188 new java.awt.Font(view.getFontName(), view.getFontStyle(), view
4189 .getFontSize()), true);
4190 // TODO: allow custom charWidth/Heights to be restored by updating them
4191 // after setting font - which means set above to false
4192 af.viewport.setRenderGaps(view.getRenderGaps());
4193 af.viewport.setWrapAlignment(view.getWrapAlignment());
4194 af.viewport.setShowAnnotation(view.getShowAnnotation());
4196 af.viewport.setShowBoxes(view.getShowBoxes());
4198 af.viewport.setShowText(view.getShowText());
4200 af.viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
4201 af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
4202 af.viewport.setThresholdTextColour(view.getTextColThreshold());
4203 af.viewport.setShowUnconserved(view.hasShowUnconserved() ? view
4204 .isShowUnconserved() : false);
4205 af.viewport.setStartRes(view.getStartRes());
4206 af.viewport.setStartSeq(view.getStartSeq());
4207 af.alignPanel.updateLayout();
4208 ColourSchemeI cs = null;
4209 // apply colourschemes
4210 if (view.getBgColour() != null)
4212 if (view.getBgColour().startsWith("ucs"))
4214 cs = getUserColourScheme(jms, view.getBgColour());
4216 else if (view.getBgColour().startsWith("Annotation"))
4218 AnnotationColours viewAnnColour = view.getAnnotationColours();
4219 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
4226 cs = ColourSchemeProperty.getColour(al, view.getBgColour());
4231 cs.setThreshold(view.getPidThreshold(), true);
4232 cs.setConsensus(af.viewport.getSequenceConsensusHash());
4236 af.viewport.setGlobalColourScheme(cs);
4237 af.viewport.setColourAppliesToAllGroups(false);
4239 if (view.getConservationSelected() && cs != null)
4241 cs.setConservationInc(view.getConsThreshold());
4244 af.changeColour(cs);
4246 af.viewport.setColourAppliesToAllGroups(true);
4248 af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures());
4250 if (view.hasCentreColumnLabels())
4252 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
4254 if (view.hasIgnoreGapsinConsensus())
4256 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
4259 if (view.hasFollowHighlight())
4261 af.viewport.setFollowHighlight(view.getFollowHighlight());
4263 if (view.hasFollowSelection())
4265 af.viewport.followSelection = view.getFollowSelection();
4267 if (view.hasShowConsensusHistogram())
4269 af.viewport.setShowConsensusHistogram(view
4270 .getShowConsensusHistogram());
4274 af.viewport.setShowConsensusHistogram(true);
4276 if (view.hasShowSequenceLogo())
4278 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
4282 af.viewport.setShowSequenceLogo(false);
4284 if (view.hasNormaliseSequenceLogo())
4286 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
4288 if (view.hasShowDbRefTooltip())
4290 af.viewport.setShowDBRefs(view.getShowDbRefTooltip());
4292 if (view.hasShowNPfeatureTooltip())
4294 af.viewport.setShowNPFeats(view.hasShowNPfeatureTooltip());
4296 if (view.hasShowGroupConsensus())
4298 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
4302 af.viewport.setShowGroupConsensus(false);
4304 if (view.hasShowGroupConservation())
4306 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
4310 af.viewport.setShowGroupConservation(false);
4313 // recover featre settings
4314 if (jms.getFeatureSettings() != null)
4316 FeaturesDisplayed fdi;
4317 af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
4318 String[] renderOrder = new String[jms.getFeatureSettings()
4319 .getSettingCount()];
4320 Hashtable featureGroups = new Hashtable();
4321 Hashtable featureColours = new Hashtable();
4322 Hashtable featureOrder = new Hashtable();
4324 for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
4326 Setting setting = jms.getFeatureSettings().getSetting(fs);
4327 if (setting.hasMincolour())
4329 GraduatedColor gc = setting.hasMin() ? new GraduatedColor(
4330 new java.awt.Color(setting.getMincolour()),
4331 new java.awt.Color(setting.getColour()),
4332 setting.getMin(), setting.getMax()) : new GraduatedColor(
4333 new java.awt.Color(setting.getMincolour()),
4334 new java.awt.Color(setting.getColour()), 0, 1);
4335 if (setting.hasThreshold())
4337 gc.setThresh(setting.getThreshold());
4338 gc.setThreshType(setting.getThreshstate());
4340 gc.setAutoScaled(true); // default
4341 if (setting.hasAutoScale())
4343 gc.setAutoScaled(setting.getAutoScale());
4345 if (setting.hasColourByLabel())
4347 gc.setColourByLabel(setting.getColourByLabel());
4349 // and put in the feature colour table.
4350 featureColours.put(setting.getType(), gc);
4354 featureColours.put(setting.getType(),
4355 new java.awt.Color(setting.getColour()));
4357 renderOrder[fs] = setting.getType();
4358 if (setting.hasOrder())
4360 featureOrder.put(setting.getType(), setting.getOrder());
4364 featureOrder.put(setting.getType(), new Float(fs
4365 / jms.getFeatureSettings().getSettingCount()));
4367 if (setting.getDisplay())
4369 fdi.setVisible(setting.getType());
4372 Hashtable fgtable = new Hashtable();
4373 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
4375 Group grp = jms.getFeatureSettings().getGroup(gs);
4376 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
4378 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4379 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
4380 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
4381 FeatureRendererSettings frs = new FeatureRendererSettings(
4382 renderOrder, fgtable, featureColours, 1.0f, featureOrder);
4383 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
4384 .transferSettings(frs);
4388 if (view.getHiddenColumnsCount() > 0)
4390 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
4392 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(), view
4393 .getHiddenColumns(c).getEnd() // +1
4397 if (view.getCalcIdParam() != null)
4399 for (CalcIdParam calcIdParam : view.getCalcIdParam())
4401 if (calcIdParam != null)
4403 if (recoverCalcIdParam(calcIdParam, af.viewport))
4408 warn("Couldn't recover parameters for "
4409 + calcIdParam.getCalcId());
4414 af.setMenusFromViewport(af.viewport);
4416 // TODO: we don't need to do this if the viewport is aready visible.
4418 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
4419 * has a 'cdna/protein complement' view, in which case save it in order to
4420 * populate a SplitFrame once all views have been read in.
4422 String complementaryViewId = view.getComplementId();
4423 if (complementaryViewId == null)
4425 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
4427 // recompute any autoannotation
4428 af.alignPanel.updateAnnotation(false, true);
4429 reorderAutoannotation(af, al, autoAlan);
4430 af.alignPanel.alignmentChanged();
4434 splitFrameCandidates.put(view, af);
4439 private ColourSchemeI constructAnnotationColour(
4440 AnnotationColours viewAnnColour, AlignFrame af, Alignment al,
4441 JalviewModelSequence jms, boolean checkGroupAnnColour)
4443 boolean propagateAnnColour = false;
4444 ColourSchemeI cs = null;
4445 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
4446 if (checkGroupAnnColour && al.getGroups() != null
4447 && al.getGroups().size() > 0)
4449 // pre 2.8.1 behaviour
4450 // check to see if we should transfer annotation colours
4451 propagateAnnColour = true;
4452 for (jalview.datamodel.SequenceGroup sg : al.getGroups())
4454 if (sg.cs instanceof AnnotationColourGradient)
4456 propagateAnnColour = false;
4460 // int find annotation
4461 if (annAlignment.getAlignmentAnnotation() != null)
4463 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
4465 if (annAlignment.getAlignmentAnnotation()[i].label
4466 .equals(viewAnnColour.getAnnotation()))
4468 if (annAlignment.getAlignmentAnnotation()[i].getThreshold() == null)
4470 annAlignment.getAlignmentAnnotation()[i]
4471 .setThreshold(new jalview.datamodel.GraphLine(
4472 viewAnnColour.getThreshold(), "Threshold",
4473 java.awt.Color.black)
4478 if (viewAnnColour.getColourScheme().equals("None"))
4480 cs = new AnnotationColourGradient(
4481 annAlignment.getAlignmentAnnotation()[i],
4482 new java.awt.Color(viewAnnColour.getMinColour()),
4483 new java.awt.Color(viewAnnColour.getMaxColour()),
4484 viewAnnColour.getAboveThreshold());
4486 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
4488 cs = new AnnotationColourGradient(
4489 annAlignment.getAlignmentAnnotation()[i],
4490 getUserColourScheme(jms,
4491 viewAnnColour.getColourScheme()),
4492 viewAnnColour.getAboveThreshold());
4496 cs = new AnnotationColourGradient(
4497 annAlignment.getAlignmentAnnotation()[i],
4498 ColourSchemeProperty.getColour(al,
4499 viewAnnColour.getColourScheme()),
4500 viewAnnColour.getAboveThreshold());
4502 if (viewAnnColour.hasPerSequence())
4504 ((AnnotationColourGradient) cs).setSeqAssociated(viewAnnColour
4507 if (viewAnnColour.hasPredefinedColours())
4509 ((AnnotationColourGradient) cs)
4510 .setPredefinedColours(viewAnnColour
4511 .isPredefinedColours());
4513 if (propagateAnnColour && al.getGroups() != null)
4515 // Also use these settings for all the groups
4516 for (int g = 0; g < al.getGroups().size(); g++)
4518 jalview.datamodel.SequenceGroup sg = al.getGroups().get(g);
4526 * if (viewAnnColour.getColourScheme().equals("None" )) { sg.cs =
4527 * new AnnotationColourGradient(
4528 * annAlignment.getAlignmentAnnotation()[i], new
4529 * java.awt.Color(viewAnnColour. getMinColour()), new
4530 * java.awt.Color(viewAnnColour. getMaxColour()),
4531 * viewAnnColour.getAboveThreshold()); } else
4534 sg.cs = new AnnotationColourGradient(
4535 annAlignment.getAlignmentAnnotation()[i], sg.cs,
4536 viewAnnColour.getAboveThreshold());
4537 if (cs instanceof AnnotationColourGradient)
4539 if (viewAnnColour.hasPerSequence())
4541 ((AnnotationColourGradient) cs)
4542 .setSeqAssociated(viewAnnColour.isPerSequence());
4544 if (viewAnnColour.hasPredefinedColours())
4546 ((AnnotationColourGradient) cs)
4547 .setPredefinedColours(viewAnnColour
4548 .isPredefinedColours());
4564 private void reorderAutoannotation(AlignFrame af, Alignment al,
4565 List<JvAnnotRow> autoAlan)
4567 // copy over visualization settings for autocalculated annotation in the
4569 if (al.getAlignmentAnnotation() != null)
4572 * Kludge for magic autoannotation names (see JAL-811)
4574 String[] magicNames = new String[]
4575 { "Consensus", "Quality", "Conservation" };
4576 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
4577 Hashtable<String, JvAnnotRow> visan = new Hashtable<String, JvAnnotRow>();
4578 for (String nm : magicNames)
4580 visan.put(nm, nullAnnot);
4582 for (JvAnnotRow auan : autoAlan)
4584 visan.put(auan.template.label
4585 + (auan.template.getCalcId() == null ? "" : "\t"
4586 + auan.template.getCalcId()), auan);
4588 int hSize = al.getAlignmentAnnotation().length;
4589 List<JvAnnotRow> reorder = new ArrayList<JvAnnotRow>();
4590 // work through any autoCalculated annotation already on the view
4591 // removing it if it should be placed in a different location on the
4592 // annotation panel.
4593 List<String> remains = new ArrayList<String>(visan.keySet());
4594 for (int h = 0; h < hSize; h++)
4596 jalview.datamodel.AlignmentAnnotation jalan = al
4597 .getAlignmentAnnotation()[h];
4598 if (jalan.autoCalculated)
4601 JvAnnotRow valan = visan.get(k = jalan.label);
4602 if (jalan.getCalcId() != null)
4604 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
4609 // delete the auto calculated row from the alignment
4610 al.deleteAnnotation(jalan, false);
4614 if (valan != nullAnnot)
4616 if (jalan != valan.template)
4618 // newly created autoannotation row instance
4619 // so keep a reference to the visible annotation row
4620 // and copy over all relevant attributes
4621 if (valan.template.graphHeight >= 0)
4624 jalan.graphHeight = valan.template.graphHeight;
4626 jalan.visible = valan.template.visible;
4628 reorder.add(new JvAnnotRow(valan.order, jalan));
4633 // Add any (possibly stale) autocalculated rows that were not appended to
4634 // the view during construction
4635 for (String other : remains)
4637 JvAnnotRow othera = visan.get(other);
4638 if (othera != nullAnnot && othera.template.getCalcId() != null
4639 && othera.template.getCalcId().length() > 0)
4641 reorder.add(othera);
4644 // now put the automatic annotation in its correct place
4645 int s = 0, srt[] = new int[reorder.size()];
4646 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
4647 for (JvAnnotRow jvar : reorder)
4650 srt[s++] = jvar.order;
4653 jalview.util.QuickSort.sort(srt, rws);
4654 // and re-insert the annotation at its correct position
4655 for (JvAnnotRow jvar : rws)
4657 al.addAnnotation(jvar.template, jvar.order);
4659 af.alignPanel.adjustAnnotationHeight();
4663 Hashtable skipList = null;
4666 * TODO remove this method
4669 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
4670 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
4671 * throw new Error("Implementation Error. No skipList defined for this
4672 * Jalview2XML instance."); } return (AlignFrame)
4673 * skipList.get(view.getSequenceSetId()); }
4677 * Check if the Jalview view contained in object should be skipped or not.
4680 * @return true if view's sequenceSetId is a key in skipList
4682 private boolean skipViewport(JalviewModel object)
4684 if (skipList == null)
4689 if (skipList.containsKey(id = object.getJalviewModelSequence()
4690 .getViewport()[0].getSequenceSetId()))
4692 if (Cache.log != null && Cache.log.isDebugEnabled())
4694 Cache.log.debug("Skipping seuqence set id " + id);
4701 public void addToSkipList(AlignFrame af)
4703 if (skipList == null)
4705 skipList = new Hashtable();
4707 skipList.put(af.getViewport().getSequenceSetId(), af);
4710 public void clearSkipList()
4712 if (skipList != null)
4719 private void recoverDatasetFor(SequenceSet vamsasSet, Alignment al,
4720 boolean ignoreUnrefed)
4722 jalview.datamodel.Alignment ds = getDatasetFor(vamsasSet.getDatasetId());
4723 Vector dseqs = null;
4726 // create a list of new dataset sequences
4727 dseqs = new Vector();
4729 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
4731 Sequence vamsasSeq = vamsasSet.getSequence(i);
4732 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed);
4734 // create a new dataset
4737 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
4738 dseqs.copyInto(dsseqs);
4739 ds = new jalview.datamodel.Alignment(dsseqs);
4740 debug("Created new dataset " + vamsasSet.getDatasetId()
4741 + " for alignment " + System.identityHashCode(al));
4742 addDatasetRef(vamsasSet.getDatasetId(), ds);
4744 // set the dataset for the newly imported alignment.
4745 if (al.getDataset() == null && !ignoreUnrefed)
4754 * sequence definition to create/merge dataset sequence for
4758 * vector to add new dataset sequence to
4760 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
4761 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed)
4763 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
4765 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
4766 SequenceI dsq = null;
4767 if (sq != null && sq.getDatasetSequence() != null)
4769 dsq = sq.getDatasetSequence();
4771 if (sq == null && ignoreUnrefed)
4775 String sqid = vamsasSeq.getDsseqid();
4778 // need to create or add a new dataset sequence reference to this sequence
4781 dsq = seqRefIds.get(sqid);
4786 // make a new dataset sequence
4787 dsq = sq.createDatasetSequence();
4790 // make up a new dataset reference for this sequence
4791 sqid = seqHash(dsq);
4793 dsq.setVamsasId(uniqueSetSuffix + sqid);
4794 seqRefIds.put(sqid, dsq);
4799 dseqs.addElement(dsq);
4804 ds.addSequence(dsq);
4810 { // make this dataset sequence sq's dataset sequence
4811 sq.setDatasetSequence(dsq);
4812 // and update the current dataset alignment
4817 if (!dseqs.contains(dsq))
4824 if (ds.findIndex(dsq) < 0)
4826 ds.addSequence(dsq);
4833 // TODO: refactor this as a merge dataset sequence function
4834 // now check that sq (the dataset sequence) sequence really is the union of
4835 // all references to it
4836 // boolean pre = sq.getStart() < dsq.getStart();
4837 // boolean post = sq.getEnd() > dsq.getEnd();
4841 // StringBuffer sb = new StringBuffer();
4842 String newres = jalview.analysis.AlignSeq.extractGaps(
4843 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
4844 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
4845 && newres.length() > dsq.getLength())
4847 // Update with the longer sequence.
4851 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
4852 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
4853 * sb.append(newres.substring(newres.length() - sq.getEnd() -
4854 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
4856 dsq.setSequence(newres);
4858 // TODO: merges will never happen if we 'know' we have the real dataset
4859 // sequence - this should be detected when id==dssid
4861 .println("DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
4862 // + (pre ? "prepended" : "") + " "
4863 // + (post ? "appended" : ""));
4869 * TODO use AlignmentI here and in related methods - needs
4870 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
4872 Hashtable<String, Alignment> datasetIds = null;
4874 IdentityHashMap<Alignment, String> dataset2Ids = null;
4876 private Alignment getDatasetFor(String datasetId)
4878 if (datasetIds == null)
4880 datasetIds = new Hashtable<String, Alignment>();
4883 if (datasetIds.containsKey(datasetId))
4885 return datasetIds.get(datasetId);
4890 private void addDatasetRef(String datasetId, Alignment dataset)
4892 if (datasetIds == null)
4894 datasetIds = new Hashtable<String, Alignment>();
4896 datasetIds.put(datasetId, dataset);
4900 * make a new dataset ID for this jalview dataset alignment
4905 private String getDatasetIdRef(Alignment dataset)
4907 if (dataset.getDataset() != null)
4909 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
4911 String datasetId = makeHashCode(dataset, null);
4912 if (datasetId == null)
4914 // make a new datasetId and record it
4915 if (dataset2Ids == null)
4917 dataset2Ids = new IdentityHashMap<Alignment, String>();
4921 datasetId = dataset2Ids.get(dataset);
4923 if (datasetId == null)
4925 datasetId = "ds" + dataset2Ids.size() + 1;
4926 dataset2Ids.put(dataset, datasetId);
4932 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
4934 for (int d = 0; d < sequence.getDBRefCount(); d++)
4936 DBRef dr = sequence.getDBRef(d);
4937 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
4938 sequence.getDBRef(d).getSource(), sequence.getDBRef(d)
4939 .getVersion(), sequence.getDBRef(d).getAccessionId());
4940 if (dr.getMapping() != null)
4942 entry.setMap(addMapping(dr.getMapping()));
4944 datasetSequence.addDBRef(entry);
4948 private jalview.datamodel.Mapping addMapping(Mapping m)
4950 SequenceI dsto = null;
4951 // Mapping m = dr.getMapping();
4952 int fr[] = new int[m.getMapListFromCount() * 2];
4953 Enumeration f = m.enumerateMapListFrom();
4954 for (int _i = 0; f.hasMoreElements(); _i += 2)
4956 MapListFrom mf = (MapListFrom) f.nextElement();
4957 fr[_i] = mf.getStart();
4958 fr[_i + 1] = mf.getEnd();
4960 int fto[] = new int[m.getMapListToCount() * 2];
4961 f = m.enumerateMapListTo();
4962 for (int _i = 0; f.hasMoreElements(); _i += 2)
4964 MapListTo mf = (MapListTo) f.nextElement();
4965 fto[_i] = mf.getStart();
4966 fto[_i + 1] = mf.getEnd();
4968 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto,
4969 fr, fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
4970 if (m.getMappingChoice() != null)
4972 MappingChoice mc = m.getMappingChoice();
4973 if (mc.getDseqFor() != null)
4975 String dsfor = "" + mc.getDseqFor();
4976 if (seqRefIds.containsKey(dsfor))
4981 jmap.setTo(seqRefIds.get(dsfor));
4985 frefedSequence.add(new Object[]
4992 * local sequence definition
4994 Sequence ms = mc.getSequence();
4995 SequenceI djs = null;
4996 String sqid = ms.getDsseqid();
4997 if (sqid != null && sqid.length() > 0)
5000 * recover dataset sequence
5002 djs = seqRefIds.get(sqid);
5007 .println("Warning - making up dataset sequence id for DbRef sequence map reference");
5008 sqid = ((Object) ms).toString(); // make up a new hascode for
5009 // undefined dataset sequence hash
5010 // (unlikely to happen)
5016 * make a new dataset sequence and add it to refIds hash
5018 djs = new jalview.datamodel.Sequence(ms.getName(),
5020 djs.setStart(jmap.getMap().getToLowest());
5021 djs.setEnd(jmap.getMap().getToHighest());
5022 djs.setVamsasId(uniqueSetSuffix + sqid);
5024 seqRefIds.put(sqid, djs);
5027 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5036 public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
5037 boolean keepSeqRefs)
5040 JalviewModel jm = saveState(ap, null, null, null);
5045 jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
5049 uniqueSetSuffix = "";
5050 jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
5055 if (this.frefedSequence == null)
5057 frefedSequence = new Vector();
5060 viewportsAdded.clear();
5062 AlignFrame af = loadFromObject(jm, null, false, null);
5063 af.alignPanels.clear();
5064 af.closeMenuItem_actionPerformed(true);
5067 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5068 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5069 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5070 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5071 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5074 return af.alignPanel;
5078 * flag indicating if hashtables should be cleared on finalization TODO this
5079 * flag may not be necessary
5081 private final boolean _cleartables = true;
5083 private Hashtable jvids2vobj;
5088 * @see java.lang.Object#finalize()
5091 protected void finalize() throws Throwable
5093 // really make sure we have no buried refs left.
5098 this.seqRefIds = null;
5099 this.seqsToIds = null;
5103 private void warn(String msg)
5108 private void warn(String msg, Exception e)
5110 if (Cache.log != null)
5114 Cache.log.warn(msg, e);
5118 Cache.log.warn(msg);
5123 System.err.println("Warning: " + msg);
5126 e.printStackTrace();
5131 private void debug(String string)
5133 debug(string, null);
5136 private void debug(String msg, Exception e)
5138 if (Cache.log != null)
5142 Cache.log.debug(msg, e);
5146 Cache.log.debug(msg);
5151 System.err.println("Warning: " + msg);
5154 e.printStackTrace();
5160 * set the object to ID mapping tables used to write/recover objects and XML
5161 * ID strings for the jalview project. If external tables are provided then
5162 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
5163 * object goes out of scope. - also populates the datasetIds hashtable with
5164 * alignment objects containing dataset sequences
5167 * Map from ID strings to jalview datamodel
5169 * Map from jalview datamodel to ID strings
5173 public void setObjectMappingTables(Hashtable vobj2jv,
5174 IdentityHashMap jv2vobj)
5176 this.jv2vobj = jv2vobj;
5177 this.vobj2jv = vobj2jv;
5178 Iterator ds = jv2vobj.keySet().iterator();
5180 while (ds.hasNext())
5182 Object jvobj = ds.next();
5183 id = jv2vobj.get(jvobj).toString();
5184 if (jvobj instanceof jalview.datamodel.Alignment)
5186 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
5188 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
5191 else if (jvobj instanceof jalview.datamodel.Sequence)
5193 // register sequence object so the XML parser can recover it.
5194 if (seqRefIds == null)
5196 seqRefIds = new HashMap<String, SequenceI>();
5198 if (seqsToIds == null)
5200 seqsToIds = new IdentityHashMap<SequenceI, String>();
5202 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
5203 seqsToIds.put((SequenceI) jvobj, id);
5205 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
5208 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
5209 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
5210 if (jvann.annotationId == null)
5212 jvann.annotationId = anid;
5214 if (!jvann.annotationId.equals(anid))
5216 // TODO verify that this is the correct behaviour
5217 this.warn("Overriding Annotation ID for " + anid
5218 + " from different id : " + jvann.annotationId);
5219 jvann.annotationId = anid;
5222 else if (jvobj instanceof String)
5224 if (jvids2vobj == null)
5226 jvids2vobj = new Hashtable();
5227 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
5232 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
5238 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
5239 * objects created from the project archive. If string is null (default for
5240 * construction) then suffix will be set automatically.
5244 public void setUniqueSetSuffix(String string)
5246 uniqueSetSuffix = string;
5251 * uses skipList2 as the skipList for skipping views on sequence sets
5252 * associated with keys in the skipList
5256 public void setSkipList(Hashtable skipList2)
5258 skipList = skipList2;
5262 * Reads the jar entry of given name and returns its contents, or null if the
5263 * entry is not found.
5266 * @param jarEntryName
5269 protected String readJarEntry(jarInputStreamProvider jprovider,
5270 String jarEntryName)
5272 String result = null;
5273 BufferedReader in = null;
5278 * Reopen the jar input stream and traverse its entries to find a matching
5281 JarInputStream jin = jprovider.getJarInputStream();
5282 JarEntry entry = null;
5285 entry = jin.getNextJarEntry();
5286 } while (entry != null && !entry.getName().equals(jarEntryName));
5290 StringBuilder out = new StringBuilder(256);
5291 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
5294 while ((data = in.readLine()) != null)
5298 result = out.toString();
5302 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
5304 } catch (Exception ex)
5306 ex.printStackTrace();
5314 } catch (IOException e)
5325 * Returns an incrementing counter (0, 1, 2...)
5329 private synchronized int nextCounter()