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.FeatureColourI;
24 import jalview.api.ViewStyleI;
25 import jalview.api.structures.JalviewStructureDisplayI;
26 import jalview.bin.Cache;
27 import jalview.datamodel.AlignedCodonFrame;
28 import jalview.datamodel.Alignment;
29 import jalview.datamodel.AlignmentAnnotation;
30 import jalview.datamodel.AlignmentI;
31 import jalview.datamodel.PDBEntry;
32 import jalview.datamodel.RnaViewerModel;
33 import jalview.datamodel.SequenceGroup;
34 import jalview.datamodel.SequenceI;
35 import jalview.datamodel.StructureViewerModel;
36 import jalview.datamodel.StructureViewerModel.StructureData;
37 import jalview.ext.varna.RnaModel;
38 import jalview.gui.StructureViewer.ViewerType;
39 import jalview.schemabinding.version2.AlcodMap;
40 import jalview.schemabinding.version2.AlcodonFrame;
41 import jalview.schemabinding.version2.Annotation;
42 import jalview.schemabinding.version2.AnnotationColours;
43 import jalview.schemabinding.version2.AnnotationElement;
44 import jalview.schemabinding.version2.CalcIdParam;
45 import jalview.schemabinding.version2.DBRef;
46 import jalview.schemabinding.version2.Features;
47 import jalview.schemabinding.version2.Group;
48 import jalview.schemabinding.version2.HiddenColumns;
49 import jalview.schemabinding.version2.JGroup;
50 import jalview.schemabinding.version2.JSeq;
51 import jalview.schemabinding.version2.JalviewModel;
52 import jalview.schemabinding.version2.JalviewModelSequence;
53 import jalview.schemabinding.version2.MapListFrom;
54 import jalview.schemabinding.version2.MapListTo;
55 import jalview.schemabinding.version2.Mapping;
56 import jalview.schemabinding.version2.MappingChoice;
57 import jalview.schemabinding.version2.OtherData;
58 import jalview.schemabinding.version2.PdbentryItem;
59 import jalview.schemabinding.version2.Pdbids;
60 import jalview.schemabinding.version2.Property;
61 import jalview.schemabinding.version2.RnaViewer;
62 import jalview.schemabinding.version2.SecondaryStructure;
63 import jalview.schemabinding.version2.Sequence;
64 import jalview.schemabinding.version2.SequenceSet;
65 import jalview.schemabinding.version2.SequenceSetProperties;
66 import jalview.schemabinding.version2.Setting;
67 import jalview.schemabinding.version2.StructureState;
68 import jalview.schemabinding.version2.ThresholdLine;
69 import jalview.schemabinding.version2.Tree;
70 import jalview.schemabinding.version2.UserColours;
71 import jalview.schemabinding.version2.Viewport;
72 import jalview.schemes.AnnotationColourGradient;
73 import jalview.schemes.ColourSchemeI;
74 import jalview.schemes.ColourSchemeProperty;
75 import jalview.schemes.FeatureColour;
76 import jalview.schemes.ResidueColourScheme;
77 import jalview.schemes.ResidueProperties;
78 import jalview.schemes.UserColourScheme;
79 import jalview.structure.StructureSelectionManager;
80 import jalview.structures.models.AAStructureBindingModel;
81 import jalview.util.MessageManager;
82 import jalview.util.Platform;
83 import jalview.util.StringUtils;
84 import jalview.util.jarInputStreamProvider;
85 import jalview.viewmodel.AlignmentViewport;
86 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
87 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
88 import jalview.ws.jws2.Jws2Discoverer;
89 import jalview.ws.jws2.dm.AAConSettings;
90 import jalview.ws.jws2.jabaws2.Jws2Instance;
91 import jalview.ws.params.ArgumentI;
92 import jalview.ws.params.AutoCalcSetting;
93 import jalview.ws.params.WsParamSetI;
95 import java.awt.Color;
96 import java.awt.Rectangle;
97 import java.io.BufferedReader;
98 import java.io.DataInputStream;
99 import java.io.DataOutputStream;
101 import java.io.FileInputStream;
102 import java.io.FileOutputStream;
103 import java.io.IOException;
104 import java.io.InputStreamReader;
105 import java.io.OutputStreamWriter;
106 import java.io.PrintWriter;
107 import java.lang.reflect.InvocationTargetException;
108 import java.net.MalformedURLException;
110 import java.util.ArrayList;
111 import java.util.Enumeration;
112 import java.util.HashMap;
113 import java.util.HashSet;
114 import java.util.Hashtable;
115 import java.util.IdentityHashMap;
116 import java.util.Iterator;
117 import java.util.LinkedHashMap;
118 import java.util.List;
119 import java.util.Map;
120 import java.util.Map.Entry;
121 import java.util.Set;
122 import java.util.Vector;
123 import java.util.jar.JarEntry;
124 import java.util.jar.JarInputStream;
125 import java.util.jar.JarOutputStream;
127 import javax.swing.JInternalFrame;
128 import javax.swing.JOptionPane;
129 import javax.swing.SwingUtilities;
131 import org.exolab.castor.xml.Marshaller;
132 import org.exolab.castor.xml.Unmarshaller;
135 * Write out the current jalview desktop state as a Jalview XML stream.
137 * Note: the vamsas objects referred to here are primitive versions of the
138 * VAMSAS project schema elements - they are not the same and most likely never
142 * @version $Revision: 1.134 $
144 public class Jalview2XML
146 private static final String VIEWER_PREFIX = "viewer_";
148 private static final String RNA_PREFIX = "rna_";
150 private static final String UTF_8 = "UTF-8";
152 // use this with nextCounter() to make unique names for entities
153 private int counter = 0;
156 * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
157 * of sequence objects are created.
159 IdentityHashMap<SequenceI, String> seqsToIds = null;
162 * jalview XML Sequence ID to jalview sequence object reference (both dataset
163 * and alignment sequences. Populated as XML reps of sequence objects are
166 Map<String, SequenceI> seqRefIds = null;
168 Vector<Object[]> frefedSequence = null;
170 boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
173 * Map of reconstructed AlignFrame objects that appear to have come from
174 * SplitFrame objects (have a dna/protein complement view).
176 private Map<Viewport, AlignFrame> splitFrameCandidates = new HashMap<Viewport, AlignFrame>();
179 * Map from displayed rna structure models to their saved session state jar
182 private Map<RnaModel, String> rnaSessions = new HashMap<RnaModel, String>();
185 * create/return unique hash string for sq
188 * @return new or existing unique string for sq
190 String seqHash(SequenceI sq)
192 if (seqsToIds == null)
196 if (seqsToIds.containsKey(sq))
198 return seqsToIds.get(sq);
202 // create sequential key
203 String key = "sq" + (seqsToIds.size() + 1);
204 key = makeHashCode(sq, key); // check we don't have an external reference
206 seqsToIds.put(sq, key);
215 if (seqRefIds != null)
219 if (seqsToIds != null)
229 warn("clearSeqRefs called when _cleartables was not set. Doing nothing.");
230 // seqRefIds = new Hashtable();
231 // seqsToIds = new IdentityHashMap();
237 if (seqsToIds == null)
239 seqsToIds = new IdentityHashMap<SequenceI, String>();
241 if (seqRefIds == null)
243 seqRefIds = new HashMap<String, SequenceI>();
251 public Jalview2XML(boolean raiseGUI)
253 this.raiseGUI = raiseGUI;
256 public void resolveFrefedSequences()
258 if (frefedSequence.size() > 0)
260 int r = 0, rSize = frefedSequence.size();
263 Object[] ref = frefedSequence.elementAt(r);
266 String sref = (String) ref[0];
267 if (seqRefIds.containsKey(sref))
269 if (ref[1] instanceof jalview.datamodel.Mapping)
271 SequenceI seq = seqRefIds.get(sref);
272 while (seq.getDatasetSequence() != null)
274 seq = seq.getDatasetSequence();
276 ((jalview.datamodel.Mapping) ref[1]).setTo(seq);
280 if (ref[1] instanceof jalview.datamodel.AlignedCodonFrame)
282 SequenceI seq = seqRefIds.get(sref);
283 while (seq.getDatasetSequence() != null)
285 seq = seq.getDatasetSequence();
288 && ref[2] instanceof jalview.datamodel.Mapping)
290 jalview.datamodel.Mapping mp = (jalview.datamodel.Mapping) ref[2];
291 ((jalview.datamodel.AlignedCodonFrame) ref[1]).addMap(
292 seq, mp.getTo(), mp.getMap());
297 .println("IMPLEMENTATION ERROR: Unimplemented forward sequence references for AlcodonFrames involving "
298 + ref[2].getClass() + " type objects.");
304 .println("IMPLEMENTATION ERROR: Unimplemented forward sequence references for "
305 + ref[1].getClass() + " type objects.");
308 frefedSequence.remove(r);
314 .println("IMPLEMENTATION WARNING: Unresolved forward reference for hash string "
316 + " with objecttype "
317 + ref[1].getClass());
324 frefedSequence.remove(r);
332 * This maintains a map of viewports, the key being the seqSetId. Important to
333 * set historyItem and redoList for multiple views
335 Map<String, AlignViewport> viewportsAdded = new HashMap<String, AlignViewport>();
337 Map<String, AlignmentAnnotation> annotationIds = new HashMap<String, AlignmentAnnotation>();
339 String uniqueSetSuffix = "";
342 * List of pdbfiles added to Jar
344 List<String> pdbfiles = null;
346 // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
347 public void saveState(File statefile)
349 FileOutputStream fos = null;
352 fos = new FileOutputStream(statefile);
353 JarOutputStream jout = new JarOutputStream(fos);
356 } catch (Exception e)
358 // TODO: inform user of the problem - they need to know if their data was
360 if (errorMessage == null)
362 errorMessage = "Couldn't write Jalview Archive to output file '"
363 + statefile + "' - See console error log for details";
367 errorMessage += "(output file was '" + statefile + "')";
377 } catch (IOException e)
387 * Writes a jalview project archive to the given Jar output stream.
391 public void saveState(JarOutputStream jout)
393 AlignFrame[] frames = Desktop.getAlignFrames();
400 Hashtable<String, AlignFrame> dsses = new Hashtable<String, AlignFrame>();
403 * ensure cached data is clear before starting
405 // todo tidy up seqRefIds, seqsToIds initialisation / reset
407 splitFrameCandidates.clear();
412 // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
413 // //////////////////////////////////////////////////
415 List<String> shortNames = new ArrayList<String>();
416 List<String> viewIds = new ArrayList<String>();
419 for (int i = frames.length - 1; i > -1; i--)
421 AlignFrame af = frames[i];
425 .containsKey(af.getViewport().getSequenceSetId()))
430 String shortName = makeFilename(af, shortNames);
432 int ap, apSize = af.alignPanels.size();
434 for (ap = 0; ap < apSize; ap++)
436 AlignmentPanel apanel = af.alignPanels.get(ap);
437 String fileName = apSize == 1 ? shortName : ap + shortName;
438 if (!fileName.endsWith(".xml"))
440 fileName = fileName + ".xml";
443 saveState(apanel, fileName, jout, viewIds);
445 String dssid = getDatasetIdRef(af.getViewport().getAlignment()
447 if (!dsses.containsKey(dssid))
449 dsses.put(dssid, af);
454 writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix,
460 } catch (Exception foo)
465 } catch (Exception ex)
467 // TODO: inform user of the problem - they need to know if their data was
469 if (errorMessage == null)
471 errorMessage = "Couldn't write Jalview Archive - see error output for details";
473 ex.printStackTrace();
478 * Generates a distinct file name, based on the title of the AlignFrame, by
479 * appending _n for increasing n until an unused name is generated. The new
480 * name (without its extension) is added to the list.
484 * @return the generated name, with .xml extension
486 protected String makeFilename(AlignFrame af, List<String> namesUsed)
488 String shortName = af.getTitle();
490 if (shortName.indexOf(File.separatorChar) > -1)
492 shortName = shortName.substring(shortName
493 .lastIndexOf(File.separatorChar) + 1);
498 while (namesUsed.contains(shortName))
500 if (shortName.endsWith("_" + (count - 1)))
502 shortName = shortName.substring(0, shortName.lastIndexOf("_"));
505 shortName = shortName.concat("_" + count);
509 namesUsed.add(shortName);
511 if (!shortName.endsWith(".xml"))
513 shortName = shortName + ".xml";
518 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
519 public boolean saveAlignment(AlignFrame af, String jarFile,
525 int apSize = af.alignPanels.size();
526 FileOutputStream fos = new FileOutputStream(jarFile);
527 JarOutputStream jout = new JarOutputStream(fos);
528 Hashtable<String, AlignFrame> dsses = new Hashtable<String, AlignFrame>();
529 List<String> viewIds = new ArrayList<String>();
531 for (AlignmentPanel apanel : af.alignPanels)
533 String jfileName = apSize == 1 ? fileName : fileName + ap;
535 if (!jfileName.endsWith(".xml"))
537 jfileName = jfileName + ".xml";
539 saveState(apanel, jfileName, jout, viewIds);
540 String dssid = getDatasetIdRef(af.getViewport().getAlignment()
542 if (!dsses.containsKey(dssid))
544 dsses.put(dssid, af);
547 writeDatasetFor(dsses, fileName, jout);
551 } catch (Exception foo)
557 } catch (Exception ex)
559 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
560 ex.printStackTrace();
565 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
566 String fileName, JarOutputStream jout)
569 for (String dssids : dsses.keySet())
571 AlignFrame _af = dsses.get(dssids);
572 String jfileName = fileName + " Dataset for " + _af.getTitle();
573 if (!jfileName.endsWith(".xml"))
575 jfileName = jfileName + ".xml";
577 saveState(_af.alignPanel, jfileName, true, jout, null);
582 * create a JalviewModel from an alignment view and marshall it to a
586 * panel to create jalview model for
588 * name of alignment panel written to output stream
595 public JalviewModel saveState(AlignmentPanel ap, String fileName,
596 JarOutputStream jout, List<String> viewIds)
598 return saveState(ap, fileName, false, jout, viewIds);
602 * create a JalviewModel from an alignment view and marshall it to a
606 * panel to create jalview model for
608 * name of alignment panel written to output stream
610 * when true, only write the dataset for the alignment, not the data
611 * associated with the view.
617 public JalviewModel saveState(AlignmentPanel ap, String fileName,
618 boolean storeDS, JarOutputStream jout, List<String> viewIds)
622 viewIds = new ArrayList<String>();
627 List<UserColourScheme> userColours = new ArrayList<UserColourScheme>();
629 AlignViewport av = ap.av;
631 JalviewModel object = new JalviewModel();
632 object.setVamsasModel(new jalview.schemabinding.version2.VamsasModel());
634 object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
635 object.setVersion(jalview.bin.Cache.getDefault("VERSION",
636 "Development Build"));
639 * rjal is full height alignment, jal is actual alignment with full metadata
640 * but excludes hidden sequences.
642 jalview.datamodel.AlignmentI rjal = av.getAlignment(), jal = rjal;
644 if (av.hasHiddenRows())
646 rjal = jal.getHiddenSequences().getFullAlignment();
649 SequenceSet vamsasSet = new SequenceSet();
651 JalviewModelSequence jms = new JalviewModelSequence();
653 vamsasSet.setGapChar(jal.getGapCharacter() + "");
655 if (jal.getDataset() != null)
657 // dataset id is the dataset's hashcode
658 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
661 // switch jal and the dataset
662 jal = jal.getDataset();
666 if (jal.getProperties() != null)
668 Enumeration en = jal.getProperties().keys();
669 while (en.hasMoreElements())
671 String key = en.nextElement().toString();
672 SequenceSetProperties ssp = new SequenceSetProperties();
674 ssp.setValue(jal.getProperties().get(key).toString());
675 vamsasSet.addSequenceSetProperties(ssp);
680 Set<String> calcIdSet = new HashSet<String>();
683 for (final SequenceI jds : rjal.getSequences())
685 final SequenceI jdatasq = jds.getDatasetSequence() == null ? jds
686 : jds.getDatasetSequence();
687 String id = seqHash(jds);
689 if (seqRefIds.get(id) != null)
691 // This happens for two reasons: 1. multiple views are being serialised.
692 // 2. the hashCode has collided with another sequence's code. This DOES
693 // HAPPEN! (PF00072.15.stk does this)
694 // JBPNote: Uncomment to debug writing out of files that do not read
695 // back in due to ArrayOutOfBoundExceptions.
696 // System.err.println("vamsasSeq backref: "+id+"");
697 // System.err.println(jds.getName()+"
698 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
699 // System.err.println("Hashcode: "+seqHash(jds));
700 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
701 // System.err.println(rsq.getName()+"
702 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
703 // System.err.println("Hashcode: "+seqHash(rsq));
707 vamsasSeq = createVamsasSequence(id, jds);
708 vamsasSet.addSequence(vamsasSeq);
709 seqRefIds.put(id, jds);
713 jseq.setStart(jds.getStart());
714 jseq.setEnd(jds.getEnd());
715 jseq.setColour(av.getSequenceColour(jds).getRGB());
717 jseq.setId(id); // jseq id should be a string not a number
720 // Store any sequences this sequence represents
721 if (av.hasHiddenRows())
723 // use rjal, contains the full height alignment
724 jseq.setHidden(av.getAlignment().getHiddenSequences()
727 if (av.isHiddenRepSequence(jds))
729 jalview.datamodel.SequenceI[] reps = av
730 .getRepresentedSequences(jds)
731 .getSequencesInOrder(rjal);
733 for (int h = 0; h < reps.length; h++)
737 jseq.addHiddenSequences(rjal.findIndex(reps[h]));
742 // mark sequence as reference - if it is the reference for this view
745 jseq.setViewreference(jds == jal.getSeqrep());
749 // TODO: omit sequence features from each alignment view's XML dump if we
750 // are storing dataset
751 if (jds.getSequenceFeatures() != null)
753 jalview.datamodel.SequenceFeature[] sf = jds.getSequenceFeatures();
755 while (index < sf.length)
757 Features features = new Features();
759 features.setBegin(sf[index].getBegin());
760 features.setEnd(sf[index].getEnd());
761 features.setDescription(sf[index].getDescription());
762 features.setType(sf[index].getType());
763 features.setFeatureGroup(sf[index].getFeatureGroup());
764 features.setScore(sf[index].getScore());
765 if (sf[index].links != null)
767 for (int l = 0; l < sf[index].links.size(); l++)
769 OtherData keyValue = new OtherData();
770 keyValue.setKey("LINK_" + l);
771 keyValue.setValue(sf[index].links.elementAt(l).toString());
772 features.addOtherData(keyValue);
775 if (sf[index].otherDetails != null)
778 Iterator<String> keys = sf[index].otherDetails.keySet()
780 while (keys.hasNext())
783 OtherData keyValue = new OtherData();
784 keyValue.setKey(key);
785 keyValue.setValue(sf[index].otherDetails.get(key).toString());
786 features.addOtherData(keyValue);
790 jseq.addFeatures(features);
795 if (jdatasq.getAllPDBEntries() != null)
797 Enumeration en = jdatasq.getAllPDBEntries().elements();
798 while (en.hasMoreElements())
800 Pdbids pdb = new Pdbids();
801 jalview.datamodel.PDBEntry entry = (jalview.datamodel.PDBEntry) en
804 String pdbId = entry.getId();
806 pdb.setType(entry.getType());
809 * Store any structure views associated with this sequence. This
810 * section copes with duplicate entries in the project, so a dataset
811 * only view *should* be coped with sensibly.
813 // This must have been loaded, is it still visible?
814 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
815 String matchedFile = null;
816 for (int f = frames.length - 1; f > -1; f--)
818 if (frames[f] instanceof StructureViewerBase)
820 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
821 matchedFile = saveStructureState(ap, jds, pdb, entry,
822 viewIds, matchedFile, viewFrame);
824 * Only store each structure viewer's state once in the project
825 * jar. First time through only (storeDS==false)
827 String viewId = viewFrame.getViewId();
828 if (!storeDS && !viewIds.contains(viewId))
833 String viewerState = viewFrame.getStateInfo();
834 writeJarEntry(jout, getViewerJarEntryName(viewId),
835 viewerState.getBytes());
836 } catch (IOException e)
838 System.err.println("Error saving viewer state: "
845 if (matchedFile != null || entry.getFile() != null)
847 if (entry.getFile() != null)
850 matchedFile = entry.getFile();
852 pdb.setFile(matchedFile); // entry.getFile());
853 if (pdbfiles == null)
855 pdbfiles = new ArrayList<String>();
858 if (!pdbfiles.contains(pdbId))
861 copyFileToJar(jout, matchedFile, pdbId);
865 if (entry.getProperty() != null && !entry.getProperty().isEmpty())
867 PdbentryItem item = new PdbentryItem();
868 Hashtable properties = entry.getProperty();
869 Enumeration en2 = properties.keys();
870 while (en2.hasMoreElements())
872 Property prop = new Property();
873 String key = en2.nextElement().toString();
875 prop.setValue(properties.get(key).toString());
876 item.addProperty(prop);
878 pdb.addPdbentryItem(item);
885 saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
890 if (!storeDS && av.hasHiddenRows())
892 jal = av.getAlignment();
895 if (jal.getCodonFrames() != null)
897 List<AlignedCodonFrame> jac = jal.getCodonFrames();
898 for (AlignedCodonFrame acf : jac)
900 AlcodonFrame alc = new AlcodonFrame();
901 if (acf.getProtMappings() != null
902 && acf.getProtMappings().length > 0)
904 boolean hasMap = false;
905 SequenceI[] dnas = acf.getdnaSeqs();
906 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
907 for (int m = 0; m < pmaps.length; m++)
909 AlcodMap alcmap = new AlcodMap();
910 alcmap.setDnasq(seqHash(dnas[m]));
911 alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
913 alc.addAlcodMap(alcmap);
918 vamsasSet.addAlcodonFrame(alc);
921 // TODO: delete this ? dead code from 2.8.3->2.9 ?
923 // AlcodonFrame alc = new AlcodonFrame();
924 // vamsasSet.addAlcodonFrame(alc);
925 // for (int p = 0; p < acf.aaWidth; p++)
927 // Alcodon cmap = new Alcodon();
928 // if (acf.codons[p] != null)
930 // // Null codons indicate a gapped column in the translated peptide
932 // cmap.setPos1(acf.codons[p][0]);
933 // cmap.setPos2(acf.codons[p][1]);
934 // cmap.setPos3(acf.codons[p][2]);
936 // alc.addAlcodon(cmap);
938 // if (acf.getProtMappings() != null
939 // && acf.getProtMappings().length > 0)
941 // SequenceI[] dnas = acf.getdnaSeqs();
942 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
943 // for (int m = 0; m < pmaps.length; m++)
945 // AlcodMap alcmap = new AlcodMap();
946 // alcmap.setDnasq(seqHash(dnas[m]));
947 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
949 // alc.addAlcodMap(alcmap);
956 // /////////////////////////////////
957 if (!storeDS && av.currentTree != null)
959 // FIND ANY ASSOCIATED TREES
960 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
961 if (Desktop.desktop != null)
963 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
965 for (int t = 0; t < frames.length; t++)
967 if (frames[t] instanceof TreePanel)
969 TreePanel tp = (TreePanel) frames[t];
971 if (tp.treeCanvas.av.getAlignment() == jal)
973 Tree tree = new Tree();
974 tree.setTitle(tp.getTitle());
975 tree.setCurrentTree((av.currentTree == tp.getTree()));
976 tree.setNewick(tp.getTree().toString());
977 tree.setThreshold(tp.treeCanvas.threshold);
979 tree.setFitToWindow(tp.fitToWindow.getState());
980 tree.setFontName(tp.getTreeFont().getName());
981 tree.setFontSize(tp.getTreeFont().getSize());
982 tree.setFontStyle(tp.getTreeFont().getStyle());
983 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
985 tree.setShowBootstrap(tp.bootstrapMenu.getState());
986 tree.setShowDistances(tp.distanceMenu.getState());
988 tree.setHeight(tp.getHeight());
989 tree.setWidth(tp.getWidth());
990 tree.setXpos(tp.getX());
991 tree.setYpos(tp.getY());
992 tree.setId(makeHashCode(tp, null));
1002 * store forward refs from an annotationRow to any groups
1004 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<SequenceGroup, String>();
1007 for (SequenceI sq : jal.getSequences())
1009 // Store annotation on dataset sequences only
1010 AlignmentAnnotation[] aa = sq.getAnnotation();
1011 if (aa != null && aa.length > 0)
1013 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1020 if (jal.getAlignmentAnnotation() != null)
1022 // Store the annotation shown on the alignment.
1023 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1024 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1029 if (jal.getGroups() != null)
1031 JGroup[] groups = new JGroup[jal.getGroups().size()];
1033 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1035 JGroup jGroup = new JGroup();
1036 groups[++i] = jGroup;
1038 jGroup.setStart(sg.getStartRes());
1039 jGroup.setEnd(sg.getEndRes());
1040 jGroup.setName(sg.getName());
1041 if (groupRefs.containsKey(sg))
1043 // group has references so set its ID field
1044 jGroup.setId(groupRefs.get(sg));
1048 if (sg.cs.conservationApplied())
1050 jGroup.setConsThreshold(sg.cs.getConservationInc());
1052 if (sg.cs instanceof jalview.schemes.UserColourScheme)
1054 jGroup.setColour(setUserColourScheme(sg.cs, userColours, jms));
1058 jGroup.setColour(ColourSchemeProperty.getColourName(sg.cs));
1061 else if (sg.cs instanceof jalview.schemes.AnnotationColourGradient)
1063 jGroup.setColour("AnnotationColourGradient");
1064 jGroup.setAnnotationColours(constructAnnotationColours(
1065 (jalview.schemes.AnnotationColourGradient) sg.cs,
1068 else if (sg.cs instanceof jalview.schemes.UserColourScheme)
1070 jGroup.setColour(setUserColourScheme(sg.cs, userColours, jms));
1074 jGroup.setColour(ColourSchemeProperty.getColourName(sg.cs));
1077 jGroup.setPidThreshold(sg.cs.getThreshold());
1080 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1081 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1082 jGroup.setDisplayText(sg.getDisplayText());
1083 jGroup.setColourText(sg.getColourText());
1084 jGroup.setTextCol1(sg.textColour.getRGB());
1085 jGroup.setTextCol2(sg.textColour2.getRGB());
1086 jGroup.setTextColThreshold(sg.thresholdTextColour);
1087 jGroup.setShowUnconserved(sg.getShowNonconserved());
1088 jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1089 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1090 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1091 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1092 for (SequenceI seq : sg.getSequences())
1094 jGroup.addSeq(seqHash(seq));
1098 jms.setJGroup(groups);
1102 // /////////SAVE VIEWPORT
1103 Viewport view = new Viewport();
1104 view.setTitle(ap.alignFrame.getTitle());
1105 view.setSequenceSetId(makeHashCode(av.getSequenceSetId(),
1106 av.getSequenceSetId()));
1107 view.setId(av.getViewId());
1108 if (av.getCodingComplement() != null)
1110 view.setComplementId(av.getCodingComplement().getViewId());
1112 view.setViewName(av.viewName);
1113 view.setGatheredViews(av.isGatherViewsHere());
1115 Rectangle size = ap.av.getExplodedGeometry();
1116 Rectangle position = size;
1119 size = ap.alignFrame.getBounds();
1120 if (av.getCodingComplement() != null)
1122 position = ((SplitFrame) ap.alignFrame.getSplitViewContainer())
1130 view.setXpos(position.x);
1131 view.setYpos(position.y);
1133 view.setWidth(size.width);
1134 view.setHeight(size.height);
1136 view.setStartRes(av.startRes);
1137 view.setStartSeq(av.startSeq);
1139 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1141 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1144 else if (av.getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1146 AnnotationColours ac = constructAnnotationColours(
1147 (jalview.schemes.AnnotationColourGradient) av
1148 .getGlobalColourScheme(),
1151 view.setAnnotationColours(ac);
1152 view.setBgColour("AnnotationColourGradient");
1156 view.setBgColour(ColourSchemeProperty.getColourName(av
1157 .getGlobalColourScheme()));
1160 ColourSchemeI cs = av.getGlobalColourScheme();
1164 if (cs.conservationApplied())
1166 view.setConsThreshold(cs.getConservationInc());
1167 if (cs instanceof jalview.schemes.UserColourScheme)
1169 view.setBgColour(setUserColourScheme(cs, userColours, jms));
1173 if (cs instanceof ResidueColourScheme)
1175 view.setPidThreshold(cs.getThreshold());
1179 view.setConservationSelected(av.getConservationSelected());
1180 view.setPidSelected(av.getAbovePIDThreshold());
1181 view.setFontName(av.font.getName());
1182 view.setFontSize(av.font.getSize());
1183 view.setFontStyle(av.font.getStyle());
1184 view.setScaleProteinAsCdna(av.getViewStyle().isScaleProteinAsCdna());
1185 view.setRenderGaps(av.isRenderGaps());
1186 view.setShowAnnotation(av.isShowAnnotation());
1187 view.setShowBoxes(av.getShowBoxes());
1188 view.setShowColourText(av.getColourText());
1189 view.setShowFullId(av.getShowJVSuffix());
1190 view.setRightAlignIds(av.isRightAlignIds());
1191 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1192 view.setShowText(av.getShowText());
1193 view.setShowUnconserved(av.getShowUnconserved());
1194 view.setWrapAlignment(av.getWrapAlignment());
1195 view.setTextCol1(av.getTextColour().getRGB());
1196 view.setTextCol2(av.getTextColour2().getRGB());
1197 view.setTextColThreshold(av.getThresholdTextColour());
1198 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1199 view.setShowSequenceLogo(av.isShowSequenceLogo());
1200 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1201 view.setShowGroupConsensus(av.isShowGroupConsensus());
1202 view.setShowGroupConservation(av.isShowGroupConservation());
1203 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1204 view.setShowDbRefTooltip(av.isShowDBRefs());
1205 view.setFollowHighlight(av.isFollowHighlight());
1206 view.setFollowSelection(av.followSelection);
1207 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1208 if (av.getFeaturesDisplayed() != null)
1210 jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
1212 String[] renderOrder = ap.getSeqPanel().seqCanvas
1213 .getFeatureRenderer().getRenderOrder()
1214 .toArray(new String[0]);
1216 Vector<String> settingsAdded = new Vector<String>();
1217 if (renderOrder != null)
1219 for (String featureType : renderOrder)
1221 FeatureColourI fcol = ap.getSeqPanel().seqCanvas
1222 .getFeatureRenderer()
1223 .getFeatureStyle(featureType);
1224 Setting setting = new Setting();
1225 setting.setType(featureType);
1226 if (!fcol.isSimpleColour())
1228 setting.setColour(fcol.getMaxColour().getRGB());
1229 setting.setMincolour(fcol.getMinColour().getRGB());
1230 setting.setMin(fcol.getMin());
1231 setting.setMax(fcol.getMax());
1232 setting.setColourByLabel(fcol.isColourByLabel());
1233 setting.setAutoScale(fcol.isAutoScaled());
1234 setting.setThreshold(fcol.getThreshold());
1235 // -1 = No threshold, 0 = Below, 1 = Above
1236 setting.setThreshstate(fcol.isAboveThreshold() ? 1
1237 : (fcol.isBelowThreshold() ? 0 : -1));
1241 setting.setColour(fcol.getColour().getRGB());
1244 setting.setDisplay(av.getFeaturesDisplayed().isVisible(
1246 float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1247 .getOrder(featureType);
1250 setting.setOrder(rorder);
1252 fs.addSetting(setting);
1253 settingsAdded.addElement(featureType);
1257 // is groups actually supposed to be a map here ?
1258 Iterator<String> en = ap.getSeqPanel().seqCanvas
1259 .getFeatureRenderer()
1260 .getFeatureGroups().iterator();
1261 Vector<String> groupsAdded = new Vector<String>();
1262 while (en.hasNext())
1264 String grp = en.next();
1265 if (groupsAdded.contains(grp))
1269 Group g = new Group();
1271 g.setDisplay(((Boolean) ap.getSeqPanel().seqCanvas
1272 .getFeatureRenderer().checkGroupVisibility(grp, false))
1275 groupsAdded.addElement(grp);
1277 jms.setFeatureSettings(fs);
1280 if (av.hasHiddenColumns())
1282 if (av.getColumnSelection() == null
1283 || av.getColumnSelection().getHiddenColumns() == null)
1285 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1289 for (int c = 0; c < av.getColumnSelection().getHiddenColumns()
1292 int[] region = av.getColumnSelection().getHiddenColumns()
1294 HiddenColumns hc = new HiddenColumns();
1295 hc.setStart(region[0]);
1296 hc.setEnd(region[1]);
1297 view.addHiddenColumns(hc);
1301 if (calcIdSet.size() > 0)
1303 for (String calcId : calcIdSet)
1305 if (calcId.trim().length() > 0)
1307 CalcIdParam cidp = createCalcIdParam(calcId, av);
1308 // Some calcIds have no parameters.
1311 view.addCalcIdParam(cidp);
1317 jms.addViewport(view);
1319 object.setJalviewModelSequence(jms);
1320 object.getVamsasModel().addSequenceSet(vamsasSet);
1322 if (jout != null && fileName != null)
1324 // We may not want to write the object to disk,
1325 // eg we can copy the alignViewport to a new view object
1326 // using save and then load
1329 System.out.println("Writing jar entry " + fileName);
1330 JarEntry entry = new JarEntry(fileName);
1331 jout.putNextEntry(entry);
1332 PrintWriter pout = new PrintWriter(new OutputStreamWriter(jout,
1334 Marshaller marshaller = new Marshaller(pout);
1335 marshaller.marshal(object);
1338 } catch (Exception ex)
1340 // TODO: raise error in GUI if marshalling failed.
1341 ex.printStackTrace();
1348 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1349 * for each viewer, with
1351 * <li>viewer geometry (position, size, split pane divider location)</li>
1352 * <li>index of the selected structure in the viewer (currently shows gapped
1354 * <li>the id of the annotation holding RNA secondary structure</li>
1355 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1357 * Varna viewer state is also written out (in native Varna XML) to separate
1358 * project jar entries. A separate entry is written for each RNA structure
1359 * displayed, with the naming convention
1361 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
1369 * @param storeDataset
1371 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
1372 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
1373 boolean storeDataset)
1375 if (Desktop.desktop == null)
1379 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1380 for (int f = frames.length - 1; f > -1; f--)
1382 if (frames[f] instanceof AppVarna)
1384 AppVarna varna = (AppVarna) frames[f];
1386 * link the sequence to every viewer that is showing it and is linked to
1387 * its alignment panel
1389 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1391 String viewId = varna.getViewId();
1392 RnaViewer rna = new RnaViewer();
1393 rna.setViewId(viewId);
1394 rna.setTitle(varna.getTitle());
1395 rna.setXpos(varna.getX());
1396 rna.setYpos(varna.getY());
1397 rna.setWidth(varna.getWidth());
1398 rna.setHeight(varna.getHeight());
1399 rna.setDividerLocation(varna.getDividerLocation());
1400 rna.setSelectedRna(varna.getSelectedIndex());
1401 jseq.addRnaViewer(rna);
1404 * Store each Varna panel's state once in the project per sequence.
1405 * First time through only (storeDataset==false)
1407 // boolean storeSessions = false;
1408 // String sequenceViewId = viewId + seqsToIds.get(jds);
1409 // if (!storeDataset && !viewIds.contains(sequenceViewId))
1411 // viewIds.add(sequenceViewId);
1412 // storeSessions = true;
1414 for (RnaModel model : varna.getModels())
1416 if (model.seq == jds)
1419 * VARNA saves each view (sequence or alignment secondary
1420 * structure, gapped or trimmed) as a separate XML file
1422 String jarEntryName = rnaSessions.get(model);
1423 if (jarEntryName == null)
1426 String varnaStateFile = varna.getStateInfo(model.rna);
1427 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
1428 copyFileToJar(jout, varnaStateFile, jarEntryName);
1429 rnaSessions.put(model, jarEntryName);
1431 SecondaryStructure ss = new SecondaryStructure();
1432 String annotationId = varna.getAnnotation(jds).annotationId;
1433 ss.setAnnotationId(annotationId);
1434 ss.setViewerState(jarEntryName);
1435 ss.setGapped(model.gapped);
1436 ss.setTitle(model.title);
1437 rna.addSecondaryStructure(ss);
1446 * Copy the contents of a file to a new entry added to the output jar
1450 * @param jarEntryName
1452 protected void copyFileToJar(JarOutputStream jout, String infilePath,
1453 String jarEntryName)
1455 DataInputStream dis = null;
1458 File file = new File(infilePath);
1459 if (file.exists() && jout != null)
1461 dis = new DataInputStream(new FileInputStream(file));
1462 byte[] data = new byte[(int) file.length()];
1463 dis.readFully(data);
1464 writeJarEntry(jout, jarEntryName, data);
1466 } catch (Exception ex)
1468 ex.printStackTrace();
1476 } catch (IOException e)
1485 * Write the data to a new entry of given name in the output jar file
1488 * @param jarEntryName
1490 * @throws IOException
1492 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
1493 byte[] data) throws IOException
1497 System.out.println("Writing jar entry " + jarEntryName);
1498 jout.putNextEntry(new JarEntry(jarEntryName));
1499 DataOutputStream dout = new DataOutputStream(jout);
1500 dout.write(data, 0, data.length);
1507 * Save the state of a structure viewer
1512 * the archive XML element under which to save the state
1515 * @param matchedFile
1519 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
1520 Pdbids pdb, PDBEntry entry, List<String> viewIds,
1521 String matchedFile, StructureViewerBase viewFrame)
1523 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
1526 * Look for any bindings for this viewer to the PDB file of interest
1527 * (including part matches excluding chain id)
1529 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
1531 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
1532 final String pdbId = pdbentry.getId();
1533 if (!pdbId.equals(entry.getId())
1534 && !(entry.getId().length() > 4 && entry.getId()
1535 .toLowerCase().startsWith(pdbId.toLowerCase())))
1538 * not interested in a binding to a different PDB entry here
1542 if (matchedFile == null)
1544 matchedFile = pdbentry.getFile();
1546 else if (!matchedFile.equals(pdbentry.getFile()))
1549 .warn("Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
1550 + pdbentry.getFile());
1554 // can get at it if the ID
1555 // match is ambiguous (e.g.
1558 for (int smap = 0; smap < viewFrame.getBinding().getSequence()[peid].length; smap++)
1560 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
1561 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
1563 StructureState state = new StructureState();
1564 state.setVisible(true);
1565 state.setXpos(viewFrame.getX());
1566 state.setYpos(viewFrame.getY());
1567 state.setWidth(viewFrame.getWidth());
1568 state.setHeight(viewFrame.getHeight());
1569 final String viewId = viewFrame.getViewId();
1570 state.setViewId(viewId);
1571 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
1572 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
1573 state.setColourByJmol(viewFrame.isColouredByViewer());
1574 state.setType(viewFrame.getViewerType().toString());
1575 pdb.addStructureState(state);
1582 private AnnotationColours constructAnnotationColours(
1583 AnnotationColourGradient acg, List<UserColourScheme> userColours,
1584 JalviewModelSequence jms)
1586 AnnotationColours ac = new AnnotationColours();
1587 ac.setAboveThreshold(acg.getAboveThreshold());
1588 ac.setThreshold(acg.getAnnotationThreshold());
1589 ac.setAnnotation(acg.getAnnotation());
1590 if (acg.getBaseColour() instanceof jalview.schemes.UserColourScheme)
1592 ac.setColourScheme(setUserColourScheme(acg.getBaseColour(),
1597 ac.setColourScheme(ColourSchemeProperty.getColourName(acg
1601 ac.setMaxColour(acg.getMaxColour().getRGB());
1602 ac.setMinColour(acg.getMinColour().getRGB());
1603 ac.setPerSequence(acg.isSeqAssociated());
1604 ac.setPredefinedColours(acg.isPredefinedColours());
1608 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
1609 IdentityHashMap<SequenceGroup, String> groupRefs,
1610 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
1611 SequenceSet vamsasSet)
1614 for (int i = 0; i < aa.length; i++)
1616 Annotation an = new Annotation();
1618 AlignmentAnnotation annotation = aa[i];
1619 if (annotation.annotationId != null)
1621 annotationIds.put(annotation.annotationId, annotation);
1624 an.setId(annotation.annotationId);
1626 an.setVisible(annotation.visible);
1628 an.setDescription(annotation.description);
1630 if (annotation.sequenceRef != null)
1632 // 2.9 JAL-1781 xref on sequence id rather than name
1633 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
1635 if (annotation.groupRef != null)
1637 String groupIdr = groupRefs.get(annotation.groupRef);
1638 if (groupIdr == null)
1640 // make a locally unique String
1642 annotation.groupRef,
1643 groupIdr = ("" + System.currentTimeMillis()
1644 + annotation.groupRef.getName() + groupRefs
1647 an.setGroupRef(groupIdr.toString());
1650 // store all visualization attributes for annotation
1651 an.setGraphHeight(annotation.graphHeight);
1652 an.setCentreColLabels(annotation.centreColLabels);
1653 an.setScaleColLabels(annotation.scaleColLabel);
1654 an.setShowAllColLabels(annotation.showAllColLabels);
1655 an.setBelowAlignment(annotation.belowAlignment);
1657 if (annotation.graph > 0)
1660 an.setGraphType(annotation.graph);
1661 an.setGraphGroup(annotation.graphGroup);
1662 if (annotation.getThreshold() != null)
1664 ThresholdLine line = new ThresholdLine();
1665 line.setLabel(annotation.getThreshold().label);
1666 line.setValue(annotation.getThreshold().value);
1667 line.setColour(annotation.getThreshold().colour.getRGB());
1668 an.setThresholdLine(line);
1676 an.setLabel(annotation.label);
1678 if (annotation == av.getAlignmentQualityAnnot()
1679 || annotation == av.getAlignmentConservationAnnotation()
1680 || annotation == av.getAlignmentConsensusAnnotation()
1681 || annotation.autoCalculated)
1683 // new way of indicating autocalculated annotation -
1684 an.setAutoCalculated(annotation.autoCalculated);
1686 if (annotation.hasScore())
1688 an.setScore(annotation.getScore());
1691 if (annotation.getCalcId() != null)
1693 calcIdSet.add(annotation.getCalcId());
1694 an.setCalcId(annotation.getCalcId());
1696 if (annotation.hasProperties())
1698 for (String pr : annotation.getProperties())
1700 Property prop = new Property();
1702 prop.setValue(annotation.getProperty(pr));
1703 an.addProperty(prop);
1707 AnnotationElement ae;
1708 if (annotation.annotations != null)
1710 an.setScoreOnly(false);
1711 for (int a = 0; a < annotation.annotations.length; a++)
1713 if ((annotation == null) || (annotation.annotations[a] == null))
1718 ae = new AnnotationElement();
1719 if (annotation.annotations[a].description != null)
1721 ae.setDescription(annotation.annotations[a].description);
1723 if (annotation.annotations[a].displayCharacter != null)
1725 ae.setDisplayCharacter(annotation.annotations[a].displayCharacter);
1728 if (!Float.isNaN(annotation.annotations[a].value))
1730 ae.setValue(annotation.annotations[a].value);
1734 if (annotation.annotations[a].secondaryStructure > ' ')
1736 ae.setSecondaryStructure(annotation.annotations[a].secondaryStructure
1740 if (annotation.annotations[a].colour != null
1741 && annotation.annotations[a].colour != java.awt.Color.black)
1743 ae.setColour(annotation.annotations[a].colour.getRGB());
1746 an.addAnnotationElement(ae);
1747 if (annotation.autoCalculated)
1749 // only write one non-null entry into the annotation row -
1750 // sufficient to get the visualization attributes necessary to
1758 an.setScoreOnly(true);
1760 if (!storeDS || (storeDS && !annotation.autoCalculated))
1762 // skip autocalculated annotation - these are only provided for
1764 vamsasSet.addAnnotation(an);
1770 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
1772 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
1773 if (settings != null)
1775 CalcIdParam vCalcIdParam = new CalcIdParam();
1776 vCalcIdParam.setCalcId(calcId);
1777 vCalcIdParam.addServiceURL(settings.getServiceURI());
1778 // generic URI allowing a third party to resolve another instance of the
1779 // service used for this calculation
1780 for (String urls : settings.getServiceURLs())
1782 vCalcIdParam.addServiceURL(urls);
1784 vCalcIdParam.setVersion("1.0");
1785 if (settings.getPreset() != null)
1787 WsParamSetI setting = settings.getPreset();
1788 vCalcIdParam.setName(setting.getName());
1789 vCalcIdParam.setDescription(setting.getDescription());
1793 vCalcIdParam.setName("");
1794 vCalcIdParam.setDescription("Last used parameters");
1796 // need to be able to recover 1) settings 2) user-defined presets or
1797 // recreate settings from preset 3) predefined settings provided by
1798 // service - or settings that can be transferred (or discarded)
1799 vCalcIdParam.setParameters(settings.getWsParamFile().replace("\n",
1801 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
1802 // todo - decide if updateImmediately is needed for any projects.
1804 return vCalcIdParam;
1809 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
1812 if (calcIdParam.getVersion().equals("1.0"))
1814 Jws2Instance service = Jws2Discoverer.getDiscoverer()
1815 .getPreferredServiceFor(calcIdParam.getServiceURL());
1816 if (service != null)
1818 WsParamSetI parmSet = null;
1821 parmSet = service.getParamStore().parseServiceParameterFile(
1822 calcIdParam.getName(), calcIdParam.getDescription(),
1823 calcIdParam.getServiceURL(),
1824 calcIdParam.getParameters().replace("|\\n|", "\n"));
1825 } catch (IOException x)
1827 warn("Couldn't parse parameter data for "
1828 + calcIdParam.getCalcId(), x);
1831 List<ArgumentI> argList = null;
1832 if (calcIdParam.getName().length() > 0)
1834 parmSet = service.getParamStore()
1835 .getPreset(calcIdParam.getName());
1836 if (parmSet != null)
1838 // TODO : check we have a good match with settings in AACon -
1839 // otherwise we'll need to create a new preset
1844 argList = parmSet.getArguments();
1847 AAConSettings settings = new AAConSettings(
1848 calcIdParam.isAutoUpdate(), service, parmSet, argList);
1849 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
1850 calcIdParam.isNeedsUpdate());
1855 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
1859 throw new Error(MessageManager.formatMessage(
1860 "error.unsupported_version_calcIdparam",
1861 new Object[] { calcIdParam.toString() }));
1865 * External mapping between jalview objects and objects yielding a valid and
1866 * unique object ID string. This is null for normal Jalview project IO, but
1867 * non-null when a jalview project is being read or written as part of a
1870 IdentityHashMap jv2vobj = null;
1873 * Construct a unique ID for jvobj using either existing bindings or if none
1874 * exist, the result of the hashcode call for the object.
1877 * jalview data object
1878 * @return unique ID for referring to jvobj
1880 private String makeHashCode(Object jvobj, String altCode)
1882 if (jv2vobj != null)
1884 Object id = jv2vobj.get(jvobj);
1887 return id.toString();
1889 // check string ID mappings
1890 if (jvids2vobj != null && jvobj instanceof String)
1892 id = jvids2vobj.get(jvobj);
1896 return id.toString();
1898 // give up and warn that something has gone wrong
1899 warn("Cannot find ID for object in external mapping : " + jvobj);
1905 * return local jalview object mapped to ID, if it exists
1909 * @return null or object bound to idcode
1911 private Object retrieveExistingObj(String idcode)
1913 if (idcode != null && vobj2jv != null)
1915 return vobj2jv.get(idcode);
1921 * binding from ID strings from external mapping table to jalview data model
1924 private Hashtable vobj2jv;
1926 private Sequence createVamsasSequence(String id, SequenceI jds)
1928 return createVamsasSequence(true, id, jds, null);
1931 private Sequence createVamsasSequence(boolean recurse, String id,
1932 SequenceI jds, SequenceI parentseq)
1934 Sequence vamsasSeq = new Sequence();
1935 vamsasSeq.setId(id);
1936 vamsasSeq.setName(jds.getName());
1937 vamsasSeq.setSequence(jds.getSequenceAsString());
1938 vamsasSeq.setDescription(jds.getDescription());
1939 jalview.datamodel.DBRefEntry[] dbrefs = null;
1940 if (jds.getDatasetSequence() != null)
1942 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
1943 if (jds.getDatasetSequence().getDBRefs() != null)
1945 dbrefs = jds.getDatasetSequence().getDBRefs();
1950 vamsasSeq.setDsseqid(id); // so we can tell which sequences really are
1951 // dataset sequences only
1952 dbrefs = jds.getDBRefs();
1956 for (int d = 0; d < dbrefs.length; d++)
1958 DBRef dbref = new DBRef();
1959 dbref.setSource(dbrefs[d].getSource());
1960 dbref.setVersion(dbrefs[d].getVersion());
1961 dbref.setAccessionId(dbrefs[d].getAccessionId());
1962 if (dbrefs[d].hasMap())
1964 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
1966 dbref.setMapping(mp);
1968 vamsasSeq.addDBRef(dbref);
1974 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
1975 SequenceI parentseq, SequenceI jds, boolean recurse)
1978 if (jmp.getMap() != null)
1982 jalview.util.MapList mlst = jmp.getMap();
1983 List<int[]> r = mlst.getFromRanges();
1984 for (int[] range : r)
1986 MapListFrom mfrom = new MapListFrom();
1987 mfrom.setStart(range[0]);
1988 mfrom.setEnd(range[1]);
1989 mp.addMapListFrom(mfrom);
1991 r = mlst.getToRanges();
1992 for (int[] range : r)
1994 MapListTo mto = new MapListTo();
1995 mto.setStart(range[0]);
1996 mto.setEnd(range[1]);
1997 mp.addMapListTo(mto);
1999 mp.setMapFromUnit(mlst.getFromRatio());
2000 mp.setMapToUnit(mlst.getToRatio());
2001 if (jmp.getTo() != null)
2003 MappingChoice mpc = new MappingChoice();
2005 && (parentseq != jmp.getTo() || parentseq
2006 .getDatasetSequence() != jmp.getTo()))
2008 mpc.setSequence(createVamsasSequence(false, seqHash(jmp.getTo()),
2014 SequenceI ps = null;
2015 if (parentseq != jmp.getTo()
2016 && parentseq.getDatasetSequence() != jmp.getTo())
2018 // chaining dbref rather than a handshaking one
2019 jmpid = seqHash(ps = jmp.getTo());
2023 jmpid = seqHash(ps = parentseq);
2025 mpc.setDseqFor(jmpid);
2026 if (!seqRefIds.containsKey(mpc.getDseqFor()))
2028 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2029 seqRefIds.put(mpc.getDseqFor(), ps);
2033 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2036 mp.setMappingChoice(mpc);
2042 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2043 List<UserColourScheme> userColours, JalviewModelSequence jms)
2046 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2047 boolean newucs = false;
2048 if (!userColours.contains(ucs))
2050 userColours.add(ucs);
2053 id = "ucs" + userColours.indexOf(ucs);
2056 // actually create the scheme's entry in the XML model
2057 java.awt.Color[] colours = ucs.getColours();
2058 jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
2059 jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
2061 for (int i = 0; i < colours.length; i++)
2063 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2064 col.setName(ResidueProperties.aa[i]);
2065 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2066 jbucs.addColour(col);
2068 if (ucs.getLowerCaseColours() != null)
2070 colours = ucs.getLowerCaseColours();
2071 for (int i = 0; i < colours.length; i++)
2073 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2074 col.setName(ResidueProperties.aa[i].toLowerCase());
2075 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2076 jbucs.addColour(col);
2081 uc.setUserColourScheme(jbucs);
2082 jms.addUserColours(uc);
2088 jalview.schemes.UserColourScheme getUserColourScheme(
2089 JalviewModelSequence jms, String id)
2091 UserColours[] uc = jms.getUserColours();
2092 UserColours colours = null;
2094 for (int i = 0; i < uc.length; i++)
2096 if (uc[i].getId().equals(id))
2104 java.awt.Color[] newColours = new java.awt.Color[24];
2106 for (int i = 0; i < 24; i++)
2108 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2109 .getUserColourScheme().getColour(i).getRGB(), 16));
2112 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2115 if (colours.getUserColourScheme().getColourCount() > 24)
2117 newColours = new java.awt.Color[23];
2118 for (int i = 0; i < 23; i++)
2120 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2121 .getUserColourScheme().getColour(i + 24).getRGB(), 16));
2123 ucs.setLowerCaseColours(newColours);
2130 * contains last error message (if any) encountered by XML loader.
2132 String errorMessage = null;
2135 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2136 * exceptions are raised during project XML parsing
2138 public boolean attemptversion1parse = true;
2141 * Load a jalview project archive from a jar file
2144 * - HTTP URL or filename
2146 public AlignFrame loadJalviewAlign(final String file)
2149 jalview.gui.AlignFrame af = null;
2153 // create list to store references for any new Jmol viewers created
2154 newStructureViewers = new Vector<JalviewStructureDisplayI>();
2155 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2156 // Workaround is to make sure caller implements the JarInputStreamProvider
2158 // so we can re-open the jar input stream for each entry.
2160 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2161 af = loadJalviewAlign(jprovider);
2163 } catch (MalformedURLException e)
2165 errorMessage = "Invalid URL format for '" + file + "'";
2171 SwingUtilities.invokeAndWait(new Runnable()
2176 setLoadingFinishedForNewStructureViewers();
2179 } catch (Exception x)
2181 System.err.println("Error loading alignment: " + x.getMessage());
2187 private jarInputStreamProvider createjarInputStreamProvider(
2188 final String file) throws MalformedURLException
2191 errorMessage = null;
2192 uniqueSetSuffix = null;
2194 viewportsAdded.clear();
2195 frefedSequence = null;
2197 if (file.startsWith("http://"))
2199 url = new URL(file);
2201 final URL _url = url;
2202 return new jarInputStreamProvider()
2206 public JarInputStream getJarInputStream() throws IOException
2210 return new JarInputStream(_url.openStream());
2214 return new JarInputStream(new FileInputStream(file));
2219 public String getFilename()
2227 * Recover jalview session from a jalview project archive. Caller may
2228 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2229 * themselves. Any null fields will be initialised with default values,
2230 * non-null fields are left alone.
2235 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2237 errorMessage = null;
2238 if (uniqueSetSuffix == null)
2240 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2242 if (seqRefIds == null)
2244 seqRefIds = new HashMap<String, SequenceI>();
2246 if (frefedSequence == null)
2248 frefedSequence = new Vector<Object[]>();
2251 AlignFrame af = null, _af = null;
2252 Map<String, AlignFrame> gatherToThisFrame = new HashMap<String, AlignFrame>();
2253 final String file = jprovider.getFilename();
2256 JarInputStream jin = null;
2257 JarEntry jarentry = null;
2262 jin = jprovider.getJarInputStream();
2263 for (int i = 0; i < entryCount; i++)
2265 jarentry = jin.getNextJarEntry();
2268 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2270 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2271 JalviewModel object = new JalviewModel();
2273 Unmarshaller unmar = new Unmarshaller(object);
2274 unmar.setValidation(false);
2275 object = (JalviewModel) unmar.unmarshal(in);
2276 if (true) // !skipViewport(object))
2278 _af = loadFromObject(object, file, true, jprovider);
2280 && object.getJalviewModelSequence().getViewportCount() > 0)
2284 // store a reference to the first view
2287 if (_af.viewport.isGatherViewsHere())
2289 // if this is a gathered view, keep its reference since
2290 // after gathering views, only this frame will remain
2292 gatherToThisFrame.put(_af.viewport.getSequenceSetId(), _af);
2298 else if (jarentry != null)
2300 // Some other file here.
2303 } while (jarentry != null);
2304 resolveFrefedSequences();
2305 } catch (IOException ex)
2307 ex.printStackTrace();
2308 errorMessage = "Couldn't locate Jalview XML file : " + file;
2309 System.err.println("Exception whilst loading jalview XML file : "
2311 } catch (Exception ex)
2313 System.err.println("Parsing as Jalview Version 2 file failed.");
2314 ex.printStackTrace(System.err);
2315 if (attemptversion1parse)
2317 // Is Version 1 Jar file?
2320 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
2321 } catch (Exception ex2)
2323 System.err.println("Exception whilst loading as jalviewXMLV1:");
2324 ex2.printStackTrace();
2328 if (Desktop.instance != null)
2330 Desktop.instance.stopLoading();
2334 System.out.println("Successfully loaded archive file");
2337 ex.printStackTrace();
2339 System.err.println("Exception whilst loading jalview XML file : "
2341 } catch (OutOfMemoryError e)
2343 // Don't use the OOM Window here
2344 errorMessage = "Out of memory loading jalview XML file";
2345 System.err.println("Out of memory whilst loading jalview XML file");
2346 e.printStackTrace();
2349 if (Desktop.instance != null)
2351 Desktop.instance.stopLoading();
2355 * Regather multiple views (with the same sequence set id) to the frame (if
2356 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2357 * views instead of separate frames. Note this doesn't restore a state where
2358 * some expanded views in turn have tabbed views - the last "first tab" read
2359 * in will play the role of gatherer for all.
2361 for (AlignFrame fr : gatherToThisFrame.values())
2363 Desktop.instance.gatherViews(fr);
2366 restoreSplitFrames();
2368 if (errorMessage != null)
2376 * Try to reconstruct and display SplitFrame windows, where each contains
2377 * complementary dna and protein alignments. Done by pairing up AlignFrame
2378 * objects (created earlier) which have complementary viewport ids associated.
2380 protected void restoreSplitFrames()
2382 List<SplitFrame> gatherTo = new ArrayList<SplitFrame>();
2383 List<AlignFrame> addedToSplitFrames = new ArrayList<AlignFrame>();
2384 Map<String, AlignFrame> dna = new HashMap<String, AlignFrame>();
2387 * Identify the DNA alignments
2389 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2392 AlignFrame af = candidate.getValue();
2393 if (af.getViewport().getAlignment().isNucleotide())
2395 dna.put(candidate.getKey().getId(), af);
2400 * Try to match up the protein complements
2402 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2405 AlignFrame af = candidate.getValue();
2406 if (!af.getViewport().getAlignment().isNucleotide())
2408 String complementId = candidate.getKey().getComplementId();
2409 // only non-null complements should be in the Map
2410 if (complementId != null && dna.containsKey(complementId))
2412 final AlignFrame dnaFrame = dna.get(complementId);
2413 SplitFrame sf = createSplitFrame(dnaFrame, af);
2414 addedToSplitFrames.add(dnaFrame);
2415 addedToSplitFrames.add(af);
2416 if (af.viewport.isGatherViewsHere())
2425 * Open any that we failed to pair up (which shouldn't happen!) as
2426 * standalone AlignFrame's.
2428 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2431 AlignFrame af = candidate.getValue();
2432 if (!addedToSplitFrames.contains(af))
2434 Viewport view = candidate.getKey();
2435 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
2437 System.err.println("Failed to restore view " + view.getTitle()
2438 + " to split frame");
2443 * Gather back into tabbed views as flagged.
2445 for (SplitFrame sf : gatherTo)
2447 Desktop.instance.gatherViews(sf);
2450 splitFrameCandidates.clear();
2454 * Construct and display one SplitFrame holding DNA and protein alignments.
2457 * @param proteinFrame
2460 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
2461 AlignFrame proteinFrame)
2463 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
2464 String title = MessageManager.getString("label.linked_view_title");
2465 int width = (int) dnaFrame.getBounds().getWidth();
2466 int height = (int) (dnaFrame.getBounds().getHeight()
2467 + proteinFrame.getBounds().getHeight() + 50);
2470 * SplitFrame location is saved to both enclosed frames
2472 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
2473 Desktop.addInternalFrame(splitFrame, title, width, height);
2476 * And compute cDNA consensus (couldn't do earlier with consensus as
2477 * mappings were not yet present)
2479 proteinFrame.viewport.alignmentChanged(proteinFrame.alignPanel);
2485 * check errorMessage for a valid error message and raise an error box in the
2486 * GUI or write the current errorMessage to stderr and then clear the error
2489 protected void reportErrors()
2491 reportErrors(false);
2494 protected void reportErrors(final boolean saving)
2496 if (errorMessage != null)
2498 final String finalErrorMessage = errorMessage;
2501 javax.swing.SwingUtilities.invokeLater(new Runnable()
2506 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2507 finalErrorMessage, "Error "
2508 + (saving ? "saving" : "loading")
2509 + " Jalview file", JOptionPane.WARNING_MESSAGE);
2515 System.err.println("Problem loading Jalview file: " + errorMessage);
2518 errorMessage = null;
2521 Map<String, String> alreadyLoadedPDB = new HashMap<String, String>();
2524 * when set, local views will be updated from view stored in JalviewXML
2525 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2526 * sync if this is set to true.
2528 private final boolean updateLocalViews = false;
2531 * Returns the path to a temporary file holding the PDB file for the given PDB
2532 * id. The first time of asking, searches for a file of that name in the
2533 * Jalview project jar, and copies it to a new temporary file. Any repeat
2534 * requests just return the path to the file previously created.
2540 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId)
2542 if (alreadyLoadedPDB.containsKey(pdbId))
2544 return alreadyLoadedPDB.get(pdbId).toString();
2547 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb");
2548 if (tempFile != null)
2550 alreadyLoadedPDB.put(pdbId, tempFile);
2556 * Copies the jar entry of given name to a new temporary file and returns the
2557 * path to the file, or null if the entry is not found.
2560 * @param jarEntryName
2562 * a prefix for the temporary file name, must be at least three
2566 protected String copyJarEntry(jarInputStreamProvider jprovider,
2567 String jarEntryName, String prefix)
2569 BufferedReader in = null;
2570 PrintWriter out = null;
2574 JarInputStream jin = jprovider.getJarInputStream();
2576 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2577 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2578 * FileInputStream(jprovider)); }
2581 JarEntry entry = null;
2584 entry = jin.getNextJarEntry();
2585 } while (entry != null && !entry.getName().equals(jarEntryName));
2588 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
2589 File outFile = File.createTempFile(prefix, ".tmp");
2590 outFile.deleteOnExit();
2591 out = new PrintWriter(new FileOutputStream(outFile));
2594 while ((data = in.readLine()) != null)
2599 String t = outFile.getAbsolutePath();
2604 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
2606 } catch (Exception ex)
2608 ex.printStackTrace();
2616 } catch (IOException e)
2630 private class JvAnnotRow
2632 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2639 * persisted version of annotation row from which to take vis properties
2641 public jalview.datamodel.AlignmentAnnotation template;
2644 * original position of the annotation row in the alignment
2650 * Load alignment frame from jalview XML DOM object
2655 * filename source string
2656 * @param loadTreesAndStructures
2657 * when false only create Viewport
2659 * data source provider
2660 * @return alignment frame created from view stored in DOM
2662 AlignFrame loadFromObject(JalviewModel object, String file,
2663 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
2665 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
2666 Sequence[] vamsasSeq = vamsasSet.getSequence();
2668 JalviewModelSequence jms = object.getJalviewModelSequence();
2670 Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
2673 // ////////////////////////////////
2676 List<SequenceI> hiddenSeqs = null;
2677 jalview.datamodel.Sequence jseq;
2679 List<SequenceI> tmpseqs = new ArrayList<SequenceI>();
2681 boolean multipleView = false;
2682 SequenceI referenceseqForView = null;
2683 JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
2684 int vi = 0; // counter in vamsasSeq array
2685 for (int i = 0; i < jseqs.length; i++)
2687 String seqId = jseqs[i].getId();
2689 if (seqRefIds.get(seqId) != null)
2691 tmpseqs.add(seqRefIds.get(seqId));
2692 multipleView = true;
2696 jseq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
2697 vamsasSeq[vi].getSequence());
2698 jseq.setDescription(vamsasSeq[vi].getDescription());
2699 jseq.setStart(jseqs[i].getStart());
2700 jseq.setEnd(jseqs[i].getEnd());
2701 jseq.setVamsasId(uniqueSetSuffix + seqId);
2702 seqRefIds.put(vamsasSeq[vi].getId(), jseq);
2707 if (jseqs[i].hasViewreference() && jseqs[i].getViewreference())
2709 referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
2712 if (jseqs[i].getHidden())
2714 if (hiddenSeqs == null)
2716 hiddenSeqs = new ArrayList<SequenceI>();
2719 hiddenSeqs.add(seqRefIds.get(seqId));
2724 // Create the alignment object from the sequence set
2725 // ///////////////////////////////
2726 SequenceI[] orderedSeqs = tmpseqs
2727 .toArray(new SequenceI[tmpseqs.size()]);
2729 AlignmentI al = new Alignment(orderedSeqs);
2731 if (referenceseqForView != null)
2733 al.setSeqrep(referenceseqForView);
2735 // / Add the alignment properties
2736 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
2738 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
2739 al.setProperty(ssp.getKey(), ssp.getValue());
2743 // SequenceFeatures are added to the DatasetSequence,
2744 // so we must create or recover the dataset before loading features
2745 // ///////////////////////////////
2746 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
2748 // older jalview projects do not have a dataset id.
2749 al.setDataset(null);
2753 // recover dataset - passing on flag indicating if this a 'viewless'
2754 // sequence set (a.k.a. a stored dataset for the project)
2755 recoverDatasetFor(vamsasSet, al, object.getJalviewModelSequence()
2756 .getViewportCount() == 0);
2758 // ///////////////////////////////
2760 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
2763 // load sequence features, database references and any associated PDB
2764 // structures for the alignment
2765 for (int i = 0; i < vamsasSeq.length; i++)
2767 if (jseqs[i].getFeaturesCount() > 0)
2769 Features[] features = jseqs[i].getFeatures();
2770 for (int f = 0; f < features.length; f++)
2772 jalview.datamodel.SequenceFeature sf = new jalview.datamodel.SequenceFeature(
2773 features[f].getType(), features[f].getDescription(),
2774 features[f].getStatus(), features[f].getBegin(),
2775 features[f].getEnd(), features[f].getFeatureGroup());
2777 sf.setScore(features[f].getScore());
2778 for (int od = 0; od < features[f].getOtherDataCount(); od++)
2780 OtherData keyValue = features[f].getOtherData(od);
2781 if (keyValue.getKey().startsWith("LINK"))
2783 sf.addLink(keyValue.getValue());
2787 sf.setValue(keyValue.getKey(), keyValue.getValue());
2792 al.getSequenceAt(i).getDatasetSequence().addSequenceFeature(sf);
2795 if (vamsasSeq[i].getDBRefCount() > 0)
2797 addDBRefs(al.getSequenceAt(i).getDatasetSequence(), vamsasSeq[i]);
2799 if (jseqs[i].getPdbidsCount() > 0)
2801 Pdbids[] ids = jseqs[i].getPdbids();
2802 for (int p = 0; p < ids.length; p++)
2804 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
2805 entry.setId(ids[p].getId());
2806 if (ids[p].getType() != null)
2808 if (ids[p].getType().equalsIgnoreCase("PDB"))
2810 entry.setType(PDBEntry.Type.PDB);
2814 entry.setType(PDBEntry.Type.FILE);
2817 if (ids[p].getFile() != null)
2819 if (!pdbloaded.containsKey(ids[p].getFile()))
2821 entry.setFile(loadPDBFile(jprovider, ids[p].getId()));
2825 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
2828 StructureSelectionManager.getStructureSelectionManager(
2829 Desktop.instance).registerPDBEntry(entry);
2830 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
2834 } // end !multipleview
2836 // ///////////////////////////////
2837 // LOAD SEQUENCE MAPPINGS
2839 if (vamsasSet.getAlcodonFrameCount() > 0)
2841 // TODO Potentially this should only be done once for all views of an
2843 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
2844 for (int i = 0; i < alc.length; i++)
2846 AlignedCodonFrame cf = new AlignedCodonFrame();
2847 if (alc[i].getAlcodMapCount() > 0)
2849 AlcodMap[] maps = alc[i].getAlcodMap();
2850 for (int m = 0; m < maps.length; m++)
2852 SequenceI dnaseq = seqRefIds.get(maps[m].getDnasq());
2854 jalview.datamodel.Mapping mapping = null;
2855 // attach to dna sequence reference.
2856 if (maps[m].getMapping() != null)
2858 mapping = addMapping(maps[m].getMapping());
2860 if (dnaseq != null && mapping.getTo() != null)
2862 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
2867 frefedSequence.add(new Object[] { maps[m].getDnasq(), cf,
2871 al.addCodonFrame(cf);
2876 // ////////////////////////////////
2878 List<JvAnnotRow> autoAlan = new ArrayList<JvAnnotRow>();
2881 * store any annotations which forward reference a group's ID
2883 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<String, List<AlignmentAnnotation>>();
2885 if (vamsasSet.getAnnotationCount() > 0)
2887 Annotation[] an = vamsasSet.getAnnotation();
2889 for (int i = 0; i < an.length; i++)
2891 Annotation annotation = an[i];
2894 * test if annotation is automatically calculated for this view only
2896 boolean autoForView = false;
2897 if (annotation.getLabel().equals("Quality")
2898 || annotation.getLabel().equals("Conservation")
2899 || annotation.getLabel().equals("Consensus"))
2901 // Kludge for pre 2.5 projects which lacked the autocalculated flag
2903 if (!annotation.hasAutoCalculated())
2905 annotation.setAutoCalculated(true);
2909 || (annotation.hasAutoCalculated() && annotation
2910 .isAutoCalculated()))
2912 // remove ID - we don't recover annotation from other views for
2913 // view-specific annotation
2914 annotation.setId(null);
2917 // set visiblity for other annotation in this view
2918 String annotationId = annotation.getId();
2919 if (annotationId != null && annotationIds.containsKey(annotationId))
2921 AlignmentAnnotation jda = annotationIds.get(annotationId);
2922 // in principle Visible should always be true for annotation displayed
2923 // in multiple views
2924 if (annotation.hasVisible())
2926 jda.visible = annotation.getVisible();
2929 al.addAnnotation(jda);
2933 // Construct new annotation from model.
2934 AnnotationElement[] ae = annotation.getAnnotationElement();
2935 jalview.datamodel.Annotation[] anot = null;
2936 java.awt.Color firstColour = null;
2938 if (!annotation.getScoreOnly())
2940 anot = new jalview.datamodel.Annotation[al.getWidth()];
2941 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
2943 anpos = ae[aa].getPosition();
2945 if (anpos >= anot.length)
2950 anot[anpos] = new jalview.datamodel.Annotation(
2952 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
2953 (ae[aa].getSecondaryStructure() == null || ae[aa]
2954 .getSecondaryStructure().length() == 0) ? ' '
2955 : ae[aa].getSecondaryStructure().charAt(0),
2959 // JBPNote: Consider verifying dataflow for IO of secondary
2960 // structure annotation read from Stockholm files
2961 // this was added to try to ensure that
2962 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
2964 // anot[ae[aa].getPosition()].displayCharacter = "";
2966 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
2967 if (firstColour == null)
2969 firstColour = anot[anpos].colour;
2973 jalview.datamodel.AlignmentAnnotation jaa = null;
2975 if (annotation.getGraph())
2977 float llim = 0, hlim = 0;
2978 // if (autoForView || an[i].isAutoCalculated()) {
2981 jaa = new jalview.datamodel.AlignmentAnnotation(
2982 annotation.getLabel(), annotation.getDescription(), anot,
2983 llim, hlim, annotation.getGraphType());
2985 jaa.graphGroup = annotation.getGraphGroup();
2986 jaa._linecolour = firstColour;
2987 if (annotation.getThresholdLine() != null)
2989 jaa.setThreshold(new jalview.datamodel.GraphLine(annotation
2990 .getThresholdLine().getValue(), annotation
2991 .getThresholdLine().getLabel(), new java.awt.Color(
2992 annotation.getThresholdLine().getColour())));
2995 if (autoForView || annotation.isAutoCalculated())
2997 // Hardwire the symbol display line to ensure that labels for
2998 // histograms are displayed
3004 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
3005 an[i].getDescription(), anot);
3006 jaa._linecolour = firstColour;
3008 // register new annotation
3009 if (an[i].getId() != null)
3011 annotationIds.put(an[i].getId(), jaa);
3012 jaa.annotationId = an[i].getId();
3014 // recover sequence association
3015 String sequenceRef = an[i].getSequenceRef();
3016 if (sequenceRef != null)
3018 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3019 SequenceI sequence = seqRefIds.get(sequenceRef);
3020 if (sequence == null)
3022 // in pre-2.9 projects sequence ref is to sequence name
3023 sequence = al.findName(sequenceRef);
3025 if (sequence != null)
3027 jaa.createSequenceMapping(sequence, 1, true);
3028 sequence.addAlignmentAnnotation(jaa);
3031 // and make a note of any group association
3032 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
3034 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3035 .get(an[i].getGroupRef());
3038 aal = new ArrayList<jalview.datamodel.AlignmentAnnotation>();
3039 groupAnnotRefs.put(an[i].getGroupRef(), aal);
3044 if (an[i].hasScore())
3046 jaa.setScore(an[i].getScore());
3048 if (an[i].hasVisible())
3050 jaa.visible = an[i].getVisible();
3053 if (an[i].hasCentreColLabels())
3055 jaa.centreColLabels = an[i].getCentreColLabels();
3058 if (an[i].hasScaleColLabels())
3060 jaa.scaleColLabel = an[i].getScaleColLabels();
3062 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
3064 // newer files have an 'autoCalculated' flag and store calculation
3065 // state in viewport properties
3066 jaa.autoCalculated = true; // means annotation will be marked for
3067 // update at end of load.
3069 if (an[i].hasGraphHeight())
3071 jaa.graphHeight = an[i].getGraphHeight();
3073 if (an[i].hasBelowAlignment())
3075 jaa.belowAlignment = an[i].isBelowAlignment();
3077 jaa.setCalcId(an[i].getCalcId());
3078 if (an[i].getPropertyCount() > 0)
3080 for (jalview.schemabinding.version2.Property prop : an[i]
3083 jaa.setProperty(prop.getName(), prop.getValue());
3086 if (jaa.autoCalculated)
3088 autoAlan.add(new JvAnnotRow(i, jaa));
3091 // if (!autoForView)
3093 // add autocalculated group annotation and any user created annotation
3095 al.addAnnotation(jaa);
3099 // ///////////////////////
3101 // Create alignment markup and styles for this view
3102 if (jms.getJGroupCount() > 0)
3104 JGroup[] groups = jms.getJGroup();
3105 boolean addAnnotSchemeGroup = false;
3106 for (int i = 0; i < groups.length; i++)
3108 JGroup jGroup = groups[i];
3109 ColourSchemeI cs = null;
3110 if (jGroup.getColour() != null)
3112 if (jGroup.getColour().startsWith("ucs"))
3114 cs = getUserColourScheme(jms, jGroup.getColour());
3116 else if (jGroup.getColour().equals("AnnotationColourGradient")
3117 && jGroup.getAnnotationColours() != null)
3119 addAnnotSchemeGroup = true;
3124 cs = ColourSchemeProperty.getColour(al, jGroup.getColour());
3129 cs.setThreshold(jGroup.getPidThreshold(), true);
3133 Vector<SequenceI> seqs = new Vector<SequenceI>();
3135 for (int s = 0; s < jGroup.getSeqCount(); s++)
3137 String seqId = jGroup.getSeq(s) + "";
3138 SequenceI ts = seqRefIds.get(seqId);
3142 seqs.addElement(ts);
3146 if (seqs.size() < 1)
3151 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3152 jGroup.getDisplayBoxes(), jGroup.getDisplayText(),
3153 jGroup.getColourText(), jGroup.getStart(), jGroup.getEnd());
3155 sg.setOutlineColour(new java.awt.Color(jGroup.getOutlineColour()));
3157 sg.textColour = new java.awt.Color(jGroup.getTextCol1());
3158 sg.textColour2 = new java.awt.Color(jGroup.getTextCol2());
3159 sg.setShowNonconserved(jGroup.hasShowUnconserved() ? jGroup
3160 .isShowUnconserved() : false);
3161 sg.thresholdTextColour = jGroup.getTextColThreshold();
3162 if (jGroup.hasShowConsensusHistogram())
3164 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3167 if (jGroup.hasShowSequenceLogo())
3169 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3171 if (jGroup.hasNormaliseSequenceLogo())
3173 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3175 if (jGroup.hasIgnoreGapsinConsensus())
3177 sg.setIgnoreGapsConsensus(jGroup.getIgnoreGapsinConsensus());
3179 if (jGroup.getConsThreshold() != 0)
3181 jalview.analysis.Conservation c = new jalview.analysis.Conservation(
3182 "All", ResidueProperties.propHash, 3,
3183 sg.getSequences(null), 0, sg.getWidth() - 1);
3185 c.verdict(false, 25);
3186 sg.cs.setConservation(c);
3189 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3191 // re-instate unique group/annotation row reference
3192 List<AlignmentAnnotation> jaal = groupAnnotRefs.get(jGroup
3196 for (AlignmentAnnotation jaa : jaal)
3199 if (jaa.autoCalculated)
3201 // match up and try to set group autocalc alignment row for this
3203 if (jaa.label.startsWith("Consensus for "))
3205 sg.setConsensus(jaa);
3207 // match up and try to set group autocalc alignment row for this
3209 if (jaa.label.startsWith("Conservation for "))
3211 sg.setConservationRow(jaa);
3218 if (addAnnotSchemeGroup)
3220 // reconstruct the annotation colourscheme
3221 sg.cs = constructAnnotationColour(jGroup.getAnnotationColours(),
3222 null, al, jms, false);
3228 // only dataset in this model, so just return.
3231 // ///////////////////////////////
3234 // If we just load in the same jar file again, the sequenceSetId
3235 // will be the same, and we end up with multiple references
3236 // to the same sequenceSet. We must modify this id on load
3237 // so that each load of the file gives a unique id
3238 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3239 String viewId = (view.getId() == null ? null : view.getId()
3241 AlignFrame af = null;
3242 AlignViewport av = null;
3243 // now check to see if we really need to create a new viewport.
3244 if (multipleView && viewportsAdded.size() == 0)
3246 // We recovered an alignment for which a viewport already exists.
3247 // TODO: fix up any settings necessary for overlaying stored state onto
3248 // state recovered from another document. (may not be necessary).
3249 // we may need a binding from a viewport in memory to one recovered from
3251 // and then recover its containing af to allow the settings to be applied.
3252 // TODO: fix for vamsas demo
3254 .println("About to recover a viewport for existing alignment: Sequence set ID is "
3256 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3257 if (seqsetobj != null)
3259 if (seqsetobj instanceof String)
3261 uniqueSeqSetId = (String) seqsetobj;
3263 .println("Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
3269 .println("Warning : Collision between sequence set ID string and existing jalview object mapping.");
3275 * indicate that annotation colours are applied across all groups (pre
3276 * Jalview 2.8.1 behaviour)
3278 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan(
3279 "2.8.1", object.getVersion());
3281 AlignmentPanel ap = null;
3282 boolean isnewview = true;
3285 // Check to see if this alignment already has a view id == viewId
3286 jalview.gui.AlignmentPanel views[] = Desktop
3287 .getAlignmentPanels(uniqueSeqSetId);
3288 if (views != null && views.length > 0)
3290 for (int v = 0; v < views.length; v++)
3292 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
3294 // recover the existing alignpanel, alignframe, viewport
3295 af = views[v].alignFrame;
3298 // TODO: could even skip resetting view settings if we don't want to
3299 // change the local settings from other jalview processes
3308 af = loadViewport(file, jseqs, hiddenSeqs, al, jms, view,
3309 uniqueSeqSetId, viewId, autoAlan);
3315 * Load any trees, PDB structures and viewers
3317 * Not done if flag is false (when this method is used for New View)
3319 if (loadTreesAndStructures)
3321 loadTrees(jms, view, af, av, ap);
3322 loadPDBStructures(jprovider, jseqs, af, ap);
3323 loadRnaViewers(jprovider, jseqs, ap);
3325 // and finally return.
3330 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
3331 * panel is restored from separate jar entries, two (gapped and trimmed) per
3332 * sequence and secondary structure.
3334 * Currently each viewer shows just one sequence and structure (gapped and
3335 * trimmed), however this method is designed to support multiple sequences or
3336 * structures in viewers if wanted in future.
3342 private void loadRnaViewers(jarInputStreamProvider jprovider,
3343 JSeq[] jseqs, AlignmentPanel ap)
3346 * scan the sequences for references to viewers; create each one the first
3347 * time it is referenced, add Rna models to existing viewers
3349 for (JSeq jseq : jseqs)
3351 for (int i = 0; i < jseq.getRnaViewerCount(); i++)
3353 RnaViewer viewer = jseq.getRnaViewer(i);
3354 AppVarna appVarna = findOrCreateVarnaViewer(viewer,
3355 uniqueSetSuffix, ap);
3357 for (int j = 0; j < viewer.getSecondaryStructureCount(); j++)
3359 SecondaryStructure ss = viewer.getSecondaryStructure(j);
3360 SequenceI seq = seqRefIds.get(jseq.getId());
3361 AlignmentAnnotation ann = this.annotationIds.get(ss
3362 .getAnnotationId());
3365 * add the structure to the Varna display (with session state copied
3366 * from the jar to a temporary file)
3368 boolean gapped = ss.isGapped();
3369 String rnaTitle = ss.getTitle();
3370 String sessionState = ss.getViewerState();
3371 String tempStateFile = copyJarEntry(jprovider, sessionState,
3373 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
3374 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
3376 appVarna.setInitialSelection(viewer.getSelectedRna());
3382 * Locate and return an already instantiated matching AppVarna, or create one
3386 * @param viewIdSuffix
3390 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
3391 String viewIdSuffix, AlignmentPanel ap)
3394 * on each load a suffix is appended to the saved viewId, to avoid conflicts
3395 * if load is repeated
3397 String postLoadId = viewer.getViewId() + viewIdSuffix;
3398 for (JInternalFrame frame : getAllFrames())
3400 if (frame instanceof AppVarna)
3402 AppVarna varna = (AppVarna) frame;
3403 if (postLoadId.equals(varna.getViewId()))
3405 // this viewer is already instantiated
3406 // could in future here add ap as another 'parent' of the
3407 // AppVarna window; currently just 1-to-many
3414 * viewer not found - make it
3416 RnaViewerModel model = new RnaViewerModel(postLoadId,
3417 viewer.getTitle(), viewer.getXpos(), viewer.getYpos(),
3418 viewer.getWidth(), viewer.getHeight(),
3419 viewer.getDividerLocation());
3420 AppVarna varna = new AppVarna(model, ap);
3426 * Load any saved trees
3434 protected void loadTrees(JalviewModelSequence jms, Viewport view,
3435 AlignFrame af, AlignViewport av, AlignmentPanel ap)
3437 // TODO result of automated refactoring - are all these parameters needed?
3440 for (int t = 0; t < jms.getTreeCount(); t++)
3443 Tree tree = jms.getTree(t);
3445 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
3448 tp = af.ShowNewickTree(
3449 new jalview.io.NewickFile(tree.getNewick()),
3450 tree.getTitle(), tree.getWidth(), tree.getHeight(),
3451 tree.getXpos(), tree.getYpos());
3452 if (tree.getId() != null)
3454 // perhaps bind the tree id to something ?
3459 // update local tree attributes ?
3460 // TODO: should check if tp has been manipulated by user - if so its
3461 // settings shouldn't be modified
3462 tp.setTitle(tree.getTitle());
3463 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(), tree
3464 .getWidth(), tree.getHeight()));
3465 tp.av = av; // af.viewport; // TODO: verify 'associate with all
3468 tp.treeCanvas.av = av; // af.viewport;
3469 tp.treeCanvas.ap = ap; // af.alignPanel;
3474 warn("There was a problem recovering stored Newick tree: \n"
3475 + tree.getNewick());
3479 tp.fitToWindow.setState(tree.getFitToWindow());
3480 tp.fitToWindow_actionPerformed(null);
3482 if (tree.getFontName() != null)
3484 tp.setTreeFont(new java.awt.Font(tree.getFontName(), tree
3485 .getFontStyle(), tree.getFontSize()));
3489 tp.setTreeFont(new java.awt.Font(view.getFontName(), view
3490 .getFontStyle(), tree.getFontSize()));
3493 tp.showPlaceholders(tree.getMarkUnlinked());
3494 tp.showBootstrap(tree.getShowBootstrap());
3495 tp.showDistances(tree.getShowDistances());
3497 tp.treeCanvas.threshold = tree.getThreshold();
3499 if (tree.getCurrentTree())
3501 af.viewport.setCurrentTree(tp.getTree());
3505 } catch (Exception ex)
3507 ex.printStackTrace();
3512 * Load and link any saved structure viewers.
3519 protected void loadPDBStructures(jarInputStreamProvider jprovider,
3520 JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
3523 * Run through all PDB ids on the alignment, and collect mappings between
3524 * distinct view ids and all sequences referring to that view.
3526 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<String, StructureViewerModel>();
3528 for (int i = 0; i < jseqs.length; i++)
3530 if (jseqs[i].getPdbidsCount() > 0)
3532 Pdbids[] ids = jseqs[i].getPdbids();
3533 for (int p = 0; p < ids.length; p++)
3535 final int structureStateCount = ids[p].getStructureStateCount();
3536 for (int s = 0; s < structureStateCount; s++)
3538 // check to see if we haven't already created this structure view
3539 final StructureState structureState = ids[p]
3540 .getStructureState(s);
3541 String sviewid = (structureState.getViewId() == null) ? null
3542 : structureState.getViewId() + uniqueSetSuffix;
3543 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
3544 // Originally : ids[p].getFile()
3545 // : TODO: verify external PDB file recovery still works in normal
3546 // jalview project load
3547 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId()));
3548 jpdb.setId(ids[p].getId());
3550 int x = structureState.getXpos();
3551 int y = structureState.getYpos();
3552 int width = structureState.getWidth();
3553 int height = structureState.getHeight();
3555 // Probably don't need to do this anymore...
3556 // Desktop.desktop.getComponentAt(x, y);
3557 // TODO: NOW: check that this recovers the PDB file correctly.
3558 String pdbFile = loadPDBFile(jprovider, ids[p].getId());
3559 jalview.datamodel.SequenceI seq = seqRefIds.get(jseqs[i]
3561 if (sviewid == null)
3563 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width
3566 if (!structureViewers.containsKey(sviewid))
3568 structureViewers.put(sviewid,
3569 new StructureViewerModel(x, y, width, height, false,
3570 false, true, structureState.getViewId(),
3571 structureState.getType()));
3572 // Legacy pre-2.7 conversion JAL-823 :
3573 // do not assume any view has to be linked for colour by
3577 // assemble String[] { pdb files }, String[] { id for each
3578 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3579 // seqs_file 2}, boolean[] {
3580 // linkAlignPanel,superposeWithAlignpanel}} from hash
3581 StructureViewerModel jmoldat = structureViewers.get(sviewid);
3582 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
3583 | (structureState.hasAlignwithAlignPanel() ? structureState
3584 .getAlignwithAlignPanel() : false));
3587 * Default colour by linked panel to false if not specified (e.g.
3588 * for pre-2.7 projects)
3590 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
3591 colourWithAlignPanel |= (structureState
3592 .hasColourwithAlignPanel() ? structureState
3593 .getColourwithAlignPanel() : false);
3594 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
3597 * Default colour by viewer to true if not specified (e.g. for
3600 boolean colourByViewer = jmoldat.isColourByViewer();
3601 colourByViewer &= structureState.hasColourByJmol() ? structureState
3602 .getColourByJmol() : true;
3603 jmoldat.setColourByViewer(colourByViewer);
3605 if (jmoldat.getStateData().length() < structureState
3606 .getContent().length())
3609 jmoldat.setStateData(structureState.getContent());
3612 if (ids[p].getFile() != null)
3614 File mapkey = new File(ids[p].getFile());
3615 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
3616 if (seqstrmaps == null)
3618 jmoldat.getFileData().put(
3620 seqstrmaps = jmoldat.new StructureData(pdbFile,
3623 if (!seqstrmaps.getSeqList().contains(seq))
3625 seqstrmaps.getSeqList().add(seq);
3631 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");
3638 // Instantiate the associated structure views
3639 for (Entry<String, StructureViewerModel> entry : structureViewers
3644 createOrLinkStructureViewer(entry, af, ap, jprovider);
3645 } catch (Exception e)
3647 System.err.println("Error loading structure viewer: "
3649 // failed - try the next one
3661 protected void createOrLinkStructureViewer(
3662 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3663 AlignmentPanel ap, jarInputStreamProvider jprovider)
3665 final StructureViewerModel stateData = viewerData.getValue();
3668 * Search for any viewer windows already open from other alignment views
3669 * that exactly match the stored structure state
3671 StructureViewerBase comp = findMatchingViewer(viewerData);
3675 linkStructureViewer(ap, comp, stateData);
3680 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
3681 * "viewer_"+stateData.viewId
3683 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
3685 createChimeraViewer(viewerData, af, jprovider);
3690 * else Jmol (if pre-2.9, stateData contains JMOL state string)
3692 createJmolViewer(viewerData, af, jprovider);
3697 * Create a new Chimera viewer.
3703 protected void createChimeraViewer(
3704 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3705 jarInputStreamProvider jprovider)
3707 StructureViewerModel data = viewerData.getValue();
3708 String chimeraSessionFile = data.getStateData();
3711 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
3713 * NB this is the 'saved' viewId as in the project file XML, _not_ the
3714 * 'uniquified' sviewid used to reconstruct the viewer here
3716 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
3717 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
3720 Set<Entry<File, StructureData>> fileData = data.getFileData()
3722 List<PDBEntry> pdbs = new ArrayList<PDBEntry>();
3723 List<SequenceI[]> allseqs = new ArrayList<SequenceI[]>();
3724 for (Entry<File, StructureData> pdb : fileData)
3726 String filePath = pdb.getValue().getFilePath();
3727 String pdbId = pdb.getValue().getPdbId();
3728 // pdbs.add(new PDBEntry(filePath, pdbId));
3729 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
3730 final List<SequenceI> seqList = pdb.getValue().getSeqList();
3731 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
3735 boolean colourByChimera = data.isColourByViewer();
3736 boolean colourBySequence = data.isColourWithAlignPanel();
3738 // TODO use StructureViewer as a factory here, see JAL-1761
3739 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
3740 final SequenceI[][] seqsArray = allseqs.toArray(new SequenceI[allseqs
3742 String newViewId = viewerData.getKey();
3744 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
3745 af.alignPanel, pdbArray, seqsArray, colourByChimera,
3746 colourBySequence, newViewId);
3747 cvf.setSize(data.getWidth(), data.getHeight());
3748 cvf.setLocation(data.getX(), data.getY());
3752 * Create a new Jmol window. First parse the Jmol state to translate filenames
3753 * loaded into the view, and record the order in which files are shown in the
3754 * Jmol view, so we can add the sequence mappings in same order.
3760 protected void createJmolViewer(
3761 final Entry<String, StructureViewerModel> viewerData,
3762 AlignFrame af, jarInputStreamProvider jprovider)
3764 final StructureViewerModel svattrib = viewerData.getValue();
3765 String state = svattrib.getStateData();
3768 * Pre-2.9: state element value is the Jmol state string
3770 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
3773 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
3775 state = readJarEntry(jprovider,
3776 getViewerJarEntryName(svattrib.getViewId()));
3779 List<String> pdbfilenames = new ArrayList<String>();
3780 List<SequenceI[]> seqmaps = new ArrayList<SequenceI[]>();
3781 List<String> pdbids = new ArrayList<String>();
3782 StringBuilder newFileLoc = new StringBuilder(64);
3783 int cp = 0, ncp, ecp;
3784 Map<File, StructureData> oldFiles = svattrib.getFileData();
3785 while ((ncp = state.indexOf("load ", cp)) > -1)
3789 // look for next filename in load statement
3790 newFileLoc.append(state.substring(cp,
3791 ncp = (state.indexOf("\"", ncp + 1) + 1)));
3792 String oldfilenam = state.substring(ncp,
3793 ecp = state.indexOf("\"", ncp));
3794 // recover the new mapping data for this old filename
3795 // have to normalize filename - since Jmol and jalview do
3797 // translation differently.
3798 StructureData filedat = oldFiles.get(new File(oldfilenam));
3799 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
3800 pdbfilenames.add(filedat.getFilePath());
3801 pdbids.add(filedat.getPdbId());
3802 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
3803 newFileLoc.append("\"");
3804 cp = ecp + 1; // advance beyond last \" and set cursor so we can
3805 // look for next file statement.
3806 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
3810 // just append rest of state
3811 newFileLoc.append(state.substring(cp));
3815 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
3816 newFileLoc = new StringBuilder(state);
3817 newFileLoc.append("; load append ");
3818 for (File id : oldFiles.keySet())
3820 // add this and any other pdb files that should be present in
3822 StructureData filedat = oldFiles.get(id);
3823 newFileLoc.append(filedat.getFilePath());
3824 pdbfilenames.add(filedat.getFilePath());
3825 pdbids.add(filedat.getPdbId());
3826 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
3827 newFileLoc.append(" \"");
3828 newFileLoc.append(filedat.getFilePath());
3829 newFileLoc.append("\"");
3832 newFileLoc.append(";");
3835 if (newFileLoc.length() == 0)
3839 int histbug = newFileLoc.indexOf("history = ");
3843 * change "history = [true|false];" to "history = [1|0];"
3846 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
3847 String val = (diff == -1) ? null : newFileLoc
3848 .substring(histbug, diff);
3849 if (val != null && val.length() >= 4)
3851 if (val.contains("e")) // eh? what can it be?
3853 if (val.trim().equals("true"))
3861 newFileLoc.replace(histbug, diff, val);
3866 final String[] pdbf = pdbfilenames.toArray(new String[pdbfilenames
3868 final String[] id = pdbids.toArray(new String[pdbids.size()]);
3869 final SequenceI[][] sq = seqmaps
3870 .toArray(new SequenceI[seqmaps.size()][]);
3871 final String fileloc = newFileLoc.toString();
3872 final String sviewid = viewerData.getKey();
3873 final AlignFrame alf = af;
3874 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
3875 svattrib.getWidth(), svattrib.getHeight());
3878 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
3883 JalviewStructureDisplayI sview = null;
3886 sview = new StructureViewer(alf.alignPanel
3887 .getStructureSelectionManager()).createView(
3888 StructureViewer.ViewerType.JMOL, pdbf, id, sq,
3889 alf.alignPanel, svattrib, fileloc, rect, sviewid);
3890 addNewStructureViewer(sview);
3891 } catch (OutOfMemoryError ex)
3893 new OOMWarning("restoring structure view for PDB id " + id,
3894 (OutOfMemoryError) ex.getCause());
3895 if (sview != null && sview.isVisible())
3897 sview.closeViewer(false);
3898 sview.setVisible(false);
3904 } catch (InvocationTargetException ex)
3906 warn("Unexpected error when opening Jmol view.", ex);
3908 } catch (InterruptedException e)
3910 // e.printStackTrace();
3916 * Generates a name for the entry in the project jar file to hold state
3917 * information for a structure viewer
3922 protected String getViewerJarEntryName(String viewId)
3924 return VIEWER_PREFIX + viewId;
3928 * Returns any open frame that matches given structure viewer data. The match
3929 * is based on the unique viewId, or (for older project versions) the frame's
3935 protected StructureViewerBase findMatchingViewer(
3936 Entry<String, StructureViewerModel> viewerData)
3938 final String sviewid = viewerData.getKey();
3939 final StructureViewerModel svattrib = viewerData.getValue();
3940 StructureViewerBase comp = null;
3941 JInternalFrame[] frames = getAllFrames();
3942 for (JInternalFrame frame : frames)
3944 if (frame instanceof StructureViewerBase)
3947 * Post jalview 2.4 schema includes structure view id
3950 && ((StructureViewerBase) frame).getViewId()
3953 comp = (StructureViewerBase) frame;
3954 break; // break added in 2.9
3957 * Otherwise test for matching position and size of viewer frame
3959 else if (frame.getX() == svattrib.getX()
3960 && frame.getY() == svattrib.getY()
3961 && frame.getHeight() == svattrib.getHeight()
3962 && frame.getWidth() == svattrib.getWidth())
3964 comp = (StructureViewerBase) frame;
3965 // no break in faint hope of an exact match on viewId
3973 * Link an AlignmentPanel to an existing structure viewer.
3978 * @param useinViewerSuperpos
3979 * @param usetoColourbyseq
3980 * @param viewerColouring
3982 protected void linkStructureViewer(AlignmentPanel ap,
3983 StructureViewerBase viewer, StructureViewerModel stateData)
3985 // NOTE: if the jalview project is part of a shared session then
3986 // view synchronization should/could be done here.
3988 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
3989 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
3990 final boolean viewerColouring = stateData.isColourByViewer();
3991 Map<File, StructureData> oldFiles = stateData.getFileData();
3994 * Add mapping for sequences in this view to an already open viewer
3996 final AAStructureBindingModel binding = viewer.getBinding();
3997 for (File id : oldFiles.keySet())
3999 // add this and any other pdb files that should be present in the
4001 StructureData filedat = oldFiles.get(id);
4002 String pdbFile = filedat.getFilePath();
4003 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4004 binding.getSsm().setMapping(seq, null, pdbFile,
4005 jalview.io.AppletFormatAdapter.FILE);
4006 binding.addSequenceForStructFile(pdbFile, seq);
4008 // and add the AlignmentPanel's reference to the view panel
4009 viewer.addAlignmentPanel(ap);
4010 if (useinViewerSuperpos)
4012 viewer.useAlignmentPanelForSuperposition(ap);
4016 viewer.excludeAlignmentPanelForSuperposition(ap);
4018 if (usetoColourbyseq)
4020 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4024 viewer.excludeAlignmentPanelForColourbyseq(ap);
4029 * Get all frames within the Desktop.
4033 protected JInternalFrame[] getAllFrames()
4035 JInternalFrame[] frames = null;
4036 // TODO is this necessary - is it safe - risk of hanging?
4041 frames = Desktop.desktop.getAllFrames();
4042 } catch (ArrayIndexOutOfBoundsException e)
4044 // occasional No such child exceptions are thrown here...
4048 } catch (InterruptedException f)
4052 } while (frames == null);
4057 * Answers true if 'version' is equal to or later than 'supported', where each
4058 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4059 * changes. Development and test values for 'version' are leniently treated
4063 * - minimum version we are comparing against
4065 * - version of data being processsed
4068 public static boolean isVersionStringLaterThan(String supported,
4071 if (supported == null || version == null
4072 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4073 || version.equalsIgnoreCase("Test")
4074 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4076 System.err.println("Assuming project file with "
4077 + (version == null ? "null" : version)
4078 + " is compatible with Jalview version " + supported);
4083 return StringUtils.compareVersions(version, supported, "b") >= 0;
4087 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4089 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4091 if (newStructureViewers != null)
4093 sview.getBinding().setFinishedLoadingFromArchive(false);
4094 newStructureViewers.add(sview);
4098 protected void setLoadingFinishedForNewStructureViewers()
4100 if (newStructureViewers != null)
4102 for (JalviewStructureDisplayI sview : newStructureViewers)
4104 sview.getBinding().setFinishedLoadingFromArchive(true);
4106 newStructureViewers.clear();
4107 newStructureViewers = null;
4111 AlignFrame loadViewport(String file, JSeq[] JSEQ,
4112 List<SequenceI> hiddenSeqs, AlignmentI al,
4113 JalviewModelSequence jms, Viewport view, String uniqueSeqSetId,
4114 String viewId, List<JvAnnotRow> autoAlan)
4116 AlignFrame af = null;
4117 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
4118 uniqueSeqSetId, viewId);
4120 af.setFileName(file, "Jalview");
4122 for (int i = 0; i < JSEQ.length; i++)
4124 af.viewport.setSequenceColour(af.viewport.getAlignment()
4125 .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour()));
4130 af.getViewport().setColourByReferenceSeq(true);
4131 af.getViewport().setDisplayReferenceSeq(true);
4134 af.viewport.setGatherViewsHere(view.getGatheredViews());
4136 if (view.getSequenceSetId() != null)
4138 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4140 af.viewport.setSequenceSetId(uniqueSeqSetId);
4143 // propagate shared settings to this new view
4144 af.viewport.setHistoryList(av.getHistoryList());
4145 af.viewport.setRedoList(av.getRedoList());
4149 viewportsAdded.put(uniqueSeqSetId, af.viewport);
4151 // TODO: check if this method can be called repeatedly without
4152 // side-effects if alignpanel already registered.
4153 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4155 // apply Hidden regions to view.
4156 if (hiddenSeqs != null)
4158 for (int s = 0; s < JSEQ.length; s++)
4160 SequenceGroup hidden = new SequenceGroup();
4161 boolean isRepresentative = false;
4162 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
4164 isRepresentative = true;
4165 SequenceI sequenceToHide = al.getSequenceAt(JSEQ[s]
4166 .getHiddenSequences(r));
4167 hidden.addSequence(sequenceToHide, false);
4168 // remove from hiddenSeqs list so we don't try to hide it twice
4169 hiddenSeqs.remove(sequenceToHide);
4171 if (isRepresentative)
4173 SequenceI representativeSequence = al.getSequenceAt(s);
4174 hidden.addSequence(representativeSequence, false);
4175 af.viewport.hideRepSequences(representativeSequence, hidden);
4179 SequenceI[] hseqs = hiddenSeqs.toArray(new SequenceI[hiddenSeqs
4181 af.viewport.hideSequence(hseqs);
4184 // recover view properties and display parameters
4185 if (view.getViewName() != null)
4187 af.viewport.viewName = view.getViewName();
4188 af.setInitialTabVisible();
4190 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
4193 af.viewport.setShowAnnotation(view.getShowAnnotation());
4194 af.viewport.setAbovePIDThreshold(view.getPidSelected());
4196 af.viewport.setColourText(view.getShowColourText());
4198 af.viewport.setConservationSelected(view.getConservationSelected());
4199 af.viewport.setShowJVSuffix(view.getShowFullId());
4200 af.viewport.setRightAlignIds(view.getRightAlignIds());
4201 af.viewport.setFont(
4202 new java.awt.Font(view.getFontName(), view.getFontStyle(), view
4203 .getFontSize()), true);
4204 ViewStyleI vs = af.viewport.getViewStyle();
4205 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
4206 af.viewport.setViewStyle(vs);
4207 // TODO: allow custom charWidth/Heights to be restored by updating them
4208 // after setting font - which means set above to false
4209 af.viewport.setRenderGaps(view.getRenderGaps());
4210 af.viewport.setWrapAlignment(view.getWrapAlignment());
4211 af.viewport.setShowAnnotation(view.getShowAnnotation());
4213 af.viewport.setShowBoxes(view.getShowBoxes());
4215 af.viewport.setShowText(view.getShowText());
4217 af.viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
4218 af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
4219 af.viewport.setThresholdTextColour(view.getTextColThreshold());
4220 af.viewport.setShowUnconserved(view.hasShowUnconserved() ? view
4221 .isShowUnconserved() : false);
4222 af.viewport.setStartRes(view.getStartRes());
4223 af.viewport.setStartSeq(view.getStartSeq());
4224 af.alignPanel.updateLayout();
4225 ColourSchemeI cs = null;
4226 // apply colourschemes
4227 if (view.getBgColour() != null)
4229 if (view.getBgColour().startsWith("ucs"))
4231 cs = getUserColourScheme(jms, view.getBgColour());
4233 else if (view.getBgColour().startsWith("Annotation"))
4235 AnnotationColours viewAnnColour = view.getAnnotationColours();
4236 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
4243 cs = ColourSchemeProperty.getColour(al, view.getBgColour());
4248 cs.setThreshold(view.getPidThreshold(), true);
4249 cs.setConsensus(af.viewport.getSequenceConsensusHash());
4253 af.viewport.setGlobalColourScheme(cs);
4254 af.viewport.setColourAppliesToAllGroups(false);
4256 if (view.getConservationSelected() && cs != null)
4258 cs.setConservationInc(view.getConsThreshold());
4261 af.changeColour(cs);
4263 af.viewport.setColourAppliesToAllGroups(true);
4265 af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures());
4267 if (view.hasCentreColumnLabels())
4269 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
4271 if (view.hasIgnoreGapsinConsensus())
4273 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
4276 if (view.hasFollowHighlight())
4278 af.viewport.setFollowHighlight(view.getFollowHighlight());
4280 if (view.hasFollowSelection())
4282 af.viewport.followSelection = view.getFollowSelection();
4284 if (view.hasShowConsensusHistogram())
4286 af.viewport.setShowConsensusHistogram(view
4287 .getShowConsensusHistogram());
4291 af.viewport.setShowConsensusHistogram(true);
4293 if (view.hasShowSequenceLogo())
4295 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
4299 af.viewport.setShowSequenceLogo(false);
4301 if (view.hasNormaliseSequenceLogo())
4303 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
4305 if (view.hasShowDbRefTooltip())
4307 af.viewport.setShowDBRefs(view.getShowDbRefTooltip());
4309 if (view.hasShowNPfeatureTooltip())
4311 af.viewport.setShowNPFeats(view.hasShowNPfeatureTooltip());
4313 if (view.hasShowGroupConsensus())
4315 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
4319 af.viewport.setShowGroupConsensus(false);
4321 if (view.hasShowGroupConservation())
4323 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
4327 af.viewport.setShowGroupConservation(false);
4330 // recover featre settings
4331 if (jms.getFeatureSettings() != null)
4333 FeaturesDisplayed fdi;
4334 af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
4335 String[] renderOrder = new String[jms.getFeatureSettings()
4336 .getSettingCount()];
4337 Map<String, FeatureColourI> featureColours = new Hashtable<String, FeatureColourI>();
4338 Map<String, Float> featureOrder = new Hashtable<String, Float>();
4340 for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
4342 Setting setting = jms.getFeatureSettings().getSetting(fs);
4343 if (setting.hasMincolour())
4345 FeatureColourI gc = setting.hasMin() ? new FeatureColour(
4346 new Color(setting.getMincolour()), new Color(
4347 setting.getColour()), setting.getMin(),
4348 setting.getMax()) : new FeatureColour(new Color(
4349 setting.getMincolour()), new Color(setting.getColour()),
4351 if (setting.hasThreshold())
4353 gc.setThreshold(setting.getThreshold());
4354 int threshstate = setting.getThreshstate();
4355 // -1 = None, 0 = Below, 1 = Above threshold
4356 if (threshstate == 0)
4358 gc.setBelowThreshold(true);
4360 else if (threshstate == 1)
4362 gc.setAboveThreshold(true);
4365 gc.setAutoScaled(true); // default
4366 if (setting.hasAutoScale())
4368 gc.setAutoScaled(setting.getAutoScale());
4370 if (setting.hasColourByLabel())
4372 gc.setColourByLabel(setting.getColourByLabel());
4374 // and put in the feature colour table.
4375 featureColours.put(setting.getType(), gc);
4379 featureColours.put(setting.getType(), new FeatureColour(
4380 new Color(setting.getColour())));
4382 renderOrder[fs] = setting.getType();
4383 if (setting.hasOrder())
4385 featureOrder.put(setting.getType(), setting.getOrder());
4389 featureOrder.put(setting.getType(), new Float(fs
4390 / jms.getFeatureSettings().getSettingCount()));
4392 if (setting.getDisplay())
4394 fdi.setVisible(setting.getType());
4397 Map<String, Boolean> fgtable = new Hashtable<String, Boolean>();
4398 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
4400 Group grp = jms.getFeatureSettings().getGroup(gs);
4401 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
4403 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4404 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
4405 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
4406 FeatureRendererSettings frs = new FeatureRendererSettings(
4407 renderOrder, fgtable, featureColours, 1.0f, featureOrder);
4408 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
4409 .transferSettings(frs);
4413 if (view.getHiddenColumnsCount() > 0)
4415 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
4417 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(), view
4418 .getHiddenColumns(c).getEnd() // +1
4422 if (view.getCalcIdParam() != null)
4424 for (CalcIdParam calcIdParam : view.getCalcIdParam())
4426 if (calcIdParam != null)
4428 if (recoverCalcIdParam(calcIdParam, af.viewport))
4433 warn("Couldn't recover parameters for "
4434 + calcIdParam.getCalcId());
4439 af.setMenusFromViewport(af.viewport);
4441 // TODO: we don't need to do this if the viewport is aready visible.
4443 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
4444 * has a 'cdna/protein complement' view, in which case save it in order to
4445 * populate a SplitFrame once all views have been read in.
4447 String complementaryViewId = view.getComplementId();
4448 if (complementaryViewId == null)
4450 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
4452 // recompute any autoannotation
4453 af.alignPanel.updateAnnotation(false, true);
4454 reorderAutoannotation(af, al, autoAlan);
4455 af.alignPanel.alignmentChanged();
4459 splitFrameCandidates.put(view, af);
4464 private ColourSchemeI constructAnnotationColour(
4465 AnnotationColours viewAnnColour, AlignFrame af, AlignmentI al,
4466 JalviewModelSequence jms, boolean checkGroupAnnColour)
4468 boolean propagateAnnColour = false;
4469 ColourSchemeI cs = null;
4470 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
4471 if (checkGroupAnnColour && al.getGroups() != null
4472 && al.getGroups().size() > 0)
4474 // pre 2.8.1 behaviour
4475 // check to see if we should transfer annotation colours
4476 propagateAnnColour = true;
4477 for (jalview.datamodel.SequenceGroup sg : al.getGroups())
4479 if (sg.cs instanceof AnnotationColourGradient)
4481 propagateAnnColour = false;
4485 // int find annotation
4486 if (annAlignment.getAlignmentAnnotation() != null)
4488 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
4490 if (annAlignment.getAlignmentAnnotation()[i].label
4491 .equals(viewAnnColour.getAnnotation()))
4493 if (annAlignment.getAlignmentAnnotation()[i].getThreshold() == null)
4495 annAlignment.getAlignmentAnnotation()[i]
4496 .setThreshold(new jalview.datamodel.GraphLine(
4497 viewAnnColour.getThreshold(), "Threshold",
4498 java.awt.Color.black)
4503 if (viewAnnColour.getColourScheme().equals("None"))
4505 cs = new AnnotationColourGradient(
4506 annAlignment.getAlignmentAnnotation()[i],
4507 new java.awt.Color(viewAnnColour.getMinColour()),
4508 new java.awt.Color(viewAnnColour.getMaxColour()),
4509 viewAnnColour.getAboveThreshold());
4511 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
4513 cs = new AnnotationColourGradient(
4514 annAlignment.getAlignmentAnnotation()[i],
4515 getUserColourScheme(jms,
4516 viewAnnColour.getColourScheme()),
4517 viewAnnColour.getAboveThreshold());
4521 cs = new AnnotationColourGradient(
4522 annAlignment.getAlignmentAnnotation()[i],
4523 ColourSchemeProperty.getColour(al,
4524 viewAnnColour.getColourScheme()),
4525 viewAnnColour.getAboveThreshold());
4527 if (viewAnnColour.hasPerSequence())
4529 ((AnnotationColourGradient) cs).setSeqAssociated(viewAnnColour
4532 if (viewAnnColour.hasPredefinedColours())
4534 ((AnnotationColourGradient) cs)
4535 .setPredefinedColours(viewAnnColour
4536 .isPredefinedColours());
4538 if (propagateAnnColour && al.getGroups() != null)
4540 // Also use these settings for all the groups
4541 for (int g = 0; g < al.getGroups().size(); g++)
4543 jalview.datamodel.SequenceGroup sg = al.getGroups().get(g);
4551 * if (viewAnnColour.getColourScheme().equals("None" )) { sg.cs =
4552 * new AnnotationColourGradient(
4553 * annAlignment.getAlignmentAnnotation()[i], new
4554 * java.awt.Color(viewAnnColour. getMinColour()), new
4555 * java.awt.Color(viewAnnColour. getMaxColour()),
4556 * viewAnnColour.getAboveThreshold()); } else
4559 sg.cs = new AnnotationColourGradient(
4560 annAlignment.getAlignmentAnnotation()[i], sg.cs,
4561 viewAnnColour.getAboveThreshold());
4562 if (cs instanceof AnnotationColourGradient)
4564 if (viewAnnColour.hasPerSequence())
4566 ((AnnotationColourGradient) cs)
4567 .setSeqAssociated(viewAnnColour.isPerSequence());
4569 if (viewAnnColour.hasPredefinedColours())
4571 ((AnnotationColourGradient) cs)
4572 .setPredefinedColours(viewAnnColour
4573 .isPredefinedColours());
4589 private void reorderAutoannotation(AlignFrame af, AlignmentI al,
4590 List<JvAnnotRow> autoAlan)
4592 // copy over visualization settings for autocalculated annotation in the
4594 if (al.getAlignmentAnnotation() != null)
4597 * Kludge for magic autoannotation names (see JAL-811)
4599 String[] magicNames = new String[] { "Consensus", "Quality",
4601 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
4602 Hashtable<String, JvAnnotRow> visan = new Hashtable<String, JvAnnotRow>();
4603 for (String nm : magicNames)
4605 visan.put(nm, nullAnnot);
4607 for (JvAnnotRow auan : autoAlan)
4609 visan.put(auan.template.label
4610 + (auan.template.getCalcId() == null ? "" : "\t"
4611 + auan.template.getCalcId()), auan);
4613 int hSize = al.getAlignmentAnnotation().length;
4614 List<JvAnnotRow> reorder = new ArrayList<JvAnnotRow>();
4615 // work through any autoCalculated annotation already on the view
4616 // removing it if it should be placed in a different location on the
4617 // annotation panel.
4618 List<String> remains = new ArrayList<String>(visan.keySet());
4619 for (int h = 0; h < hSize; h++)
4621 jalview.datamodel.AlignmentAnnotation jalan = al
4622 .getAlignmentAnnotation()[h];
4623 if (jalan.autoCalculated)
4626 JvAnnotRow valan = visan.get(k = jalan.label);
4627 if (jalan.getCalcId() != null)
4629 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
4634 // delete the auto calculated row from the alignment
4635 al.deleteAnnotation(jalan, false);
4639 if (valan != nullAnnot)
4641 if (jalan != valan.template)
4643 // newly created autoannotation row instance
4644 // so keep a reference to the visible annotation row
4645 // and copy over all relevant attributes
4646 if (valan.template.graphHeight >= 0)
4649 jalan.graphHeight = valan.template.graphHeight;
4651 jalan.visible = valan.template.visible;
4653 reorder.add(new JvAnnotRow(valan.order, jalan));
4658 // Add any (possibly stale) autocalculated rows that were not appended to
4659 // the view during construction
4660 for (String other : remains)
4662 JvAnnotRow othera = visan.get(other);
4663 if (othera != nullAnnot && othera.template.getCalcId() != null
4664 && othera.template.getCalcId().length() > 0)
4666 reorder.add(othera);
4669 // now put the automatic annotation in its correct place
4670 int s = 0, srt[] = new int[reorder.size()];
4671 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
4672 for (JvAnnotRow jvar : reorder)
4675 srt[s++] = jvar.order;
4678 jalview.util.QuickSort.sort(srt, rws);
4679 // and re-insert the annotation at its correct position
4680 for (JvAnnotRow jvar : rws)
4682 al.addAnnotation(jvar.template, jvar.order);
4684 af.alignPanel.adjustAnnotationHeight();
4688 Hashtable skipList = null;
4691 * TODO remove this method
4694 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
4695 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
4696 * throw new Error("Implementation Error. No skipList defined for this
4697 * Jalview2XML instance."); } return (AlignFrame)
4698 * skipList.get(view.getSequenceSetId()); }
4702 * Check if the Jalview view contained in object should be skipped or not.
4705 * @return true if view's sequenceSetId is a key in skipList
4707 private boolean skipViewport(JalviewModel object)
4709 if (skipList == null)
4714 if (skipList.containsKey(id = object.getJalviewModelSequence()
4715 .getViewport()[0].getSequenceSetId()))
4717 if (Cache.log != null && Cache.log.isDebugEnabled())
4719 Cache.log.debug("Skipping seuqence set id " + id);
4726 public void addToSkipList(AlignFrame af)
4728 if (skipList == null)
4730 skipList = new Hashtable();
4732 skipList.put(af.getViewport().getSequenceSetId(), af);
4735 public void clearSkipList()
4737 if (skipList != null)
4744 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
4745 boolean ignoreUnrefed)
4747 jalview.datamodel.AlignmentI ds = getDatasetFor(vamsasSet
4749 Vector dseqs = null;
4752 // create a list of new dataset sequences
4753 dseqs = new Vector();
4755 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
4757 Sequence vamsasSeq = vamsasSet.getSequence(i);
4758 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed);
4760 // create a new dataset
4763 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
4764 dseqs.copyInto(dsseqs);
4765 ds = new jalview.datamodel.Alignment(dsseqs);
4766 debug("Created new dataset " + vamsasSet.getDatasetId()
4767 + " for alignment " + System.identityHashCode(al));
4768 addDatasetRef(vamsasSet.getDatasetId(), ds);
4770 // set the dataset for the newly imported alignment.
4771 if (al.getDataset() == null && !ignoreUnrefed)
4780 * sequence definition to create/merge dataset sequence for
4784 * vector to add new dataset sequence to
4786 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
4787 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed)
4789 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
4791 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
4792 SequenceI dsq = null;
4793 if (sq != null && sq.getDatasetSequence() != null)
4795 dsq = sq.getDatasetSequence();
4797 if (sq == null && ignoreUnrefed)
4801 String sqid = vamsasSeq.getDsseqid();
4804 // need to create or add a new dataset sequence reference to this sequence
4807 dsq = seqRefIds.get(sqid);
4812 // make a new dataset sequence
4813 dsq = sq.createDatasetSequence();
4816 // make up a new dataset reference for this sequence
4817 sqid = seqHash(dsq);
4819 dsq.setVamsasId(uniqueSetSuffix + sqid);
4820 seqRefIds.put(sqid, dsq);
4825 dseqs.addElement(dsq);
4830 ds.addSequence(dsq);
4836 { // make this dataset sequence sq's dataset sequence
4837 sq.setDatasetSequence(dsq);
4838 // and update the current dataset alignment
4843 if (!dseqs.contains(dsq))
4850 if (ds.findIndex(dsq) < 0)
4852 ds.addSequence(dsq);
4859 // TODO: refactor this as a merge dataset sequence function
4860 // now check that sq (the dataset sequence) sequence really is the union of
4861 // all references to it
4862 // boolean pre = sq.getStart() < dsq.getStart();
4863 // boolean post = sq.getEnd() > dsq.getEnd();
4867 // StringBuffer sb = new StringBuffer();
4868 String newres = jalview.analysis.AlignSeq.extractGaps(
4869 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
4870 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
4871 && newres.length() > dsq.getLength())
4873 // Update with the longer sequence.
4877 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
4878 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
4879 * sb.append(newres.substring(newres.length() - sq.getEnd() -
4880 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
4882 dsq.setSequence(newres);
4884 // TODO: merges will never happen if we 'know' we have the real dataset
4885 // sequence - this should be detected when id==dssid
4887 .println("DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
4888 // + (pre ? "prepended" : "") + " "
4889 // + (post ? "appended" : ""));
4895 * TODO use AlignmentI here and in related methods - needs
4896 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
4898 Hashtable<String, AlignmentI> datasetIds = null;
4900 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
4902 private AlignmentI getDatasetFor(String datasetId)
4904 if (datasetIds == null)
4906 datasetIds = new Hashtable<String, AlignmentI>();
4909 if (datasetIds.containsKey(datasetId))
4911 return datasetIds.get(datasetId);
4916 private void addDatasetRef(String datasetId, AlignmentI dataset)
4918 if (datasetIds == null)
4920 datasetIds = new Hashtable<String, AlignmentI>();
4922 datasetIds.put(datasetId, dataset);
4926 * make a new dataset ID for this jalview dataset alignment
4931 private String getDatasetIdRef(AlignmentI dataset)
4933 if (dataset.getDataset() != null)
4935 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
4937 String datasetId = makeHashCode(dataset, null);
4938 if (datasetId == null)
4940 // make a new datasetId and record it
4941 if (dataset2Ids == null)
4943 dataset2Ids = new IdentityHashMap<AlignmentI, String>();
4947 datasetId = dataset2Ids.get(dataset);
4949 if (datasetId == null)
4951 datasetId = "ds" + dataset2Ids.size() + 1;
4952 dataset2Ids.put(dataset, datasetId);
4958 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
4960 for (int d = 0; d < sequence.getDBRefCount(); d++)
4962 DBRef dr = sequence.getDBRef(d);
4963 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
4964 sequence.getDBRef(d).getSource(), sequence.getDBRef(d)
4965 .getVersion(), sequence.getDBRef(d).getAccessionId());
4966 if (dr.getMapping() != null)
4968 entry.setMap(addMapping(dr.getMapping()));
4970 datasetSequence.addDBRef(entry);
4974 private jalview.datamodel.Mapping addMapping(Mapping m)
4976 SequenceI dsto = null;
4977 // Mapping m = dr.getMapping();
4978 int fr[] = new int[m.getMapListFromCount() * 2];
4979 Enumeration f = m.enumerateMapListFrom();
4980 for (int _i = 0; f.hasMoreElements(); _i += 2)
4982 MapListFrom mf = (MapListFrom) f.nextElement();
4983 fr[_i] = mf.getStart();
4984 fr[_i + 1] = mf.getEnd();
4986 int fto[] = new int[m.getMapListToCount() * 2];
4987 f = m.enumerateMapListTo();
4988 for (int _i = 0; f.hasMoreElements(); _i += 2)
4990 MapListTo mf = (MapListTo) f.nextElement();
4991 fto[_i] = mf.getStart();
4992 fto[_i + 1] = mf.getEnd();
4994 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto,
4995 fr, fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
4996 if (m.getMappingChoice() != null)
4998 MappingChoice mc = m.getMappingChoice();
4999 if (mc.getDseqFor() != null)
5001 String dsfor = "" + mc.getDseqFor();
5002 if (seqRefIds.containsKey(dsfor))
5007 jmap.setTo(seqRefIds.get(dsfor));
5011 frefedSequence.add(new Object[] { dsfor, jmap });
5017 * local sequence definition
5019 Sequence ms = mc.getSequence();
5020 SequenceI djs = null;
5021 String sqid = ms.getDsseqid();
5022 if (sqid != null && sqid.length() > 0)
5025 * recover dataset sequence
5027 djs = seqRefIds.get(sqid);
5032 .println("Warning - making up dataset sequence id for DbRef sequence map reference");
5033 sqid = ((Object) ms).toString(); // make up a new hascode for
5034 // undefined dataset sequence hash
5035 // (unlikely to happen)
5041 * make a new dataset sequence and add it to refIds hash
5043 djs = new jalview.datamodel.Sequence(ms.getName(),
5045 djs.setStart(jmap.getMap().getToLowest());
5046 djs.setEnd(jmap.getMap().getToHighest());
5047 djs.setVamsasId(uniqueSetSuffix + sqid);
5049 seqRefIds.put(sqid, djs);
5052 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5061 public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
5062 boolean keepSeqRefs)
5065 JalviewModel jm = saveState(ap, null, null, null);
5070 jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
5074 uniqueSetSuffix = "";
5075 jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
5080 if (this.frefedSequence == null)
5082 frefedSequence = new Vector();
5085 viewportsAdded.clear();
5087 AlignFrame af = loadFromObject(jm, null, false, null);
5088 af.alignPanels.clear();
5089 af.closeMenuItem_actionPerformed(true);
5092 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5093 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5094 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5095 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5096 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5099 return af.alignPanel;
5103 * flag indicating if hashtables should be cleared on finalization TODO this
5104 * flag may not be necessary
5106 private final boolean _cleartables = true;
5108 private Hashtable jvids2vobj;
5113 * @see java.lang.Object#finalize()
5116 protected void finalize() throws Throwable
5118 // really make sure we have no buried refs left.
5123 this.seqRefIds = null;
5124 this.seqsToIds = null;
5128 private void warn(String msg)
5133 private void warn(String msg, Exception e)
5135 if (Cache.log != null)
5139 Cache.log.warn(msg, e);
5143 Cache.log.warn(msg);
5148 System.err.println("Warning: " + msg);
5151 e.printStackTrace();
5156 private void debug(String string)
5158 debug(string, null);
5161 private void debug(String msg, Exception e)
5163 if (Cache.log != null)
5167 Cache.log.debug(msg, e);
5171 Cache.log.debug(msg);
5176 System.err.println("Warning: " + msg);
5179 e.printStackTrace();
5185 * set the object to ID mapping tables used to write/recover objects and XML
5186 * ID strings for the jalview project. If external tables are provided then
5187 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
5188 * object goes out of scope. - also populates the datasetIds hashtable with
5189 * alignment objects containing dataset sequences
5192 * Map from ID strings to jalview datamodel
5194 * Map from jalview datamodel to ID strings
5198 public void setObjectMappingTables(Hashtable vobj2jv,
5199 IdentityHashMap jv2vobj)
5201 this.jv2vobj = jv2vobj;
5202 this.vobj2jv = vobj2jv;
5203 Iterator ds = jv2vobj.keySet().iterator();
5205 while (ds.hasNext())
5207 Object jvobj = ds.next();
5208 id = jv2vobj.get(jvobj).toString();
5209 if (jvobj instanceof jalview.datamodel.Alignment)
5211 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
5213 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
5216 else if (jvobj instanceof jalview.datamodel.Sequence)
5218 // register sequence object so the XML parser can recover it.
5219 if (seqRefIds == null)
5221 seqRefIds = new HashMap<String, SequenceI>();
5223 if (seqsToIds == null)
5225 seqsToIds = new IdentityHashMap<SequenceI, String>();
5227 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
5228 seqsToIds.put((SequenceI) jvobj, id);
5230 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
5233 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
5234 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
5235 if (jvann.annotationId == null)
5237 jvann.annotationId = anid;
5239 if (!jvann.annotationId.equals(anid))
5241 // TODO verify that this is the correct behaviour
5242 this.warn("Overriding Annotation ID for " + anid
5243 + " from different id : " + jvann.annotationId);
5244 jvann.annotationId = anid;
5247 else if (jvobj instanceof String)
5249 if (jvids2vobj == null)
5251 jvids2vobj = new Hashtable();
5252 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
5257 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
5263 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
5264 * objects created from the project archive. If string is null (default for
5265 * construction) then suffix will be set automatically.
5269 public void setUniqueSetSuffix(String string)
5271 uniqueSetSuffix = string;
5276 * uses skipList2 as the skipList for skipping views on sequence sets
5277 * associated with keys in the skipList
5281 public void setSkipList(Hashtable skipList2)
5283 skipList = skipList2;
5287 * Reads the jar entry of given name and returns its contents, or null if the
5288 * entry is not found.
5291 * @param jarEntryName
5294 protected String readJarEntry(jarInputStreamProvider jprovider,
5295 String jarEntryName)
5297 String result = null;
5298 BufferedReader in = null;
5303 * Reopen the jar input stream and traverse its entries to find a matching
5306 JarInputStream jin = jprovider.getJarInputStream();
5307 JarEntry entry = null;
5310 entry = jin.getNextJarEntry();
5311 } while (entry != null && !entry.getName().equals(jarEntryName));
5315 StringBuilder out = new StringBuilder(256);
5316 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
5319 while ((data = in.readLine()) != null)
5323 result = out.toString();
5327 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
5329 } catch (Exception ex)
5331 ex.printStackTrace();
5339 } catch (IOException e)
5350 * Returns an incrementing counter (0, 1, 2...)
5354 private synchronized int nextCounter()