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
679 : jds.getDatasetSequence();
680 String id = seqHash(jds);
682 if (seqRefIds.get(id) != null)
684 // This happens for two reasons: 1. multiple views are being serialised.
685 // 2. the hashCode has collided with another sequence's code. This DOES
686 // HAPPEN! (PF00072.15.stk does this)
687 // JBPNote: Uncomment to debug writing out of files that do not read
688 // back in due to ArrayOutOfBoundExceptions.
689 // System.err.println("vamsasSeq backref: "+id+"");
690 // System.err.println(jds.getName()+"
691 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
692 // System.err.println("Hashcode: "+seqHash(jds));
693 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
694 // System.err.println(rsq.getName()+"
695 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
696 // System.err.println("Hashcode: "+seqHash(rsq));
700 vamsasSeq = createVamsasSequence(id, jds);
701 vamsasSet.addSequence(vamsasSeq);
702 seqRefIds.put(id, jds);
706 jseq.setStart(jds.getStart());
707 jseq.setEnd(jds.getEnd());
708 jseq.setColour(av.getSequenceColour(jds).getRGB());
710 jseq.setId(id); // jseq id should be a string not a number
713 // Store any sequences this sequence represents
714 if (av.hasHiddenRows())
716 jseq.setHidden(av.getAlignment().getHiddenSequences()
719 if (av.isHiddenRepSequence(jal.getSequenceAt(i)))
721 jalview.datamodel.SequenceI[] reps = av
722 .getRepresentedSequences(jal.getSequenceAt(i))
723 .getSequencesInOrder(jal);
725 for (int h = 0; h < reps.length; h++)
727 if (reps[h] != jal.getSequenceAt(i))
729 jseq.addHiddenSequences(jal.findIndex(reps[h]));
736 if (jds.getSequenceFeatures() != null)
738 jalview.datamodel.SequenceFeature[] sf = jds.getSequenceFeatures();
740 while (index < sf.length)
742 Features features = new Features();
744 features.setBegin(sf[index].getBegin());
745 features.setEnd(sf[index].getEnd());
746 features.setDescription(sf[index].getDescription());
747 features.setType(sf[index].getType());
748 features.setFeatureGroup(sf[index].getFeatureGroup());
749 features.setScore(sf[index].getScore());
750 if (sf[index].links != null)
752 for (int l = 0; l < sf[index].links.size(); l++)
754 OtherData keyValue = new OtherData();
755 keyValue.setKey("LINK_" + l);
756 keyValue.setValue(sf[index].links.elementAt(l).toString());
757 features.addOtherData(keyValue);
760 if (sf[index].otherDetails != null)
763 Enumeration keys = sf[index].otherDetails.keys();
764 while (keys.hasMoreElements())
766 key = keys.nextElement().toString();
767 OtherData keyValue = new OtherData();
768 keyValue.setKey(key);
769 keyValue.setValue(sf[index].otherDetails.get(key).toString());
770 features.addOtherData(keyValue);
774 jseq.addFeatures(features);
779 if (jdatasq.getPDBId() != null)
781 Enumeration en = jdatasq.getPDBId().elements();
782 while (en.hasMoreElements())
784 Pdbids pdb = new Pdbids();
785 jalview.datamodel.PDBEntry entry = (jalview.datamodel.PDBEntry) en
788 String pdbId = entry.getId();
790 pdb.setType(entry.getType());
793 * Store any structure views associated with this sequence. This
794 * section copes with duplicate entries in the project, so a dataset
795 * only view *should* be coped with sensibly.
797 // This must have been loaded, is it still visible?
798 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
799 String matchedFile = null;
800 for (int f = frames.length - 1; f > -1; f--)
802 if (frames[f] instanceof StructureViewerBase)
804 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
805 matchedFile = saveStructureState(ap, jds, pdb, entry,
806 viewIds, matchedFile, viewFrame);
808 * Only store each structure viewer's state once in the project
809 * jar. First time through only (storeDS==false)
811 String viewId = viewFrame.getViewId();
812 if (!storeDS && !viewIds.contains(viewId))
817 String viewerState = viewFrame.getStateInfo();
818 writeJarEntry(jout, getViewerJarEntryName(viewId),
819 viewerState.getBytes());
820 } catch (IOException e)
822 System.err.println("Error saving viewer state: "
829 if (matchedFile != null || entry.getFile() != null)
831 if (entry.getFile() != null)
834 matchedFile = entry.getFile();
836 pdb.setFile(matchedFile); // entry.getFile());
837 if (pdbfiles == null)
839 pdbfiles = new ArrayList<String>();
842 if (!pdbfiles.contains(pdbId))
845 copyFileToJar(jout, matchedFile, pdbId);
849 if (entry.getProperty() != null && !entry.getProperty().isEmpty())
851 PdbentryItem item = new PdbentryItem();
852 Hashtable properties = entry.getProperty();
853 Enumeration en2 = properties.keys();
854 while (en2.hasMoreElements())
856 Property prop = new Property();
857 String key = en2.nextElement().toString();
859 prop.setValue(properties.get(key).toString());
860 item.addProperty(prop);
862 pdb.addPdbentryItem(item);
869 saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
874 if (!storeDS && av.hasHiddenRows())
876 jal = av.getAlignment();
879 if (jal.getCodonFrames() != null)
881 Set<AlignedCodonFrame> jac = jal.getCodonFrames();
882 for (AlignedCodonFrame acf : jac)
884 AlcodonFrame alc = new AlcodonFrame();
885 vamsasSet.addAlcodonFrame(alc);
886 if (acf.getProtMappings() != null
887 && acf.getProtMappings().length > 0)
889 SequenceI[] dnas = acf.getdnaSeqs();
890 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
891 for (int m = 0; m < pmaps.length; m++)
893 AlcodMap alcmap = new AlcodMap();
894 alcmap.setDnasq(seqHash(dnas[m]));
895 alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
897 alc.addAlcodMap(alcmap);
902 // AlcodonFrame alc = new AlcodonFrame();
903 // vamsasSet.addAlcodonFrame(alc);
904 // for (int p = 0; p < acf.aaWidth; p++)
906 // Alcodon cmap = new Alcodon();
907 // if (acf.codons[p] != null)
909 // // Null codons indicate a gapped column in the translated peptide
911 // cmap.setPos1(acf.codons[p][0]);
912 // cmap.setPos2(acf.codons[p][1]);
913 // cmap.setPos3(acf.codons[p][2]);
915 // alc.addAlcodon(cmap);
917 // if (acf.getProtMappings() != null
918 // && acf.getProtMappings().length > 0)
920 // SequenceI[] dnas = acf.getdnaSeqs();
921 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
922 // for (int m = 0; m < pmaps.length; m++)
924 // AlcodMap alcmap = new AlcodMap();
925 // alcmap.setDnasq(seqHash(dnas[m]));
926 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
928 // alc.addAlcodMap(alcmap);
935 // /////////////////////////////////
936 if (!storeDS && av.currentTree != null)
938 // FIND ANY ASSOCIATED TREES
939 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
940 if (Desktop.desktop != null)
942 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
944 for (int t = 0; t < frames.length; t++)
946 if (frames[t] instanceof TreePanel)
948 TreePanel tp = (TreePanel) frames[t];
950 if (tp.treeCanvas.av.getAlignment() == jal)
952 Tree tree = new Tree();
953 tree.setTitle(tp.getTitle());
954 tree.setCurrentTree((av.currentTree == tp.getTree()));
955 tree.setNewick(tp.getTree().toString());
956 tree.setThreshold(tp.treeCanvas.threshold);
958 tree.setFitToWindow(tp.fitToWindow.getState());
959 tree.setFontName(tp.getTreeFont().getName());
960 tree.setFontSize(tp.getTreeFont().getSize());
961 tree.setFontStyle(tp.getTreeFont().getStyle());
962 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
964 tree.setShowBootstrap(tp.bootstrapMenu.getState());
965 tree.setShowDistances(tp.distanceMenu.getState());
967 tree.setHeight(tp.getHeight());
968 tree.setWidth(tp.getWidth());
969 tree.setXpos(tp.getX());
970 tree.setYpos(tp.getY());
971 tree.setId(makeHashCode(tp, null));
981 * store forward refs from an annotationRow to any groups
983 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<SequenceGroup, String>();
986 for (SequenceI sq : jal.getSequences())
988 // Store annotation on dataset sequences only
989 AlignmentAnnotation[] aa = sq.getAnnotation();
990 if (aa != null && aa.length > 0)
992 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
999 if (jal.getAlignmentAnnotation() != null)
1001 // Store the annotation shown on the alignment.
1002 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1003 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1008 if (jal.getGroups() != null)
1010 JGroup[] groups = new JGroup[jal.getGroups().size()];
1012 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1014 JGroup jGroup = new JGroup();
1015 groups[++i] = jGroup;
1017 jGroup.setStart(sg.getStartRes());
1018 jGroup.setEnd(sg.getEndRes());
1019 jGroup.setName(sg.getName());
1020 if (groupRefs.containsKey(sg))
1022 // group has references so set its ID field
1023 jGroup.setId(groupRefs.get(sg));
1027 if (sg.cs.conservationApplied())
1029 jGroup.setConsThreshold(sg.cs.getConservationInc());
1031 if (sg.cs instanceof jalview.schemes.UserColourScheme)
1033 jGroup.setColour(setUserColourScheme(sg.cs, userColours, jms));
1037 jGroup.setColour(ColourSchemeProperty.getColourName(sg.cs));
1040 else if (sg.cs instanceof jalview.schemes.AnnotationColourGradient)
1042 jGroup.setColour("AnnotationColourGradient");
1043 jGroup.setAnnotationColours(constructAnnotationColours(
1044 (jalview.schemes.AnnotationColourGradient) sg.cs,
1047 else if (sg.cs instanceof jalview.schemes.UserColourScheme)
1049 jGroup.setColour(setUserColourScheme(sg.cs, userColours, jms));
1053 jGroup.setColour(ColourSchemeProperty.getColourName(sg.cs));
1056 jGroup.setPidThreshold(sg.cs.getThreshold());
1059 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1060 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1061 jGroup.setDisplayText(sg.getDisplayText());
1062 jGroup.setColourText(sg.getColourText());
1063 jGroup.setTextCol1(sg.textColour.getRGB());
1064 jGroup.setTextCol2(sg.textColour2.getRGB());
1065 jGroup.setTextColThreshold(sg.thresholdTextColour);
1066 jGroup.setShowUnconserved(sg.getShowNonconserved());
1067 jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1068 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1069 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1070 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1071 for (SequenceI seq : sg.getSequences())
1073 jGroup.addSeq(seqHash(seq));
1077 jms.setJGroup(groups);
1081 // /////////SAVE VIEWPORT
1082 Viewport view = new Viewport();
1083 view.setTitle(ap.alignFrame.getTitle());
1084 view.setSequenceSetId(makeHashCode(av.getSequenceSetId(),
1085 av.getSequenceSetId()));
1086 view.setId(av.getViewId());
1087 if (av.getCodingComplement() != null)
1089 view.setComplementId(av.getCodingComplement().getViewId());
1091 view.setViewName(av.viewName);
1092 view.setGatheredViews(av.isGatherViewsHere());
1094 Rectangle position = ap.av.getExplodedGeometry();
1095 if (position == null)
1097 position = ap.alignFrame.getBounds();
1099 view.setXpos(position.x);
1100 view.setYpos(position.y);
1101 view.setWidth(position.width);
1102 view.setHeight(position.height);
1104 view.setStartRes(av.startRes);
1105 view.setStartSeq(av.startSeq);
1107 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1109 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1112 else if (av.getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1114 AnnotationColours ac = constructAnnotationColours(
1115 (jalview.schemes.AnnotationColourGradient) av
1116 .getGlobalColourScheme(),
1119 view.setAnnotationColours(ac);
1120 view.setBgColour("AnnotationColourGradient");
1124 view.setBgColour(ColourSchemeProperty.getColourName(av
1125 .getGlobalColourScheme()));
1128 ColourSchemeI cs = av.getGlobalColourScheme();
1132 if (cs.conservationApplied())
1134 view.setConsThreshold(cs.getConservationInc());
1135 if (cs instanceof jalview.schemes.UserColourScheme)
1137 view.setBgColour(setUserColourScheme(cs, userColours, jms));
1141 if (cs instanceof ResidueColourScheme)
1143 view.setPidThreshold(cs.getThreshold());
1147 view.setConservationSelected(av.getConservationSelected());
1148 view.setPidSelected(av.getAbovePIDThreshold());
1149 view.setFontName(av.font.getName());
1150 view.setFontSize(av.font.getSize());
1151 view.setFontStyle(av.font.getStyle());
1152 view.setRenderGaps(av.isRenderGaps());
1153 view.setShowAnnotation(av.isShowAnnotation());
1154 view.setShowBoxes(av.getShowBoxes());
1155 view.setShowColourText(av.getColourText());
1156 view.setShowFullId(av.getShowJVSuffix());
1157 view.setRightAlignIds(av.isRightAlignIds());
1158 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1159 view.setShowText(av.getShowText());
1160 view.setShowUnconserved(av.getShowUnconserved());
1161 view.setWrapAlignment(av.getWrapAlignment());
1162 view.setTextCol1(av.getTextColour().getRGB());
1163 view.setTextCol2(av.getTextColour2().getRGB());
1164 view.setTextColThreshold(av.getThresholdTextColour());
1165 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1166 view.setShowSequenceLogo(av.isShowSequenceLogo());
1167 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1168 view.setShowGroupConsensus(av.isShowGroupConsensus());
1169 view.setShowGroupConservation(av.isShowGroupConservation());
1170 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1171 view.setShowDbRefTooltip(av.isShowDBRefs());
1172 view.setFollowHighlight(av.isFollowHighlight());
1173 view.setFollowSelection(av.followSelection);
1174 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1175 if (av.getFeaturesDisplayed() != null)
1177 jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
1179 String[] renderOrder = ap.getSeqPanel().seqCanvas
1180 .getFeatureRenderer().getRenderOrder()
1181 .toArray(new String[0]);
1183 Vector settingsAdded = new Vector();
1184 Object gstyle = null;
1185 GraduatedColor gcol = null;
1186 if (renderOrder != null)
1188 for (int ro = 0; ro < renderOrder.length; ro++)
1190 gstyle = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1191 .getFeatureStyle(renderOrder[ro]);
1192 Setting setting = new Setting();
1193 setting.setType(renderOrder[ro]);
1194 if (gstyle instanceof GraduatedColor)
1196 gcol = (GraduatedColor) gstyle;
1197 setting.setColour(gcol.getMaxColor().getRGB());
1198 setting.setMincolour(gcol.getMinColor().getRGB());
1199 setting.setMin(gcol.getMin());
1200 setting.setMax(gcol.getMax());
1201 setting.setColourByLabel(gcol.isColourByLabel());
1202 setting.setAutoScale(gcol.isAutoScale());
1203 setting.setThreshold(gcol.getThresh());
1204 setting.setThreshstate(gcol.getThreshType());
1208 setting.setColour(ap.getSeqPanel().seqCanvas
1209 .getFeatureRenderer().getColour(renderOrder[ro])
1213 setting.setDisplay(av.getFeaturesDisplayed().isVisible(
1215 float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1216 .getOrder(renderOrder[ro]);
1219 setting.setOrder(rorder);
1221 fs.addSetting(setting);
1222 settingsAdded.addElement(renderOrder[ro]);
1226 // Make sure we save none displayed feature settings
1227 Iterator en = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1228 .getFeatureColours().keySet().iterator();
1229 while (en.hasNext())
1231 String key = en.next().toString();
1232 if (settingsAdded.contains(key))
1237 Setting setting = new Setting();
1238 setting.setType(key);
1239 setting.setColour(ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1240 .getColour(key).getRGB());
1242 setting.setDisplay(false);
1243 float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1247 setting.setOrder(rorder);
1249 fs.addSetting(setting);
1250 settingsAdded.addElement(key);
1252 // is groups actually supposed to be a map here ?
1253 en = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1254 .getFeatureGroups().iterator();
1255 Vector groupsAdded = new Vector();
1256 while (en.hasNext())
1258 String grp = en.next().toString();
1259 if (groupsAdded.contains(grp))
1263 Group g = new Group();
1265 g.setDisplay(((Boolean) ap.getSeqPanel().seqCanvas
1266 .getFeatureRenderer().checkGroupVisibility(grp, false))
1269 groupsAdded.addElement(grp);
1271 jms.setFeatureSettings(fs);
1275 if (av.hasHiddenColumns())
1277 if (av.getColumnSelection() == null
1278 || av.getColumnSelection().getHiddenColumns() == null)
1280 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1284 for (int c = 0; c < av.getColumnSelection().getHiddenColumns()
1287 int[] region = av.getColumnSelection().getHiddenColumns()
1289 HiddenColumns hc = new HiddenColumns();
1290 hc.setStart(region[0]);
1291 hc.setEnd(region[1]);
1292 view.addHiddenColumns(hc);
1296 if (calcIdSet.size() > 0)
1298 for (String calcId : calcIdSet)
1300 if (calcId.trim().length() > 0)
1302 CalcIdParam cidp = createCalcIdParam(calcId, av);
1303 // Some calcIds have no parameters.
1306 view.addCalcIdParam(cidp);
1312 jms.addViewport(view);
1314 object.setJalviewModelSequence(jms);
1315 object.getVamsasModel().addSequenceSet(vamsasSet);
1317 if (jout != null && fileName != null)
1319 // We may not want to write the object to disk,
1320 // eg we can copy the alignViewport to a new view object
1321 // using save and then load
1324 System.out.println("Writing jar entry " + fileName);
1325 JarEntry entry = new JarEntry(fileName);
1326 jout.putNextEntry(entry);
1327 PrintWriter pout = new PrintWriter(new OutputStreamWriter(jout,
1329 Marshaller marshaller = new Marshaller(pout);
1330 marshaller.marshal(object);
1333 } catch (Exception ex)
1335 // TODO: raise error in GUI if marshalling failed.
1336 ex.printStackTrace();
1343 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1344 * for each viewer, with
1346 * <li>viewer geometry (position, size, split pane divider location)</li>
1347 * <li>index of the selected structure in the viewer (currently shows gapped
1349 * <li>the id of the annotation holding RNA secondary structure</li>
1350 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1352 * Varna viewer state is also written out (in native Varna XML) to separate
1353 * project jar entries. A separate entry is written for each RNA structure
1354 * displayed, with the naming convention
1356 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
1364 * @param storeDataset
1366 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
1367 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
1368 boolean storeDataset)
1370 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1371 for (int f = frames.length - 1; f > -1; f--)
1373 if (frames[f] instanceof AppVarna)
1375 AppVarna varna = (AppVarna) frames[f];
1377 * link the sequence to every viewer that is showing it and is linked to
1378 * its alignment panel
1380 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1382 String viewId = varna.getViewId();
1383 RnaViewer rna = new RnaViewer();
1384 rna.setViewId(viewId);
1385 rna.setTitle(varna.getTitle());
1386 rna.setXpos(varna.getX());
1387 rna.setYpos(varna.getY());
1388 rna.setWidth(varna.getWidth());
1389 rna.setHeight(varna.getHeight());
1390 rna.setDividerLocation(varna.getDividerLocation());
1391 rna.setSelectedRna(varna.getSelectedIndex());
1392 jseq.addRnaViewer(rna);
1395 * Store each Varna panel's state once in the project per sequence.
1396 * First time through only (storeDataset==false)
1398 // boolean storeSessions = false;
1399 // String sequenceViewId = viewId + seqsToIds.get(jds);
1400 // if (!storeDataset && !viewIds.contains(sequenceViewId))
1402 // viewIds.add(sequenceViewId);
1403 // storeSessions = true;
1405 for (RnaModel model : varna.getModels())
1407 if (model.seq == jds)
1410 * VARNA saves each view (sequence or alignment secondary
1411 * structure, gapped or trimmed) as a separate XML file
1413 String jarEntryName = rnaSessions.get(model);
1414 if (jarEntryName == null)
1417 String varnaStateFile = varna.getStateInfo(model.rna);
1418 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
1419 copyFileToJar(jout, varnaStateFile, jarEntryName);
1420 rnaSessions.put(model, jarEntryName);
1422 SecondaryStructure ss = new SecondaryStructure();
1423 String annotationId = varna.getAnnotation(jds).annotationId;
1424 ss.setAnnotationId(annotationId);
1425 ss.setViewerState(jarEntryName);
1426 ss.setGapped(model.gapped);
1427 ss.setTitle(model.title);
1428 rna.addSecondaryStructure(ss);
1437 * Copy the contents of a file to a new entry added to the output jar
1441 * @param jarEntryName
1443 protected void copyFileToJar(JarOutputStream jout, String infilePath,
1444 String jarEntryName)
1446 DataInputStream dis = null;
1449 File file = new File(infilePath);
1450 if (file.exists() && jout != null)
1452 dis = new DataInputStream(new FileInputStream(file));
1453 byte[] data = new byte[(int) file.length()];
1454 dis.readFully(data);
1455 writeJarEntry(jout, jarEntryName, data);
1457 } catch (Exception ex)
1459 ex.printStackTrace();
1467 } catch (IOException e)
1476 * Write the data to a new entry of given name in the output jar file
1479 * @param jarEntryName
1481 * @throws IOException
1483 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
1484 byte[] data) throws IOException
1488 System.out.println("Writing jar entry " + jarEntryName);
1489 jout.putNextEntry(new JarEntry(jarEntryName));
1490 DataOutputStream dout = new DataOutputStream(jout);
1491 dout.write(data, 0, data.length);
1498 * Save the state of a structure viewer
1503 * the archive XML element under which to save the state
1506 * @param matchedFile
1510 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
1511 Pdbids pdb, PDBEntry entry, List<String> viewIds,
1512 String matchedFile, StructureViewerBase viewFrame)
1514 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
1517 * Look for any bindings for this viewer to the PDB file of interest
1518 * (including part matches excluding chain id)
1520 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
1522 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
1523 final String pdbId = pdbentry.getId();
1524 if (!pdbId.equals(entry.getId())
1525 && !(entry.getId().length() > 4 && entry.getId()
1526 .toLowerCase().startsWith(pdbId.toLowerCase())))
1529 * not interested in a binding to a different PDB entry here
1533 if (matchedFile == null)
1535 matchedFile = pdbentry.getFile();
1537 else if (!matchedFile.equals(pdbentry.getFile()))
1540 .warn("Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
1541 + pdbentry.getFile());
1545 // can get at it if the ID
1546 // match is ambiguous (e.g.
1549 for (int smap = 0; smap < viewFrame.getBinding().getSequence()[peid].length; smap++)
1551 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
1552 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
1554 StructureState state = new StructureState();
1555 state.setVisible(true);
1556 state.setXpos(viewFrame.getX());
1557 state.setYpos(viewFrame.getY());
1558 state.setWidth(viewFrame.getWidth());
1559 state.setHeight(viewFrame.getHeight());
1560 final String viewId = viewFrame.getViewId();
1561 state.setViewId(viewId);
1562 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
1563 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
1564 state.setColourByJmol(viewFrame.isColouredByViewer());
1565 state.setType(viewFrame.getViewerType().toString());
1566 pdb.addStructureState(state);
1573 private AnnotationColours constructAnnotationColours(
1574 AnnotationColourGradient acg, List<UserColourScheme> userColours,
1575 JalviewModelSequence jms)
1577 AnnotationColours ac = new AnnotationColours();
1578 ac.setAboveThreshold(acg.getAboveThreshold());
1579 ac.setThreshold(acg.getAnnotationThreshold());
1580 ac.setAnnotation(acg.getAnnotation());
1581 if (acg.getBaseColour() instanceof jalview.schemes.UserColourScheme)
1583 ac.setColourScheme(setUserColourScheme(acg.getBaseColour(),
1588 ac.setColourScheme(ColourSchemeProperty.getColourName(acg
1592 ac.setMaxColour(acg.getMaxColour().getRGB());
1593 ac.setMinColour(acg.getMinColour().getRGB());
1594 ac.setPerSequence(acg.isSeqAssociated());
1595 ac.setPredefinedColours(acg.isPredefinedColours());
1599 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
1600 IdentityHashMap<SequenceGroup, String> groupRefs,
1601 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
1602 SequenceSet vamsasSet)
1605 for (int i = 0; i < aa.length; i++)
1607 Annotation an = new Annotation();
1609 AlignmentAnnotation annotation = aa[i];
1610 if (annotation.annotationId != null)
1612 annotationIds.put(annotation.annotationId, annotation);
1615 an.setId(annotation.annotationId);
1617 an.setVisible(annotation.visible);
1619 an.setDescription(annotation.description);
1621 if (annotation.sequenceRef != null)
1623 // 2.9 JAL-1781 xref on sequence id rather than name
1624 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
1626 if (annotation.groupRef != null)
1628 String groupIdr = groupRefs.get(annotation.groupRef);
1629 if (groupIdr == null)
1631 // make a locally unique String
1633 annotation.groupRef,
1634 groupIdr = ("" + System.currentTimeMillis()
1635 + annotation.groupRef.getName() + groupRefs
1638 an.setGroupRef(groupIdr.toString());
1641 // store all visualization attributes for annotation
1642 an.setGraphHeight(annotation.graphHeight);
1643 an.setCentreColLabels(annotation.centreColLabels);
1644 an.setScaleColLabels(annotation.scaleColLabel);
1645 an.setShowAllColLabels(annotation.showAllColLabels);
1646 an.setBelowAlignment(annotation.belowAlignment);
1648 if (annotation.graph > 0)
1651 an.setGraphType(annotation.graph);
1652 an.setGraphGroup(annotation.graphGroup);
1653 if (annotation.getThreshold() != null)
1655 ThresholdLine line = new ThresholdLine();
1656 line.setLabel(annotation.getThreshold().label);
1657 line.setValue(annotation.getThreshold().value);
1658 line.setColour(annotation.getThreshold().colour.getRGB());
1659 an.setThresholdLine(line);
1667 an.setLabel(annotation.label);
1669 if (annotation == av.getAlignmentQualityAnnot()
1670 || annotation == av.getAlignmentConservationAnnotation()
1671 || annotation == av.getAlignmentConsensusAnnotation()
1672 || annotation.autoCalculated)
1674 // new way of indicating autocalculated annotation -
1675 an.setAutoCalculated(annotation.autoCalculated);
1677 if (annotation.hasScore())
1679 an.setScore(annotation.getScore());
1682 if (annotation.getCalcId() != null)
1684 calcIdSet.add(annotation.getCalcId());
1685 an.setCalcId(annotation.getCalcId());
1687 if (annotation.hasProperties())
1689 for (String pr : annotation.getProperties())
1691 Property prop = new Property();
1693 prop.setValue(annotation.getProperty(pr));
1694 an.addProperty(prop);
1698 AnnotationElement ae;
1699 if (annotation.annotations != null)
1701 an.setScoreOnly(false);
1702 for (int a = 0; a < annotation.annotations.length; a++)
1704 if ((annotation == null) || (annotation.annotations[a] == null))
1709 ae = new AnnotationElement();
1710 if (annotation.annotations[a].description != null)
1712 ae.setDescription(annotation.annotations[a].description);
1714 if (annotation.annotations[a].displayCharacter != null)
1716 ae.setDisplayCharacter(annotation.annotations[a].displayCharacter);
1719 if (!Float.isNaN(annotation.annotations[a].value))
1721 ae.setValue(annotation.annotations[a].value);
1725 if (annotation.annotations[a].secondaryStructure > ' ')
1727 ae.setSecondaryStructure(annotation.annotations[a].secondaryStructure
1731 if (annotation.annotations[a].colour != null
1732 && annotation.annotations[a].colour != java.awt.Color.black)
1734 ae.setColour(annotation.annotations[a].colour.getRGB());
1737 an.addAnnotationElement(ae);
1738 if (annotation.autoCalculated)
1740 // only write one non-null entry into the annotation row -
1741 // sufficient to get the visualization attributes necessary to
1749 an.setScoreOnly(true);
1751 if (!storeDS || (storeDS && !annotation.autoCalculated))
1753 // skip autocalculated annotation - these are only provided for
1755 vamsasSet.addAnnotation(an);
1761 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
1763 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
1764 if (settings != null)
1766 CalcIdParam vCalcIdParam = new CalcIdParam();
1767 vCalcIdParam.setCalcId(calcId);
1768 vCalcIdParam.addServiceURL(settings.getServiceURI());
1769 // generic URI allowing a third party to resolve another instance of the
1770 // service used for this calculation
1771 for (String urls : settings.getServiceURLs())
1773 vCalcIdParam.addServiceURL(urls);
1775 vCalcIdParam.setVersion("1.0");
1776 if (settings.getPreset() != null)
1778 WsParamSetI setting = settings.getPreset();
1779 vCalcIdParam.setName(setting.getName());
1780 vCalcIdParam.setDescription(setting.getDescription());
1784 vCalcIdParam.setName("");
1785 vCalcIdParam.setDescription("Last used parameters");
1787 // need to be able to recover 1) settings 2) user-defined presets or
1788 // recreate settings from preset 3) predefined settings provided by
1789 // service - or settings that can be transferred (or discarded)
1790 vCalcIdParam.setParameters(settings.getWsParamFile().replace("\n",
1792 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
1793 // todo - decide if updateImmediately is needed for any projects.
1795 return vCalcIdParam;
1800 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
1803 if (calcIdParam.getVersion().equals("1.0"))
1805 Jws2Instance service = Jws2Discoverer.getDiscoverer()
1806 .getPreferredServiceFor(calcIdParam.getServiceURL());
1807 if (service != null)
1809 WsParamSetI parmSet = null;
1812 parmSet = service.getParamStore().parseServiceParameterFile(
1813 calcIdParam.getName(), calcIdParam.getDescription(),
1814 calcIdParam.getServiceURL(),
1815 calcIdParam.getParameters().replace("|\\n|", "\n"));
1816 } catch (IOException x)
1818 warn("Couldn't parse parameter data for "
1819 + calcIdParam.getCalcId(), x);
1822 List<ArgumentI> argList = null;
1823 if (calcIdParam.getName().length() > 0)
1825 parmSet = service.getParamStore()
1826 .getPreset(calcIdParam.getName());
1827 if (parmSet != null)
1829 // TODO : check we have a good match with settings in AACon -
1830 // otherwise we'll need to create a new preset
1835 argList = parmSet.getArguments();
1838 AAConSettings settings = new AAConSettings(
1839 calcIdParam.isAutoUpdate(), service, parmSet, argList);
1840 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
1841 calcIdParam.isNeedsUpdate());
1846 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
1850 throw new Error(MessageManager.formatMessage(
1851 "error.unsupported_version_calcIdparam", new Object[]
1852 { calcIdParam.toString() }));
1856 * External mapping between jalview objects and objects yielding a valid and
1857 * unique object ID string. This is null for normal Jalview project IO, but
1858 * non-null when a jalview project is being read or written as part of a
1861 IdentityHashMap jv2vobj = null;
1864 * Construct a unique ID for jvobj using either existing bindings or if none
1865 * exist, the result of the hashcode call for the object.
1868 * jalview data object
1869 * @return unique ID for referring to jvobj
1871 private String makeHashCode(Object jvobj, String altCode)
1873 if (jv2vobj != null)
1875 Object id = jv2vobj.get(jvobj);
1878 return id.toString();
1880 // check string ID mappings
1881 if (jvids2vobj != null && jvobj instanceof String)
1883 id = jvids2vobj.get(jvobj);
1887 return id.toString();
1889 // give up and warn that something has gone wrong
1890 warn("Cannot find ID for object in external mapping : " + jvobj);
1896 * return local jalview object mapped to ID, if it exists
1900 * @return null or object bound to idcode
1902 private Object retrieveExistingObj(String idcode)
1904 if (idcode != null && vobj2jv != null)
1906 return vobj2jv.get(idcode);
1912 * binding from ID strings from external mapping table to jalview data model
1915 private Hashtable vobj2jv;
1917 private Sequence createVamsasSequence(String id, SequenceI jds)
1919 return createVamsasSequence(true, id, jds, null);
1922 private Sequence createVamsasSequence(boolean recurse, String id,
1923 SequenceI jds, SequenceI parentseq)
1925 Sequence vamsasSeq = new Sequence();
1926 vamsasSeq.setId(id);
1927 vamsasSeq.setName(jds.getName());
1928 vamsasSeq.setSequence(jds.getSequenceAsString());
1929 vamsasSeq.setDescription(jds.getDescription());
1930 jalview.datamodel.DBRefEntry[] dbrefs = null;
1931 if (jds.getDatasetSequence() != null)
1933 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
1934 if (jds.getDatasetSequence().getDBRef() != null)
1936 dbrefs = jds.getDatasetSequence().getDBRef();
1941 vamsasSeq.setDsseqid(id); // so we can tell which sequences really are
1942 // dataset sequences only
1943 dbrefs = jds.getDBRef();
1947 for (int d = 0; d < dbrefs.length; d++)
1949 DBRef dbref = new DBRef();
1950 dbref.setSource(dbrefs[d].getSource());
1951 dbref.setVersion(dbrefs[d].getVersion());
1952 dbref.setAccessionId(dbrefs[d].getAccessionId());
1953 if (dbrefs[d].hasMap())
1955 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
1957 dbref.setMapping(mp);
1959 vamsasSeq.addDBRef(dbref);
1965 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
1966 SequenceI parentseq, SequenceI jds, boolean recurse)
1969 if (jmp.getMap() != null)
1973 jalview.util.MapList mlst = jmp.getMap();
1974 List<int[]> r = mlst.getFromRanges();
1975 for (int[] range : r)
1977 MapListFrom mfrom = new MapListFrom();
1978 mfrom.setStart(range[0]);
1979 mfrom.setEnd(range[1]);
1980 mp.addMapListFrom(mfrom);
1982 r = mlst.getToRanges();
1983 for (int[] range : r)
1985 MapListTo mto = new MapListTo();
1986 mto.setStart(range[0]);
1987 mto.setEnd(range[1]);
1988 mp.addMapListTo(mto);
1990 mp.setMapFromUnit(mlst.getFromRatio());
1991 mp.setMapToUnit(mlst.getToRatio());
1992 if (jmp.getTo() != null)
1994 MappingChoice mpc = new MappingChoice();
1996 && (parentseq != jmp.getTo() || parentseq
1997 .getDatasetSequence() != jmp.getTo()))
1999 mpc.setSequence(createVamsasSequence(false, seqHash(jmp.getTo()),
2005 SequenceI ps = null;
2006 if (parentseq != jmp.getTo()
2007 && parentseq.getDatasetSequence() != jmp.getTo())
2009 // chaining dbref rather than a handshaking one
2010 jmpid = seqHash(ps = jmp.getTo());
2014 jmpid = seqHash(ps = parentseq);
2016 mpc.setDseqFor(jmpid);
2017 if (!seqRefIds.containsKey(mpc.getDseqFor()))
2019 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2020 seqRefIds.put(mpc.getDseqFor(), ps);
2024 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2027 mp.setMappingChoice(mpc);
2033 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2034 List<UserColourScheme> userColours, JalviewModelSequence jms)
2037 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2038 boolean newucs = false;
2039 if (!userColours.contains(ucs))
2041 userColours.add(ucs);
2044 id = "ucs" + userColours.indexOf(ucs);
2047 // actually create the scheme's entry in the XML model
2048 java.awt.Color[] colours = ucs.getColours();
2049 jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
2050 jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
2052 for (int i = 0; i < colours.length; i++)
2054 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2055 col.setName(ResidueProperties.aa[i]);
2056 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2057 jbucs.addColour(col);
2059 if (ucs.getLowerCaseColours() != null)
2061 colours = ucs.getLowerCaseColours();
2062 for (int i = 0; i < colours.length; i++)
2064 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2065 col.setName(ResidueProperties.aa[i].toLowerCase());
2066 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2067 jbucs.addColour(col);
2072 uc.setUserColourScheme(jbucs);
2073 jms.addUserColours(uc);
2079 jalview.schemes.UserColourScheme getUserColourScheme(
2080 JalviewModelSequence jms, String id)
2082 UserColours[] uc = jms.getUserColours();
2083 UserColours colours = null;
2085 for (int i = 0; i < uc.length; i++)
2087 if (uc[i].getId().equals(id))
2095 java.awt.Color[] newColours = new java.awt.Color[24];
2097 for (int i = 0; i < 24; i++)
2099 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2100 .getUserColourScheme().getColour(i).getRGB(), 16));
2103 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2106 if (colours.getUserColourScheme().getColourCount() > 24)
2108 newColours = new java.awt.Color[23];
2109 for (int i = 0; i < 23; i++)
2111 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2112 .getUserColourScheme().getColour(i + 24).getRGB(), 16));
2114 ucs.setLowerCaseColours(newColours);
2121 * contains last error message (if any) encountered by XML loader.
2123 String errorMessage = null;
2126 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2127 * exceptions are raised during project XML parsing
2129 public boolean attemptversion1parse = true;
2132 * Load a jalview project archive from a jar file
2135 * - HTTP URL or filename
2137 public AlignFrame loadJalviewAlign(final String file)
2140 jalview.gui.AlignFrame af = null;
2144 // create list to store references for any new Jmol viewers created
2145 newStructureViewers = new Vector<JalviewStructureDisplayI>();
2146 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2147 // Workaround is to make sure caller implements the JarInputStreamProvider
2149 // so we can re-open the jar input stream for each entry.
2151 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2152 af = loadJalviewAlign(jprovider);
2154 } catch (MalformedURLException e)
2156 errorMessage = "Invalid URL format for '" + file + "'";
2162 SwingUtilities.invokeAndWait(new Runnable()
2166 setLoadingFinishedForNewStructureViewers();
2169 } catch (Exception x)
2171 System.err.println("Error loading alignment: " + x.getMessage());
2177 private jarInputStreamProvider createjarInputStreamProvider(
2178 final String file) throws MalformedURLException
2181 errorMessage = null;
2182 uniqueSetSuffix = null;
2184 viewportsAdded.clear();
2185 frefedSequence = null;
2187 if (file.startsWith("http://"))
2189 url = new URL(file);
2191 final URL _url = url;
2192 return new jarInputStreamProvider()
2196 public JarInputStream getJarInputStream() throws IOException
2200 return new JarInputStream(_url.openStream());
2204 return new JarInputStream(new FileInputStream(file));
2209 public String getFilename()
2217 * Recover jalview session from a jalview project archive. Caller may
2218 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2219 * themselves. Any null fields will be initialised with default values,
2220 * non-null fields are left alone.
2225 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2227 errorMessage = null;
2228 if (uniqueSetSuffix == null)
2230 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2232 if (seqRefIds == null)
2234 seqRefIds = new HashMap<String, SequenceI>();
2236 if (frefedSequence == null)
2238 frefedSequence = new Vector();
2241 AlignFrame af = null, _af = null;
2242 Map<String, AlignFrame> gatherToThisFrame = new HashMap<String, AlignFrame>();
2243 final String file = jprovider.getFilename();
2246 JarInputStream jin = null;
2247 JarEntry jarentry = null;
2252 jin = jprovider.getJarInputStream();
2253 for (int i = 0; i < entryCount; i++)
2255 jarentry = jin.getNextJarEntry();
2258 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2260 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2261 JalviewModel object = new JalviewModel();
2263 Unmarshaller unmar = new Unmarshaller(object);
2264 unmar.setValidation(false);
2265 object = (JalviewModel) unmar.unmarshal(in);
2266 if (true) // !skipViewport(object))
2268 _af = loadFromObject(object, file, true, jprovider);
2269 if (object.getJalviewModelSequence().getViewportCount() > 0)
2272 if (af.viewport.isGatherViewsHere())
2274 gatherToThisFrame.put(af.viewport.getSequenceSetId(), af);
2280 else if (jarentry != null)
2282 // Some other file here.
2285 } while (jarentry != null);
2286 resolveFrefedSequences();
2287 } catch (IOException ex)
2289 ex.printStackTrace();
2290 errorMessage = "Couldn't locate Jalview XML file : " + file;
2291 System.err.println("Exception whilst loading jalview XML file : "
2293 } catch (Exception ex)
2295 System.err.println("Parsing as Jalview Version 2 file failed.");
2296 ex.printStackTrace(System.err);
2297 if (attemptversion1parse)
2299 // Is Version 1 Jar file?
2302 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
2303 } catch (Exception ex2)
2305 System.err.println("Exception whilst loading as jalviewXMLV1:");
2306 ex2.printStackTrace();
2310 if (Desktop.instance != null)
2312 Desktop.instance.stopLoading();
2316 System.out.println("Successfully loaded archive file");
2319 ex.printStackTrace();
2321 System.err.println("Exception whilst loading jalview XML file : "
2323 } catch (OutOfMemoryError e)
2325 // Don't use the OOM Window here
2326 errorMessage = "Out of memory loading jalview XML file";
2327 System.err.println("Out of memory whilst loading jalview XML file");
2328 e.printStackTrace();
2331 if (Desktop.instance != null)
2333 Desktop.instance.stopLoading();
2337 * Regather multiple views (with the same sequence set id) to the frame (if
2338 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2339 * views instead of separate frames. Note this doesn't restore a state where
2340 * some expanded views in turn have tabbed views - the last "first tab" read
2341 * in will play the role of gatherer for all.
2343 for (AlignFrame fr : gatherToThisFrame.values())
2345 Desktop.instance.gatherViews(fr);
2348 restoreSplitFrames();
2350 if (errorMessage != null)
2358 * Try to reconstruct and display SplitFrame windows, where each contains
2359 * complementary dna and protein alignments. Done by pairing up AlignFrame
2360 * objects (created earlier) which have complementary viewport ids associated.
2362 protected void restoreSplitFrames()
2364 List<SplitFrame> gatherTo = new ArrayList<SplitFrame>();
2365 List<AlignFrame> addedToSplitFrames = new ArrayList<AlignFrame>();
2366 Map<String, AlignFrame> dna = new HashMap<String, AlignFrame>();
2369 * Identify the DNA alignments
2371 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2374 AlignFrame af = candidate.getValue();
2375 if (af.getViewport().getAlignment().isNucleotide())
2377 dna.put(candidate.getKey().getId(), af);
2382 * Try to match up the protein complements
2384 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2387 AlignFrame af = candidate.getValue();
2388 if (!af.getViewport().getAlignment().isNucleotide())
2390 String complementId = candidate.getKey().getComplementId();
2391 // only non-null complements should be in the Map
2392 if (complementId != null && dna.containsKey(complementId))
2394 final AlignFrame dnaFrame = dna.get(complementId);
2395 SplitFrame sf = createSplitFrame(dnaFrame, af);
2396 addedToSplitFrames.add(dnaFrame);
2397 addedToSplitFrames.add(af);
2398 if (af.viewport.isGatherViewsHere())
2407 * Open any that we failed to pair up (which shouldn't happen!) as
2408 * standalone AlignFrame's.
2410 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2413 AlignFrame af = candidate.getValue();
2414 if (!addedToSplitFrames.contains(af))
2416 Viewport view = candidate.getKey();
2417 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
2419 System.err.println("Failed to restore view " + view.getTitle()
2420 + " to split frame");
2425 * Gather back into tabbed views as flagged.
2427 for (SplitFrame sf : gatherTo)
2429 Desktop.instance.gatherViews(sf);
2432 splitFrameCandidates.clear();
2436 * Construct and display one SplitFrame holding DNA and protein alignments.
2439 * @param proteinFrame
2442 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
2443 AlignFrame proteinFrame)
2445 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
2446 String title = MessageManager.getString("label.linked_view_title");
2447 int width = (int) dnaFrame.getBounds().getWidth();
2448 int height = (int) (dnaFrame.getBounds().getHeight()
2449 + proteinFrame.getBounds().getHeight() + 50);
2450 Desktop.addInternalFrame(splitFrame, title, width, height);
2453 * And compute cDNA consensus (couldn't do earlier with consensus as
2454 * mappings were not yet present)
2456 proteinFrame.viewport.alignmentChanged(proteinFrame.alignPanel);
2462 * check errorMessage for a valid error message and raise an error box in the
2463 * GUI or write the current errorMessage to stderr and then clear the error
2466 protected void reportErrors()
2468 reportErrors(false);
2471 protected void reportErrors(final boolean saving)
2473 if (errorMessage != null)
2475 final String finalErrorMessage = errorMessage;
2478 javax.swing.SwingUtilities.invokeLater(new Runnable()
2483 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2484 finalErrorMessage, "Error "
2485 + (saving ? "saving" : "loading")
2486 + " Jalview file", JOptionPane.WARNING_MESSAGE);
2492 System.err.println("Problem loading Jalview file: " + errorMessage);
2495 errorMessage = null;
2498 Map<String, String> alreadyLoadedPDB = new HashMap<String, String>();
2501 * when set, local views will be updated from view stored in JalviewXML
2502 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2503 * sync if this is set to true.
2505 private final boolean updateLocalViews = false;
2508 * Returns the path to a temporary file holding the PDB file for the given PDB
2509 * id. The first time of asking, searches for a file of that name in the
2510 * Jalview project jar, and copies it to a new temporary file. Any repeat
2511 * requests just return the path to the file previously created.
2517 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId)
2519 if (alreadyLoadedPDB.containsKey(pdbId))
2521 return alreadyLoadedPDB.get(pdbId).toString();
2524 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb");
2525 if (tempFile != null)
2527 alreadyLoadedPDB.put(pdbId, tempFile);
2533 * Copies the jar entry of given name to a new temporary file and returns the
2534 * path to the file, or null if the entry is not found.
2537 * @param jarEntryName
2539 * a prefix for the temporary file name, must be at least three
2543 protected String copyJarEntry(jarInputStreamProvider jprovider,
2544 String jarEntryName, String prefix)
2546 BufferedReader in = null;
2547 PrintWriter out = null;
2551 JarInputStream jin = jprovider.getJarInputStream();
2553 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2554 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2555 * FileInputStream(jprovider)); }
2558 JarEntry entry = null;
2561 entry = jin.getNextJarEntry();
2562 } while (entry != null && !entry.getName().equals(jarEntryName));
2565 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
2566 File outFile = File.createTempFile(prefix, ".tmp");
2567 outFile.deleteOnExit();
2568 out = new PrintWriter(new FileOutputStream(outFile));
2571 while ((data = in.readLine()) != null)
2576 String t = outFile.getAbsolutePath();
2581 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
2583 } catch (Exception ex)
2585 ex.printStackTrace();
2593 } catch (IOException e)
2607 private class JvAnnotRow
2609 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2616 * persisted version of annotation row from which to take vis properties
2618 public jalview.datamodel.AlignmentAnnotation template;
2621 * original position of the annotation row in the alignment
2627 * Load alignment frame from jalview XML DOM object
2632 * filename source string
2633 * @param loadTreesAndStructures
2634 * when false only create Viewport
2636 * data source provider
2637 * @return alignment frame created from view stored in DOM
2639 AlignFrame loadFromObject(JalviewModel object, String file,
2640 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
2642 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
2643 Sequence[] vamsasSeq = vamsasSet.getSequence();
2645 JalviewModelSequence jms = object.getJalviewModelSequence();
2647 Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
2650 // ////////////////////////////////
2653 List<SequenceI> hiddenSeqs = null;
2654 jalview.datamodel.Sequence jseq;
2656 List<SequenceI> tmpseqs = new ArrayList<SequenceI>();
2658 boolean multipleView = false;
2660 JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
2661 int vi = 0; // counter in vamsasSeq array
2662 for (int i = 0; i < jseqs.length; i++)
2664 String seqId = jseqs[i].getId();
2666 if (seqRefIds.get(seqId) != null)
2668 tmpseqs.add(seqRefIds.get(seqId));
2669 multipleView = true;
2673 jseq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
2674 vamsasSeq[vi].getSequence());
2675 jseq.setDescription(vamsasSeq[vi].getDescription());
2676 jseq.setStart(jseqs[i].getStart());
2677 jseq.setEnd(jseqs[i].getEnd());
2678 jseq.setVamsasId(uniqueSetSuffix + seqId);
2679 seqRefIds.put(vamsasSeq[vi].getId(), jseq);
2684 if (jseqs[i].getHidden())
2686 if (hiddenSeqs == null)
2688 hiddenSeqs = new ArrayList<SequenceI>();
2691 hiddenSeqs.add(seqRefIds.get(seqId));
2697 // Create the alignment object from the sequence set
2698 // ///////////////////////////////
2699 SequenceI[] orderedSeqs = tmpseqs
2700 .toArray(new SequenceI[tmpseqs.size()]);
2702 Alignment al = new Alignment(orderedSeqs);
2704 // / Add the alignment properties
2705 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
2707 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
2708 al.setProperty(ssp.getKey(), ssp.getValue());
2712 // SequenceFeatures are added to the DatasetSequence,
2713 // so we must create or recover the dataset before loading features
2714 // ///////////////////////////////
2715 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
2717 // older jalview projects do not have a dataset id.
2718 al.setDataset(null);
2722 // recover dataset - passing on flag indicating if this a 'viewless'
2723 // sequence set (a.k.a. a stored dataset for the project)
2724 recoverDatasetFor(vamsasSet, al, object.getJalviewModelSequence()
2725 .getViewportCount() == 0);
2727 // ///////////////////////////////
2729 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
2732 // load sequence features, database references and any associated PDB
2733 // structures for the alignment
2734 for (int i = 0; i < vamsasSeq.length; i++)
2736 if (jseqs[i].getFeaturesCount() > 0)
2738 Features[] features = jseqs[i].getFeatures();
2739 for (int f = 0; f < features.length; f++)
2741 jalview.datamodel.SequenceFeature sf = new jalview.datamodel.SequenceFeature(
2742 features[f].getType(), features[f].getDescription(),
2743 features[f].getStatus(), features[f].getBegin(),
2744 features[f].getEnd(), features[f].getFeatureGroup());
2746 sf.setScore(features[f].getScore());
2747 for (int od = 0; od < features[f].getOtherDataCount(); od++)
2749 OtherData keyValue = features[f].getOtherData(od);
2750 if (keyValue.getKey().startsWith("LINK"))
2752 sf.addLink(keyValue.getValue());
2756 sf.setValue(keyValue.getKey(), keyValue.getValue());
2761 al.getSequenceAt(i).getDatasetSequence().addSequenceFeature(sf);
2764 if (vamsasSeq[i].getDBRefCount() > 0)
2766 addDBRefs(al.getSequenceAt(i).getDatasetSequence(), vamsasSeq[i]);
2768 if (jseqs[i].getPdbidsCount() > 0)
2770 Pdbids[] ids = jseqs[i].getPdbids();
2771 for (int p = 0; p < ids.length; p++)
2773 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
2774 entry.setId(ids[p].getId());
2775 if (ids[p].getType() != null)
2777 if (ids[p].getType().equalsIgnoreCase("PDB"))
2779 entry.setType(PDBEntry.Type.PDB);
2783 entry.setType(PDBEntry.Type.FILE);
2786 if (ids[p].getFile() != null)
2788 if (!pdbloaded.containsKey(ids[p].getFile()))
2790 entry.setFile(loadPDBFile(jprovider, ids[p].getId()));
2794 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
2797 StructureSelectionManager.getStructureSelectionManager(
2798 Desktop.instance).registerPDBEntry(entry);
2799 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
2803 } // end !multipleview
2805 // ///////////////////////////////
2806 // LOAD SEQUENCE MAPPINGS
2808 if (vamsasSet.getAlcodonFrameCount() > 0)
2810 // TODO Potentially this should only be done once for all views of an
2812 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
2813 for (int i = 0; i < alc.length; i++)
2815 AlignedCodonFrame cf = new AlignedCodonFrame();
2816 if (alc[i].getAlcodMapCount() > 0)
2818 AlcodMap[] maps = alc[i].getAlcodMap();
2819 for (int m = 0; m < maps.length; m++)
2821 SequenceI dnaseq = seqRefIds.get(maps[m].getDnasq());
2823 jalview.datamodel.Mapping mapping = null;
2824 // attach to dna sequence reference.
2825 if (maps[m].getMapping() != null)
2827 mapping = addMapping(maps[m].getMapping());
2831 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
2836 frefedSequence.add(new Object[]
2837 { maps[m].getDnasq(), cf, mapping });
2841 al.addCodonFrame(cf);
2845 // ////////////////////////////////
2847 List<JvAnnotRow> autoAlan = new ArrayList<JvAnnotRow>();
2850 * store any annotations which forward reference a group's ID
2852 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<String, List<AlignmentAnnotation>>();
2854 if (vamsasSet.getAnnotationCount() > 0)
2856 Annotation[] an = vamsasSet.getAnnotation();
2858 for (int i = 0; i < an.length; i++)
2860 Annotation annotation = an[i];
2863 * test if annotation is automatically calculated for this view only
2865 boolean autoForView = false;
2866 if (annotation.getLabel().equals("Quality")
2867 || annotation.getLabel().equals("Conservation")
2868 || annotation.getLabel().equals("Consensus"))
2870 // Kludge for pre 2.5 projects which lacked the autocalculated flag
2872 if (!annotation.hasAutoCalculated())
2874 annotation.setAutoCalculated(true);
2878 || (annotation.hasAutoCalculated() && annotation
2879 .isAutoCalculated()))
2881 // remove ID - we don't recover annotation from other views for
2882 // view-specific annotation
2883 annotation.setId(null);
2886 // set visiblity for other annotation in this view
2887 String annotationId = annotation.getId();
2888 if (annotationId != null && annotationIds.containsKey(annotationId))
2890 AlignmentAnnotation jda = annotationIds.get(annotationId);
2891 // in principle Visible should always be true for annotation displayed
2892 // in multiple views
2893 if (annotation.hasVisible())
2895 jda.visible = annotation.getVisible();
2898 al.addAnnotation(jda);
2902 // Construct new annotation from model.
2903 AnnotationElement[] ae = annotation.getAnnotationElement();
2904 jalview.datamodel.Annotation[] anot = null;
2905 java.awt.Color firstColour = null;
2907 if (!annotation.getScoreOnly())
2909 anot = new jalview.datamodel.Annotation[al.getWidth()];
2910 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
2912 anpos = ae[aa].getPosition();
2914 if (anpos >= anot.length)
2919 anot[anpos] = new jalview.datamodel.Annotation(
2921 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
2922 (ae[aa].getSecondaryStructure() == null || ae[aa]
2923 .getSecondaryStructure().length() == 0) ? ' '
2924 : ae[aa].getSecondaryStructure().charAt(0),
2928 // JBPNote: Consider verifying dataflow for IO of secondary
2929 // structure annotation read from Stockholm files
2930 // this was added to try to ensure that
2931 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
2933 // anot[ae[aa].getPosition()].displayCharacter = "";
2935 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
2936 if (firstColour == null)
2938 firstColour = anot[anpos].colour;
2942 jalview.datamodel.AlignmentAnnotation jaa = null;
2944 if (annotation.getGraph())
2946 float llim = 0, hlim = 0;
2947 // if (autoForView || an[i].isAutoCalculated()) {
2950 jaa = new jalview.datamodel.AlignmentAnnotation(
2951 annotation.getLabel(), annotation.getDescription(), anot,
2952 llim, hlim, annotation.getGraphType());
2954 jaa.graphGroup = annotation.getGraphGroup();
2955 jaa._linecolour = firstColour;
2956 if (annotation.getThresholdLine() != null)
2958 jaa.setThreshold(new jalview.datamodel.GraphLine(annotation
2959 .getThresholdLine().getValue(), annotation
2960 .getThresholdLine().getLabel(), new java.awt.Color(
2961 annotation.getThresholdLine().getColour())));
2964 if (autoForView || annotation.isAutoCalculated())
2966 // Hardwire the symbol display line to ensure that labels for
2967 // histograms are displayed
2973 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
2974 an[i].getDescription(), anot);
2975 jaa._linecolour = firstColour;
2977 // register new annotation
2978 if (an[i].getId() != null)
2980 annotationIds.put(an[i].getId(), jaa);
2981 jaa.annotationId = an[i].getId();
2983 // recover sequence association
2984 String sequenceRef = an[i].getSequenceRef();
2985 if (sequenceRef != null)
2987 // from 2.9 sequenceRef is to sequence id (JAL-1781)
2988 SequenceI sequence = seqRefIds.get(sequenceRef);
2989 if (sequence == null)
2991 // in pre-2.9 projects sequence ref is to sequence name
2992 sequence = al.findName(sequenceRef);
2994 if (sequence != null)
2996 jaa.createSequenceMapping(sequence, 1, true);
2997 sequence.addAlignmentAnnotation(jaa);
3000 // and make a note of any group association
3001 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
3003 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3004 .get(an[i].getGroupRef());
3007 aal = new ArrayList<jalview.datamodel.AlignmentAnnotation>();
3008 groupAnnotRefs.put(an[i].getGroupRef(), aal);
3013 if (an[i].hasScore())
3015 jaa.setScore(an[i].getScore());
3017 if (an[i].hasVisible())
3019 jaa.visible = an[i].getVisible();
3022 if (an[i].hasCentreColLabels())
3024 jaa.centreColLabels = an[i].getCentreColLabels();
3027 if (an[i].hasScaleColLabels())
3029 jaa.scaleColLabel = an[i].getScaleColLabels();
3031 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
3033 // newer files have an 'autoCalculated' flag and store calculation
3034 // state in viewport properties
3035 jaa.autoCalculated = true; // means annotation will be marked for
3036 // update at end of load.
3038 if (an[i].hasGraphHeight())
3040 jaa.graphHeight = an[i].getGraphHeight();
3042 if (an[i].hasBelowAlignment())
3044 jaa.belowAlignment = an[i].isBelowAlignment();
3046 jaa.setCalcId(an[i].getCalcId());
3047 if (an[i].getPropertyCount() > 0)
3049 for (jalview.schemabinding.version2.Property prop : an[i]
3052 jaa.setProperty(prop.getName(), prop.getValue());
3055 if (jaa.autoCalculated)
3057 autoAlan.add(new JvAnnotRow(i, jaa));
3060 // if (!autoForView)
3062 // add autocalculated group annotation and any user created annotation
3064 al.addAnnotation(jaa);
3068 // ///////////////////////
3070 // Create alignment markup and styles for this view
3071 if (jms.getJGroupCount() > 0)
3073 JGroup[] groups = jms.getJGroup();
3074 boolean addAnnotSchemeGroup = false;
3075 for (int i = 0; i < groups.length; i++)
3077 JGroup jGroup = groups[i];
3078 ColourSchemeI cs = null;
3079 if (jGroup.getColour() != null)
3081 if (jGroup.getColour().startsWith("ucs"))
3083 cs = getUserColourScheme(jms, jGroup.getColour());
3085 else if (jGroup.getColour().equals("AnnotationColourGradient")
3086 && jGroup.getAnnotationColours() != null)
3088 addAnnotSchemeGroup = true;
3093 cs = ColourSchemeProperty.getColour(al, jGroup.getColour());
3098 cs.setThreshold(jGroup.getPidThreshold(), true);
3102 Vector<SequenceI> seqs = new Vector<SequenceI>();
3104 for (int s = 0; s < jGroup.getSeqCount(); s++)
3106 String seqId = jGroup.getSeq(s) + "";
3107 SequenceI ts = seqRefIds.get(seqId);
3111 seqs.addElement(ts);
3115 if (seqs.size() < 1)
3120 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3121 jGroup.getDisplayBoxes(), jGroup.getDisplayText(),
3122 jGroup.getColourText(), jGroup.getStart(), jGroup.getEnd());
3124 sg.setOutlineColour(new java.awt.Color(jGroup.getOutlineColour()));
3126 sg.textColour = new java.awt.Color(jGroup.getTextCol1());
3127 sg.textColour2 = new java.awt.Color(jGroup.getTextCol2());
3128 sg.setShowNonconserved(jGroup.hasShowUnconserved() ? jGroup
3129 .isShowUnconserved() : false);
3130 sg.thresholdTextColour = jGroup.getTextColThreshold();
3131 if (jGroup.hasShowConsensusHistogram())
3133 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3136 if (jGroup.hasShowSequenceLogo())
3138 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3140 if (jGroup.hasNormaliseSequenceLogo())
3142 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3144 if (jGroup.hasIgnoreGapsinConsensus())
3146 sg.setIgnoreGapsConsensus(jGroup.getIgnoreGapsinConsensus());
3148 if (jGroup.getConsThreshold() != 0)
3150 jalview.analysis.Conservation c = new jalview.analysis.Conservation(
3151 "All", ResidueProperties.propHash, 3,
3152 sg.getSequences(null), 0, sg.getWidth() - 1);
3154 c.verdict(false, 25);
3155 sg.cs.setConservation(c);
3158 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3160 // re-instate unique group/annotation row reference
3161 List<AlignmentAnnotation> jaal = groupAnnotRefs.get(jGroup
3165 for (AlignmentAnnotation jaa : jaal)
3168 if (jaa.autoCalculated)
3170 // match up and try to set group autocalc alignment row for this
3172 if (jaa.label.startsWith("Consensus for "))
3174 sg.setConsensus(jaa);
3176 // match up and try to set group autocalc alignment row for this
3178 if (jaa.label.startsWith("Conservation for "))
3180 sg.setConservationRow(jaa);
3187 if (addAnnotSchemeGroup)
3189 // reconstruct the annotation colourscheme
3190 sg.cs = constructAnnotationColour(jGroup.getAnnotationColours(),
3191 null, al, jms, false);
3197 // only dataset in this model, so just return.
3200 // ///////////////////////////////
3203 // If we just load in the same jar file again, the sequenceSetId
3204 // will be the same, and we end up with multiple references
3205 // to the same sequenceSet. We must modify this id on load
3206 // so that each load of the file gives a unique id
3207 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3208 String viewId = (view.getId() == null ? null : view.getId()
3210 AlignFrame af = null;
3211 AlignViewport av = null;
3212 // now check to see if we really need to create a new viewport.
3213 if (multipleView && viewportsAdded.size() == 0)
3215 // We recovered an alignment for which a viewport already exists.
3216 // TODO: fix up any settings necessary for overlaying stored state onto
3217 // state recovered from another document. (may not be necessary).
3218 // we may need a binding from a viewport in memory to one recovered from
3220 // and then recover its containing af to allow the settings to be applied.
3221 // TODO: fix for vamsas demo
3223 .println("About to recover a viewport for existing alignment: Sequence set ID is "
3225 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3226 if (seqsetobj != null)
3228 if (seqsetobj instanceof String)
3230 uniqueSeqSetId = (String) seqsetobj;
3232 .println("Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
3238 .println("Warning : Collision between sequence set ID string and existing jalview object mapping.");
3244 * indicate that annotation colours are applied across all groups (pre
3245 * Jalview 2.8.1 behaviour)
3247 boolean doGroupAnnColour = isVersionStringLaterThan("2.8.1",
3248 object.getVersion());
3250 AlignmentPanel ap = null;
3251 boolean isnewview = true;
3254 // Check to see if this alignment already has a view id == viewId
3255 jalview.gui.AlignmentPanel views[] = Desktop
3256 .getAlignmentPanels(uniqueSeqSetId);
3257 if (views != null && views.length > 0)
3259 for (int v = 0; v < views.length; v++)
3261 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
3263 // recover the existing alignpanel, alignframe, viewport
3264 af = views[v].alignFrame;
3267 // TODO: could even skip resetting view settings if we don't want to
3268 // change the local settings from other jalview processes
3277 af = loadViewport(file, jseqs, hiddenSeqs, al, jms, view,
3278 uniqueSeqSetId, viewId, autoAlan);
3284 * Load any trees, PDB structures and viewers
3286 * Not done if flag is false (when this method is used for New View)
3288 if (loadTreesAndStructures)
3290 loadTrees(jms, view, af, av, ap);
3291 loadPDBStructures(jprovider, jseqs, af, ap);
3292 loadRnaViewers(jprovider, jseqs, ap);
3294 // and finally return.
3299 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
3300 * panel is restored from separate jar entries, two (gapped and trimmed) per
3301 * sequence and secondary structure.
3303 * Currently each viewer shows just one sequence and structure (gapped and
3304 * trimmed), however this method is designed to support multiple sequences or
3305 * structures in viewers if wanted in future.
3311 private void loadRnaViewers(jarInputStreamProvider jprovider,
3312 JSeq[] jseqs, AlignmentPanel ap)
3315 * scan the sequences for references to viewers; create each one the first
3316 * time it is referenced, add Rna models to existing viewers
3318 for (JSeq jseq : jseqs)
3320 for (int i = 0; i < jseq.getRnaViewerCount(); i++)
3322 RnaViewer viewer = jseq.getRnaViewer(i);
3323 AppVarna appVarna = findOrCreateVarnaViewer(viewer,
3324 uniqueSetSuffix, ap);
3326 for (int j = 0; j < viewer.getSecondaryStructureCount(); j++)
3328 SecondaryStructure ss = viewer.getSecondaryStructure(j);
3329 SequenceI seq = seqRefIds.get(jseq.getId());
3330 AlignmentAnnotation ann = this.annotationIds.get(ss
3331 .getAnnotationId());
3334 * add the structure to the Varna display (with session state copied
3335 * from the jar to a temporary file)
3337 boolean gapped = ss.isGapped();
3338 String rnaTitle = ss.getTitle();
3339 String sessionState = ss.getViewerState();
3340 String tempStateFile = copyJarEntry(jprovider, sessionState,
3342 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
3343 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
3345 appVarna.setInitialSelection(viewer.getSelectedRna());
3351 * Locate and return an already instantiated matching AppVarna, or create one
3355 * @param viewIdSuffix
3359 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
3360 String viewIdSuffix, AlignmentPanel ap)
3363 * on each load a suffix is appended to the saved viewId, to avoid conflicts
3364 * if load is repeated
3366 String postLoadId = viewer.getViewId() + viewIdSuffix;
3367 for (JInternalFrame frame : getAllFrames())
3369 if (frame instanceof AppVarna)
3371 AppVarna varna = (AppVarna) frame;
3372 if (postLoadId.equals(varna.getViewId()))
3374 // this viewer is already instantiated
3375 // could in future here add ap as another 'parent' of the
3376 // AppVarna window; currently just 1-to-many
3383 * viewer not found - make it
3385 RnaViewerModel model = new RnaViewerModel(postLoadId,
3386 viewer.getTitle(), viewer.getXpos(), viewer.getYpos(),
3387 viewer.getWidth(), viewer.getHeight(),
3388 viewer.getDividerLocation());
3389 AppVarna varna = new AppVarna(model, ap);
3395 * Load any saved trees
3403 protected void loadTrees(JalviewModelSequence jms, Viewport view,
3404 AlignFrame af, AlignViewport av, AlignmentPanel ap)
3406 // TODO result of automated refactoring - are all these parameters needed?
3409 for (int t = 0; t < jms.getTreeCount(); t++)
3412 Tree tree = jms.getTree(t);
3414 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
3417 tp = af.ShowNewickTree(
3418 new jalview.io.NewickFile(tree.getNewick()),
3419 tree.getTitle(), tree.getWidth(), tree.getHeight(),
3420 tree.getXpos(), tree.getYpos());
3421 if (tree.getId() != null)
3423 // perhaps bind the tree id to something ?
3428 // update local tree attributes ?
3429 // TODO: should check if tp has been manipulated by user - if so its
3430 // settings shouldn't be modified
3431 tp.setTitle(tree.getTitle());
3432 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(), tree
3433 .getWidth(), tree.getHeight()));
3434 tp.av = av; // af.viewport; // TODO: verify 'associate with all
3437 tp.treeCanvas.av = av; // af.viewport;
3438 tp.treeCanvas.ap = ap; // af.alignPanel;
3443 warn("There was a problem recovering stored Newick tree: \n"
3444 + tree.getNewick());
3448 tp.fitToWindow.setState(tree.getFitToWindow());
3449 tp.fitToWindow_actionPerformed(null);
3451 if (tree.getFontName() != null)
3453 tp.setTreeFont(new java.awt.Font(tree.getFontName(), tree
3454 .getFontStyle(), tree.getFontSize()));
3458 tp.setTreeFont(new java.awt.Font(view.getFontName(), view
3459 .getFontStyle(), tree.getFontSize()));
3462 tp.showPlaceholders(tree.getMarkUnlinked());
3463 tp.showBootstrap(tree.getShowBootstrap());
3464 tp.showDistances(tree.getShowDistances());
3466 tp.treeCanvas.threshold = tree.getThreshold();
3468 if (tree.getCurrentTree())
3470 af.viewport.setCurrentTree(tp.getTree());
3474 } catch (Exception ex)
3476 ex.printStackTrace();
3481 * Load and link any saved structure viewers.
3488 protected void loadPDBStructures(jarInputStreamProvider jprovider,
3489 JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
3492 * Run through all PDB ids on the alignment, and collect mappings between
3493 * distinct view ids and all sequences referring to that view.
3495 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<String, StructureViewerModel>();
3497 for (int i = 0; i < jseqs.length; i++)
3499 if (jseqs[i].getPdbidsCount() > 0)
3501 Pdbids[] ids = jseqs[i].getPdbids();
3502 for (int p = 0; p < ids.length; p++)
3504 final int structureStateCount = ids[p].getStructureStateCount();
3505 for (int s = 0; s < structureStateCount; s++)
3507 // check to see if we haven't already created this structure view
3508 final StructureState structureState = ids[p]
3509 .getStructureState(s);
3510 String sviewid = (structureState.getViewId() == null) ? null
3511 : structureState.getViewId() + uniqueSetSuffix;
3512 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
3513 // Originally : ids[p].getFile()
3514 // : TODO: verify external PDB file recovery still works in normal
3515 // jalview project load
3516 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId()));
3517 jpdb.setId(ids[p].getId());
3519 int x = structureState.getXpos();
3520 int y = structureState.getYpos();
3521 int width = structureState.getWidth();
3522 int height = structureState.getHeight();
3524 // Probably don't need to do this anymore...
3525 // Desktop.desktop.getComponentAt(x, y);
3526 // TODO: NOW: check that this recovers the PDB file correctly.
3527 String pdbFile = loadPDBFile(jprovider, ids[p].getId());
3528 jalview.datamodel.SequenceI seq = seqRefIds.get(jseqs[i]
3530 if (sviewid == null)
3532 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width
3535 if (!structureViewers.containsKey(sviewid))
3537 structureViewers.put(sviewid,
3538 new StructureViewerModel(x, y, width, height, false,
3539 false, true, structureState.getViewId(),
3540 structureState.getType()));
3541 // Legacy pre-2.7 conversion JAL-823 :
3542 // do not assume any view has to be linked for colour by
3546 // assemble String[] { pdb files }, String[] { id for each
3547 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3548 // seqs_file 2}, boolean[] {
3549 // linkAlignPanel,superposeWithAlignpanel}} from hash
3550 StructureViewerModel jmoldat = structureViewers.get(sviewid);
3551 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
3552 | (structureState.hasAlignwithAlignPanel() ? structureState
3553 .getAlignwithAlignPanel() : false));
3556 * Default colour by linked panel to false if not specified (e.g.
3557 * for pre-2.7 projects)
3559 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
3560 colourWithAlignPanel |= (structureState
3561 .hasColourwithAlignPanel() ? structureState
3562 .getColourwithAlignPanel() : false);
3563 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
3566 * Default colour by viewer to true if not specified (e.g. for
3569 boolean colourByViewer = jmoldat.isColourByViewer();
3570 colourByViewer &= structureState.hasColourByJmol() ? structureState
3571 .getColourByJmol() : true;
3572 jmoldat.setColourByViewer(colourByViewer);
3574 if (jmoldat.getStateData().length() < structureState
3575 .getContent().length())
3578 jmoldat.setStateData(structureState.getContent());
3581 if (ids[p].getFile() != null)
3583 File mapkey = new File(ids[p].getFile());
3584 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
3585 if (seqstrmaps == null)
3587 jmoldat.getFileData().put(
3589 seqstrmaps = jmoldat.new StructureData(pdbFile,
3592 if (!seqstrmaps.getSeqList().contains(seq))
3594 seqstrmaps.getSeqList().add(seq);
3600 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");
3607 // Instantiate the associated structure views
3608 for (Entry<String, StructureViewerModel> entry : structureViewers
3613 createOrLinkStructureViewer(entry, af, ap, jprovider);
3614 } catch (Exception e)
3616 System.err.println("Error loading structure viewer: "
3618 // failed - try the next one
3630 protected void createOrLinkStructureViewer(
3631 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3632 AlignmentPanel ap, jarInputStreamProvider jprovider)
3634 final StructureViewerModel stateData = viewerData.getValue();
3637 * Search for any viewer windows already open from other alignment views
3638 * that exactly match the stored structure state
3640 StructureViewerBase comp = findMatchingViewer(viewerData);
3644 linkStructureViewer(ap, comp, stateData);
3649 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
3650 * "viewer_"+stateData.viewId
3652 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
3654 createChimeraViewer(viewerData, af, jprovider);
3659 * else Jmol (if pre-2.9, stateData contains JMOL state string)
3661 createJmolViewer(viewerData, af, jprovider);
3666 * Create a new Chimera viewer.
3672 protected void createChimeraViewer(
3673 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3674 jarInputStreamProvider jprovider)
3676 StructureViewerModel data = viewerData.getValue();
3677 String chimeraSessionFile = data.getStateData();
3680 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
3682 * NB this is the 'saved' viewId as in the project file XML, _not_ the
3683 * 'uniquified' sviewid used to reconstruct the viewer here
3685 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
3686 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
3689 Set<Entry<File, StructureData>> fileData = data.getFileData()
3691 List<PDBEntry> pdbs = new ArrayList<PDBEntry>();
3692 List<SequenceI[]> allseqs = new ArrayList<SequenceI[]>();
3693 for (Entry<File, StructureData> pdb : fileData)
3695 String filePath = pdb.getValue().getFilePath();
3696 String pdbId = pdb.getValue().getPdbId();
3697 // pdbs.add(new PDBEntry(filePath, pdbId));
3698 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
3699 final List<SequenceI> seqList = pdb.getValue().getSeqList();
3700 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
3704 boolean colourByChimera = data.isColourByViewer();
3705 boolean colourBySequence = data.isColourWithAlignPanel();
3707 // TODO use StructureViewer as a factory here, see JAL-1761
3708 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
3709 final SequenceI[][] seqsArray = allseqs.toArray(new SequenceI[allseqs
3711 String newViewId = viewerData.getKey();
3713 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
3714 af.alignPanel, pdbArray, seqsArray, colourByChimera,
3715 colourBySequence, newViewId);
3716 cvf.setSize(data.getWidth(), data.getHeight());
3717 cvf.setLocation(data.getX(), data.getY());
3721 * Create a new Jmol window. First parse the Jmol state to translate filenames
3722 * loaded into the view, and record the order in which files are shown in the
3723 * Jmol view, so we can add the sequence mappings in same order.
3729 protected void createJmolViewer(
3730 final Entry<String, StructureViewerModel> viewerData,
3731 AlignFrame af, jarInputStreamProvider jprovider)
3733 final StructureViewerModel svattrib = viewerData.getValue();
3734 String state = svattrib.getStateData();
3737 * Pre-2.9: state element value is the Jmol state string
3739 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
3742 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
3744 state = readJarEntry(jprovider,
3745 getViewerJarEntryName(svattrib.getViewId()));
3748 List<String> pdbfilenames = new ArrayList<String>();
3749 List<SequenceI[]> seqmaps = new ArrayList<SequenceI[]>();
3750 List<String> pdbids = new ArrayList<String>();
3751 StringBuilder newFileLoc = new StringBuilder(64);
3752 int cp = 0, ncp, ecp;
3753 Map<File, StructureData> oldFiles = svattrib.getFileData();
3754 while ((ncp = state.indexOf("load ", cp)) > -1)
3758 // look for next filename in load statement
3759 newFileLoc.append(state.substring(cp,
3760 ncp = (state.indexOf("\"", ncp + 1) + 1)));
3761 String oldfilenam = state.substring(ncp,
3762 ecp = state.indexOf("\"", ncp));
3763 // recover the new mapping data for this old filename
3764 // have to normalize filename - since Jmol and jalview do
3766 // translation differently.
3767 StructureData filedat = oldFiles.get(new File(oldfilenam));
3768 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
3769 pdbfilenames.add(filedat.getFilePath());
3770 pdbids.add(filedat.getPdbId());
3771 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
3772 newFileLoc.append("\"");
3773 cp = ecp + 1; // advance beyond last \" and set cursor so we can
3774 // look for next file statement.
3775 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
3779 // just append rest of state
3780 newFileLoc.append(state.substring(cp));
3784 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
3785 newFileLoc = new StringBuilder(state);
3786 newFileLoc.append("; load append ");
3787 for (File id : oldFiles.keySet())
3789 // add this and any other pdb files that should be present in
3791 StructureData filedat = oldFiles.get(id);
3792 newFileLoc.append(filedat.getFilePath());
3793 pdbfilenames.add(filedat.getFilePath());
3794 pdbids.add(filedat.getPdbId());
3795 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
3796 newFileLoc.append(" \"");
3797 newFileLoc.append(filedat.getFilePath());
3798 newFileLoc.append("\"");
3801 newFileLoc.append(";");
3804 if (newFileLoc.length() > 0)
3806 int histbug = newFileLoc.indexOf("history = ");
3808 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
3809 String val = (diff == -1) ? null : newFileLoc
3810 .substring(histbug, diff);
3811 if (val != null && val.length() >= 4)
3813 if (val.contains("e"))
3815 if (val.trim().equals("true"))
3823 newFileLoc.replace(histbug, diff, val);
3827 final String[] pdbf = pdbfilenames.toArray(new String[pdbfilenames
3829 final String[] id = pdbids.toArray(new String[pdbids.size()]);
3830 final SequenceI[][] sq = seqmaps
3831 .toArray(new SequenceI[seqmaps.size()][]);
3832 final String fileloc = newFileLoc.toString();
3833 final String sviewid = viewerData.getKey();
3834 final AlignFrame alf = af;
3835 final Rectangle rect = new Rectangle(svattrib.getX(),
3836 svattrib.getY(), svattrib.getWidth(), svattrib.getHeight());
3839 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
3844 JalviewStructureDisplayI sview = null;
3847 sview = new StructureViewer(alf.alignPanel
3848 .getStructureSelectionManager()).createView(
3849 StructureViewer.ViewerType.JMOL, pdbf, id, sq,
3850 alf.alignPanel, svattrib, fileloc, rect, sviewid);
3851 addNewStructureViewer(sview);
3852 } catch (OutOfMemoryError ex)
3854 new OOMWarning("restoring structure view for PDB id " + id,
3855 (OutOfMemoryError) ex.getCause());
3856 if (sview != null && sview.isVisible())
3858 sview.closeViewer(false);
3859 sview.setVisible(false);
3865 } catch (InvocationTargetException ex)
3867 warn("Unexpected error when opening Jmol view.", ex);
3869 } catch (InterruptedException e)
3871 // e.printStackTrace();
3877 * Generates a name for the entry in the project jar file to hold state
3878 * information for a structure viewer
3883 protected String getViewerJarEntryName(String viewId)
3885 return VIEWER_PREFIX + viewId;
3889 * Returns any open frame that matches given structure viewer data. The match
3890 * is based on the unique viewId, or (for older project versions) the frame's
3896 protected StructureViewerBase findMatchingViewer(
3897 Entry<String, StructureViewerModel> viewerData)
3899 final String sviewid = viewerData.getKey();
3900 final StructureViewerModel svattrib = viewerData.getValue();
3901 StructureViewerBase comp = null;
3902 JInternalFrame[] frames = getAllFrames();
3903 for (JInternalFrame frame : frames)
3905 if (frame instanceof StructureViewerBase)
3908 * Post jalview 2.4 schema includes structure view id
3911 && ((StructureViewerBase) frame).getViewId()
3914 comp = (StructureViewerBase) frame;
3915 break; // break added in 2.9
3918 * Otherwise test for matching position and size of viewer frame
3920 else if (frame.getX() == svattrib.getX()
3921 && frame.getY() == svattrib.getY()
3922 && frame.getHeight() == svattrib.getHeight()
3923 && frame.getWidth() == svattrib.getWidth())
3925 comp = (StructureViewerBase) frame;
3926 // no break in faint hope of an exact match on viewId
3934 * Link an AlignmentPanel to an existing structure viewer.
3939 * @param useinViewerSuperpos
3940 * @param usetoColourbyseq
3941 * @param viewerColouring
3943 protected void linkStructureViewer(AlignmentPanel ap,
3944 StructureViewerBase viewer, StructureViewerModel stateData)
3946 // NOTE: if the jalview project is part of a shared session then
3947 // view synchronization should/could be done here.
3949 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
3950 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
3951 final boolean viewerColouring = stateData.isColourByViewer();
3952 Map<File, StructureData> oldFiles = stateData.getFileData();
3955 * Add mapping for sequences in this view to an already open viewer
3957 final AAStructureBindingModel binding = viewer.getBinding();
3958 for (File id : oldFiles.keySet())
3960 // add this and any other pdb files that should be present in the
3962 StructureData filedat = oldFiles.get(id);
3963 String pdbFile = filedat.getFilePath();
3964 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
3965 binding.getSsm().setMapping(seq, null, pdbFile,
3966 jalview.io.AppletFormatAdapter.FILE);
3967 binding.addSequenceForStructFile(pdbFile, seq);
3969 // and add the AlignmentPanel's reference to the view panel
3970 viewer.addAlignmentPanel(ap);
3971 if (useinViewerSuperpos)
3973 viewer.useAlignmentPanelForSuperposition(ap);
3977 viewer.excludeAlignmentPanelForSuperposition(ap);
3979 if (usetoColourbyseq)
3981 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
3985 viewer.excludeAlignmentPanelForColourbyseq(ap);
3990 * Get all frames within the Desktop.
3994 protected JInternalFrame[] getAllFrames()
3996 JInternalFrame[] frames = null;
3997 // TODO is this necessary - is it safe - risk of hanging?
4002 frames = Desktop.desktop.getAllFrames();
4003 } catch (ArrayIndexOutOfBoundsException e)
4005 // occasional No such child exceptions are thrown here...
4009 } catch (InterruptedException f)
4013 } while (frames == null);
4020 * - minimum version we are comparing against
4022 * - version of data being processsed.
4023 * @return true if version is development/null or evaluates to the same or
4024 * later X.Y.Z (where X,Y,Z are like [0-9]+b?[0-9]*)
4026 protected boolean isVersionStringLaterThan(String supported,
4029 if (version == null || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4030 || version.equalsIgnoreCase("Test")
4031 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4033 System.err.println("Assuming project file with "
4034 + (version == null ? "null" : version)
4035 + " is compatible with Jalview version " + supported);
4040 StringTokenizer currentV = new StringTokenizer(supported, "."), fileV = new StringTokenizer(
4042 while (currentV.hasMoreTokens() && fileV.hasMoreTokens())
4044 // convert b to decimal to catch bugfix releases within a series
4045 String curT = currentV.nextToken().toLowerCase().replace('b', '.');
4046 String fileT = fileV.nextToken().toLowerCase().replace('b', '.');
4049 if (Float.valueOf(curT) > Float.valueOf(fileT))
4051 // current version is newer than the version that wrote the file
4054 } catch (NumberFormatException nfe)
4057 .println("** WARNING: Version comparison failed for tokens ("
4061 + ")\n** Current: '"
4062 + supported + "' and Version: '" + version + "'");
4065 if (currentV.hasMoreElements())
4067 // fileV has no minor version but identical series to current
4074 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4076 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4078 if (newStructureViewers != null)
4080 sview.getBinding().setFinishedLoadingFromArchive(false);
4081 newStructureViewers.add(sview);
4085 protected void setLoadingFinishedForNewStructureViewers()
4087 if (newStructureViewers != null)
4089 for (JalviewStructureDisplayI sview : newStructureViewers)
4091 sview.getBinding().setFinishedLoadingFromArchive(true);
4093 newStructureViewers.clear();
4094 newStructureViewers = null;
4098 AlignFrame loadViewport(String file, JSeq[] JSEQ,
4099 List<SequenceI> hiddenSeqs, Alignment al,
4100 JalviewModelSequence jms, Viewport view, String uniqueSeqSetId,
4101 String viewId, List<JvAnnotRow> autoAlan)
4103 AlignFrame af = null;
4104 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
4105 uniqueSeqSetId, viewId);
4107 af.setFileName(file, "Jalview");
4109 for (int i = 0; i < JSEQ.length; i++)
4111 af.viewport.setSequenceColour(af.viewport.getAlignment()
4112 .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour()));
4115 af.viewport.setGatherViewsHere(view.getGatheredViews());
4117 if (view.getSequenceSetId() != null)
4119 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4121 af.viewport.setSequenceSetId(uniqueSeqSetId);
4124 // propagate shared settings to this new view
4125 af.viewport.setHistoryList(av.getHistoryList());
4126 af.viewport.setRedoList(av.getRedoList());
4130 viewportsAdded.put(uniqueSeqSetId, af.viewport);
4132 // TODO: check if this method can be called repeatedly without
4133 // side-effects if alignpanel already registered.
4134 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4136 // apply Hidden regions to view.
4137 if (hiddenSeqs != null)
4139 for (int s = 0; s < JSEQ.length; s++)
4141 jalview.datamodel.SequenceGroup hidden = new jalview.datamodel.SequenceGroup();
4143 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
4146 al.getSequenceAt(JSEQ[s].getHiddenSequences(r)), false);
4148 af.viewport.hideRepSequences(al.getSequenceAt(s), hidden);
4151 // jalview.datamodel.SequenceI[] hseqs = new
4152 // jalview.datamodel.SequenceI[hiddenSeqs
4155 // for (int s = 0; s < hiddenSeqs.size(); s++)
4157 // hseqs[s] = (jalview.datamodel.SequenceI) hiddenSeqs.elementAt(s);
4160 SequenceI[] hseqs = hiddenSeqs.toArray(new SequenceI[hiddenSeqs
4162 af.viewport.hideSequence(hseqs);
4165 // recover view properties and display parameters
4166 if (view.getViewName() != null)
4168 af.viewport.viewName = view.getViewName();
4169 af.setInitialTabVisible();
4171 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
4174 af.viewport.setShowAnnotation(view.getShowAnnotation());
4175 af.viewport.setAbovePIDThreshold(view.getPidSelected());
4177 af.viewport.setColourText(view.getShowColourText());
4179 af.viewport.setConservationSelected(view.getConservationSelected());
4180 af.viewport.setShowJVSuffix(view.getShowFullId());
4181 af.viewport.setRightAlignIds(view.getRightAlignIds());
4182 af.viewport.setFont(
4183 new java.awt.Font(view.getFontName(), view.getFontStyle(), view
4184 .getFontSize()), true);
4185 // TODO: allow custom charWidth/Heights to be restored by updating them
4186 // after setting font - which means set above to false
4187 af.viewport.setRenderGaps(view.getRenderGaps());
4188 af.viewport.setWrapAlignment(view.getWrapAlignment());
4189 af.viewport.setShowAnnotation(view.getShowAnnotation());
4191 af.viewport.setShowBoxes(view.getShowBoxes());
4193 af.viewport.setShowText(view.getShowText());
4195 af.viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
4196 af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
4197 af.viewport.setThresholdTextColour(view.getTextColThreshold());
4198 af.viewport.setShowUnconserved(view.hasShowUnconserved() ? view
4199 .isShowUnconserved() : false);
4200 af.viewport.setStartRes(view.getStartRes());
4201 af.viewport.setStartSeq(view.getStartSeq());
4202 af.alignPanel.updateLayout();
4203 ColourSchemeI cs = null;
4204 // apply colourschemes
4205 if (view.getBgColour() != null)
4207 if (view.getBgColour().startsWith("ucs"))
4209 cs = getUserColourScheme(jms, view.getBgColour());
4211 else if (view.getBgColour().startsWith("Annotation"))
4213 AnnotationColours viewAnnColour = view.getAnnotationColours();
4214 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
4221 cs = ColourSchemeProperty.getColour(al, view.getBgColour());
4226 cs.setThreshold(view.getPidThreshold(), true);
4227 cs.setConsensus(af.viewport.getSequenceConsensusHash());
4231 af.viewport.setGlobalColourScheme(cs);
4232 af.viewport.setColourAppliesToAllGroups(false);
4234 if (view.getConservationSelected() && cs != null)
4236 cs.setConservationInc(view.getConsThreshold());
4239 af.changeColour(cs);
4241 af.viewport.setColourAppliesToAllGroups(true);
4243 af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures());
4245 if (view.hasCentreColumnLabels())
4247 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
4249 if (view.hasIgnoreGapsinConsensus())
4251 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
4254 if (view.hasFollowHighlight())
4256 af.viewport.setFollowHighlight(view.getFollowHighlight());
4258 if (view.hasFollowSelection())
4260 af.viewport.followSelection = view.getFollowSelection();
4262 if (view.hasShowConsensusHistogram())
4264 af.viewport.setShowConsensusHistogram(view
4265 .getShowConsensusHistogram());
4269 af.viewport.setShowConsensusHistogram(true);
4271 if (view.hasShowSequenceLogo())
4273 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
4277 af.viewport.setShowSequenceLogo(false);
4279 if (view.hasNormaliseSequenceLogo())
4281 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
4283 if (view.hasShowDbRefTooltip())
4285 af.viewport.setShowDBRefs(view.getShowDbRefTooltip());
4287 if (view.hasShowNPfeatureTooltip())
4289 af.viewport.setShowNPFeats(view.hasShowNPfeatureTooltip());
4291 if (view.hasShowGroupConsensus())
4293 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
4297 af.viewport.setShowGroupConsensus(false);
4299 if (view.hasShowGroupConservation())
4301 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
4305 af.viewport.setShowGroupConservation(false);
4308 // recover featre settings
4309 if (jms.getFeatureSettings() != null)
4311 FeaturesDisplayed fdi;
4312 af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
4313 String[] renderOrder = new String[jms.getFeatureSettings()
4314 .getSettingCount()];
4315 Hashtable featureGroups = new Hashtable();
4316 Hashtable featureColours = new Hashtable();
4317 Hashtable featureOrder = new Hashtable();
4319 for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
4321 Setting setting = jms.getFeatureSettings().getSetting(fs);
4322 if (setting.hasMincolour())
4324 GraduatedColor gc = setting.hasMin() ? new GraduatedColor(
4325 new java.awt.Color(setting.getMincolour()),
4326 new java.awt.Color(setting.getColour()),
4327 setting.getMin(), setting.getMax()) : new GraduatedColor(
4328 new java.awt.Color(setting.getMincolour()),
4329 new java.awt.Color(setting.getColour()), 0, 1);
4330 if (setting.hasThreshold())
4332 gc.setThresh(setting.getThreshold());
4333 gc.setThreshType(setting.getThreshstate());
4335 gc.setAutoScaled(true); // default
4336 if (setting.hasAutoScale())
4338 gc.setAutoScaled(setting.getAutoScale());
4340 if (setting.hasColourByLabel())
4342 gc.setColourByLabel(setting.getColourByLabel());
4344 // and put in the feature colour table.
4345 featureColours.put(setting.getType(), gc);
4349 featureColours.put(setting.getType(),
4350 new java.awt.Color(setting.getColour()));
4352 renderOrder[fs] = setting.getType();
4353 if (setting.hasOrder())
4355 featureOrder.put(setting.getType(), setting.getOrder());
4359 featureOrder.put(setting.getType(), new Float(fs
4360 / jms.getFeatureSettings().getSettingCount()));
4362 if (setting.getDisplay())
4364 fdi.setVisible(setting.getType());
4367 Hashtable fgtable = new Hashtable();
4368 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
4370 Group grp = jms.getFeatureSettings().getGroup(gs);
4371 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
4373 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4374 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
4375 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
4376 FeatureRendererSettings frs = new FeatureRendererSettings(
4377 renderOrder, fgtable, featureColours, 1.0f, featureOrder);
4378 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
4379 .transferSettings(frs);
4383 if (view.getHiddenColumnsCount() > 0)
4385 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
4387 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(), view
4388 .getHiddenColumns(c).getEnd() // +1
4392 if (view.getCalcIdParam() != null)
4394 for (CalcIdParam calcIdParam : view.getCalcIdParam())
4396 if (calcIdParam != null)
4398 if (recoverCalcIdParam(calcIdParam, af.viewport))
4403 warn("Couldn't recover parameters for "
4404 + calcIdParam.getCalcId());
4409 af.setMenusFromViewport(af.viewport);
4411 // TODO: we don't need to do this if the viewport is aready visible.
4413 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
4414 * has a 'cdna/protein complement' view, in which case save it in order to
4415 * populate a SplitFrame once all views have been read in.
4417 String complementaryViewId = view.getComplementId();
4418 if (complementaryViewId == null)
4420 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
4422 // recompute any autoannotation
4423 af.alignPanel.updateAnnotation(false, true);
4424 reorderAutoannotation(af, al, autoAlan);
4425 af.alignPanel.alignmentChanged();
4429 splitFrameCandidates.put(view, af);
4434 private ColourSchemeI constructAnnotationColour(
4435 AnnotationColours viewAnnColour, AlignFrame af, Alignment al,
4436 JalviewModelSequence jms, boolean checkGroupAnnColour)
4438 boolean propagateAnnColour = false;
4439 ColourSchemeI cs = null;
4440 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
4441 if (checkGroupAnnColour && al.getGroups() != null
4442 && al.getGroups().size() > 0)
4444 // pre 2.8.1 behaviour
4445 // check to see if we should transfer annotation colours
4446 propagateAnnColour = true;
4447 for (jalview.datamodel.SequenceGroup sg : al.getGroups())
4449 if (sg.cs instanceof AnnotationColourGradient)
4451 propagateAnnColour = false;
4455 // int find annotation
4456 if (annAlignment.getAlignmentAnnotation() != null)
4458 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
4460 if (annAlignment.getAlignmentAnnotation()[i].label
4461 .equals(viewAnnColour.getAnnotation()))
4463 if (annAlignment.getAlignmentAnnotation()[i].getThreshold() == null)
4465 annAlignment.getAlignmentAnnotation()[i]
4466 .setThreshold(new jalview.datamodel.GraphLine(
4467 viewAnnColour.getThreshold(), "Threshold",
4468 java.awt.Color.black)
4473 if (viewAnnColour.getColourScheme().equals("None"))
4475 cs = new AnnotationColourGradient(
4476 annAlignment.getAlignmentAnnotation()[i],
4477 new java.awt.Color(viewAnnColour.getMinColour()),
4478 new java.awt.Color(viewAnnColour.getMaxColour()),
4479 viewAnnColour.getAboveThreshold());
4481 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
4483 cs = new AnnotationColourGradient(
4484 annAlignment.getAlignmentAnnotation()[i],
4485 getUserColourScheme(jms,
4486 viewAnnColour.getColourScheme()),
4487 viewAnnColour.getAboveThreshold());
4491 cs = new AnnotationColourGradient(
4492 annAlignment.getAlignmentAnnotation()[i],
4493 ColourSchemeProperty.getColour(al,
4494 viewAnnColour.getColourScheme()),
4495 viewAnnColour.getAboveThreshold());
4497 if (viewAnnColour.hasPerSequence())
4499 ((AnnotationColourGradient) cs).setSeqAssociated(viewAnnColour
4502 if (viewAnnColour.hasPredefinedColours())
4504 ((AnnotationColourGradient) cs)
4505 .setPredefinedColours(viewAnnColour
4506 .isPredefinedColours());
4508 if (propagateAnnColour && al.getGroups() != null)
4510 // Also use these settings for all the groups
4511 for (int g = 0; g < al.getGroups().size(); g++)
4513 jalview.datamodel.SequenceGroup sg = al.getGroups().get(g);
4521 * if (viewAnnColour.getColourScheme().equals("None" )) { sg.cs =
4522 * new AnnotationColourGradient(
4523 * annAlignment.getAlignmentAnnotation()[i], new
4524 * java.awt.Color(viewAnnColour. getMinColour()), new
4525 * java.awt.Color(viewAnnColour. getMaxColour()),
4526 * viewAnnColour.getAboveThreshold()); } else
4529 sg.cs = new AnnotationColourGradient(
4530 annAlignment.getAlignmentAnnotation()[i], sg.cs,
4531 viewAnnColour.getAboveThreshold());
4532 if (cs instanceof AnnotationColourGradient)
4534 if (viewAnnColour.hasPerSequence())
4536 ((AnnotationColourGradient) cs)
4537 .setSeqAssociated(viewAnnColour.isPerSequence());
4539 if (viewAnnColour.hasPredefinedColours())
4541 ((AnnotationColourGradient) cs)
4542 .setPredefinedColours(viewAnnColour
4543 .isPredefinedColours());
4559 private void reorderAutoannotation(AlignFrame af, Alignment al,
4560 List<JvAnnotRow> autoAlan)
4562 // copy over visualization settings for autocalculated annotation in the
4564 if (al.getAlignmentAnnotation() != null)
4567 * Kludge for magic autoannotation names (see JAL-811)
4569 String[] magicNames = new String[]
4570 { "Consensus", "Quality", "Conservation" };
4571 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
4572 Hashtable<String, JvAnnotRow> visan = new Hashtable<String, JvAnnotRow>();
4573 for (String nm : magicNames)
4575 visan.put(nm, nullAnnot);
4577 for (JvAnnotRow auan : autoAlan)
4579 visan.put(auan.template.label
4580 + (auan.template.getCalcId() == null ? "" : "\t"
4581 + auan.template.getCalcId()), auan);
4583 int hSize = al.getAlignmentAnnotation().length;
4584 List<JvAnnotRow> reorder = new ArrayList<JvAnnotRow>();
4585 // work through any autoCalculated annotation already on the view
4586 // removing it if it should be placed in a different location on the
4587 // annotation panel.
4588 List<String> remains = new ArrayList<String>(visan.keySet());
4589 for (int h = 0; h < hSize; h++)
4591 jalview.datamodel.AlignmentAnnotation jalan = al
4592 .getAlignmentAnnotation()[h];
4593 if (jalan.autoCalculated)
4596 JvAnnotRow valan = visan.get(k = jalan.label);
4597 if (jalan.getCalcId() != null)
4599 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
4604 // delete the auto calculated row from the alignment
4605 al.deleteAnnotation(jalan, false);
4609 if (valan != nullAnnot)
4611 if (jalan != valan.template)
4613 // newly created autoannotation row instance
4614 // so keep a reference to the visible annotation row
4615 // and copy over all relevant attributes
4616 if (valan.template.graphHeight >= 0)
4619 jalan.graphHeight = valan.template.graphHeight;
4621 jalan.visible = valan.template.visible;
4623 reorder.add(new JvAnnotRow(valan.order, jalan));
4628 // Add any (possibly stale) autocalculated rows that were not appended to
4629 // the view during construction
4630 for (String other : remains)
4632 JvAnnotRow othera = visan.get(other);
4633 if (othera != nullAnnot && othera.template.getCalcId() != null
4634 && othera.template.getCalcId().length() > 0)
4636 reorder.add(othera);
4639 // now put the automatic annotation in its correct place
4640 int s = 0, srt[] = new int[reorder.size()];
4641 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
4642 for (JvAnnotRow jvar : reorder)
4645 srt[s++] = jvar.order;
4648 jalview.util.QuickSort.sort(srt, rws);
4649 // and re-insert the annotation at its correct position
4650 for (JvAnnotRow jvar : rws)
4652 al.addAnnotation(jvar.template, jvar.order);
4654 af.alignPanel.adjustAnnotationHeight();
4658 Hashtable skipList = null;
4661 * TODO remove this method
4664 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
4665 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
4666 * throw new Error("Implementation Error. No skipList defined for this
4667 * Jalview2XML instance."); } return (AlignFrame)
4668 * skipList.get(view.getSequenceSetId()); }
4672 * Check if the Jalview view contained in object should be skipped or not.
4675 * @return true if view's sequenceSetId is a key in skipList
4677 private boolean skipViewport(JalviewModel object)
4679 if (skipList == null)
4684 if (skipList.containsKey(id = object.getJalviewModelSequence()
4685 .getViewport()[0].getSequenceSetId()))
4687 if (Cache.log != null && Cache.log.isDebugEnabled())
4689 Cache.log.debug("Skipping seuqence set id " + id);
4696 public void addToSkipList(AlignFrame af)
4698 if (skipList == null)
4700 skipList = new Hashtable();
4702 skipList.put(af.getViewport().getSequenceSetId(), af);
4705 public void clearSkipList()
4707 if (skipList != null)
4714 private void recoverDatasetFor(SequenceSet vamsasSet, Alignment al,
4715 boolean ignoreUnrefed)
4717 jalview.datamodel.Alignment ds = getDatasetFor(vamsasSet.getDatasetId());
4718 Vector dseqs = null;
4721 // create a list of new dataset sequences
4722 dseqs = new Vector();
4724 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
4726 Sequence vamsasSeq = vamsasSet.getSequence(i);
4727 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed);
4729 // create a new dataset
4732 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
4733 dseqs.copyInto(dsseqs);
4734 ds = new jalview.datamodel.Alignment(dsseqs);
4735 debug("Created new dataset " + vamsasSet.getDatasetId()
4736 + " for alignment " + System.identityHashCode(al));
4737 addDatasetRef(vamsasSet.getDatasetId(), ds);
4739 // set the dataset for the newly imported alignment.
4740 if (al.getDataset() == null && !ignoreUnrefed)
4749 * sequence definition to create/merge dataset sequence for
4753 * vector to add new dataset sequence to
4755 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
4756 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed)
4758 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
4760 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
4761 SequenceI dsq = null;
4762 if (sq != null && sq.getDatasetSequence() != null)
4764 dsq = sq.getDatasetSequence();
4766 if (sq == null && ignoreUnrefed)
4770 String sqid = vamsasSeq.getDsseqid();
4773 // need to create or add a new dataset sequence reference to this sequence
4776 dsq = seqRefIds.get(sqid);
4781 // make a new dataset sequence
4782 dsq = sq.createDatasetSequence();
4785 // make up a new dataset reference for this sequence
4786 sqid = seqHash(dsq);
4788 dsq.setVamsasId(uniqueSetSuffix + sqid);
4789 seqRefIds.put(sqid, dsq);
4794 dseqs.addElement(dsq);
4799 ds.addSequence(dsq);
4805 { // make this dataset sequence sq's dataset sequence
4806 sq.setDatasetSequence(dsq);
4807 // and update the current dataset alignment
4812 if (!dseqs.contains(dsq))
4819 if (ds.findIndex(dsq) < 0)
4821 ds.addSequence(dsq);
4828 // TODO: refactor this as a merge dataset sequence function
4829 // now check that sq (the dataset sequence) sequence really is the union of
4830 // all references to it
4831 // boolean pre = sq.getStart() < dsq.getStart();
4832 // boolean post = sq.getEnd() > dsq.getEnd();
4836 // StringBuffer sb = new StringBuffer();
4837 String newres = jalview.analysis.AlignSeq.extractGaps(
4838 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
4839 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
4840 && newres.length() > dsq.getLength())
4842 // Update with the longer sequence.
4846 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
4847 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
4848 * sb.append(newres.substring(newres.length() - sq.getEnd() -
4849 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
4851 dsq.setSequence(newres);
4853 // TODO: merges will never happen if we 'know' we have the real dataset
4854 // sequence - this should be detected when id==dssid
4856 .println("DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
4857 // + (pre ? "prepended" : "") + " "
4858 // + (post ? "appended" : ""));
4864 * TODO use AlignmentI here and in related methods - needs
4865 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
4867 Hashtable<String, Alignment> datasetIds = null;
4869 IdentityHashMap<Alignment, String> dataset2Ids = null;
4871 private Alignment getDatasetFor(String datasetId)
4873 if (datasetIds == null)
4875 datasetIds = new Hashtable<String, Alignment>();
4878 if (datasetIds.containsKey(datasetId))
4880 return datasetIds.get(datasetId);
4885 private void addDatasetRef(String datasetId, Alignment dataset)
4887 if (datasetIds == null)
4889 datasetIds = new Hashtable<String, Alignment>();
4891 datasetIds.put(datasetId, dataset);
4895 * make a new dataset ID for this jalview dataset alignment
4900 private String getDatasetIdRef(Alignment dataset)
4902 if (dataset.getDataset() != null)
4904 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
4906 String datasetId = makeHashCode(dataset, null);
4907 if (datasetId == null)
4909 // make a new datasetId and record it
4910 if (dataset2Ids == null)
4912 dataset2Ids = new IdentityHashMap<Alignment, String>();
4916 datasetId = dataset2Ids.get(dataset);
4918 if (datasetId == null)
4920 datasetId = "ds" + dataset2Ids.size() + 1;
4921 dataset2Ids.put(dataset, datasetId);
4927 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
4929 for (int d = 0; d < sequence.getDBRefCount(); d++)
4931 DBRef dr = sequence.getDBRef(d);
4932 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
4933 sequence.getDBRef(d).getSource(), sequence.getDBRef(d)
4934 .getVersion(), sequence.getDBRef(d).getAccessionId());
4935 if (dr.getMapping() != null)
4937 entry.setMap(addMapping(dr.getMapping()));
4939 datasetSequence.addDBRef(entry);
4943 private jalview.datamodel.Mapping addMapping(Mapping m)
4945 SequenceI dsto = null;
4946 // Mapping m = dr.getMapping();
4947 int fr[] = new int[m.getMapListFromCount() * 2];
4948 Enumeration f = m.enumerateMapListFrom();
4949 for (int _i = 0; f.hasMoreElements(); _i += 2)
4951 MapListFrom mf = (MapListFrom) f.nextElement();
4952 fr[_i] = mf.getStart();
4953 fr[_i + 1] = mf.getEnd();
4955 int fto[] = new int[m.getMapListToCount() * 2];
4956 f = m.enumerateMapListTo();
4957 for (int _i = 0; f.hasMoreElements(); _i += 2)
4959 MapListTo mf = (MapListTo) f.nextElement();
4960 fto[_i] = mf.getStart();
4961 fto[_i + 1] = mf.getEnd();
4963 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto,
4964 fr, fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
4965 if (m.getMappingChoice() != null)
4967 MappingChoice mc = m.getMappingChoice();
4968 if (mc.getDseqFor() != null)
4970 String dsfor = "" + mc.getDseqFor();
4971 if (seqRefIds.containsKey(dsfor))
4976 jmap.setTo(seqRefIds.get(dsfor));
4980 frefedSequence.add(new Object[]
4987 * local sequence definition
4989 Sequence ms = mc.getSequence();
4990 SequenceI djs = null;
4991 String sqid = ms.getDsseqid();
4992 if (sqid != null && sqid.length() > 0)
4995 * recover dataset sequence
4997 djs = seqRefIds.get(sqid);
5002 .println("Warning - making up dataset sequence id for DbRef sequence map reference");
5003 sqid = ((Object) ms).toString(); // make up a new hascode for
5004 // undefined dataset sequence hash
5005 // (unlikely to happen)
5011 * make a new dataset sequence and add it to refIds hash
5013 djs = new jalview.datamodel.Sequence(ms.getName(),
5015 djs.setStart(jmap.getMap().getToLowest());
5016 djs.setEnd(jmap.getMap().getToHighest());
5017 djs.setVamsasId(uniqueSetSuffix + sqid);
5019 seqRefIds.put(sqid, djs);
5022 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5031 public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
5032 boolean keepSeqRefs)
5035 JalviewModel jm = saveState(ap, null, null, null);
5040 jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
5044 uniqueSetSuffix = "";
5045 jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
5050 if (this.frefedSequence == null)
5052 frefedSequence = new Vector();
5055 viewportsAdded.clear();
5057 AlignFrame af = loadFromObject(jm, null, false, null);
5058 af.alignPanels.clear();
5059 af.closeMenuItem_actionPerformed(true);
5062 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5063 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5064 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5065 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5066 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5069 return af.alignPanel;
5073 * flag indicating if hashtables should be cleared on finalization TODO this
5074 * flag may not be necessary
5076 private final boolean _cleartables = true;
5078 private Hashtable jvids2vobj;
5083 * @see java.lang.Object#finalize()
5086 protected void finalize() throws Throwable
5088 // really make sure we have no buried refs left.
5093 this.seqRefIds = null;
5094 this.seqsToIds = null;
5098 private void warn(String msg)
5103 private void warn(String msg, Exception e)
5105 if (Cache.log != null)
5109 Cache.log.warn(msg, e);
5113 Cache.log.warn(msg);
5118 System.err.println("Warning: " + msg);
5121 e.printStackTrace();
5126 private void debug(String string)
5128 debug(string, null);
5131 private void debug(String msg, Exception e)
5133 if (Cache.log != null)
5137 Cache.log.debug(msg, e);
5141 Cache.log.debug(msg);
5146 System.err.println("Warning: " + msg);
5149 e.printStackTrace();
5155 * set the object to ID mapping tables used to write/recover objects and XML
5156 * ID strings for the jalview project. If external tables are provided then
5157 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
5158 * object goes out of scope. - also populates the datasetIds hashtable with
5159 * alignment objects containing dataset sequences
5162 * Map from ID strings to jalview datamodel
5164 * Map from jalview datamodel to ID strings
5168 public void setObjectMappingTables(Hashtable vobj2jv,
5169 IdentityHashMap jv2vobj)
5171 this.jv2vobj = jv2vobj;
5172 this.vobj2jv = vobj2jv;
5173 Iterator ds = jv2vobj.keySet().iterator();
5175 while (ds.hasNext())
5177 Object jvobj = ds.next();
5178 id = jv2vobj.get(jvobj).toString();
5179 if (jvobj instanceof jalview.datamodel.Alignment)
5181 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
5183 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
5186 else if (jvobj instanceof jalview.datamodel.Sequence)
5188 // register sequence object so the XML parser can recover it.
5189 if (seqRefIds == null)
5191 seqRefIds = new HashMap<String, SequenceI>();
5193 if (seqsToIds == null)
5195 seqsToIds = new IdentityHashMap<SequenceI, String>();
5197 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
5198 seqsToIds.put((SequenceI) jvobj, id);
5200 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
5203 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
5204 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
5205 if (jvann.annotationId == null)
5207 jvann.annotationId = anid;
5209 if (!jvann.annotationId.equals(anid))
5211 // TODO verify that this is the correct behaviour
5212 this.warn("Overriding Annotation ID for " + anid
5213 + " from different id : " + jvann.annotationId);
5214 jvann.annotationId = anid;
5217 else if (jvobj instanceof String)
5219 if (jvids2vobj == null)
5221 jvids2vobj = new Hashtable();
5222 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
5227 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
5233 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
5234 * objects created from the project archive. If string is null (default for
5235 * construction) then suffix will be set automatically.
5239 public void setUniqueSetSuffix(String string)
5241 uniqueSetSuffix = string;
5246 * uses skipList2 as the skipList for skipping views on sequence sets
5247 * associated with keys in the skipList
5251 public void setSkipList(Hashtable skipList2)
5253 skipList = skipList2;
5257 * Reads the jar entry of given name and returns its contents, or null if the
5258 * entry is not found.
5261 * @param jarEntryName
5264 protected String readJarEntry(jarInputStreamProvider jprovider,
5265 String jarEntryName)
5267 String result = null;
5268 BufferedReader in = null;
5273 * Reopen the jar input stream and traverse its entries to find a matching
5276 JarInputStream jin = jprovider.getJarInputStream();
5277 JarEntry entry = null;
5280 entry = jin.getNextJarEntry();
5281 } while (entry != null && !entry.getName().equals(jarEntryName));
5285 StringBuilder out = new StringBuilder(256);
5286 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
5289 while ((data = in.readLine()) != null)
5293 result = out.toString();
5297 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
5299 } catch (Exception ex)
5301 ex.printStackTrace();
5309 } catch (IOException e)
5320 * Returns an incrementing counter (0, 1, 2...)
5324 private synchronized int nextCounter()