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.getAllPDBEntries() != null)
781 Enumeration en = jdatasq.getAllPDBEntries().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 if (Desktop.desktop == null)
1374 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1375 for (int f = frames.length - 1; f > -1; f--)
1377 if (frames[f] instanceof AppVarna)
1379 AppVarna varna = (AppVarna) frames[f];
1381 * link the sequence to every viewer that is showing it and is linked to
1382 * its alignment panel
1384 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1386 String viewId = varna.getViewId();
1387 RnaViewer rna = new RnaViewer();
1388 rna.setViewId(viewId);
1389 rna.setTitle(varna.getTitle());
1390 rna.setXpos(varna.getX());
1391 rna.setYpos(varna.getY());
1392 rna.setWidth(varna.getWidth());
1393 rna.setHeight(varna.getHeight());
1394 rna.setDividerLocation(varna.getDividerLocation());
1395 rna.setSelectedRna(varna.getSelectedIndex());
1396 jseq.addRnaViewer(rna);
1399 * Store each Varna panel's state once in the project per sequence.
1400 * First time through only (storeDataset==false)
1402 // boolean storeSessions = false;
1403 // String sequenceViewId = viewId + seqsToIds.get(jds);
1404 // if (!storeDataset && !viewIds.contains(sequenceViewId))
1406 // viewIds.add(sequenceViewId);
1407 // storeSessions = true;
1409 for (RnaModel model : varna.getModels())
1411 if (model.seq == jds)
1414 * VARNA saves each view (sequence or alignment secondary
1415 * structure, gapped or trimmed) as a separate XML file
1417 String jarEntryName = rnaSessions.get(model);
1418 if (jarEntryName == null)
1421 String varnaStateFile = varna.getStateInfo(model.rna);
1422 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
1423 copyFileToJar(jout, varnaStateFile, jarEntryName);
1424 rnaSessions.put(model, jarEntryName);
1426 SecondaryStructure ss = new SecondaryStructure();
1427 String annotationId = varna.getAnnotation(jds).annotationId;
1428 ss.setAnnotationId(annotationId);
1429 ss.setViewerState(jarEntryName);
1430 ss.setGapped(model.gapped);
1431 ss.setTitle(model.title);
1432 rna.addSecondaryStructure(ss);
1441 * Copy the contents of a file to a new entry added to the output jar
1445 * @param jarEntryName
1447 protected void copyFileToJar(JarOutputStream jout, String infilePath,
1448 String jarEntryName)
1450 DataInputStream dis = null;
1453 File file = new File(infilePath);
1454 if (file.exists() && jout != null)
1456 dis = new DataInputStream(new FileInputStream(file));
1457 byte[] data = new byte[(int) file.length()];
1458 dis.readFully(data);
1459 writeJarEntry(jout, jarEntryName, data);
1461 } catch (Exception ex)
1463 ex.printStackTrace();
1471 } catch (IOException e)
1480 * Write the data to a new entry of given name in the output jar file
1483 * @param jarEntryName
1485 * @throws IOException
1487 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
1488 byte[] data) throws IOException
1492 System.out.println("Writing jar entry " + jarEntryName);
1493 jout.putNextEntry(new JarEntry(jarEntryName));
1494 DataOutputStream dout = new DataOutputStream(jout);
1495 dout.write(data, 0, data.length);
1502 * Save the state of a structure viewer
1507 * the archive XML element under which to save the state
1510 * @param matchedFile
1514 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
1515 Pdbids pdb, PDBEntry entry, List<String> viewIds,
1516 String matchedFile, StructureViewerBase viewFrame)
1518 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
1521 * Look for any bindings for this viewer to the PDB file of interest
1522 * (including part matches excluding chain id)
1524 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
1526 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
1527 final String pdbId = pdbentry.getId();
1528 if (!pdbId.equals(entry.getId())
1529 && !(entry.getId().length() > 4 && entry.getId()
1530 .toLowerCase().startsWith(pdbId.toLowerCase())))
1533 * not interested in a binding to a different PDB entry here
1537 if (matchedFile == null)
1539 matchedFile = pdbentry.getFile();
1541 else if (!matchedFile.equals(pdbentry.getFile()))
1544 .warn("Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
1545 + pdbentry.getFile());
1549 // can get at it if the ID
1550 // match is ambiguous (e.g.
1553 for (int smap = 0; smap < viewFrame.getBinding().getSequence()[peid].length; smap++)
1555 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
1556 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
1558 StructureState state = new StructureState();
1559 state.setVisible(true);
1560 state.setXpos(viewFrame.getX());
1561 state.setYpos(viewFrame.getY());
1562 state.setWidth(viewFrame.getWidth());
1563 state.setHeight(viewFrame.getHeight());
1564 final String viewId = viewFrame.getViewId();
1565 state.setViewId(viewId);
1566 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
1567 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
1568 state.setColourByJmol(viewFrame.isColouredByViewer());
1569 state.setType(viewFrame.getViewerType().toString());
1570 pdb.addStructureState(state);
1577 private AnnotationColours constructAnnotationColours(
1578 AnnotationColourGradient acg, List<UserColourScheme> userColours,
1579 JalviewModelSequence jms)
1581 AnnotationColours ac = new AnnotationColours();
1582 ac.setAboveThreshold(acg.getAboveThreshold());
1583 ac.setThreshold(acg.getAnnotationThreshold());
1584 ac.setAnnotation(acg.getAnnotation());
1585 if (acg.getBaseColour() instanceof jalview.schemes.UserColourScheme)
1587 ac.setColourScheme(setUserColourScheme(acg.getBaseColour(),
1592 ac.setColourScheme(ColourSchemeProperty.getColourName(acg
1596 ac.setMaxColour(acg.getMaxColour().getRGB());
1597 ac.setMinColour(acg.getMinColour().getRGB());
1598 ac.setPerSequence(acg.isSeqAssociated());
1599 ac.setPredefinedColours(acg.isPredefinedColours());
1603 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
1604 IdentityHashMap<SequenceGroup, String> groupRefs,
1605 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
1606 SequenceSet vamsasSet)
1609 for (int i = 0; i < aa.length; i++)
1611 Annotation an = new Annotation();
1613 AlignmentAnnotation annotation = aa[i];
1614 if (annotation.annotationId != null)
1616 annotationIds.put(annotation.annotationId, annotation);
1619 an.setId(annotation.annotationId);
1621 an.setVisible(annotation.visible);
1623 an.setDescription(annotation.description);
1625 if (annotation.sequenceRef != null)
1627 // 2.9 JAL-1781 xref on sequence id rather than name
1628 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
1630 if (annotation.groupRef != null)
1632 String groupIdr = groupRefs.get(annotation.groupRef);
1633 if (groupIdr == null)
1635 // make a locally unique String
1637 annotation.groupRef,
1638 groupIdr = ("" + System.currentTimeMillis()
1639 + annotation.groupRef.getName() + groupRefs
1642 an.setGroupRef(groupIdr.toString());
1645 // store all visualization attributes for annotation
1646 an.setGraphHeight(annotation.graphHeight);
1647 an.setCentreColLabels(annotation.centreColLabels);
1648 an.setScaleColLabels(annotation.scaleColLabel);
1649 an.setShowAllColLabels(annotation.showAllColLabels);
1650 an.setBelowAlignment(annotation.belowAlignment);
1652 if (annotation.graph > 0)
1655 an.setGraphType(annotation.graph);
1656 an.setGraphGroup(annotation.graphGroup);
1657 if (annotation.getThreshold() != null)
1659 ThresholdLine line = new ThresholdLine();
1660 line.setLabel(annotation.getThreshold().label);
1661 line.setValue(annotation.getThreshold().value);
1662 line.setColour(annotation.getThreshold().colour.getRGB());
1663 an.setThresholdLine(line);
1671 an.setLabel(annotation.label);
1673 if (annotation == av.getAlignmentQualityAnnot()
1674 || annotation == av.getAlignmentConservationAnnotation()
1675 || annotation == av.getAlignmentConsensusAnnotation()
1676 || annotation.autoCalculated)
1678 // new way of indicating autocalculated annotation -
1679 an.setAutoCalculated(annotation.autoCalculated);
1681 if (annotation.hasScore())
1683 an.setScore(annotation.getScore());
1686 if (annotation.getCalcId() != null)
1688 calcIdSet.add(annotation.getCalcId());
1689 an.setCalcId(annotation.getCalcId());
1691 if (annotation.hasProperties())
1693 for (String pr : annotation.getProperties())
1695 Property prop = new Property();
1697 prop.setValue(annotation.getProperty(pr));
1698 an.addProperty(prop);
1702 AnnotationElement ae;
1703 if (annotation.annotations != null)
1705 an.setScoreOnly(false);
1706 for (int a = 0; a < annotation.annotations.length; a++)
1708 if ((annotation == null) || (annotation.annotations[a] == null))
1713 ae = new AnnotationElement();
1714 if (annotation.annotations[a].description != null)
1716 ae.setDescription(annotation.annotations[a].description);
1718 if (annotation.annotations[a].displayCharacter != null)
1720 ae.setDisplayCharacter(annotation.annotations[a].displayCharacter);
1723 if (!Float.isNaN(annotation.annotations[a].value))
1725 ae.setValue(annotation.annotations[a].value);
1729 if (annotation.annotations[a].secondaryStructure > ' ')
1731 ae.setSecondaryStructure(annotation.annotations[a].secondaryStructure
1735 if (annotation.annotations[a].colour != null
1736 && annotation.annotations[a].colour != java.awt.Color.black)
1738 ae.setColour(annotation.annotations[a].colour.getRGB());
1741 an.addAnnotationElement(ae);
1742 if (annotation.autoCalculated)
1744 // only write one non-null entry into the annotation row -
1745 // sufficient to get the visualization attributes necessary to
1753 an.setScoreOnly(true);
1755 if (!storeDS || (storeDS && !annotation.autoCalculated))
1757 // skip autocalculated annotation - these are only provided for
1759 vamsasSet.addAnnotation(an);
1765 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
1767 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
1768 if (settings != null)
1770 CalcIdParam vCalcIdParam = new CalcIdParam();
1771 vCalcIdParam.setCalcId(calcId);
1772 vCalcIdParam.addServiceURL(settings.getServiceURI());
1773 // generic URI allowing a third party to resolve another instance of the
1774 // service used for this calculation
1775 for (String urls : settings.getServiceURLs())
1777 vCalcIdParam.addServiceURL(urls);
1779 vCalcIdParam.setVersion("1.0");
1780 if (settings.getPreset() != null)
1782 WsParamSetI setting = settings.getPreset();
1783 vCalcIdParam.setName(setting.getName());
1784 vCalcIdParam.setDescription(setting.getDescription());
1788 vCalcIdParam.setName("");
1789 vCalcIdParam.setDescription("Last used parameters");
1791 // need to be able to recover 1) settings 2) user-defined presets or
1792 // recreate settings from preset 3) predefined settings provided by
1793 // service - or settings that can be transferred (or discarded)
1794 vCalcIdParam.setParameters(settings.getWsParamFile().replace("\n",
1796 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
1797 // todo - decide if updateImmediately is needed for any projects.
1799 return vCalcIdParam;
1804 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
1807 if (calcIdParam.getVersion().equals("1.0"))
1809 Jws2Instance service = Jws2Discoverer.getDiscoverer()
1810 .getPreferredServiceFor(calcIdParam.getServiceURL());
1811 if (service != null)
1813 WsParamSetI parmSet = null;
1816 parmSet = service.getParamStore().parseServiceParameterFile(
1817 calcIdParam.getName(), calcIdParam.getDescription(),
1818 calcIdParam.getServiceURL(),
1819 calcIdParam.getParameters().replace("|\\n|", "\n"));
1820 } catch (IOException x)
1822 warn("Couldn't parse parameter data for "
1823 + calcIdParam.getCalcId(), x);
1826 List<ArgumentI> argList = null;
1827 if (calcIdParam.getName().length() > 0)
1829 parmSet = service.getParamStore()
1830 .getPreset(calcIdParam.getName());
1831 if (parmSet != null)
1833 // TODO : check we have a good match with settings in AACon -
1834 // otherwise we'll need to create a new preset
1839 argList = parmSet.getArguments();
1842 AAConSettings settings = new AAConSettings(
1843 calcIdParam.isAutoUpdate(), service, parmSet, argList);
1844 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
1845 calcIdParam.isNeedsUpdate());
1850 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
1854 throw new Error(MessageManager.formatMessage(
1855 "error.unsupported_version_calcIdparam", new Object[]
1856 { calcIdParam.toString() }));
1860 * External mapping between jalview objects and objects yielding a valid and
1861 * unique object ID string. This is null for normal Jalview project IO, but
1862 * non-null when a jalview project is being read or written as part of a
1865 IdentityHashMap jv2vobj = null;
1868 * Construct a unique ID for jvobj using either existing bindings or if none
1869 * exist, the result of the hashcode call for the object.
1872 * jalview data object
1873 * @return unique ID for referring to jvobj
1875 private String makeHashCode(Object jvobj, String altCode)
1877 if (jv2vobj != null)
1879 Object id = jv2vobj.get(jvobj);
1882 return id.toString();
1884 // check string ID mappings
1885 if (jvids2vobj != null && jvobj instanceof String)
1887 id = jvids2vobj.get(jvobj);
1891 return id.toString();
1893 // give up and warn that something has gone wrong
1894 warn("Cannot find ID for object in external mapping : " + jvobj);
1900 * return local jalview object mapped to ID, if it exists
1904 * @return null or object bound to idcode
1906 private Object retrieveExistingObj(String idcode)
1908 if (idcode != null && vobj2jv != null)
1910 return vobj2jv.get(idcode);
1916 * binding from ID strings from external mapping table to jalview data model
1919 private Hashtable vobj2jv;
1921 private Sequence createVamsasSequence(String id, SequenceI jds)
1923 return createVamsasSequence(true, id, jds, null);
1926 private Sequence createVamsasSequence(boolean recurse, String id,
1927 SequenceI jds, SequenceI parentseq)
1929 Sequence vamsasSeq = new Sequence();
1930 vamsasSeq.setId(id);
1931 vamsasSeq.setName(jds.getName());
1932 vamsasSeq.setSequence(jds.getSequenceAsString());
1933 vamsasSeq.setDescription(jds.getDescription());
1934 jalview.datamodel.DBRefEntry[] dbrefs = null;
1935 if (jds.getDatasetSequence() != null)
1937 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
1938 if (jds.getDatasetSequence().getDBRef() != null)
1940 dbrefs = jds.getDatasetSequence().getDBRef();
1945 vamsasSeq.setDsseqid(id); // so we can tell which sequences really are
1946 // dataset sequences only
1947 dbrefs = jds.getDBRef();
1951 for (int d = 0; d < dbrefs.length; d++)
1953 DBRef dbref = new DBRef();
1954 dbref.setSource(dbrefs[d].getSource());
1955 dbref.setVersion(dbrefs[d].getVersion());
1956 dbref.setAccessionId(dbrefs[d].getAccessionId());
1957 if (dbrefs[d].hasMap())
1959 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
1961 dbref.setMapping(mp);
1963 vamsasSeq.addDBRef(dbref);
1969 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
1970 SequenceI parentseq, SequenceI jds, boolean recurse)
1973 if (jmp.getMap() != null)
1977 jalview.util.MapList mlst = jmp.getMap();
1978 List<int[]> r = mlst.getFromRanges();
1979 for (int[] range : r)
1981 MapListFrom mfrom = new MapListFrom();
1982 mfrom.setStart(range[0]);
1983 mfrom.setEnd(range[1]);
1984 mp.addMapListFrom(mfrom);
1986 r = mlst.getToRanges();
1987 for (int[] range : r)
1989 MapListTo mto = new MapListTo();
1990 mto.setStart(range[0]);
1991 mto.setEnd(range[1]);
1992 mp.addMapListTo(mto);
1994 mp.setMapFromUnit(mlst.getFromRatio());
1995 mp.setMapToUnit(mlst.getToRatio());
1996 if (jmp.getTo() != null)
1998 MappingChoice mpc = new MappingChoice();
2000 && (parentseq != jmp.getTo() || parentseq
2001 .getDatasetSequence() != jmp.getTo()))
2003 mpc.setSequence(createVamsasSequence(false, seqHash(jmp.getTo()),
2009 SequenceI ps = null;
2010 if (parentseq != jmp.getTo()
2011 && parentseq.getDatasetSequence() != jmp.getTo())
2013 // chaining dbref rather than a handshaking one
2014 jmpid = seqHash(ps = jmp.getTo());
2018 jmpid = seqHash(ps = parentseq);
2020 mpc.setDseqFor(jmpid);
2021 if (!seqRefIds.containsKey(mpc.getDseqFor()))
2023 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2024 seqRefIds.put(mpc.getDseqFor(), ps);
2028 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2031 mp.setMappingChoice(mpc);
2037 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2038 List<UserColourScheme> userColours, JalviewModelSequence jms)
2041 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2042 boolean newucs = false;
2043 if (!userColours.contains(ucs))
2045 userColours.add(ucs);
2048 id = "ucs" + userColours.indexOf(ucs);
2051 // actually create the scheme's entry in the XML model
2052 java.awt.Color[] colours = ucs.getColours();
2053 jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
2054 jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
2056 for (int i = 0; i < colours.length; i++)
2058 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2059 col.setName(ResidueProperties.aa[i]);
2060 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2061 jbucs.addColour(col);
2063 if (ucs.getLowerCaseColours() != null)
2065 colours = ucs.getLowerCaseColours();
2066 for (int i = 0; i < colours.length; i++)
2068 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2069 col.setName(ResidueProperties.aa[i].toLowerCase());
2070 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2071 jbucs.addColour(col);
2076 uc.setUserColourScheme(jbucs);
2077 jms.addUserColours(uc);
2083 jalview.schemes.UserColourScheme getUserColourScheme(
2084 JalviewModelSequence jms, String id)
2086 UserColours[] uc = jms.getUserColours();
2087 UserColours colours = null;
2089 for (int i = 0; i < uc.length; i++)
2091 if (uc[i].getId().equals(id))
2099 java.awt.Color[] newColours = new java.awt.Color[24];
2101 for (int i = 0; i < 24; i++)
2103 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2104 .getUserColourScheme().getColour(i).getRGB(), 16));
2107 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2110 if (colours.getUserColourScheme().getColourCount() > 24)
2112 newColours = new java.awt.Color[23];
2113 for (int i = 0; i < 23; i++)
2115 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2116 .getUserColourScheme().getColour(i + 24).getRGB(), 16));
2118 ucs.setLowerCaseColours(newColours);
2125 * contains last error message (if any) encountered by XML loader.
2127 String errorMessage = null;
2130 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2131 * exceptions are raised during project XML parsing
2133 public boolean attemptversion1parse = true;
2136 * Load a jalview project archive from a jar file
2139 * - HTTP URL or filename
2141 public AlignFrame loadJalviewAlign(final String file)
2144 jalview.gui.AlignFrame af = null;
2148 // create list to store references for any new Jmol viewers created
2149 newStructureViewers = new Vector<JalviewStructureDisplayI>();
2150 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2151 // Workaround is to make sure caller implements the JarInputStreamProvider
2153 // so we can re-open the jar input stream for each entry.
2155 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2156 af = loadJalviewAlign(jprovider);
2158 } catch (MalformedURLException e)
2160 errorMessage = "Invalid URL format for '" + file + "'";
2166 SwingUtilities.invokeAndWait(new Runnable()
2170 setLoadingFinishedForNewStructureViewers();
2173 } catch (Exception x)
2175 System.err.println("Error loading alignment: " + x.getMessage());
2181 private jarInputStreamProvider createjarInputStreamProvider(
2182 final String file) throws MalformedURLException
2185 errorMessage = null;
2186 uniqueSetSuffix = null;
2188 viewportsAdded.clear();
2189 frefedSequence = null;
2191 if (file.startsWith("http://"))
2193 url = new URL(file);
2195 final URL _url = url;
2196 return new jarInputStreamProvider()
2200 public JarInputStream getJarInputStream() throws IOException
2204 return new JarInputStream(_url.openStream());
2208 return new JarInputStream(new FileInputStream(file));
2213 public String getFilename()
2221 * Recover jalview session from a jalview project archive. Caller may
2222 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2223 * themselves. Any null fields will be initialised with default values,
2224 * non-null fields are left alone.
2229 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2231 errorMessage = null;
2232 if (uniqueSetSuffix == null)
2234 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2236 if (seqRefIds == null)
2238 seqRefIds = new HashMap<String, SequenceI>();
2240 if (frefedSequence == null)
2242 frefedSequence = new Vector();
2245 AlignFrame af = null, _af = null;
2246 Map<String, AlignFrame> gatherToThisFrame = new HashMap<String, AlignFrame>();
2247 final String file = jprovider.getFilename();
2250 JarInputStream jin = null;
2251 JarEntry jarentry = null;
2256 jin = jprovider.getJarInputStream();
2257 for (int i = 0; i < entryCount; i++)
2259 jarentry = jin.getNextJarEntry();
2262 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2264 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2265 JalviewModel object = new JalviewModel();
2267 Unmarshaller unmar = new Unmarshaller(object);
2268 unmar.setValidation(false);
2269 object = (JalviewModel) unmar.unmarshal(in);
2270 if (true) // !skipViewport(object))
2272 _af = loadFromObject(object, file, true, jprovider);
2273 if (object.getJalviewModelSequence().getViewportCount() > 0)
2276 if (af.viewport.isGatherViewsHere())
2278 gatherToThisFrame.put(af.viewport.getSequenceSetId(), af);
2284 else if (jarentry != null)
2286 // Some other file here.
2289 } while (jarentry != null);
2290 resolveFrefedSequences();
2291 } catch (IOException ex)
2293 ex.printStackTrace();
2294 errorMessage = "Couldn't locate Jalview XML file : " + file;
2295 System.err.println("Exception whilst loading jalview XML file : "
2297 } catch (Exception ex)
2299 System.err.println("Parsing as Jalview Version 2 file failed.");
2300 ex.printStackTrace(System.err);
2301 if (attemptversion1parse)
2303 // Is Version 1 Jar file?
2306 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
2307 } catch (Exception ex2)
2309 System.err.println("Exception whilst loading as jalviewXMLV1:");
2310 ex2.printStackTrace();
2314 if (Desktop.instance != null)
2316 Desktop.instance.stopLoading();
2320 System.out.println("Successfully loaded archive file");
2323 ex.printStackTrace();
2325 System.err.println("Exception whilst loading jalview XML file : "
2327 } catch (OutOfMemoryError e)
2329 // Don't use the OOM Window here
2330 errorMessage = "Out of memory loading jalview XML file";
2331 System.err.println("Out of memory whilst loading jalview XML file");
2332 e.printStackTrace();
2335 if (Desktop.instance != null)
2337 Desktop.instance.stopLoading();
2341 * Regather multiple views (with the same sequence set id) to the frame (if
2342 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2343 * views instead of separate frames. Note this doesn't restore a state where
2344 * some expanded views in turn have tabbed views - the last "first tab" read
2345 * in will play the role of gatherer for all.
2347 for (AlignFrame fr : gatherToThisFrame.values())
2349 Desktop.instance.gatherViews(fr);
2352 restoreSplitFrames();
2354 if (errorMessage != null)
2362 * Try to reconstruct and display SplitFrame windows, where each contains
2363 * complementary dna and protein alignments. Done by pairing up AlignFrame
2364 * objects (created earlier) which have complementary viewport ids associated.
2366 protected void restoreSplitFrames()
2368 List<SplitFrame> gatherTo = new ArrayList<SplitFrame>();
2369 List<AlignFrame> addedToSplitFrames = new ArrayList<AlignFrame>();
2370 Map<String, AlignFrame> dna = new HashMap<String, AlignFrame>();
2373 * Identify the DNA alignments
2375 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2378 AlignFrame af = candidate.getValue();
2379 if (af.getViewport().getAlignment().isNucleotide())
2381 dna.put(candidate.getKey().getId(), af);
2386 * Try to match up the protein complements
2388 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2391 AlignFrame af = candidate.getValue();
2392 if (!af.getViewport().getAlignment().isNucleotide())
2394 String complementId = candidate.getKey().getComplementId();
2395 // only non-null complements should be in the Map
2396 if (complementId != null && dna.containsKey(complementId))
2398 final AlignFrame dnaFrame = dna.get(complementId);
2399 SplitFrame sf = createSplitFrame(dnaFrame, af);
2400 addedToSplitFrames.add(dnaFrame);
2401 addedToSplitFrames.add(af);
2402 if (af.viewport.isGatherViewsHere())
2411 * Open any that we failed to pair up (which shouldn't happen!) as
2412 * standalone AlignFrame's.
2414 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2417 AlignFrame af = candidate.getValue();
2418 if (!addedToSplitFrames.contains(af))
2420 Viewport view = candidate.getKey();
2421 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
2423 System.err.println("Failed to restore view " + view.getTitle()
2424 + " to split frame");
2429 * Gather back into tabbed views as flagged.
2431 for (SplitFrame sf : gatherTo)
2433 Desktop.instance.gatherViews(sf);
2436 splitFrameCandidates.clear();
2440 * Construct and display one SplitFrame holding DNA and protein alignments.
2443 * @param proteinFrame
2446 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
2447 AlignFrame proteinFrame)
2449 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
2450 String title = MessageManager.getString("label.linked_view_title");
2451 int width = (int) dnaFrame.getBounds().getWidth();
2452 int height = (int) (dnaFrame.getBounds().getHeight()
2453 + proteinFrame.getBounds().getHeight() + 50);
2454 Desktop.addInternalFrame(splitFrame, title, width, height);
2457 * And compute cDNA consensus (couldn't do earlier with consensus as
2458 * mappings were not yet present)
2460 proteinFrame.viewport.alignmentChanged(proteinFrame.alignPanel);
2466 * check errorMessage for a valid error message and raise an error box in the
2467 * GUI or write the current errorMessage to stderr and then clear the error
2470 protected void reportErrors()
2472 reportErrors(false);
2475 protected void reportErrors(final boolean saving)
2477 if (errorMessage != null)
2479 final String finalErrorMessage = errorMessage;
2482 javax.swing.SwingUtilities.invokeLater(new Runnable()
2487 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2488 finalErrorMessage, "Error "
2489 + (saving ? "saving" : "loading")
2490 + " Jalview file", JOptionPane.WARNING_MESSAGE);
2496 System.err.println("Problem loading Jalview file: " + errorMessage);
2499 errorMessage = null;
2502 Map<String, String> alreadyLoadedPDB = new HashMap<String, String>();
2505 * when set, local views will be updated from view stored in JalviewXML
2506 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2507 * sync if this is set to true.
2509 private final boolean updateLocalViews = false;
2512 * Returns the path to a temporary file holding the PDB file for the given PDB
2513 * id. The first time of asking, searches for a file of that name in the
2514 * Jalview project jar, and copies it to a new temporary file. Any repeat
2515 * requests just return the path to the file previously created.
2521 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId)
2523 if (alreadyLoadedPDB.containsKey(pdbId))
2525 return alreadyLoadedPDB.get(pdbId).toString();
2528 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb");
2529 if (tempFile != null)
2531 alreadyLoadedPDB.put(pdbId, tempFile);
2537 * Copies the jar entry of given name to a new temporary file and returns the
2538 * path to the file, or null if the entry is not found.
2541 * @param jarEntryName
2543 * a prefix for the temporary file name, must be at least three
2547 protected String copyJarEntry(jarInputStreamProvider jprovider,
2548 String jarEntryName, String prefix)
2550 BufferedReader in = null;
2551 PrintWriter out = null;
2555 JarInputStream jin = jprovider.getJarInputStream();
2557 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2558 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2559 * FileInputStream(jprovider)); }
2562 JarEntry entry = null;
2565 entry = jin.getNextJarEntry();
2566 } while (entry != null && !entry.getName().equals(jarEntryName));
2569 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
2570 File outFile = File.createTempFile(prefix, ".tmp");
2571 outFile.deleteOnExit();
2572 out = new PrintWriter(new FileOutputStream(outFile));
2575 while ((data = in.readLine()) != null)
2580 String t = outFile.getAbsolutePath();
2585 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
2587 } catch (Exception ex)
2589 ex.printStackTrace();
2597 } catch (IOException e)
2611 private class JvAnnotRow
2613 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2620 * persisted version of annotation row from which to take vis properties
2622 public jalview.datamodel.AlignmentAnnotation template;
2625 * original position of the annotation row in the alignment
2631 * Load alignment frame from jalview XML DOM object
2636 * filename source string
2637 * @param loadTreesAndStructures
2638 * when false only create Viewport
2640 * data source provider
2641 * @return alignment frame created from view stored in DOM
2643 AlignFrame loadFromObject(JalviewModel object, String file,
2644 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
2646 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
2647 Sequence[] vamsasSeq = vamsasSet.getSequence();
2649 JalviewModelSequence jms = object.getJalviewModelSequence();
2651 Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
2654 // ////////////////////////////////
2657 List<SequenceI> hiddenSeqs = null;
2658 jalview.datamodel.Sequence jseq;
2660 List<SequenceI> tmpseqs = new ArrayList<SequenceI>();
2662 boolean multipleView = false;
2664 JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
2665 int vi = 0; // counter in vamsasSeq array
2666 for (int i = 0; i < jseqs.length; i++)
2668 String seqId = jseqs[i].getId();
2670 if (seqRefIds.get(seqId) != null)
2672 tmpseqs.add(seqRefIds.get(seqId));
2673 multipleView = true;
2677 jseq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
2678 vamsasSeq[vi].getSequence());
2679 jseq.setDescription(vamsasSeq[vi].getDescription());
2680 jseq.setStart(jseqs[i].getStart());
2681 jseq.setEnd(jseqs[i].getEnd());
2682 jseq.setVamsasId(uniqueSetSuffix + seqId);
2683 seqRefIds.put(vamsasSeq[vi].getId(), jseq);
2688 if (jseqs[i].getHidden())
2690 if (hiddenSeqs == null)
2692 hiddenSeqs = new ArrayList<SequenceI>();
2695 hiddenSeqs.add(seqRefIds.get(seqId));
2701 // Create the alignment object from the sequence set
2702 // ///////////////////////////////
2703 SequenceI[] orderedSeqs = tmpseqs
2704 .toArray(new SequenceI[tmpseqs.size()]);
2706 Alignment al = new Alignment(orderedSeqs);
2708 // / Add the alignment properties
2709 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
2711 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
2712 al.setProperty(ssp.getKey(), ssp.getValue());
2716 // SequenceFeatures are added to the DatasetSequence,
2717 // so we must create or recover the dataset before loading features
2718 // ///////////////////////////////
2719 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
2721 // older jalview projects do not have a dataset id.
2722 al.setDataset(null);
2726 // recover dataset - passing on flag indicating if this a 'viewless'
2727 // sequence set (a.k.a. a stored dataset for the project)
2728 recoverDatasetFor(vamsasSet, al, object.getJalviewModelSequence()
2729 .getViewportCount() == 0);
2731 // ///////////////////////////////
2733 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
2736 // load sequence features, database references and any associated PDB
2737 // structures for the alignment
2738 for (int i = 0; i < vamsasSeq.length; i++)
2740 if (jseqs[i].getFeaturesCount() > 0)
2742 Features[] features = jseqs[i].getFeatures();
2743 for (int f = 0; f < features.length; f++)
2745 jalview.datamodel.SequenceFeature sf = new jalview.datamodel.SequenceFeature(
2746 features[f].getType(), features[f].getDescription(),
2747 features[f].getStatus(), features[f].getBegin(),
2748 features[f].getEnd(), features[f].getFeatureGroup());
2750 sf.setScore(features[f].getScore());
2751 for (int od = 0; od < features[f].getOtherDataCount(); od++)
2753 OtherData keyValue = features[f].getOtherData(od);
2754 if (keyValue.getKey().startsWith("LINK"))
2756 sf.addLink(keyValue.getValue());
2760 sf.setValue(keyValue.getKey(), keyValue.getValue());
2765 al.getSequenceAt(i).getDatasetSequence().addSequenceFeature(sf);
2768 if (vamsasSeq[i].getDBRefCount() > 0)
2770 addDBRefs(al.getSequenceAt(i).getDatasetSequence(), vamsasSeq[i]);
2772 if (jseqs[i].getPdbidsCount() > 0)
2774 Pdbids[] ids = jseqs[i].getPdbids();
2775 for (int p = 0; p < ids.length; p++)
2777 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
2778 entry.setId(ids[p].getId());
2779 if (ids[p].getType() != null)
2781 if (ids[p].getType().equalsIgnoreCase("PDB"))
2783 entry.setType(PDBEntry.Type.PDB);
2787 entry.setType(PDBEntry.Type.FILE);
2790 if (ids[p].getFile() != null)
2792 if (!pdbloaded.containsKey(ids[p].getFile()))
2794 entry.setFile(loadPDBFile(jprovider, ids[p].getId()));
2798 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
2801 StructureSelectionManager.getStructureSelectionManager(
2802 Desktop.instance).registerPDBEntry(entry);
2803 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
2807 } // end !multipleview
2809 // ///////////////////////////////
2810 // LOAD SEQUENCE MAPPINGS
2812 if (vamsasSet.getAlcodonFrameCount() > 0)
2814 // TODO Potentially this should only be done once for all views of an
2816 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
2817 for (int i = 0; i < alc.length; i++)
2819 AlignedCodonFrame cf = new AlignedCodonFrame();
2820 if (alc[i].getAlcodMapCount() > 0)
2822 AlcodMap[] maps = alc[i].getAlcodMap();
2823 for (int m = 0; m < maps.length; m++)
2825 SequenceI dnaseq = seqRefIds.get(maps[m].getDnasq());
2827 jalview.datamodel.Mapping mapping = null;
2828 // attach to dna sequence reference.
2829 if (maps[m].getMapping() != null)
2831 mapping = addMapping(maps[m].getMapping());
2835 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
2840 frefedSequence.add(new Object[]
2841 { maps[m].getDnasq(), cf, mapping });
2845 al.addCodonFrame(cf);
2849 // ////////////////////////////////
2851 List<JvAnnotRow> autoAlan = new ArrayList<JvAnnotRow>();
2854 * store any annotations which forward reference a group's ID
2856 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<String, List<AlignmentAnnotation>>();
2858 if (vamsasSet.getAnnotationCount() > 0)
2860 Annotation[] an = vamsasSet.getAnnotation();
2862 for (int i = 0; i < an.length; i++)
2864 Annotation annotation = an[i];
2867 * test if annotation is automatically calculated for this view only
2869 boolean autoForView = false;
2870 if (annotation.getLabel().equals("Quality")
2871 || annotation.getLabel().equals("Conservation")
2872 || annotation.getLabel().equals("Consensus"))
2874 // Kludge for pre 2.5 projects which lacked the autocalculated flag
2876 if (!annotation.hasAutoCalculated())
2878 annotation.setAutoCalculated(true);
2882 || (annotation.hasAutoCalculated() && annotation
2883 .isAutoCalculated()))
2885 // remove ID - we don't recover annotation from other views for
2886 // view-specific annotation
2887 annotation.setId(null);
2890 // set visiblity for other annotation in this view
2891 String annotationId = annotation.getId();
2892 if (annotationId != null && annotationIds.containsKey(annotationId))
2894 AlignmentAnnotation jda = annotationIds.get(annotationId);
2895 // in principle Visible should always be true for annotation displayed
2896 // in multiple views
2897 if (annotation.hasVisible())
2899 jda.visible = annotation.getVisible();
2902 al.addAnnotation(jda);
2906 // Construct new annotation from model.
2907 AnnotationElement[] ae = annotation.getAnnotationElement();
2908 jalview.datamodel.Annotation[] anot = null;
2909 java.awt.Color firstColour = null;
2911 if (!annotation.getScoreOnly())
2913 anot = new jalview.datamodel.Annotation[al.getWidth()];
2914 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
2916 anpos = ae[aa].getPosition();
2918 if (anpos >= anot.length)
2923 anot[anpos] = new jalview.datamodel.Annotation(
2925 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
2926 (ae[aa].getSecondaryStructure() == null || ae[aa]
2927 .getSecondaryStructure().length() == 0) ? ' '
2928 : ae[aa].getSecondaryStructure().charAt(0),
2932 // JBPNote: Consider verifying dataflow for IO of secondary
2933 // structure annotation read from Stockholm files
2934 // this was added to try to ensure that
2935 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
2937 // anot[ae[aa].getPosition()].displayCharacter = "";
2939 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
2940 if (firstColour == null)
2942 firstColour = anot[anpos].colour;
2946 jalview.datamodel.AlignmentAnnotation jaa = null;
2948 if (annotation.getGraph())
2950 float llim = 0, hlim = 0;
2951 // if (autoForView || an[i].isAutoCalculated()) {
2954 jaa = new jalview.datamodel.AlignmentAnnotation(
2955 annotation.getLabel(), annotation.getDescription(), anot,
2956 llim, hlim, annotation.getGraphType());
2958 jaa.graphGroup = annotation.getGraphGroup();
2959 jaa._linecolour = firstColour;
2960 if (annotation.getThresholdLine() != null)
2962 jaa.setThreshold(new jalview.datamodel.GraphLine(annotation
2963 .getThresholdLine().getValue(), annotation
2964 .getThresholdLine().getLabel(), new java.awt.Color(
2965 annotation.getThresholdLine().getColour())));
2968 if (autoForView || annotation.isAutoCalculated())
2970 // Hardwire the symbol display line to ensure that labels for
2971 // histograms are displayed
2977 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
2978 an[i].getDescription(), anot);
2979 jaa._linecolour = firstColour;
2981 // register new annotation
2982 if (an[i].getId() != null)
2984 annotationIds.put(an[i].getId(), jaa);
2985 jaa.annotationId = an[i].getId();
2987 // recover sequence association
2988 String sequenceRef = an[i].getSequenceRef();
2989 if (sequenceRef != null)
2991 // from 2.9 sequenceRef is to sequence id (JAL-1781)
2992 SequenceI sequence = seqRefIds.get(sequenceRef);
2993 if (sequence == null)
2995 // in pre-2.9 projects sequence ref is to sequence name
2996 sequence = al.findName(sequenceRef);
2998 if (sequence != null)
3000 jaa.createSequenceMapping(sequence, 1, true);
3001 sequence.addAlignmentAnnotation(jaa);
3004 // and make a note of any group association
3005 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
3007 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3008 .get(an[i].getGroupRef());
3011 aal = new ArrayList<jalview.datamodel.AlignmentAnnotation>();
3012 groupAnnotRefs.put(an[i].getGroupRef(), aal);
3017 if (an[i].hasScore())
3019 jaa.setScore(an[i].getScore());
3021 if (an[i].hasVisible())
3023 jaa.visible = an[i].getVisible();
3026 if (an[i].hasCentreColLabels())
3028 jaa.centreColLabels = an[i].getCentreColLabels();
3031 if (an[i].hasScaleColLabels())
3033 jaa.scaleColLabel = an[i].getScaleColLabels();
3035 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
3037 // newer files have an 'autoCalculated' flag and store calculation
3038 // state in viewport properties
3039 jaa.autoCalculated = true; // means annotation will be marked for
3040 // update at end of load.
3042 if (an[i].hasGraphHeight())
3044 jaa.graphHeight = an[i].getGraphHeight();
3046 if (an[i].hasBelowAlignment())
3048 jaa.belowAlignment = an[i].isBelowAlignment();
3050 jaa.setCalcId(an[i].getCalcId());
3051 if (an[i].getPropertyCount() > 0)
3053 for (jalview.schemabinding.version2.Property prop : an[i]
3056 jaa.setProperty(prop.getName(), prop.getValue());
3059 if (jaa.autoCalculated)
3061 autoAlan.add(new JvAnnotRow(i, jaa));
3064 // if (!autoForView)
3066 // add autocalculated group annotation and any user created annotation
3068 al.addAnnotation(jaa);
3072 // ///////////////////////
3074 // Create alignment markup and styles for this view
3075 if (jms.getJGroupCount() > 0)
3077 JGroup[] groups = jms.getJGroup();
3078 boolean addAnnotSchemeGroup = false;
3079 for (int i = 0; i < groups.length; i++)
3081 JGroup jGroup = groups[i];
3082 ColourSchemeI cs = null;
3083 if (jGroup.getColour() != null)
3085 if (jGroup.getColour().startsWith("ucs"))
3087 cs = getUserColourScheme(jms, jGroup.getColour());
3089 else if (jGroup.getColour().equals("AnnotationColourGradient")
3090 && jGroup.getAnnotationColours() != null)
3092 addAnnotSchemeGroup = true;
3097 cs = ColourSchemeProperty.getColour(al, jGroup.getColour());
3102 cs.setThreshold(jGroup.getPidThreshold(), true);
3106 Vector<SequenceI> seqs = new Vector<SequenceI>();
3108 for (int s = 0; s < jGroup.getSeqCount(); s++)
3110 String seqId = jGroup.getSeq(s) + "";
3111 SequenceI ts = seqRefIds.get(seqId);
3115 seqs.addElement(ts);
3119 if (seqs.size() < 1)
3124 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3125 jGroup.getDisplayBoxes(), jGroup.getDisplayText(),
3126 jGroup.getColourText(), jGroup.getStart(), jGroup.getEnd());
3128 sg.setOutlineColour(new java.awt.Color(jGroup.getOutlineColour()));
3130 sg.textColour = new java.awt.Color(jGroup.getTextCol1());
3131 sg.textColour2 = new java.awt.Color(jGroup.getTextCol2());
3132 sg.setShowNonconserved(jGroup.hasShowUnconserved() ? jGroup
3133 .isShowUnconserved() : false);
3134 sg.thresholdTextColour = jGroup.getTextColThreshold();
3135 if (jGroup.hasShowConsensusHistogram())
3137 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3140 if (jGroup.hasShowSequenceLogo())
3142 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3144 if (jGroup.hasNormaliseSequenceLogo())
3146 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3148 if (jGroup.hasIgnoreGapsinConsensus())
3150 sg.setIgnoreGapsConsensus(jGroup.getIgnoreGapsinConsensus());
3152 if (jGroup.getConsThreshold() != 0)
3154 jalview.analysis.Conservation c = new jalview.analysis.Conservation(
3155 "All", ResidueProperties.propHash, 3,
3156 sg.getSequences(null), 0, sg.getWidth() - 1);
3158 c.verdict(false, 25);
3159 sg.cs.setConservation(c);
3162 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3164 // re-instate unique group/annotation row reference
3165 List<AlignmentAnnotation> jaal = groupAnnotRefs.get(jGroup
3169 for (AlignmentAnnotation jaa : jaal)
3172 if (jaa.autoCalculated)
3174 // match up and try to set group autocalc alignment row for this
3176 if (jaa.label.startsWith("Consensus for "))
3178 sg.setConsensus(jaa);
3180 // match up and try to set group autocalc alignment row for this
3182 if (jaa.label.startsWith("Conservation for "))
3184 sg.setConservationRow(jaa);
3191 if (addAnnotSchemeGroup)
3193 // reconstruct the annotation colourscheme
3194 sg.cs = constructAnnotationColour(jGroup.getAnnotationColours(),
3195 null, al, jms, false);
3201 // only dataset in this model, so just return.
3204 // ///////////////////////////////
3207 // If we just load in the same jar file again, the sequenceSetId
3208 // will be the same, and we end up with multiple references
3209 // to the same sequenceSet. We must modify this id on load
3210 // so that each load of the file gives a unique id
3211 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3212 String viewId = (view.getId() == null ? null : view.getId()
3214 AlignFrame af = null;
3215 AlignViewport av = null;
3216 // now check to see if we really need to create a new viewport.
3217 if (multipleView && viewportsAdded.size() == 0)
3219 // We recovered an alignment for which a viewport already exists.
3220 // TODO: fix up any settings necessary for overlaying stored state onto
3221 // state recovered from another document. (may not be necessary).
3222 // we may need a binding from a viewport in memory to one recovered from
3224 // and then recover its containing af to allow the settings to be applied.
3225 // TODO: fix for vamsas demo
3227 .println("About to recover a viewport for existing alignment: Sequence set ID is "
3229 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3230 if (seqsetobj != null)
3232 if (seqsetobj instanceof String)
3234 uniqueSeqSetId = (String) seqsetobj;
3236 .println("Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
3242 .println("Warning : Collision between sequence set ID string and existing jalview object mapping.");
3248 * indicate that annotation colours are applied across all groups (pre
3249 * Jalview 2.8.1 behaviour)
3251 boolean doGroupAnnColour = isVersionStringLaterThan("2.8.1",
3252 object.getVersion());
3254 AlignmentPanel ap = null;
3255 boolean isnewview = true;
3258 // Check to see if this alignment already has a view id == viewId
3259 jalview.gui.AlignmentPanel views[] = Desktop
3260 .getAlignmentPanels(uniqueSeqSetId);
3261 if (views != null && views.length > 0)
3263 for (int v = 0; v < views.length; v++)
3265 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
3267 // recover the existing alignpanel, alignframe, viewport
3268 af = views[v].alignFrame;
3271 // TODO: could even skip resetting view settings if we don't want to
3272 // change the local settings from other jalview processes
3281 af = loadViewport(file, jseqs, hiddenSeqs, al, jms, view,
3282 uniqueSeqSetId, viewId, autoAlan);
3288 * Load any trees, PDB structures and viewers
3290 * Not done if flag is false (when this method is used for New View)
3292 if (loadTreesAndStructures)
3294 loadTrees(jms, view, af, av, ap);
3295 loadPDBStructures(jprovider, jseqs, af, ap);
3296 loadRnaViewers(jprovider, jseqs, ap);
3298 // and finally return.
3303 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
3304 * panel is restored from separate jar entries, two (gapped and trimmed) per
3305 * sequence and secondary structure.
3307 * Currently each viewer shows just one sequence and structure (gapped and
3308 * trimmed), however this method is designed to support multiple sequences or
3309 * structures in viewers if wanted in future.
3315 private void loadRnaViewers(jarInputStreamProvider jprovider,
3316 JSeq[] jseqs, AlignmentPanel ap)
3319 * scan the sequences for references to viewers; create each one the first
3320 * time it is referenced, add Rna models to existing viewers
3322 for (JSeq jseq : jseqs)
3324 for (int i = 0; i < jseq.getRnaViewerCount(); i++)
3326 RnaViewer viewer = jseq.getRnaViewer(i);
3327 AppVarna appVarna = findOrCreateVarnaViewer(viewer,
3328 uniqueSetSuffix, ap);
3330 for (int j = 0; j < viewer.getSecondaryStructureCount(); j++)
3332 SecondaryStructure ss = viewer.getSecondaryStructure(j);
3333 SequenceI seq = seqRefIds.get(jseq.getId());
3334 AlignmentAnnotation ann = this.annotationIds.get(ss
3335 .getAnnotationId());
3338 * add the structure to the Varna display (with session state copied
3339 * from the jar to a temporary file)
3341 boolean gapped = ss.isGapped();
3342 String rnaTitle = ss.getTitle();
3343 String sessionState = ss.getViewerState();
3344 String tempStateFile = copyJarEntry(jprovider, sessionState,
3346 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
3347 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
3349 appVarna.setInitialSelection(viewer.getSelectedRna());
3355 * Locate and return an already instantiated matching AppVarna, or create one
3359 * @param viewIdSuffix
3363 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
3364 String viewIdSuffix, AlignmentPanel ap)
3367 * on each load a suffix is appended to the saved viewId, to avoid conflicts
3368 * if load is repeated
3370 String postLoadId = viewer.getViewId() + viewIdSuffix;
3371 for (JInternalFrame frame : getAllFrames())
3373 if (frame instanceof AppVarna)
3375 AppVarna varna = (AppVarna) frame;
3376 if (postLoadId.equals(varna.getViewId()))
3378 // this viewer is already instantiated
3379 // could in future here add ap as another 'parent' of the
3380 // AppVarna window; currently just 1-to-many
3387 * viewer not found - make it
3389 RnaViewerModel model = new RnaViewerModel(postLoadId,
3390 viewer.getTitle(), viewer.getXpos(), viewer.getYpos(),
3391 viewer.getWidth(), viewer.getHeight(),
3392 viewer.getDividerLocation());
3393 AppVarna varna = new AppVarna(model, ap);
3399 * Load any saved trees
3407 protected void loadTrees(JalviewModelSequence jms, Viewport view,
3408 AlignFrame af, AlignViewport av, AlignmentPanel ap)
3410 // TODO result of automated refactoring - are all these parameters needed?
3413 for (int t = 0; t < jms.getTreeCount(); t++)
3416 Tree tree = jms.getTree(t);
3418 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
3421 tp = af.ShowNewickTree(
3422 new jalview.io.NewickFile(tree.getNewick()),
3423 tree.getTitle(), tree.getWidth(), tree.getHeight(),
3424 tree.getXpos(), tree.getYpos());
3425 if (tree.getId() != null)
3427 // perhaps bind the tree id to something ?
3432 // update local tree attributes ?
3433 // TODO: should check if tp has been manipulated by user - if so its
3434 // settings shouldn't be modified
3435 tp.setTitle(tree.getTitle());
3436 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(), tree
3437 .getWidth(), tree.getHeight()));
3438 tp.av = av; // af.viewport; // TODO: verify 'associate with all
3441 tp.treeCanvas.av = av; // af.viewport;
3442 tp.treeCanvas.ap = ap; // af.alignPanel;
3447 warn("There was a problem recovering stored Newick tree: \n"
3448 + tree.getNewick());
3452 tp.fitToWindow.setState(tree.getFitToWindow());
3453 tp.fitToWindow_actionPerformed(null);
3455 if (tree.getFontName() != null)
3457 tp.setTreeFont(new java.awt.Font(tree.getFontName(), tree
3458 .getFontStyle(), tree.getFontSize()));
3462 tp.setTreeFont(new java.awt.Font(view.getFontName(), view
3463 .getFontStyle(), tree.getFontSize()));
3466 tp.showPlaceholders(tree.getMarkUnlinked());
3467 tp.showBootstrap(tree.getShowBootstrap());
3468 tp.showDistances(tree.getShowDistances());
3470 tp.treeCanvas.threshold = tree.getThreshold();
3472 if (tree.getCurrentTree())
3474 af.viewport.setCurrentTree(tp.getTree());
3478 } catch (Exception ex)
3480 ex.printStackTrace();
3485 * Load and link any saved structure viewers.
3492 protected void loadPDBStructures(jarInputStreamProvider jprovider,
3493 JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
3496 * Run through all PDB ids on the alignment, and collect mappings between
3497 * distinct view ids and all sequences referring to that view.
3499 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<String, StructureViewerModel>();
3501 for (int i = 0; i < jseqs.length; i++)
3503 if (jseqs[i].getPdbidsCount() > 0)
3505 Pdbids[] ids = jseqs[i].getPdbids();
3506 for (int p = 0; p < ids.length; p++)
3508 final int structureStateCount = ids[p].getStructureStateCount();
3509 for (int s = 0; s < structureStateCount; s++)
3511 // check to see if we haven't already created this structure view
3512 final StructureState structureState = ids[p]
3513 .getStructureState(s);
3514 String sviewid = (structureState.getViewId() == null) ? null
3515 : structureState.getViewId() + uniqueSetSuffix;
3516 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
3517 // Originally : ids[p].getFile()
3518 // : TODO: verify external PDB file recovery still works in normal
3519 // jalview project load
3520 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId()));
3521 jpdb.setId(ids[p].getId());
3523 int x = structureState.getXpos();
3524 int y = structureState.getYpos();
3525 int width = structureState.getWidth();
3526 int height = structureState.getHeight();
3528 // Probably don't need to do this anymore...
3529 // Desktop.desktop.getComponentAt(x, y);
3530 // TODO: NOW: check that this recovers the PDB file correctly.
3531 String pdbFile = loadPDBFile(jprovider, ids[p].getId());
3532 jalview.datamodel.SequenceI seq = seqRefIds.get(jseqs[i]
3534 if (sviewid == null)
3536 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width
3539 if (!structureViewers.containsKey(sviewid))
3541 structureViewers.put(sviewid,
3542 new StructureViewerModel(x, y, width, height, false,
3543 false, true, structureState.getViewId(),
3544 structureState.getType()));
3545 // Legacy pre-2.7 conversion JAL-823 :
3546 // do not assume any view has to be linked for colour by
3550 // assemble String[] { pdb files }, String[] { id for each
3551 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3552 // seqs_file 2}, boolean[] {
3553 // linkAlignPanel,superposeWithAlignpanel}} from hash
3554 StructureViewerModel jmoldat = structureViewers.get(sviewid);
3555 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
3556 | (structureState.hasAlignwithAlignPanel() ? structureState
3557 .getAlignwithAlignPanel() : false));
3560 * Default colour by linked panel to false if not specified (e.g.
3561 * for pre-2.7 projects)
3563 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
3564 colourWithAlignPanel |= (structureState
3565 .hasColourwithAlignPanel() ? structureState
3566 .getColourwithAlignPanel() : false);
3567 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
3570 * Default colour by viewer to true if not specified (e.g. for
3573 boolean colourByViewer = jmoldat.isColourByViewer();
3574 colourByViewer &= structureState.hasColourByJmol() ? structureState
3575 .getColourByJmol() : true;
3576 jmoldat.setColourByViewer(colourByViewer);
3578 if (jmoldat.getStateData().length() < structureState
3579 .getContent().length())
3582 jmoldat.setStateData(structureState.getContent());
3585 if (ids[p].getFile() != null)
3587 File mapkey = new File(ids[p].getFile());
3588 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
3589 if (seqstrmaps == null)
3591 jmoldat.getFileData().put(
3593 seqstrmaps = jmoldat.new StructureData(pdbFile,
3596 if (!seqstrmaps.getSeqList().contains(seq))
3598 seqstrmaps.getSeqList().add(seq);
3604 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");
3611 // Instantiate the associated structure views
3612 for (Entry<String, StructureViewerModel> entry : structureViewers
3617 createOrLinkStructureViewer(entry, af, ap, jprovider);
3618 } catch (Exception e)
3620 System.err.println("Error loading structure viewer: "
3622 // failed - try the next one
3634 protected void createOrLinkStructureViewer(
3635 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3636 AlignmentPanel ap, jarInputStreamProvider jprovider)
3638 final StructureViewerModel stateData = viewerData.getValue();
3641 * Search for any viewer windows already open from other alignment views
3642 * that exactly match the stored structure state
3644 StructureViewerBase comp = findMatchingViewer(viewerData);
3648 linkStructureViewer(ap, comp, stateData);
3653 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
3654 * "viewer_"+stateData.viewId
3656 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
3658 createChimeraViewer(viewerData, af, jprovider);
3663 * else Jmol (if pre-2.9, stateData contains JMOL state string)
3665 createJmolViewer(viewerData, af, jprovider);
3670 * Create a new Chimera viewer.
3676 protected void createChimeraViewer(
3677 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3678 jarInputStreamProvider jprovider)
3680 StructureViewerModel data = viewerData.getValue();
3681 String chimeraSessionFile = data.getStateData();
3684 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
3686 * NB this is the 'saved' viewId as in the project file XML, _not_ the
3687 * 'uniquified' sviewid used to reconstruct the viewer here
3689 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
3690 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
3693 Set<Entry<File, StructureData>> fileData = data.getFileData()
3695 List<PDBEntry> pdbs = new ArrayList<PDBEntry>();
3696 List<SequenceI[]> allseqs = new ArrayList<SequenceI[]>();
3697 for (Entry<File, StructureData> pdb : fileData)
3699 String filePath = pdb.getValue().getFilePath();
3700 String pdbId = pdb.getValue().getPdbId();
3701 // pdbs.add(new PDBEntry(filePath, pdbId));
3702 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
3703 final List<SequenceI> seqList = pdb.getValue().getSeqList();
3704 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
3708 boolean colourByChimera = data.isColourByViewer();
3709 boolean colourBySequence = data.isColourWithAlignPanel();
3711 // TODO use StructureViewer as a factory here, see JAL-1761
3712 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
3713 final SequenceI[][] seqsArray = allseqs.toArray(new SequenceI[allseqs
3715 String newViewId = viewerData.getKey();
3717 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
3718 af.alignPanel, pdbArray, seqsArray, colourByChimera,
3719 colourBySequence, newViewId);
3720 cvf.setSize(data.getWidth(), data.getHeight());
3721 cvf.setLocation(data.getX(), data.getY());
3725 * Create a new Jmol window. First parse the Jmol state to translate filenames
3726 * loaded into the view, and record the order in which files are shown in the
3727 * Jmol view, so we can add the sequence mappings in same order.
3733 protected void createJmolViewer(
3734 final Entry<String, StructureViewerModel> viewerData,
3735 AlignFrame af, jarInputStreamProvider jprovider)
3737 final StructureViewerModel svattrib = viewerData.getValue();
3738 String state = svattrib.getStateData();
3741 * Pre-2.9: state element value is the Jmol state string
3743 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
3746 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
3748 state = readJarEntry(jprovider,
3749 getViewerJarEntryName(svattrib.getViewId()));
3752 List<String> pdbfilenames = new ArrayList<String>();
3753 List<SequenceI[]> seqmaps = new ArrayList<SequenceI[]>();
3754 List<String> pdbids = new ArrayList<String>();
3755 StringBuilder newFileLoc = new StringBuilder(64);
3756 int cp = 0, ncp, ecp;
3757 Map<File, StructureData> oldFiles = svattrib.getFileData();
3758 while ((ncp = state.indexOf("load ", cp)) > -1)
3762 // look for next filename in load statement
3763 newFileLoc.append(state.substring(cp,
3764 ncp = (state.indexOf("\"", ncp + 1) + 1)));
3765 String oldfilenam = state.substring(ncp,
3766 ecp = state.indexOf("\"", ncp));
3767 // recover the new mapping data for this old filename
3768 // have to normalize filename - since Jmol and jalview do
3770 // translation differently.
3771 StructureData filedat = oldFiles.get(new File(oldfilenam));
3772 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
3773 pdbfilenames.add(filedat.getFilePath());
3774 pdbids.add(filedat.getPdbId());
3775 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
3776 newFileLoc.append("\"");
3777 cp = ecp + 1; // advance beyond last \" and set cursor so we can
3778 // look for next file statement.
3779 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
3783 // just append rest of state
3784 newFileLoc.append(state.substring(cp));
3788 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
3789 newFileLoc = new StringBuilder(state);
3790 newFileLoc.append("; load append ");
3791 for (File id : oldFiles.keySet())
3793 // add this and any other pdb files that should be present in
3795 StructureData filedat = oldFiles.get(id);
3796 newFileLoc.append(filedat.getFilePath());
3797 pdbfilenames.add(filedat.getFilePath());
3798 pdbids.add(filedat.getPdbId());
3799 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
3800 newFileLoc.append(" \"");
3801 newFileLoc.append(filedat.getFilePath());
3802 newFileLoc.append("\"");
3805 newFileLoc.append(";");
3808 if (newFileLoc.length() == 0)
3812 int histbug = newFileLoc.indexOf("history = ");
3816 * change "history = [true|false];" to "history = [1|0];"
3819 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
3820 String val = (diff == -1) ? null : newFileLoc
3821 .substring(histbug, diff);
3822 if (val != null && val.length() >= 4)
3824 if (val.contains("e")) // eh? what can it be?
3826 if (val.trim().equals("true"))
3834 newFileLoc.replace(histbug, diff, val);
3839 final String[] pdbf = pdbfilenames.toArray(new String[pdbfilenames
3841 final String[] id = pdbids.toArray(new String[pdbids.size()]);
3842 final SequenceI[][] sq = seqmaps
3843 .toArray(new SequenceI[seqmaps.size()][]);
3844 final String fileloc = newFileLoc.toString();
3845 final String sviewid = viewerData.getKey();
3846 final AlignFrame alf = af;
3847 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
3848 svattrib.getWidth(), svattrib.getHeight());
3851 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
3856 JalviewStructureDisplayI sview = null;
3859 sview = new StructureViewer(alf.alignPanel
3860 .getStructureSelectionManager()).createView(
3861 StructureViewer.ViewerType.JMOL, pdbf, id, sq,
3862 alf.alignPanel, svattrib, fileloc, rect, sviewid);
3863 addNewStructureViewer(sview);
3864 } catch (OutOfMemoryError ex)
3866 new OOMWarning("restoring structure view for PDB id " + id,
3867 (OutOfMemoryError) ex.getCause());
3868 if (sview != null && sview.isVisible())
3870 sview.closeViewer(false);
3871 sview.setVisible(false);
3877 } catch (InvocationTargetException ex)
3879 warn("Unexpected error when opening Jmol view.", ex);
3881 } catch (InterruptedException e)
3883 // e.printStackTrace();
3889 * Generates a name for the entry in the project jar file to hold state
3890 * information for a structure viewer
3895 protected String getViewerJarEntryName(String viewId)
3897 return VIEWER_PREFIX + viewId;
3901 * Returns any open frame that matches given structure viewer data. The match
3902 * is based on the unique viewId, or (for older project versions) the frame's
3908 protected StructureViewerBase findMatchingViewer(
3909 Entry<String, StructureViewerModel> viewerData)
3911 final String sviewid = viewerData.getKey();
3912 final StructureViewerModel svattrib = viewerData.getValue();
3913 StructureViewerBase comp = null;
3914 JInternalFrame[] frames = getAllFrames();
3915 for (JInternalFrame frame : frames)
3917 if (frame instanceof StructureViewerBase)
3920 * Post jalview 2.4 schema includes structure view id
3923 && ((StructureViewerBase) frame).getViewId()
3926 comp = (StructureViewerBase) frame;
3927 break; // break added in 2.9
3930 * Otherwise test for matching position and size of viewer frame
3932 else if (frame.getX() == svattrib.getX()
3933 && frame.getY() == svattrib.getY()
3934 && frame.getHeight() == svattrib.getHeight()
3935 && frame.getWidth() == svattrib.getWidth())
3937 comp = (StructureViewerBase) frame;
3938 // no break in faint hope of an exact match on viewId
3946 * Link an AlignmentPanel to an existing structure viewer.
3951 * @param useinViewerSuperpos
3952 * @param usetoColourbyseq
3953 * @param viewerColouring
3955 protected void linkStructureViewer(AlignmentPanel ap,
3956 StructureViewerBase viewer, StructureViewerModel stateData)
3958 // NOTE: if the jalview project is part of a shared session then
3959 // view synchronization should/could be done here.
3961 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
3962 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
3963 final boolean viewerColouring = stateData.isColourByViewer();
3964 Map<File, StructureData> oldFiles = stateData.getFileData();
3967 * Add mapping for sequences in this view to an already open viewer
3969 final AAStructureBindingModel binding = viewer.getBinding();
3970 for (File id : oldFiles.keySet())
3972 // add this and any other pdb files that should be present in the
3974 StructureData filedat = oldFiles.get(id);
3975 String pdbFile = filedat.getFilePath();
3976 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
3977 binding.getSsm().setMapping(seq, null, pdbFile,
3978 jalview.io.AppletFormatAdapter.FILE);
3979 binding.addSequenceForStructFile(pdbFile, seq);
3981 // and add the AlignmentPanel's reference to the view panel
3982 viewer.addAlignmentPanel(ap);
3983 if (useinViewerSuperpos)
3985 viewer.useAlignmentPanelForSuperposition(ap);
3989 viewer.excludeAlignmentPanelForSuperposition(ap);
3991 if (usetoColourbyseq)
3993 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
3997 viewer.excludeAlignmentPanelForColourbyseq(ap);
4002 * Get all frames within the Desktop.
4006 protected JInternalFrame[] getAllFrames()
4008 JInternalFrame[] frames = null;
4009 // TODO is this necessary - is it safe - risk of hanging?
4014 frames = Desktop.desktop.getAllFrames();
4015 } catch (ArrayIndexOutOfBoundsException e)
4017 // occasional No such child exceptions are thrown here...
4021 } catch (InterruptedException f)
4025 } while (frames == null);
4032 * - minimum version we are comparing against
4034 * - version of data being processsed.
4035 * @return true if version is development/null or evaluates to the same or
4036 * later X.Y.Z (where X,Y,Z are like [0-9]+b?[0-9]*)
4038 protected boolean isVersionStringLaterThan(String supported,
4041 if (version == null || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4042 || version.equalsIgnoreCase("Test")
4043 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4045 System.err.println("Assuming project file with "
4046 + (version == null ? "null" : version)
4047 + " is compatible with Jalview version " + supported);
4052 StringTokenizer currentV = new StringTokenizer(supported, "."), fileV = new StringTokenizer(
4054 while (currentV.hasMoreTokens() && fileV.hasMoreTokens())
4056 // convert b to decimal to catch bugfix releases within a series
4057 String curT = currentV.nextToken().toLowerCase().replace('b', '.');
4058 String fileT = fileV.nextToken().toLowerCase().replace('b', '.');
4061 if (Float.valueOf(curT) > Float.valueOf(fileT))
4063 // current version is newer than the version that wrote the file
4066 } catch (NumberFormatException nfe)
4069 .println("** WARNING: Version comparison failed for tokens ("
4073 + ")\n** Current: '"
4074 + supported + "' and Version: '" + version + "'");
4077 if (currentV.hasMoreElements())
4079 // fileV has no minor version but identical series to current
4086 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4088 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4090 if (newStructureViewers != null)
4092 sview.getBinding().setFinishedLoadingFromArchive(false);
4093 newStructureViewers.add(sview);
4097 protected void setLoadingFinishedForNewStructureViewers()
4099 if (newStructureViewers != null)
4101 for (JalviewStructureDisplayI sview : newStructureViewers)
4103 sview.getBinding().setFinishedLoadingFromArchive(true);
4105 newStructureViewers.clear();
4106 newStructureViewers = null;
4110 AlignFrame loadViewport(String file, JSeq[] JSEQ,
4111 List<SequenceI> hiddenSeqs, Alignment al,
4112 JalviewModelSequence jms, Viewport view, String uniqueSeqSetId,
4113 String viewId, List<JvAnnotRow> autoAlan)
4115 AlignFrame af = null;
4116 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
4117 uniqueSeqSetId, viewId);
4119 af.setFileName(file, "Jalview");
4121 for (int i = 0; i < JSEQ.length; i++)
4123 af.viewport.setSequenceColour(af.viewport.getAlignment()
4124 .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour()));
4127 af.viewport.setGatherViewsHere(view.getGatheredViews());
4129 if (view.getSequenceSetId() != null)
4131 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4133 af.viewport.setSequenceSetId(uniqueSeqSetId);
4136 // propagate shared settings to this new view
4137 af.viewport.setHistoryList(av.getHistoryList());
4138 af.viewport.setRedoList(av.getRedoList());
4142 viewportsAdded.put(uniqueSeqSetId, af.viewport);
4144 // TODO: check if this method can be called repeatedly without
4145 // side-effects if alignpanel already registered.
4146 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4148 // apply Hidden regions to view.
4149 if (hiddenSeqs != null)
4151 for (int s = 0; s < JSEQ.length; s++)
4153 jalview.datamodel.SequenceGroup hidden = new jalview.datamodel.SequenceGroup();
4155 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
4158 al.getSequenceAt(JSEQ[s].getHiddenSequences(r)), false);
4160 af.viewport.hideRepSequences(al.getSequenceAt(s), hidden);
4163 // jalview.datamodel.SequenceI[] hseqs = new
4164 // jalview.datamodel.SequenceI[hiddenSeqs
4167 // for (int s = 0; s < hiddenSeqs.size(); s++)
4169 // hseqs[s] = (jalview.datamodel.SequenceI) hiddenSeqs.elementAt(s);
4172 SequenceI[] hseqs = hiddenSeqs.toArray(new SequenceI[hiddenSeqs
4174 af.viewport.hideSequence(hseqs);
4177 // recover view properties and display parameters
4178 if (view.getViewName() != null)
4180 af.viewport.viewName = view.getViewName();
4181 af.setInitialTabVisible();
4183 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
4186 af.viewport.setShowAnnotation(view.getShowAnnotation());
4187 af.viewport.setAbovePIDThreshold(view.getPidSelected());
4189 af.viewport.setColourText(view.getShowColourText());
4191 af.viewport.setConservationSelected(view.getConservationSelected());
4192 af.viewport.setShowJVSuffix(view.getShowFullId());
4193 af.viewport.setRightAlignIds(view.getRightAlignIds());
4194 af.viewport.setFont(
4195 new java.awt.Font(view.getFontName(), view.getFontStyle(), view
4196 .getFontSize()), true);
4197 // TODO: allow custom charWidth/Heights to be restored by updating them
4198 // after setting font - which means set above to false
4199 af.viewport.setRenderGaps(view.getRenderGaps());
4200 af.viewport.setWrapAlignment(view.getWrapAlignment());
4201 af.viewport.setShowAnnotation(view.getShowAnnotation());
4203 af.viewport.setShowBoxes(view.getShowBoxes());
4205 af.viewport.setShowText(view.getShowText());
4207 af.viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
4208 af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
4209 af.viewport.setThresholdTextColour(view.getTextColThreshold());
4210 af.viewport.setShowUnconserved(view.hasShowUnconserved() ? view
4211 .isShowUnconserved() : false);
4212 af.viewport.setStartRes(view.getStartRes());
4213 af.viewport.setStartSeq(view.getStartSeq());
4214 af.alignPanel.updateLayout();
4215 ColourSchemeI cs = null;
4216 // apply colourschemes
4217 if (view.getBgColour() != null)
4219 if (view.getBgColour().startsWith("ucs"))
4221 cs = getUserColourScheme(jms, view.getBgColour());
4223 else if (view.getBgColour().startsWith("Annotation"))
4225 AnnotationColours viewAnnColour = view.getAnnotationColours();
4226 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
4233 cs = ColourSchemeProperty.getColour(al, view.getBgColour());
4238 cs.setThreshold(view.getPidThreshold(), true);
4239 cs.setConsensus(af.viewport.getSequenceConsensusHash());
4243 af.viewport.setGlobalColourScheme(cs);
4244 af.viewport.setColourAppliesToAllGroups(false);
4246 if (view.getConservationSelected() && cs != null)
4248 cs.setConservationInc(view.getConsThreshold());
4251 af.changeColour(cs);
4253 af.viewport.setColourAppliesToAllGroups(true);
4255 af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures());
4257 if (view.hasCentreColumnLabels())
4259 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
4261 if (view.hasIgnoreGapsinConsensus())
4263 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
4266 if (view.hasFollowHighlight())
4268 af.viewport.setFollowHighlight(view.getFollowHighlight());
4270 if (view.hasFollowSelection())
4272 af.viewport.followSelection = view.getFollowSelection();
4274 if (view.hasShowConsensusHistogram())
4276 af.viewport.setShowConsensusHistogram(view
4277 .getShowConsensusHistogram());
4281 af.viewport.setShowConsensusHistogram(true);
4283 if (view.hasShowSequenceLogo())
4285 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
4289 af.viewport.setShowSequenceLogo(false);
4291 if (view.hasNormaliseSequenceLogo())
4293 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
4295 if (view.hasShowDbRefTooltip())
4297 af.viewport.setShowDBRefs(view.getShowDbRefTooltip());
4299 if (view.hasShowNPfeatureTooltip())
4301 af.viewport.setShowNPFeats(view.hasShowNPfeatureTooltip());
4303 if (view.hasShowGroupConsensus())
4305 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
4309 af.viewport.setShowGroupConsensus(false);
4311 if (view.hasShowGroupConservation())
4313 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
4317 af.viewport.setShowGroupConservation(false);
4320 // recover featre settings
4321 if (jms.getFeatureSettings() != null)
4323 FeaturesDisplayed fdi;
4324 af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
4325 String[] renderOrder = new String[jms.getFeatureSettings()
4326 .getSettingCount()];
4327 Hashtable featureGroups = new Hashtable();
4328 Hashtable featureColours = new Hashtable();
4329 Hashtable featureOrder = new Hashtable();
4331 for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
4333 Setting setting = jms.getFeatureSettings().getSetting(fs);
4334 if (setting.hasMincolour())
4336 GraduatedColor gc = setting.hasMin() ? new GraduatedColor(
4337 new java.awt.Color(setting.getMincolour()),
4338 new java.awt.Color(setting.getColour()),
4339 setting.getMin(), setting.getMax()) : new GraduatedColor(
4340 new java.awt.Color(setting.getMincolour()),
4341 new java.awt.Color(setting.getColour()), 0, 1);
4342 if (setting.hasThreshold())
4344 gc.setThresh(setting.getThreshold());
4345 gc.setThreshType(setting.getThreshstate());
4347 gc.setAutoScaled(true); // default
4348 if (setting.hasAutoScale())
4350 gc.setAutoScaled(setting.getAutoScale());
4352 if (setting.hasColourByLabel())
4354 gc.setColourByLabel(setting.getColourByLabel());
4356 // and put in the feature colour table.
4357 featureColours.put(setting.getType(), gc);
4361 featureColours.put(setting.getType(),
4362 new java.awt.Color(setting.getColour()));
4364 renderOrder[fs] = setting.getType();
4365 if (setting.hasOrder())
4367 featureOrder.put(setting.getType(), setting.getOrder());
4371 featureOrder.put(setting.getType(), new Float(fs
4372 / jms.getFeatureSettings().getSettingCount()));
4374 if (setting.getDisplay())
4376 fdi.setVisible(setting.getType());
4379 Hashtable fgtable = new Hashtable();
4380 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
4382 Group grp = jms.getFeatureSettings().getGroup(gs);
4383 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
4385 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4386 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
4387 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
4388 FeatureRendererSettings frs = new FeatureRendererSettings(
4389 renderOrder, fgtable, featureColours, 1.0f, featureOrder);
4390 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
4391 .transferSettings(frs);
4395 if (view.getHiddenColumnsCount() > 0)
4397 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
4399 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(), view
4400 .getHiddenColumns(c).getEnd() // +1
4404 if (view.getCalcIdParam() != null)
4406 for (CalcIdParam calcIdParam : view.getCalcIdParam())
4408 if (calcIdParam != null)
4410 if (recoverCalcIdParam(calcIdParam, af.viewport))
4415 warn("Couldn't recover parameters for "
4416 + calcIdParam.getCalcId());
4421 af.setMenusFromViewport(af.viewport);
4423 // TODO: we don't need to do this if the viewport is aready visible.
4425 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
4426 * has a 'cdna/protein complement' view, in which case save it in order to
4427 * populate a SplitFrame once all views have been read in.
4429 String complementaryViewId = view.getComplementId();
4430 if (complementaryViewId == null)
4432 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
4434 // recompute any autoannotation
4435 af.alignPanel.updateAnnotation(false, true);
4436 reorderAutoannotation(af, al, autoAlan);
4437 af.alignPanel.alignmentChanged();
4441 splitFrameCandidates.put(view, af);
4446 private ColourSchemeI constructAnnotationColour(
4447 AnnotationColours viewAnnColour, AlignFrame af, Alignment al,
4448 JalviewModelSequence jms, boolean checkGroupAnnColour)
4450 boolean propagateAnnColour = false;
4451 ColourSchemeI cs = null;
4452 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
4453 if (checkGroupAnnColour && al.getGroups() != null
4454 && al.getGroups().size() > 0)
4456 // pre 2.8.1 behaviour
4457 // check to see if we should transfer annotation colours
4458 propagateAnnColour = true;
4459 for (jalview.datamodel.SequenceGroup sg : al.getGroups())
4461 if (sg.cs instanceof AnnotationColourGradient)
4463 propagateAnnColour = false;
4467 // int find annotation
4468 if (annAlignment.getAlignmentAnnotation() != null)
4470 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
4472 if (annAlignment.getAlignmentAnnotation()[i].label
4473 .equals(viewAnnColour.getAnnotation()))
4475 if (annAlignment.getAlignmentAnnotation()[i].getThreshold() == null)
4477 annAlignment.getAlignmentAnnotation()[i]
4478 .setThreshold(new jalview.datamodel.GraphLine(
4479 viewAnnColour.getThreshold(), "Threshold",
4480 java.awt.Color.black)
4485 if (viewAnnColour.getColourScheme().equals("None"))
4487 cs = new AnnotationColourGradient(
4488 annAlignment.getAlignmentAnnotation()[i],
4489 new java.awt.Color(viewAnnColour.getMinColour()),
4490 new java.awt.Color(viewAnnColour.getMaxColour()),
4491 viewAnnColour.getAboveThreshold());
4493 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
4495 cs = new AnnotationColourGradient(
4496 annAlignment.getAlignmentAnnotation()[i],
4497 getUserColourScheme(jms,
4498 viewAnnColour.getColourScheme()),
4499 viewAnnColour.getAboveThreshold());
4503 cs = new AnnotationColourGradient(
4504 annAlignment.getAlignmentAnnotation()[i],
4505 ColourSchemeProperty.getColour(al,
4506 viewAnnColour.getColourScheme()),
4507 viewAnnColour.getAboveThreshold());
4509 if (viewAnnColour.hasPerSequence())
4511 ((AnnotationColourGradient) cs).setSeqAssociated(viewAnnColour
4514 if (viewAnnColour.hasPredefinedColours())
4516 ((AnnotationColourGradient) cs)
4517 .setPredefinedColours(viewAnnColour
4518 .isPredefinedColours());
4520 if (propagateAnnColour && al.getGroups() != null)
4522 // Also use these settings for all the groups
4523 for (int g = 0; g < al.getGroups().size(); g++)
4525 jalview.datamodel.SequenceGroup sg = al.getGroups().get(g);
4533 * if (viewAnnColour.getColourScheme().equals("None" )) { sg.cs =
4534 * new AnnotationColourGradient(
4535 * annAlignment.getAlignmentAnnotation()[i], new
4536 * java.awt.Color(viewAnnColour. getMinColour()), new
4537 * java.awt.Color(viewAnnColour. getMaxColour()),
4538 * viewAnnColour.getAboveThreshold()); } else
4541 sg.cs = new AnnotationColourGradient(
4542 annAlignment.getAlignmentAnnotation()[i], sg.cs,
4543 viewAnnColour.getAboveThreshold());
4544 if (cs instanceof AnnotationColourGradient)
4546 if (viewAnnColour.hasPerSequence())
4548 ((AnnotationColourGradient) cs)
4549 .setSeqAssociated(viewAnnColour.isPerSequence());
4551 if (viewAnnColour.hasPredefinedColours())
4553 ((AnnotationColourGradient) cs)
4554 .setPredefinedColours(viewAnnColour
4555 .isPredefinedColours());
4571 private void reorderAutoannotation(AlignFrame af, Alignment al,
4572 List<JvAnnotRow> autoAlan)
4574 // copy over visualization settings for autocalculated annotation in the
4576 if (al.getAlignmentAnnotation() != null)
4579 * Kludge for magic autoannotation names (see JAL-811)
4581 String[] magicNames = new String[]
4582 { "Consensus", "Quality", "Conservation" };
4583 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
4584 Hashtable<String, JvAnnotRow> visan = new Hashtable<String, JvAnnotRow>();
4585 for (String nm : magicNames)
4587 visan.put(nm, nullAnnot);
4589 for (JvAnnotRow auan : autoAlan)
4591 visan.put(auan.template.label
4592 + (auan.template.getCalcId() == null ? "" : "\t"
4593 + auan.template.getCalcId()), auan);
4595 int hSize = al.getAlignmentAnnotation().length;
4596 List<JvAnnotRow> reorder = new ArrayList<JvAnnotRow>();
4597 // work through any autoCalculated annotation already on the view
4598 // removing it if it should be placed in a different location on the
4599 // annotation panel.
4600 List<String> remains = new ArrayList<String>(visan.keySet());
4601 for (int h = 0; h < hSize; h++)
4603 jalview.datamodel.AlignmentAnnotation jalan = al
4604 .getAlignmentAnnotation()[h];
4605 if (jalan.autoCalculated)
4608 JvAnnotRow valan = visan.get(k = jalan.label);
4609 if (jalan.getCalcId() != null)
4611 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
4616 // delete the auto calculated row from the alignment
4617 al.deleteAnnotation(jalan, false);
4621 if (valan != nullAnnot)
4623 if (jalan != valan.template)
4625 // newly created autoannotation row instance
4626 // so keep a reference to the visible annotation row
4627 // and copy over all relevant attributes
4628 if (valan.template.graphHeight >= 0)
4631 jalan.graphHeight = valan.template.graphHeight;
4633 jalan.visible = valan.template.visible;
4635 reorder.add(new JvAnnotRow(valan.order, jalan));
4640 // Add any (possibly stale) autocalculated rows that were not appended to
4641 // the view during construction
4642 for (String other : remains)
4644 JvAnnotRow othera = visan.get(other);
4645 if (othera != nullAnnot && othera.template.getCalcId() != null
4646 && othera.template.getCalcId().length() > 0)
4648 reorder.add(othera);
4651 // now put the automatic annotation in its correct place
4652 int s = 0, srt[] = new int[reorder.size()];
4653 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
4654 for (JvAnnotRow jvar : reorder)
4657 srt[s++] = jvar.order;
4660 jalview.util.QuickSort.sort(srt, rws);
4661 // and re-insert the annotation at its correct position
4662 for (JvAnnotRow jvar : rws)
4664 al.addAnnotation(jvar.template, jvar.order);
4666 af.alignPanel.adjustAnnotationHeight();
4670 Hashtable skipList = null;
4673 * TODO remove this method
4676 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
4677 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
4678 * throw new Error("Implementation Error. No skipList defined for this
4679 * Jalview2XML instance."); } return (AlignFrame)
4680 * skipList.get(view.getSequenceSetId()); }
4684 * Check if the Jalview view contained in object should be skipped or not.
4687 * @return true if view's sequenceSetId is a key in skipList
4689 private boolean skipViewport(JalviewModel object)
4691 if (skipList == null)
4696 if (skipList.containsKey(id = object.getJalviewModelSequence()
4697 .getViewport()[0].getSequenceSetId()))
4699 if (Cache.log != null && Cache.log.isDebugEnabled())
4701 Cache.log.debug("Skipping seuqence set id " + id);
4708 public void addToSkipList(AlignFrame af)
4710 if (skipList == null)
4712 skipList = new Hashtable();
4714 skipList.put(af.getViewport().getSequenceSetId(), af);
4717 public void clearSkipList()
4719 if (skipList != null)
4726 private void recoverDatasetFor(SequenceSet vamsasSet, Alignment al,
4727 boolean ignoreUnrefed)
4729 jalview.datamodel.Alignment ds = getDatasetFor(vamsasSet.getDatasetId());
4730 Vector dseqs = null;
4733 // create a list of new dataset sequences
4734 dseqs = new Vector();
4736 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
4738 Sequence vamsasSeq = vamsasSet.getSequence(i);
4739 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed);
4741 // create a new dataset
4744 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
4745 dseqs.copyInto(dsseqs);
4746 ds = new jalview.datamodel.Alignment(dsseqs);
4747 debug("Created new dataset " + vamsasSet.getDatasetId()
4748 + " for alignment " + System.identityHashCode(al));
4749 addDatasetRef(vamsasSet.getDatasetId(), ds);
4751 // set the dataset for the newly imported alignment.
4752 if (al.getDataset() == null && !ignoreUnrefed)
4761 * sequence definition to create/merge dataset sequence for
4765 * vector to add new dataset sequence to
4767 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
4768 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed)
4770 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
4772 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
4773 SequenceI dsq = null;
4774 if (sq != null && sq.getDatasetSequence() != null)
4776 dsq = sq.getDatasetSequence();
4778 if (sq == null && ignoreUnrefed)
4782 String sqid = vamsasSeq.getDsseqid();
4785 // need to create or add a new dataset sequence reference to this sequence
4788 dsq = seqRefIds.get(sqid);
4793 // make a new dataset sequence
4794 dsq = sq.createDatasetSequence();
4797 // make up a new dataset reference for this sequence
4798 sqid = seqHash(dsq);
4800 dsq.setVamsasId(uniqueSetSuffix + sqid);
4801 seqRefIds.put(sqid, dsq);
4806 dseqs.addElement(dsq);
4811 ds.addSequence(dsq);
4817 { // make this dataset sequence sq's dataset sequence
4818 sq.setDatasetSequence(dsq);
4819 // and update the current dataset alignment
4824 if (!dseqs.contains(dsq))
4831 if (ds.findIndex(dsq) < 0)
4833 ds.addSequence(dsq);
4840 // TODO: refactor this as a merge dataset sequence function
4841 // now check that sq (the dataset sequence) sequence really is the union of
4842 // all references to it
4843 // boolean pre = sq.getStart() < dsq.getStart();
4844 // boolean post = sq.getEnd() > dsq.getEnd();
4848 // StringBuffer sb = new StringBuffer();
4849 String newres = jalview.analysis.AlignSeq.extractGaps(
4850 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
4851 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
4852 && newres.length() > dsq.getLength())
4854 // Update with the longer sequence.
4858 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
4859 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
4860 * sb.append(newres.substring(newres.length() - sq.getEnd() -
4861 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
4863 dsq.setSequence(newres);
4865 // TODO: merges will never happen if we 'know' we have the real dataset
4866 // sequence - this should be detected when id==dssid
4868 .println("DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
4869 // + (pre ? "prepended" : "") + " "
4870 // + (post ? "appended" : ""));
4876 * TODO use AlignmentI here and in related methods - needs
4877 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
4879 Hashtable<String, Alignment> datasetIds = null;
4881 IdentityHashMap<Alignment, String> dataset2Ids = null;
4883 private Alignment getDatasetFor(String datasetId)
4885 if (datasetIds == null)
4887 datasetIds = new Hashtable<String, Alignment>();
4890 if (datasetIds.containsKey(datasetId))
4892 return datasetIds.get(datasetId);
4897 private void addDatasetRef(String datasetId, Alignment dataset)
4899 if (datasetIds == null)
4901 datasetIds = new Hashtable<String, Alignment>();
4903 datasetIds.put(datasetId, dataset);
4907 * make a new dataset ID for this jalview dataset alignment
4912 private String getDatasetIdRef(Alignment dataset)
4914 if (dataset.getDataset() != null)
4916 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
4918 String datasetId = makeHashCode(dataset, null);
4919 if (datasetId == null)
4921 // make a new datasetId and record it
4922 if (dataset2Ids == null)
4924 dataset2Ids = new IdentityHashMap<Alignment, String>();
4928 datasetId = dataset2Ids.get(dataset);
4930 if (datasetId == null)
4932 datasetId = "ds" + dataset2Ids.size() + 1;
4933 dataset2Ids.put(dataset, datasetId);
4939 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
4941 for (int d = 0; d < sequence.getDBRefCount(); d++)
4943 DBRef dr = sequence.getDBRef(d);
4944 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
4945 sequence.getDBRef(d).getSource(), sequence.getDBRef(d)
4946 .getVersion(), sequence.getDBRef(d).getAccessionId());
4947 if (dr.getMapping() != null)
4949 entry.setMap(addMapping(dr.getMapping()));
4951 datasetSequence.addDBRef(entry);
4955 private jalview.datamodel.Mapping addMapping(Mapping m)
4957 SequenceI dsto = null;
4958 // Mapping m = dr.getMapping();
4959 int fr[] = new int[m.getMapListFromCount() * 2];
4960 Enumeration f = m.enumerateMapListFrom();
4961 for (int _i = 0; f.hasMoreElements(); _i += 2)
4963 MapListFrom mf = (MapListFrom) f.nextElement();
4964 fr[_i] = mf.getStart();
4965 fr[_i + 1] = mf.getEnd();
4967 int fto[] = new int[m.getMapListToCount() * 2];
4968 f = m.enumerateMapListTo();
4969 for (int _i = 0; f.hasMoreElements(); _i += 2)
4971 MapListTo mf = (MapListTo) f.nextElement();
4972 fto[_i] = mf.getStart();
4973 fto[_i + 1] = mf.getEnd();
4975 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto,
4976 fr, fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
4977 if (m.getMappingChoice() != null)
4979 MappingChoice mc = m.getMappingChoice();
4980 if (mc.getDseqFor() != null)
4982 String dsfor = "" + mc.getDseqFor();
4983 if (seqRefIds.containsKey(dsfor))
4988 jmap.setTo(seqRefIds.get(dsfor));
4992 frefedSequence.add(new Object[]
4999 * local sequence definition
5001 Sequence ms = mc.getSequence();
5002 SequenceI djs = null;
5003 String sqid = ms.getDsseqid();
5004 if (sqid != null && sqid.length() > 0)
5007 * recover dataset sequence
5009 djs = seqRefIds.get(sqid);
5014 .println("Warning - making up dataset sequence id for DbRef sequence map reference");
5015 sqid = ((Object) ms).toString(); // make up a new hascode for
5016 // undefined dataset sequence hash
5017 // (unlikely to happen)
5023 * make a new dataset sequence and add it to refIds hash
5025 djs = new jalview.datamodel.Sequence(ms.getName(),
5027 djs.setStart(jmap.getMap().getToLowest());
5028 djs.setEnd(jmap.getMap().getToHighest());
5029 djs.setVamsasId(uniqueSetSuffix + sqid);
5031 seqRefIds.put(sqid, djs);
5034 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5043 public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
5044 boolean keepSeqRefs)
5047 JalviewModel jm = saveState(ap, null, null, null);
5052 jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
5056 uniqueSetSuffix = "";
5057 jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
5062 if (this.frefedSequence == null)
5064 frefedSequence = new Vector();
5067 viewportsAdded.clear();
5069 AlignFrame af = loadFromObject(jm, null, false, null);
5070 af.alignPanels.clear();
5071 af.closeMenuItem_actionPerformed(true);
5074 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5075 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5076 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5077 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5078 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5081 return af.alignPanel;
5085 * flag indicating if hashtables should be cleared on finalization TODO this
5086 * flag may not be necessary
5088 private final boolean _cleartables = true;
5090 private Hashtable jvids2vobj;
5095 * @see java.lang.Object#finalize()
5098 protected void finalize() throws Throwable
5100 // really make sure we have no buried refs left.
5105 this.seqRefIds = null;
5106 this.seqsToIds = null;
5110 private void warn(String msg)
5115 private void warn(String msg, Exception e)
5117 if (Cache.log != null)
5121 Cache.log.warn(msg, e);
5125 Cache.log.warn(msg);
5130 System.err.println("Warning: " + msg);
5133 e.printStackTrace();
5138 private void debug(String string)
5140 debug(string, null);
5143 private void debug(String msg, Exception e)
5145 if (Cache.log != null)
5149 Cache.log.debug(msg, e);
5153 Cache.log.debug(msg);
5158 System.err.println("Warning: " + msg);
5161 e.printStackTrace();
5167 * set the object to ID mapping tables used to write/recover objects and XML
5168 * ID strings for the jalview project. If external tables are provided then
5169 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
5170 * object goes out of scope. - also populates the datasetIds hashtable with
5171 * alignment objects containing dataset sequences
5174 * Map from ID strings to jalview datamodel
5176 * Map from jalview datamodel to ID strings
5180 public void setObjectMappingTables(Hashtable vobj2jv,
5181 IdentityHashMap jv2vobj)
5183 this.jv2vobj = jv2vobj;
5184 this.vobj2jv = vobj2jv;
5185 Iterator ds = jv2vobj.keySet().iterator();
5187 while (ds.hasNext())
5189 Object jvobj = ds.next();
5190 id = jv2vobj.get(jvobj).toString();
5191 if (jvobj instanceof jalview.datamodel.Alignment)
5193 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
5195 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
5198 else if (jvobj instanceof jalview.datamodel.Sequence)
5200 // register sequence object so the XML parser can recover it.
5201 if (seqRefIds == null)
5203 seqRefIds = new HashMap<String, SequenceI>();
5205 if (seqsToIds == null)
5207 seqsToIds = new IdentityHashMap<SequenceI, String>();
5209 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
5210 seqsToIds.put((SequenceI) jvobj, id);
5212 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
5215 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
5216 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
5217 if (jvann.annotationId == null)
5219 jvann.annotationId = anid;
5221 if (!jvann.annotationId.equals(anid))
5223 // TODO verify that this is the correct behaviour
5224 this.warn("Overriding Annotation ID for " + anid
5225 + " from different id : " + jvann.annotationId);
5226 jvann.annotationId = anid;
5229 else if (jvobj instanceof String)
5231 if (jvids2vobj == null)
5233 jvids2vobj = new Hashtable();
5234 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
5239 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
5245 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
5246 * objects created from the project archive. If string is null (default for
5247 * construction) then suffix will be set automatically.
5251 public void setUniqueSetSuffix(String string)
5253 uniqueSetSuffix = string;
5258 * uses skipList2 as the skipList for skipping views on sequence sets
5259 * associated with keys in the skipList
5263 public void setSkipList(Hashtable skipList2)
5265 skipList = skipList2;
5269 * Reads the jar entry of given name and returns its contents, or null if the
5270 * entry is not found.
5273 * @param jarEntryName
5276 protected String readJarEntry(jarInputStreamProvider jprovider,
5277 String jarEntryName)
5279 String result = null;
5280 BufferedReader in = null;
5285 * Reopen the jar input stream and traverse its entries to find a matching
5288 JarInputStream jin = jprovider.getJarInputStream();
5289 JarEntry entry = null;
5292 entry = jin.getNextJarEntry();
5293 } while (entry != null && !entry.getName().equals(jarEntryName));
5297 StringBuilder out = new StringBuilder(256);
5298 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
5301 while ((data = in.readLine()) != null)
5305 result = out.toString();
5309 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
5311 } catch (Exception ex)
5313 ex.printStackTrace();
5321 } catch (IOException e)
5332 * Returns an incrementing counter (0, 1, 2...)
5336 private synchronized int nextCounter()