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 (int i = 0; i < rjal.getHeight(); i++)
685 final SequenceI jds = rjal.getSequenceAt(i);
686 final SequenceI jdatasq = jds.getDatasetSequence() == null ? jds
687 : jds.getDatasetSequence();
688 String id = seqHash(jds);
690 if (seqRefIds.get(id) != null)
692 // This happens for two reasons: 1. multiple views are being serialised.
693 // 2. the hashCode has collided with another sequence's code. This DOES
694 // HAPPEN! (PF00072.15.stk does this)
695 // JBPNote: Uncomment to debug writing out of files that do not read
696 // back in due to ArrayOutOfBoundExceptions.
697 // System.err.println("vamsasSeq backref: "+id+"");
698 // System.err.println(jds.getName()+"
699 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
700 // System.err.println("Hashcode: "+seqHash(jds));
701 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
702 // System.err.println(rsq.getName()+"
703 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
704 // System.err.println("Hashcode: "+seqHash(rsq));
708 vamsasSeq = createVamsasSequence(id, jds);
709 vamsasSet.addSequence(vamsasSeq);
710 seqRefIds.put(id, jds);
714 jseq.setStart(jds.getStart());
715 jseq.setEnd(jds.getEnd());
716 jseq.setColour(av.getSequenceColour(jds).getRGB());
718 jseq.setId(id); // jseq id should be a string not a number
721 // Store any sequences this sequence represents
722 if (av.hasHiddenRows())
724 // use rjal, contains the full height alignment
725 jseq.setHidden(av.getAlignment().getHiddenSequences()
728 if (av.isHiddenRepSequence(rjal.getSequenceAt(i)))
730 jalview.datamodel.SequenceI[] reps = av
731 .getRepresentedSequences(rjal.getSequenceAt(i))
732 .getSequencesInOrder(rjal);
734 for (int h = 0; h < reps.length; h++)
736 if (reps[h] != rjal.getSequenceAt(i))
738 jseq.addHiddenSequences(rjal.findIndex(reps[h]));
743 // mark sequence as reference - if it is the reference for this view
746 jseq.setViewreference(rjal.getSequenceAt(i) == jal.getSeqrep());
750 // TODO: omit sequence features from each alignment view's XML dump if we
751 // are storing dataset
752 if (jds.getSequenceFeatures() != null)
754 jalview.datamodel.SequenceFeature[] sf = jds.getSequenceFeatures();
756 while (index < sf.length)
758 Features features = new Features();
760 features.setBegin(sf[index].getBegin());
761 features.setEnd(sf[index].getEnd());
762 features.setDescription(sf[index].getDescription());
763 features.setType(sf[index].getType());
764 features.setFeatureGroup(sf[index].getFeatureGroup());
765 features.setScore(sf[index].getScore());
766 if (sf[index].links != null)
768 for (int l = 0; l < sf[index].links.size(); l++)
770 OtherData keyValue = new OtherData();
771 keyValue.setKey("LINK_" + l);
772 keyValue.setValue(sf[index].links.elementAt(l).toString());
773 features.addOtherData(keyValue);
776 if (sf[index].otherDetails != null)
779 Iterator<String> keys = sf[index].otherDetails.keySet()
781 while (keys.hasNext())
784 OtherData keyValue = new OtherData();
785 keyValue.setKey(key);
786 keyValue.setValue(sf[index].otherDetails.get(key).toString());
787 features.addOtherData(keyValue);
791 jseq.addFeatures(features);
796 if (jdatasq.getAllPDBEntries() != null)
798 Enumeration en = jdatasq.getAllPDBEntries().elements();
799 while (en.hasMoreElements())
801 Pdbids pdb = new Pdbids();
802 jalview.datamodel.PDBEntry entry = (jalview.datamodel.PDBEntry) en
805 String pdbId = entry.getId();
807 pdb.setType(entry.getType());
810 * Store any structure views associated with this sequence. This
811 * section copes with duplicate entries in the project, so a dataset
812 * only view *should* be coped with sensibly.
814 // This must have been loaded, is it still visible?
815 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
816 String matchedFile = null;
817 for (int f = frames.length - 1; f > -1; f--)
819 if (frames[f] instanceof StructureViewerBase)
821 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
822 matchedFile = saveStructureState(ap, jds, pdb, entry,
823 viewIds, matchedFile, viewFrame);
825 * Only store each structure viewer's state once in the project
826 * jar. First time through only (storeDS==false)
828 String viewId = viewFrame.getViewId();
829 if (!storeDS && !viewIds.contains(viewId))
834 String viewerState = viewFrame.getStateInfo();
835 writeJarEntry(jout, getViewerJarEntryName(viewId),
836 viewerState.getBytes());
837 } catch (IOException e)
839 System.err.println("Error saving viewer state: "
846 if (matchedFile != null || entry.getFile() != null)
848 if (entry.getFile() != null)
851 matchedFile = entry.getFile();
853 pdb.setFile(matchedFile); // entry.getFile());
854 if (pdbfiles == null)
856 pdbfiles = new ArrayList<String>();
859 if (!pdbfiles.contains(pdbId))
862 copyFileToJar(jout, matchedFile, pdbId);
866 if (entry.getProperty() != null && !entry.getProperty().isEmpty())
868 PdbentryItem item = new PdbentryItem();
869 Hashtable properties = entry.getProperty();
870 Enumeration en2 = properties.keys();
871 while (en2.hasMoreElements())
873 Property prop = new Property();
874 String key = en2.nextElement().toString();
876 prop.setValue(properties.get(key).toString());
877 item.addProperty(prop);
879 pdb.addPdbentryItem(item);
886 saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
891 if (!storeDS && av.hasHiddenRows())
893 jal = av.getAlignment();
896 if (jal.getCodonFrames() != null)
898 List<AlignedCodonFrame> jac = jal.getCodonFrames();
899 for (AlignedCodonFrame acf : jac)
901 AlcodonFrame alc = new AlcodonFrame();
902 vamsasSet.addAlcodonFrame(alc);
903 if (acf.getProtMappings() != null
904 && acf.getProtMappings().length > 0)
906 SequenceI[] dnas = acf.getdnaSeqs();
907 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
908 for (int m = 0; m < pmaps.length; m++)
910 AlcodMap alcmap = new AlcodMap();
911 alcmap.setDnasq(seqHash(dnas[m]));
912 alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
914 alc.addAlcodMap(alcmap);
917 // TODO: delete this ? dead code from 2.8.3->2.9 ?
919 // AlcodonFrame alc = new AlcodonFrame();
920 // vamsasSet.addAlcodonFrame(alc);
921 // for (int p = 0; p < acf.aaWidth; p++)
923 // Alcodon cmap = new Alcodon();
924 // if (acf.codons[p] != null)
926 // // Null codons indicate a gapped column in the translated peptide
928 // cmap.setPos1(acf.codons[p][0]);
929 // cmap.setPos2(acf.codons[p][1]);
930 // cmap.setPos3(acf.codons[p][2]);
932 // alc.addAlcodon(cmap);
934 // if (acf.getProtMappings() != null
935 // && acf.getProtMappings().length > 0)
937 // SequenceI[] dnas = acf.getdnaSeqs();
938 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
939 // for (int m = 0; m < pmaps.length; m++)
941 // AlcodMap alcmap = new AlcodMap();
942 // alcmap.setDnasq(seqHash(dnas[m]));
943 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
945 // alc.addAlcodMap(alcmap);
952 // /////////////////////////////////
953 if (!storeDS && av.currentTree != null)
955 // FIND ANY ASSOCIATED TREES
956 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
957 if (Desktop.desktop != null)
959 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
961 for (int t = 0; t < frames.length; t++)
963 if (frames[t] instanceof TreePanel)
965 TreePanel tp = (TreePanel) frames[t];
967 if (tp.treeCanvas.av.getAlignment() == jal)
969 Tree tree = new Tree();
970 tree.setTitle(tp.getTitle());
971 tree.setCurrentTree((av.currentTree == tp.getTree()));
972 tree.setNewick(tp.getTree().toString());
973 tree.setThreshold(tp.treeCanvas.threshold);
975 tree.setFitToWindow(tp.fitToWindow.getState());
976 tree.setFontName(tp.getTreeFont().getName());
977 tree.setFontSize(tp.getTreeFont().getSize());
978 tree.setFontStyle(tp.getTreeFont().getStyle());
979 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
981 tree.setShowBootstrap(tp.bootstrapMenu.getState());
982 tree.setShowDistances(tp.distanceMenu.getState());
984 tree.setHeight(tp.getHeight());
985 tree.setWidth(tp.getWidth());
986 tree.setXpos(tp.getX());
987 tree.setYpos(tp.getY());
988 tree.setId(makeHashCode(tp, null));
998 * store forward refs from an annotationRow to any groups
1000 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<SequenceGroup, String>();
1003 for (SequenceI sq : jal.getSequences())
1005 // Store annotation on dataset sequences only
1006 AlignmentAnnotation[] aa = sq.getAnnotation();
1007 if (aa != null && aa.length > 0)
1009 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1016 if (jal.getAlignmentAnnotation() != null)
1018 // Store the annotation shown on the alignment.
1019 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1020 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1025 if (jal.getGroups() != null)
1027 JGroup[] groups = new JGroup[jal.getGroups().size()];
1029 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1031 JGroup jGroup = new JGroup();
1032 groups[++i] = jGroup;
1034 jGroup.setStart(sg.getStartRes());
1035 jGroup.setEnd(sg.getEndRes());
1036 jGroup.setName(sg.getName());
1037 if (groupRefs.containsKey(sg))
1039 // group has references so set its ID field
1040 jGroup.setId(groupRefs.get(sg));
1044 if (sg.cs.conservationApplied())
1046 jGroup.setConsThreshold(sg.cs.getConservationInc());
1048 if (sg.cs instanceof jalview.schemes.UserColourScheme)
1050 jGroup.setColour(setUserColourScheme(sg.cs, userColours, jms));
1054 jGroup.setColour(ColourSchemeProperty.getColourName(sg.cs));
1057 else if (sg.cs instanceof jalview.schemes.AnnotationColourGradient)
1059 jGroup.setColour("AnnotationColourGradient");
1060 jGroup.setAnnotationColours(constructAnnotationColours(
1061 (jalview.schemes.AnnotationColourGradient) sg.cs,
1064 else if (sg.cs instanceof jalview.schemes.UserColourScheme)
1066 jGroup.setColour(setUserColourScheme(sg.cs, userColours, jms));
1070 jGroup.setColour(ColourSchemeProperty.getColourName(sg.cs));
1073 jGroup.setPidThreshold(sg.cs.getThreshold());
1076 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1077 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1078 jGroup.setDisplayText(sg.getDisplayText());
1079 jGroup.setColourText(sg.getColourText());
1080 jGroup.setTextCol1(sg.textColour.getRGB());
1081 jGroup.setTextCol2(sg.textColour2.getRGB());
1082 jGroup.setTextColThreshold(sg.thresholdTextColour);
1083 jGroup.setShowUnconserved(sg.getShowNonconserved());
1084 jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1085 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1086 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1087 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1088 for (SequenceI seq : sg.getSequences())
1090 jGroup.addSeq(seqHash(seq));
1094 jms.setJGroup(groups);
1098 // /////////SAVE VIEWPORT
1099 Viewport view = new Viewport();
1100 view.setTitle(ap.alignFrame.getTitle());
1101 view.setSequenceSetId(makeHashCode(av.getSequenceSetId(),
1102 av.getSequenceSetId()));
1103 view.setId(av.getViewId());
1104 if (av.getCodingComplement() != null)
1106 view.setComplementId(av.getCodingComplement().getViewId());
1108 view.setViewName(av.viewName);
1109 view.setGatheredViews(av.isGatherViewsHere());
1111 Rectangle size = ap.av.getExplodedGeometry();
1112 Rectangle position = size;
1115 size = ap.alignFrame.getBounds();
1116 if (av.getCodingComplement() != null)
1118 position = ((SplitFrame) ap.alignFrame.getSplitViewContainer())
1126 view.setXpos(position.x);
1127 view.setYpos(position.y);
1129 view.setWidth(size.width);
1130 view.setHeight(size.height);
1132 view.setStartRes(av.startRes);
1133 view.setStartSeq(av.startSeq);
1135 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1137 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1140 else if (av.getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1142 AnnotationColours ac = constructAnnotationColours(
1143 (jalview.schemes.AnnotationColourGradient) av
1144 .getGlobalColourScheme(),
1147 view.setAnnotationColours(ac);
1148 view.setBgColour("AnnotationColourGradient");
1152 view.setBgColour(ColourSchemeProperty.getColourName(av
1153 .getGlobalColourScheme()));
1156 ColourSchemeI cs = av.getGlobalColourScheme();
1160 if (cs.conservationApplied())
1162 view.setConsThreshold(cs.getConservationInc());
1163 if (cs instanceof jalview.schemes.UserColourScheme)
1165 view.setBgColour(setUserColourScheme(cs, userColours, jms));
1169 if (cs instanceof ResidueColourScheme)
1171 view.setPidThreshold(cs.getThreshold());
1175 view.setConservationSelected(av.getConservationSelected());
1176 view.setPidSelected(av.getAbovePIDThreshold());
1177 view.setFontName(av.font.getName());
1178 view.setFontSize(av.font.getSize());
1179 view.setFontStyle(av.font.getStyle());
1180 view.setScaleProteinAsCdna(av.getViewStyle().isScaleProteinAsCdna());
1181 view.setRenderGaps(av.isRenderGaps());
1182 view.setShowAnnotation(av.isShowAnnotation());
1183 view.setShowBoxes(av.getShowBoxes());
1184 view.setShowColourText(av.getColourText());
1185 view.setShowFullId(av.getShowJVSuffix());
1186 view.setRightAlignIds(av.isRightAlignIds());
1187 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1188 view.setShowText(av.getShowText());
1189 view.setShowUnconserved(av.getShowUnconserved());
1190 view.setWrapAlignment(av.getWrapAlignment());
1191 view.setTextCol1(av.getTextColour().getRGB());
1192 view.setTextCol2(av.getTextColour2().getRGB());
1193 view.setTextColThreshold(av.getThresholdTextColour());
1194 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1195 view.setShowSequenceLogo(av.isShowSequenceLogo());
1196 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1197 view.setShowGroupConsensus(av.isShowGroupConsensus());
1198 view.setShowGroupConservation(av.isShowGroupConservation());
1199 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1200 view.setShowDbRefTooltip(av.isShowDBRefs());
1201 view.setFollowHighlight(av.isFollowHighlight());
1202 view.setFollowSelection(av.followSelection);
1203 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1204 if (av.getFeaturesDisplayed() != null)
1206 jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
1208 String[] renderOrder = ap.getSeqPanel().seqCanvas
1209 .getFeatureRenderer().getRenderOrder()
1210 .toArray(new String[0]);
1212 Vector<String> settingsAdded = new Vector<String>();
1213 if (renderOrder != null)
1215 for (String featureType : renderOrder)
1217 FeatureColourI fcol = ap.getSeqPanel().seqCanvas
1218 .getFeatureRenderer()
1219 .getFeatureStyle(featureType);
1220 Setting setting = new Setting();
1221 setting.setType(featureType);
1222 if (!fcol.isSimpleColour())
1224 setting.setColour(fcol.getMaxColour().getRGB());
1225 setting.setMincolour(fcol.getMinColour().getRGB());
1226 setting.setMin(fcol.getMin());
1227 setting.setMax(fcol.getMax());
1228 setting.setColourByLabel(fcol.isColourByLabel());
1229 setting.setAutoScale(fcol.isAutoScaled());
1230 setting.setThreshold(fcol.getThreshold());
1231 // -1 = No threshold, 0 = Below, 1 = Above
1232 setting.setThreshstate(fcol.isAboveThreshold() ? 1
1233 : (fcol.isBelowThreshold() ? 0 : -1));
1237 setting.setColour(fcol.getColour().getRGB());
1240 setting.setDisplay(av.getFeaturesDisplayed().isVisible(
1242 float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1243 .getOrder(featureType);
1246 setting.setOrder(rorder);
1248 fs.addSetting(setting);
1249 settingsAdded.addElement(featureType);
1253 // is groups actually supposed to be a map here ?
1254 Iterator<String> en = ap.getSeqPanel().seqCanvas
1255 .getFeatureRenderer()
1256 .getFeatureGroups().iterator();
1257 Vector<String> groupsAdded = new Vector<String>();
1258 while (en.hasNext())
1260 String grp = en.next();
1261 if (groupsAdded.contains(grp))
1265 Group g = new Group();
1267 g.setDisplay(((Boolean) ap.getSeqPanel().seqCanvas
1268 .getFeatureRenderer().checkGroupVisibility(grp, false))
1271 groupsAdded.addElement(grp);
1273 jms.setFeatureSettings(fs);
1276 if (av.hasHiddenColumns())
1278 if (av.getColumnSelection() == null
1279 || av.getColumnSelection().getHiddenColumns() == null)
1281 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1285 for (int c = 0; c < av.getColumnSelection().getHiddenColumns()
1288 int[] region = av.getColumnSelection().getHiddenColumns()
1290 HiddenColumns hc = new HiddenColumns();
1291 hc.setStart(region[0]);
1292 hc.setEnd(region[1]);
1293 view.addHiddenColumns(hc);
1297 if (calcIdSet.size() > 0)
1299 for (String calcId : calcIdSet)
1301 if (calcId.trim().length() > 0)
1303 CalcIdParam cidp = createCalcIdParam(calcId, av);
1304 // Some calcIds have no parameters.
1307 view.addCalcIdParam(cidp);
1313 jms.addViewport(view);
1315 object.setJalviewModelSequence(jms);
1316 object.getVamsasModel().addSequenceSet(vamsasSet);
1318 if (jout != null && fileName != null)
1320 // We may not want to write the object to disk,
1321 // eg we can copy the alignViewport to a new view object
1322 // using save and then load
1325 System.out.println("Writing jar entry " + fileName);
1326 JarEntry entry = new JarEntry(fileName);
1327 jout.putNextEntry(entry);
1328 PrintWriter pout = new PrintWriter(new OutputStreamWriter(jout,
1330 Marshaller marshaller = new Marshaller(pout);
1331 marshaller.marshal(object);
1334 } catch (Exception ex)
1336 // TODO: raise error in GUI if marshalling failed.
1337 ex.printStackTrace();
1344 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1345 * for each viewer, with
1347 * <li>viewer geometry (position, size, split pane divider location)</li>
1348 * <li>index of the selected structure in the viewer (currently shows gapped
1350 * <li>the id of the annotation holding RNA secondary structure</li>
1351 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1353 * Varna viewer state is also written out (in native Varna XML) to separate
1354 * project jar entries. A separate entry is written for each RNA structure
1355 * displayed, with the naming convention
1357 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
1365 * @param storeDataset
1367 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
1368 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
1369 boolean storeDataset)
1371 if (Desktop.desktop == null)
1375 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1376 for (int f = frames.length - 1; f > -1; f--)
1378 if (frames[f] instanceof AppVarna)
1380 AppVarna varna = (AppVarna) frames[f];
1382 * link the sequence to every viewer that is showing it and is linked to
1383 * its alignment panel
1385 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1387 String viewId = varna.getViewId();
1388 RnaViewer rna = new RnaViewer();
1389 rna.setViewId(viewId);
1390 rna.setTitle(varna.getTitle());
1391 rna.setXpos(varna.getX());
1392 rna.setYpos(varna.getY());
1393 rna.setWidth(varna.getWidth());
1394 rna.setHeight(varna.getHeight());
1395 rna.setDividerLocation(varna.getDividerLocation());
1396 rna.setSelectedRna(varna.getSelectedIndex());
1397 jseq.addRnaViewer(rna);
1400 * Store each Varna panel's state once in the project per sequence.
1401 * First time through only (storeDataset==false)
1403 // boolean storeSessions = false;
1404 // String sequenceViewId = viewId + seqsToIds.get(jds);
1405 // if (!storeDataset && !viewIds.contains(sequenceViewId))
1407 // viewIds.add(sequenceViewId);
1408 // storeSessions = true;
1410 for (RnaModel model : varna.getModels())
1412 if (model.seq == jds)
1415 * VARNA saves each view (sequence or alignment secondary
1416 * structure, gapped or trimmed) as a separate XML file
1418 String jarEntryName = rnaSessions.get(model);
1419 if (jarEntryName == null)
1422 String varnaStateFile = varna.getStateInfo(model.rna);
1423 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
1424 copyFileToJar(jout, varnaStateFile, jarEntryName);
1425 rnaSessions.put(model, jarEntryName);
1427 SecondaryStructure ss = new SecondaryStructure();
1428 String annotationId = varna.getAnnotation(jds).annotationId;
1429 ss.setAnnotationId(annotationId);
1430 ss.setViewerState(jarEntryName);
1431 ss.setGapped(model.gapped);
1432 ss.setTitle(model.title);
1433 rna.addSecondaryStructure(ss);
1442 * Copy the contents of a file to a new entry added to the output jar
1446 * @param jarEntryName
1448 protected void copyFileToJar(JarOutputStream jout, String infilePath,
1449 String jarEntryName)
1451 DataInputStream dis = null;
1454 File file = new File(infilePath);
1455 if (file.exists() && jout != null)
1457 dis = new DataInputStream(new FileInputStream(file));
1458 byte[] data = new byte[(int) file.length()];
1459 dis.readFully(data);
1460 writeJarEntry(jout, jarEntryName, data);
1462 } catch (Exception ex)
1464 ex.printStackTrace();
1472 } catch (IOException e)
1481 * Write the data to a new entry of given name in the output jar file
1484 * @param jarEntryName
1486 * @throws IOException
1488 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
1489 byte[] data) throws IOException
1493 System.out.println("Writing jar entry " + jarEntryName);
1494 jout.putNextEntry(new JarEntry(jarEntryName));
1495 DataOutputStream dout = new DataOutputStream(jout);
1496 dout.write(data, 0, data.length);
1503 * Save the state of a structure viewer
1508 * the archive XML element under which to save the state
1511 * @param matchedFile
1515 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
1516 Pdbids pdb, PDBEntry entry, List<String> viewIds,
1517 String matchedFile, StructureViewerBase viewFrame)
1519 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
1522 * Look for any bindings for this viewer to the PDB file of interest
1523 * (including part matches excluding chain id)
1525 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
1527 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
1528 final String pdbId = pdbentry.getId();
1529 if (!pdbId.equals(entry.getId())
1530 && !(entry.getId().length() > 4 && entry.getId()
1531 .toLowerCase().startsWith(pdbId.toLowerCase())))
1534 * not interested in a binding to a different PDB entry here
1538 if (matchedFile == null)
1540 matchedFile = pdbentry.getFile();
1542 else if (!matchedFile.equals(pdbentry.getFile()))
1545 .warn("Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
1546 + pdbentry.getFile());
1550 // can get at it if the ID
1551 // match is ambiguous (e.g.
1554 for (int smap = 0; smap < viewFrame.getBinding().getSequence()[peid].length; smap++)
1556 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
1557 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
1559 StructureState state = new StructureState();
1560 state.setVisible(true);
1561 state.setXpos(viewFrame.getX());
1562 state.setYpos(viewFrame.getY());
1563 state.setWidth(viewFrame.getWidth());
1564 state.setHeight(viewFrame.getHeight());
1565 final String viewId = viewFrame.getViewId();
1566 state.setViewId(viewId);
1567 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
1568 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
1569 state.setColourByJmol(viewFrame.isColouredByViewer());
1570 state.setType(viewFrame.getViewerType().toString());
1571 pdb.addStructureState(state);
1578 private AnnotationColours constructAnnotationColours(
1579 AnnotationColourGradient acg, List<UserColourScheme> userColours,
1580 JalviewModelSequence jms)
1582 AnnotationColours ac = new AnnotationColours();
1583 ac.setAboveThreshold(acg.getAboveThreshold());
1584 ac.setThreshold(acg.getAnnotationThreshold());
1585 ac.setAnnotation(acg.getAnnotation());
1586 if (acg.getBaseColour() instanceof jalview.schemes.UserColourScheme)
1588 ac.setColourScheme(setUserColourScheme(acg.getBaseColour(),
1593 ac.setColourScheme(ColourSchemeProperty.getColourName(acg
1597 ac.setMaxColour(acg.getMaxColour().getRGB());
1598 ac.setMinColour(acg.getMinColour().getRGB());
1599 ac.setPerSequence(acg.isSeqAssociated());
1600 ac.setPredefinedColours(acg.isPredefinedColours());
1604 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
1605 IdentityHashMap<SequenceGroup, String> groupRefs,
1606 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
1607 SequenceSet vamsasSet)
1610 for (int i = 0; i < aa.length; i++)
1612 Annotation an = new Annotation();
1614 AlignmentAnnotation annotation = aa[i];
1615 if (annotation.annotationId != null)
1617 annotationIds.put(annotation.annotationId, annotation);
1620 an.setId(annotation.annotationId);
1622 an.setVisible(annotation.visible);
1624 an.setDescription(annotation.description);
1626 if (annotation.sequenceRef != null)
1628 // 2.9 JAL-1781 xref on sequence id rather than name
1629 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
1631 if (annotation.groupRef != null)
1633 String groupIdr = groupRefs.get(annotation.groupRef);
1634 if (groupIdr == null)
1636 // make a locally unique String
1638 annotation.groupRef,
1639 groupIdr = ("" + System.currentTimeMillis()
1640 + annotation.groupRef.getName() + groupRefs
1643 an.setGroupRef(groupIdr.toString());
1646 // store all visualization attributes for annotation
1647 an.setGraphHeight(annotation.graphHeight);
1648 an.setCentreColLabels(annotation.centreColLabels);
1649 an.setScaleColLabels(annotation.scaleColLabel);
1650 an.setShowAllColLabels(annotation.showAllColLabels);
1651 an.setBelowAlignment(annotation.belowAlignment);
1653 if (annotation.graph > 0)
1656 an.setGraphType(annotation.graph);
1657 an.setGraphGroup(annotation.graphGroup);
1658 if (annotation.getThreshold() != null)
1660 ThresholdLine line = new ThresholdLine();
1661 line.setLabel(annotation.getThreshold().label);
1662 line.setValue(annotation.getThreshold().value);
1663 line.setColour(annotation.getThreshold().colour.getRGB());
1664 an.setThresholdLine(line);
1672 an.setLabel(annotation.label);
1674 if (annotation == av.getAlignmentQualityAnnot()
1675 || annotation == av.getAlignmentConservationAnnotation()
1676 || annotation == av.getAlignmentConsensusAnnotation()
1677 || annotation.autoCalculated)
1679 // new way of indicating autocalculated annotation -
1680 an.setAutoCalculated(annotation.autoCalculated);
1682 if (annotation.hasScore())
1684 an.setScore(annotation.getScore());
1687 if (annotation.getCalcId() != null)
1689 calcIdSet.add(annotation.getCalcId());
1690 an.setCalcId(annotation.getCalcId());
1692 if (annotation.hasProperties())
1694 for (String pr : annotation.getProperties())
1696 Property prop = new Property();
1698 prop.setValue(annotation.getProperty(pr));
1699 an.addProperty(prop);
1703 AnnotationElement ae;
1704 if (annotation.annotations != null)
1706 an.setScoreOnly(false);
1707 for (int a = 0; a < annotation.annotations.length; a++)
1709 if ((annotation == null) || (annotation.annotations[a] == null))
1714 ae = new AnnotationElement();
1715 if (annotation.annotations[a].description != null)
1717 ae.setDescription(annotation.annotations[a].description);
1719 if (annotation.annotations[a].displayCharacter != null)
1721 ae.setDisplayCharacter(annotation.annotations[a].displayCharacter);
1724 if (!Float.isNaN(annotation.annotations[a].value))
1726 ae.setValue(annotation.annotations[a].value);
1730 if (annotation.annotations[a].secondaryStructure > ' ')
1732 ae.setSecondaryStructure(annotation.annotations[a].secondaryStructure
1736 if (annotation.annotations[a].colour != null
1737 && annotation.annotations[a].colour != java.awt.Color.black)
1739 ae.setColour(annotation.annotations[a].colour.getRGB());
1742 an.addAnnotationElement(ae);
1743 if (annotation.autoCalculated)
1745 // only write one non-null entry into the annotation row -
1746 // sufficient to get the visualization attributes necessary to
1754 an.setScoreOnly(true);
1756 if (!storeDS || (storeDS && !annotation.autoCalculated))
1758 // skip autocalculated annotation - these are only provided for
1760 vamsasSet.addAnnotation(an);
1766 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
1768 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
1769 if (settings != null)
1771 CalcIdParam vCalcIdParam = new CalcIdParam();
1772 vCalcIdParam.setCalcId(calcId);
1773 vCalcIdParam.addServiceURL(settings.getServiceURI());
1774 // generic URI allowing a third party to resolve another instance of the
1775 // service used for this calculation
1776 for (String urls : settings.getServiceURLs())
1778 vCalcIdParam.addServiceURL(urls);
1780 vCalcIdParam.setVersion("1.0");
1781 if (settings.getPreset() != null)
1783 WsParamSetI setting = settings.getPreset();
1784 vCalcIdParam.setName(setting.getName());
1785 vCalcIdParam.setDescription(setting.getDescription());
1789 vCalcIdParam.setName("");
1790 vCalcIdParam.setDescription("Last used parameters");
1792 // need to be able to recover 1) settings 2) user-defined presets or
1793 // recreate settings from preset 3) predefined settings provided by
1794 // service - or settings that can be transferred (or discarded)
1795 vCalcIdParam.setParameters(settings.getWsParamFile().replace("\n",
1797 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
1798 // todo - decide if updateImmediately is needed for any projects.
1800 return vCalcIdParam;
1805 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
1808 if (calcIdParam.getVersion().equals("1.0"))
1810 Jws2Instance service = Jws2Discoverer.getDiscoverer()
1811 .getPreferredServiceFor(calcIdParam.getServiceURL());
1812 if (service != null)
1814 WsParamSetI parmSet = null;
1817 parmSet = service.getParamStore().parseServiceParameterFile(
1818 calcIdParam.getName(), calcIdParam.getDescription(),
1819 calcIdParam.getServiceURL(),
1820 calcIdParam.getParameters().replace("|\\n|", "\n"));
1821 } catch (IOException x)
1823 warn("Couldn't parse parameter data for "
1824 + calcIdParam.getCalcId(), x);
1827 List<ArgumentI> argList = null;
1828 if (calcIdParam.getName().length() > 0)
1830 parmSet = service.getParamStore()
1831 .getPreset(calcIdParam.getName());
1832 if (parmSet != null)
1834 // TODO : check we have a good match with settings in AACon -
1835 // otherwise we'll need to create a new preset
1840 argList = parmSet.getArguments();
1843 AAConSettings settings = new AAConSettings(
1844 calcIdParam.isAutoUpdate(), service, parmSet, argList);
1845 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
1846 calcIdParam.isNeedsUpdate());
1851 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
1855 throw new Error(MessageManager.formatMessage(
1856 "error.unsupported_version_calcIdparam",
1857 new Object[] { calcIdParam.toString() }));
1861 * External mapping between jalview objects and objects yielding a valid and
1862 * unique object ID string. This is null for normal Jalview project IO, but
1863 * non-null when a jalview project is being read or written as part of a
1866 IdentityHashMap jv2vobj = null;
1869 * Construct a unique ID for jvobj using either existing bindings or if none
1870 * exist, the result of the hashcode call for the object.
1873 * jalview data object
1874 * @return unique ID for referring to jvobj
1876 private String makeHashCode(Object jvobj, String altCode)
1878 if (jv2vobj != null)
1880 Object id = jv2vobj.get(jvobj);
1883 return id.toString();
1885 // check string ID mappings
1886 if (jvids2vobj != null && jvobj instanceof String)
1888 id = jvids2vobj.get(jvobj);
1892 return id.toString();
1894 // give up and warn that something has gone wrong
1895 warn("Cannot find ID for object in external mapping : " + jvobj);
1901 * return local jalview object mapped to ID, if it exists
1905 * @return null or object bound to idcode
1907 private Object retrieveExistingObj(String idcode)
1909 if (idcode != null && vobj2jv != null)
1911 return vobj2jv.get(idcode);
1917 * binding from ID strings from external mapping table to jalview data model
1920 private Hashtable vobj2jv;
1922 private Sequence createVamsasSequence(String id, SequenceI jds)
1924 return createVamsasSequence(true, id, jds, null);
1927 private Sequence createVamsasSequence(boolean recurse, String id,
1928 SequenceI jds, SequenceI parentseq)
1930 Sequence vamsasSeq = new Sequence();
1931 vamsasSeq.setId(id);
1932 vamsasSeq.setName(jds.getName());
1933 vamsasSeq.setSequence(jds.getSequenceAsString());
1934 vamsasSeq.setDescription(jds.getDescription());
1935 jalview.datamodel.DBRefEntry[] dbrefs = null;
1936 if (jds.getDatasetSequence() != null)
1938 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
1939 if (jds.getDatasetSequence().getDBRefs() != null)
1941 dbrefs = jds.getDatasetSequence().getDBRefs();
1946 vamsasSeq.setDsseqid(id); // so we can tell which sequences really are
1947 // dataset sequences only
1948 dbrefs = jds.getDBRefs();
1952 for (int d = 0; d < dbrefs.length; d++)
1954 DBRef dbref = new DBRef();
1955 dbref.setSource(dbrefs[d].getSource());
1956 dbref.setVersion(dbrefs[d].getVersion());
1957 dbref.setAccessionId(dbrefs[d].getAccessionId());
1958 if (dbrefs[d].hasMap())
1960 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
1962 dbref.setMapping(mp);
1964 vamsasSeq.addDBRef(dbref);
1970 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
1971 SequenceI parentseq, SequenceI jds, boolean recurse)
1974 if (jmp.getMap() != null)
1978 jalview.util.MapList mlst = jmp.getMap();
1979 List<int[]> r = mlst.getFromRanges();
1980 for (int[] range : r)
1982 MapListFrom mfrom = new MapListFrom();
1983 mfrom.setStart(range[0]);
1984 mfrom.setEnd(range[1]);
1985 mp.addMapListFrom(mfrom);
1987 r = mlst.getToRanges();
1988 for (int[] range : r)
1990 MapListTo mto = new MapListTo();
1991 mto.setStart(range[0]);
1992 mto.setEnd(range[1]);
1993 mp.addMapListTo(mto);
1995 mp.setMapFromUnit(mlst.getFromRatio());
1996 mp.setMapToUnit(mlst.getToRatio());
1997 if (jmp.getTo() != null)
1999 MappingChoice mpc = new MappingChoice();
2001 && (parentseq != jmp.getTo() || parentseq
2002 .getDatasetSequence() != jmp.getTo()))
2004 mpc.setSequence(createVamsasSequence(false, seqHash(jmp.getTo()),
2010 SequenceI ps = null;
2011 if (parentseq != jmp.getTo()
2012 && parentseq.getDatasetSequence() != jmp.getTo())
2014 // chaining dbref rather than a handshaking one
2015 jmpid = seqHash(ps = jmp.getTo());
2019 jmpid = seqHash(ps = parentseq);
2021 mpc.setDseqFor(jmpid);
2022 if (!seqRefIds.containsKey(mpc.getDseqFor()))
2024 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2025 seqRefIds.put(mpc.getDseqFor(), ps);
2029 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2032 mp.setMappingChoice(mpc);
2038 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2039 List<UserColourScheme> userColours, JalviewModelSequence jms)
2042 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2043 boolean newucs = false;
2044 if (!userColours.contains(ucs))
2046 userColours.add(ucs);
2049 id = "ucs" + userColours.indexOf(ucs);
2052 // actually create the scheme's entry in the XML model
2053 java.awt.Color[] colours = ucs.getColours();
2054 jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
2055 jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
2057 for (int i = 0; i < colours.length; i++)
2059 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2060 col.setName(ResidueProperties.aa[i]);
2061 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2062 jbucs.addColour(col);
2064 if (ucs.getLowerCaseColours() != null)
2066 colours = ucs.getLowerCaseColours();
2067 for (int i = 0; i < colours.length; i++)
2069 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2070 col.setName(ResidueProperties.aa[i].toLowerCase());
2071 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2072 jbucs.addColour(col);
2077 uc.setUserColourScheme(jbucs);
2078 jms.addUserColours(uc);
2084 jalview.schemes.UserColourScheme getUserColourScheme(
2085 JalviewModelSequence jms, String id)
2087 UserColours[] uc = jms.getUserColours();
2088 UserColours colours = null;
2090 for (int i = 0; i < uc.length; i++)
2092 if (uc[i].getId().equals(id))
2100 java.awt.Color[] newColours = new java.awt.Color[24];
2102 for (int i = 0; i < 24; i++)
2104 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2105 .getUserColourScheme().getColour(i).getRGB(), 16));
2108 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2111 if (colours.getUserColourScheme().getColourCount() > 24)
2113 newColours = new java.awt.Color[23];
2114 for (int i = 0; i < 23; i++)
2116 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2117 .getUserColourScheme().getColour(i + 24).getRGB(), 16));
2119 ucs.setLowerCaseColours(newColours);
2126 * contains last error message (if any) encountered by XML loader.
2128 String errorMessage = null;
2131 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2132 * exceptions are raised during project XML parsing
2134 public boolean attemptversion1parse = true;
2137 * Load a jalview project archive from a jar file
2140 * - HTTP URL or filename
2142 public AlignFrame loadJalviewAlign(final String file)
2145 jalview.gui.AlignFrame af = null;
2149 // create list to store references for any new Jmol viewers created
2150 newStructureViewers = new Vector<JalviewStructureDisplayI>();
2151 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2152 // Workaround is to make sure caller implements the JarInputStreamProvider
2154 // so we can re-open the jar input stream for each entry.
2156 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2157 af = loadJalviewAlign(jprovider);
2159 } catch (MalformedURLException e)
2161 errorMessage = "Invalid URL format for '" + file + "'";
2167 SwingUtilities.invokeAndWait(new Runnable()
2172 setLoadingFinishedForNewStructureViewers();
2175 } catch (Exception x)
2177 System.err.println("Error loading alignment: " + x.getMessage());
2183 private jarInputStreamProvider createjarInputStreamProvider(
2184 final String file) throws MalformedURLException
2187 errorMessage = null;
2188 uniqueSetSuffix = null;
2190 viewportsAdded.clear();
2191 frefedSequence = null;
2193 if (file.startsWith("http://"))
2195 url = new URL(file);
2197 final URL _url = url;
2198 return new jarInputStreamProvider()
2202 public JarInputStream getJarInputStream() throws IOException
2206 return new JarInputStream(_url.openStream());
2210 return new JarInputStream(new FileInputStream(file));
2215 public String getFilename()
2223 * Recover jalview session from a jalview project archive. Caller may
2224 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2225 * themselves. Any null fields will be initialised with default values,
2226 * non-null fields are left alone.
2231 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2233 errorMessage = null;
2234 if (uniqueSetSuffix == null)
2236 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2238 if (seqRefIds == null)
2240 seqRefIds = new HashMap<String, SequenceI>();
2242 if (frefedSequence == null)
2244 frefedSequence = new Vector<Object[]>();
2247 AlignFrame af = null, _af = null;
2248 Map<String, AlignFrame> gatherToThisFrame = new HashMap<String, AlignFrame>();
2249 final String file = jprovider.getFilename();
2252 JarInputStream jin = null;
2253 JarEntry jarentry = null;
2258 jin = jprovider.getJarInputStream();
2259 for (int i = 0; i < entryCount; i++)
2261 jarentry = jin.getNextJarEntry();
2264 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2266 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2267 JalviewModel object = new JalviewModel();
2269 Unmarshaller unmar = new Unmarshaller(object);
2270 unmar.setValidation(false);
2271 object = (JalviewModel) unmar.unmarshal(in);
2272 if (true) // !skipViewport(object))
2274 _af = loadFromObject(object, file, true, jprovider);
2275 if (object.getJalviewModelSequence().getViewportCount() > 0)
2278 if (af.viewport.isGatherViewsHere())
2280 gatherToThisFrame.put(af.viewport.getSequenceSetId(), af);
2286 else if (jarentry != null)
2288 // Some other file here.
2291 } while (jarentry != null);
2292 resolveFrefedSequences();
2293 } catch (IOException ex)
2295 ex.printStackTrace();
2296 errorMessage = "Couldn't locate Jalview XML file : " + file;
2297 System.err.println("Exception whilst loading jalview XML file : "
2299 } catch (Exception ex)
2301 System.err.println("Parsing as Jalview Version 2 file failed.");
2302 ex.printStackTrace(System.err);
2303 if (attemptversion1parse)
2305 // Is Version 1 Jar file?
2308 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
2309 } catch (Exception ex2)
2311 System.err.println("Exception whilst loading as jalviewXMLV1:");
2312 ex2.printStackTrace();
2316 if (Desktop.instance != null)
2318 Desktop.instance.stopLoading();
2322 System.out.println("Successfully loaded archive file");
2325 ex.printStackTrace();
2327 System.err.println("Exception whilst loading jalview XML file : "
2329 } catch (OutOfMemoryError e)
2331 // Don't use the OOM Window here
2332 errorMessage = "Out of memory loading jalview XML file";
2333 System.err.println("Out of memory whilst loading jalview XML file");
2334 e.printStackTrace();
2337 if (Desktop.instance != null)
2339 Desktop.instance.stopLoading();
2343 * Regather multiple views (with the same sequence set id) to the frame (if
2344 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2345 * views instead of separate frames. Note this doesn't restore a state where
2346 * some expanded views in turn have tabbed views - the last "first tab" read
2347 * in will play the role of gatherer for all.
2349 for (AlignFrame fr : gatherToThisFrame.values())
2351 Desktop.instance.gatherViews(fr);
2354 restoreSplitFrames();
2356 if (errorMessage != null)
2364 * Try to reconstruct and display SplitFrame windows, where each contains
2365 * complementary dna and protein alignments. Done by pairing up AlignFrame
2366 * objects (created earlier) which have complementary viewport ids associated.
2368 protected void restoreSplitFrames()
2370 List<SplitFrame> gatherTo = new ArrayList<SplitFrame>();
2371 List<AlignFrame> addedToSplitFrames = new ArrayList<AlignFrame>();
2372 Map<String, AlignFrame> dna = new HashMap<String, AlignFrame>();
2375 * Identify the DNA alignments
2377 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2380 AlignFrame af = candidate.getValue();
2381 if (af.getViewport().getAlignment().isNucleotide())
2383 dna.put(candidate.getKey().getId(), af);
2388 * Try to match up the protein complements
2390 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2393 AlignFrame af = candidate.getValue();
2394 if (!af.getViewport().getAlignment().isNucleotide())
2396 String complementId = candidate.getKey().getComplementId();
2397 // only non-null complements should be in the Map
2398 if (complementId != null && dna.containsKey(complementId))
2400 final AlignFrame dnaFrame = dna.get(complementId);
2401 SplitFrame sf = createSplitFrame(dnaFrame, af);
2402 addedToSplitFrames.add(dnaFrame);
2403 addedToSplitFrames.add(af);
2404 if (af.viewport.isGatherViewsHere())
2413 * Open any that we failed to pair up (which shouldn't happen!) as
2414 * standalone AlignFrame's.
2416 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2419 AlignFrame af = candidate.getValue();
2420 if (!addedToSplitFrames.contains(af))
2422 Viewport view = candidate.getKey();
2423 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
2425 System.err.println("Failed to restore view " + view.getTitle()
2426 + " to split frame");
2431 * Gather back into tabbed views as flagged.
2433 for (SplitFrame sf : gatherTo)
2435 Desktop.instance.gatherViews(sf);
2438 splitFrameCandidates.clear();
2442 * Construct and display one SplitFrame holding DNA and protein alignments.
2445 * @param proteinFrame
2448 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
2449 AlignFrame proteinFrame)
2451 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
2452 String title = MessageManager.getString("label.linked_view_title");
2453 int width = (int) dnaFrame.getBounds().getWidth();
2454 int height = (int) (dnaFrame.getBounds().getHeight()
2455 + proteinFrame.getBounds().getHeight() + 50);
2458 * SplitFrame location is saved to both enclosed frames
2460 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
2461 Desktop.addInternalFrame(splitFrame, title, width, height);
2464 * And compute cDNA consensus (couldn't do earlier with consensus as
2465 * mappings were not yet present)
2467 proteinFrame.viewport.alignmentChanged(proteinFrame.alignPanel);
2473 * check errorMessage for a valid error message and raise an error box in the
2474 * GUI or write the current errorMessage to stderr and then clear the error
2477 protected void reportErrors()
2479 reportErrors(false);
2482 protected void reportErrors(final boolean saving)
2484 if (errorMessage != null)
2486 final String finalErrorMessage = errorMessage;
2489 javax.swing.SwingUtilities.invokeLater(new Runnable()
2494 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2495 finalErrorMessage, "Error "
2496 + (saving ? "saving" : "loading")
2497 + " Jalview file", JOptionPane.WARNING_MESSAGE);
2503 System.err.println("Problem loading Jalview file: " + errorMessage);
2506 errorMessage = null;
2509 Map<String, String> alreadyLoadedPDB = new HashMap<String, String>();
2512 * when set, local views will be updated from view stored in JalviewXML
2513 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2514 * sync if this is set to true.
2516 private final boolean updateLocalViews = false;
2519 * Returns the path to a temporary file holding the PDB file for the given PDB
2520 * id. The first time of asking, searches for a file of that name in the
2521 * Jalview project jar, and copies it to a new temporary file. Any repeat
2522 * requests just return the path to the file previously created.
2528 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId)
2530 if (alreadyLoadedPDB.containsKey(pdbId))
2532 return alreadyLoadedPDB.get(pdbId).toString();
2535 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb");
2536 if (tempFile != null)
2538 alreadyLoadedPDB.put(pdbId, tempFile);
2544 * Copies the jar entry of given name to a new temporary file and returns the
2545 * path to the file, or null if the entry is not found.
2548 * @param jarEntryName
2550 * a prefix for the temporary file name, must be at least three
2554 protected String copyJarEntry(jarInputStreamProvider jprovider,
2555 String jarEntryName, String prefix)
2557 BufferedReader in = null;
2558 PrintWriter out = null;
2562 JarInputStream jin = jprovider.getJarInputStream();
2564 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2565 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2566 * FileInputStream(jprovider)); }
2569 JarEntry entry = null;
2572 entry = jin.getNextJarEntry();
2573 } while (entry != null && !entry.getName().equals(jarEntryName));
2576 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
2577 File outFile = File.createTempFile(prefix, ".tmp");
2578 outFile.deleteOnExit();
2579 out = new PrintWriter(new FileOutputStream(outFile));
2582 while ((data = in.readLine()) != null)
2587 String t = outFile.getAbsolutePath();
2592 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
2594 } catch (Exception ex)
2596 ex.printStackTrace();
2604 } catch (IOException e)
2618 private class JvAnnotRow
2620 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2627 * persisted version of annotation row from which to take vis properties
2629 public jalview.datamodel.AlignmentAnnotation template;
2632 * original position of the annotation row in the alignment
2638 * Load alignment frame from jalview XML DOM object
2643 * filename source string
2644 * @param loadTreesAndStructures
2645 * when false only create Viewport
2647 * data source provider
2648 * @return alignment frame created from view stored in DOM
2650 AlignFrame loadFromObject(JalviewModel object, String file,
2651 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
2653 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
2654 Sequence[] vamsasSeq = vamsasSet.getSequence();
2656 JalviewModelSequence jms = object.getJalviewModelSequence();
2658 Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
2661 // ////////////////////////////////
2664 List<SequenceI> hiddenSeqs = null;
2665 jalview.datamodel.Sequence jseq;
2667 List<SequenceI> tmpseqs = new ArrayList<SequenceI>();
2669 boolean multipleView = false;
2670 SequenceI referenceseqForView = null;
2671 JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
2672 int vi = 0; // counter in vamsasSeq array
2673 for (int i = 0; i < jseqs.length; i++)
2675 String seqId = jseqs[i].getId();
2677 if (seqRefIds.get(seqId) != null)
2679 tmpseqs.add(seqRefIds.get(seqId));
2680 multipleView = true;
2684 jseq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
2685 vamsasSeq[vi].getSequence());
2686 jseq.setDescription(vamsasSeq[vi].getDescription());
2687 jseq.setStart(jseqs[i].getStart());
2688 jseq.setEnd(jseqs[i].getEnd());
2689 jseq.setVamsasId(uniqueSetSuffix + seqId);
2690 seqRefIds.put(vamsasSeq[vi].getId(), jseq);
2695 if (jseqs[i].hasViewreference() && jseqs[i].getViewreference())
2697 referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
2700 if (jseqs[i].getHidden())
2702 if (hiddenSeqs == null)
2704 hiddenSeqs = new ArrayList<SequenceI>();
2707 hiddenSeqs.add(seqRefIds.get(seqId));
2712 // Create the alignment object from the sequence set
2713 // ///////////////////////////////
2714 SequenceI[] orderedSeqs = tmpseqs
2715 .toArray(new SequenceI[tmpseqs.size()]);
2717 Alignment al = new Alignment(orderedSeqs);
2719 if (referenceseqForView != null)
2721 al.setSeqrep(referenceseqForView);
2723 // / Add the alignment properties
2724 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
2726 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
2727 al.setProperty(ssp.getKey(), ssp.getValue());
2731 // SequenceFeatures are added to the DatasetSequence,
2732 // so we must create or recover the dataset before loading features
2733 // ///////////////////////////////
2734 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
2736 // older jalview projects do not have a dataset id.
2737 al.setDataset(null);
2741 // recover dataset - passing on flag indicating if this a 'viewless'
2742 // sequence set (a.k.a. a stored dataset for the project)
2743 recoverDatasetFor(vamsasSet, al, object.getJalviewModelSequence()
2744 .getViewportCount() == 0);
2746 // ///////////////////////////////
2748 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
2751 // load sequence features, database references and any associated PDB
2752 // structures for the alignment
2753 for (int i = 0; i < vamsasSeq.length; i++)
2755 if (jseqs[i].getFeaturesCount() > 0)
2757 Features[] features = jseqs[i].getFeatures();
2758 for (int f = 0; f < features.length; f++)
2760 jalview.datamodel.SequenceFeature sf = new jalview.datamodel.SequenceFeature(
2761 features[f].getType(), features[f].getDescription(),
2762 features[f].getStatus(), features[f].getBegin(),
2763 features[f].getEnd(), features[f].getFeatureGroup());
2765 sf.setScore(features[f].getScore());
2766 for (int od = 0; od < features[f].getOtherDataCount(); od++)
2768 OtherData keyValue = features[f].getOtherData(od);
2769 if (keyValue.getKey().startsWith("LINK"))
2771 sf.addLink(keyValue.getValue());
2775 sf.setValue(keyValue.getKey(), keyValue.getValue());
2780 al.getSequenceAt(i).getDatasetSequence().addSequenceFeature(sf);
2783 if (vamsasSeq[i].getDBRefCount() > 0)
2785 addDBRefs(al.getSequenceAt(i).getDatasetSequence(), vamsasSeq[i]);
2787 if (jseqs[i].getPdbidsCount() > 0)
2789 Pdbids[] ids = jseqs[i].getPdbids();
2790 for (int p = 0; p < ids.length; p++)
2792 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
2793 entry.setId(ids[p].getId());
2794 if (ids[p].getType() != null)
2796 if (ids[p].getType().equalsIgnoreCase("PDB"))
2798 entry.setType(PDBEntry.Type.PDB);
2802 entry.setType(PDBEntry.Type.FILE);
2805 if (ids[p].getFile() != null)
2807 if (!pdbloaded.containsKey(ids[p].getFile()))
2809 entry.setFile(loadPDBFile(jprovider, ids[p].getId()));
2813 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
2816 StructureSelectionManager.getStructureSelectionManager(
2817 Desktop.instance).registerPDBEntry(entry);
2818 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
2822 } // end !multipleview
2824 // ///////////////////////////////
2825 // LOAD SEQUENCE MAPPINGS
2827 if (vamsasSet.getAlcodonFrameCount() > 0)
2829 // TODO Potentially this should only be done once for all views of an
2831 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
2832 for (int i = 0; i < alc.length; i++)
2834 AlignedCodonFrame cf = new AlignedCodonFrame();
2835 if (alc[i].getAlcodMapCount() > 0)
2837 AlcodMap[] maps = alc[i].getAlcodMap();
2838 for (int m = 0; m < maps.length; m++)
2840 SequenceI dnaseq = seqRefIds.get(maps[m].getDnasq());
2842 jalview.datamodel.Mapping mapping = null;
2843 // attach to dna sequence reference.
2844 if (maps[m].getMapping() != null)
2846 mapping = addMapping(maps[m].getMapping());
2848 if (dnaseq != null && mapping.getTo() != null)
2850 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
2855 frefedSequence.add(new Object[] { maps[m].getDnasq(), cf,
2860 al.addCodonFrame(cf);
2864 // ////////////////////////////////
2866 List<JvAnnotRow> autoAlan = new ArrayList<JvAnnotRow>();
2869 * store any annotations which forward reference a group's ID
2871 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<String, List<AlignmentAnnotation>>();
2873 if (vamsasSet.getAnnotationCount() > 0)
2875 Annotation[] an = vamsasSet.getAnnotation();
2877 for (int i = 0; i < an.length; i++)
2879 Annotation annotation = an[i];
2882 * test if annotation is automatically calculated for this view only
2884 boolean autoForView = false;
2885 if (annotation.getLabel().equals("Quality")
2886 || annotation.getLabel().equals("Conservation")
2887 || annotation.getLabel().equals("Consensus"))
2889 // Kludge for pre 2.5 projects which lacked the autocalculated flag
2891 if (!annotation.hasAutoCalculated())
2893 annotation.setAutoCalculated(true);
2897 || (annotation.hasAutoCalculated() && annotation
2898 .isAutoCalculated()))
2900 // remove ID - we don't recover annotation from other views for
2901 // view-specific annotation
2902 annotation.setId(null);
2905 // set visiblity for other annotation in this view
2906 String annotationId = annotation.getId();
2907 if (annotationId != null && annotationIds.containsKey(annotationId))
2909 AlignmentAnnotation jda = annotationIds.get(annotationId);
2910 // in principle Visible should always be true for annotation displayed
2911 // in multiple views
2912 if (annotation.hasVisible())
2914 jda.visible = annotation.getVisible();
2917 al.addAnnotation(jda);
2921 // Construct new annotation from model.
2922 AnnotationElement[] ae = annotation.getAnnotationElement();
2923 jalview.datamodel.Annotation[] anot = null;
2924 java.awt.Color firstColour = null;
2926 if (!annotation.getScoreOnly())
2928 anot = new jalview.datamodel.Annotation[al.getWidth()];
2929 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
2931 anpos = ae[aa].getPosition();
2933 if (anpos >= anot.length)
2938 anot[anpos] = new jalview.datamodel.Annotation(
2940 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
2941 (ae[aa].getSecondaryStructure() == null || ae[aa]
2942 .getSecondaryStructure().length() == 0) ? ' '
2943 : ae[aa].getSecondaryStructure().charAt(0),
2947 // JBPNote: Consider verifying dataflow for IO of secondary
2948 // structure annotation read from Stockholm files
2949 // this was added to try to ensure that
2950 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
2952 // anot[ae[aa].getPosition()].displayCharacter = "";
2954 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
2955 if (firstColour == null)
2957 firstColour = anot[anpos].colour;
2961 jalview.datamodel.AlignmentAnnotation jaa = null;
2963 if (annotation.getGraph())
2965 float llim = 0, hlim = 0;
2966 // if (autoForView || an[i].isAutoCalculated()) {
2969 jaa = new jalview.datamodel.AlignmentAnnotation(
2970 annotation.getLabel(), annotation.getDescription(), anot,
2971 llim, hlim, annotation.getGraphType());
2973 jaa.graphGroup = annotation.getGraphGroup();
2974 jaa._linecolour = firstColour;
2975 if (annotation.getThresholdLine() != null)
2977 jaa.setThreshold(new jalview.datamodel.GraphLine(annotation
2978 .getThresholdLine().getValue(), annotation
2979 .getThresholdLine().getLabel(), new java.awt.Color(
2980 annotation.getThresholdLine().getColour())));
2983 if (autoForView || annotation.isAutoCalculated())
2985 // Hardwire the symbol display line to ensure that labels for
2986 // histograms are displayed
2992 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
2993 an[i].getDescription(), anot);
2994 jaa._linecolour = firstColour;
2996 // register new annotation
2997 if (an[i].getId() != null)
2999 annotationIds.put(an[i].getId(), jaa);
3000 jaa.annotationId = an[i].getId();
3002 // recover sequence association
3003 String sequenceRef = an[i].getSequenceRef();
3004 if (sequenceRef != null)
3006 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3007 SequenceI sequence = seqRefIds.get(sequenceRef);
3008 if (sequence == null)
3010 // in pre-2.9 projects sequence ref is to sequence name
3011 sequence = al.findName(sequenceRef);
3013 if (sequence != null)
3015 jaa.createSequenceMapping(sequence, 1, true);
3016 sequence.addAlignmentAnnotation(jaa);
3019 // and make a note of any group association
3020 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
3022 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3023 .get(an[i].getGroupRef());
3026 aal = new ArrayList<jalview.datamodel.AlignmentAnnotation>();
3027 groupAnnotRefs.put(an[i].getGroupRef(), aal);
3032 if (an[i].hasScore())
3034 jaa.setScore(an[i].getScore());
3036 if (an[i].hasVisible())
3038 jaa.visible = an[i].getVisible();
3041 if (an[i].hasCentreColLabels())
3043 jaa.centreColLabels = an[i].getCentreColLabels();
3046 if (an[i].hasScaleColLabels())
3048 jaa.scaleColLabel = an[i].getScaleColLabels();
3050 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
3052 // newer files have an 'autoCalculated' flag and store calculation
3053 // state in viewport properties
3054 jaa.autoCalculated = true; // means annotation will be marked for
3055 // update at end of load.
3057 if (an[i].hasGraphHeight())
3059 jaa.graphHeight = an[i].getGraphHeight();
3061 if (an[i].hasBelowAlignment())
3063 jaa.belowAlignment = an[i].isBelowAlignment();
3065 jaa.setCalcId(an[i].getCalcId());
3066 if (an[i].getPropertyCount() > 0)
3068 for (jalview.schemabinding.version2.Property prop : an[i]
3071 jaa.setProperty(prop.getName(), prop.getValue());
3074 if (jaa.autoCalculated)
3076 autoAlan.add(new JvAnnotRow(i, jaa));
3079 // if (!autoForView)
3081 // add autocalculated group annotation and any user created annotation
3083 al.addAnnotation(jaa);
3087 // ///////////////////////
3089 // Create alignment markup and styles for this view
3090 if (jms.getJGroupCount() > 0)
3092 JGroup[] groups = jms.getJGroup();
3093 boolean addAnnotSchemeGroup = false;
3094 for (int i = 0; i < groups.length; i++)
3096 JGroup jGroup = groups[i];
3097 ColourSchemeI cs = null;
3098 if (jGroup.getColour() != null)
3100 if (jGroup.getColour().startsWith("ucs"))
3102 cs = getUserColourScheme(jms, jGroup.getColour());
3104 else if (jGroup.getColour().equals("AnnotationColourGradient")
3105 && jGroup.getAnnotationColours() != null)
3107 addAnnotSchemeGroup = true;
3112 cs = ColourSchemeProperty.getColour(al, jGroup.getColour());
3117 cs.setThreshold(jGroup.getPidThreshold(), true);
3121 Vector<SequenceI> seqs = new Vector<SequenceI>();
3123 for (int s = 0; s < jGroup.getSeqCount(); s++)
3125 String seqId = jGroup.getSeq(s) + "";
3126 SequenceI ts = seqRefIds.get(seqId);
3130 seqs.addElement(ts);
3134 if (seqs.size() < 1)
3139 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3140 jGroup.getDisplayBoxes(), jGroup.getDisplayText(),
3141 jGroup.getColourText(), jGroup.getStart(), jGroup.getEnd());
3143 sg.setOutlineColour(new java.awt.Color(jGroup.getOutlineColour()));
3145 sg.textColour = new java.awt.Color(jGroup.getTextCol1());
3146 sg.textColour2 = new java.awt.Color(jGroup.getTextCol2());
3147 sg.setShowNonconserved(jGroup.hasShowUnconserved() ? jGroup
3148 .isShowUnconserved() : false);
3149 sg.thresholdTextColour = jGroup.getTextColThreshold();
3150 if (jGroup.hasShowConsensusHistogram())
3152 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3155 if (jGroup.hasShowSequenceLogo())
3157 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3159 if (jGroup.hasNormaliseSequenceLogo())
3161 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3163 if (jGroup.hasIgnoreGapsinConsensus())
3165 sg.setIgnoreGapsConsensus(jGroup.getIgnoreGapsinConsensus());
3167 if (jGroup.getConsThreshold() != 0)
3169 jalview.analysis.Conservation c = new jalview.analysis.Conservation(
3170 "All", ResidueProperties.propHash, 3,
3171 sg.getSequences(null), 0, sg.getWidth() - 1);
3173 c.verdict(false, 25);
3174 sg.cs.setConservation(c);
3177 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3179 // re-instate unique group/annotation row reference
3180 List<AlignmentAnnotation> jaal = groupAnnotRefs.get(jGroup
3184 for (AlignmentAnnotation jaa : jaal)
3187 if (jaa.autoCalculated)
3189 // match up and try to set group autocalc alignment row for this
3191 if (jaa.label.startsWith("Consensus for "))
3193 sg.setConsensus(jaa);
3195 // match up and try to set group autocalc alignment row for this
3197 if (jaa.label.startsWith("Conservation for "))
3199 sg.setConservationRow(jaa);
3206 if (addAnnotSchemeGroup)
3208 // reconstruct the annotation colourscheme
3209 sg.cs = constructAnnotationColour(jGroup.getAnnotationColours(),
3210 null, al, jms, false);
3216 // only dataset in this model, so just return.
3219 // ///////////////////////////////
3222 // If we just load in the same jar file again, the sequenceSetId
3223 // will be the same, and we end up with multiple references
3224 // to the same sequenceSet. We must modify this id on load
3225 // so that each load of the file gives a unique id
3226 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3227 String viewId = (view.getId() == null ? null : view.getId()
3229 AlignFrame af = null;
3230 AlignViewport av = null;
3231 // now check to see if we really need to create a new viewport.
3232 if (multipleView && viewportsAdded.size() == 0)
3234 // We recovered an alignment for which a viewport already exists.
3235 // TODO: fix up any settings necessary for overlaying stored state onto
3236 // state recovered from another document. (may not be necessary).
3237 // we may need a binding from a viewport in memory to one recovered from
3239 // and then recover its containing af to allow the settings to be applied.
3240 // TODO: fix for vamsas demo
3242 .println("About to recover a viewport for existing alignment: Sequence set ID is "
3244 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3245 if (seqsetobj != null)
3247 if (seqsetobj instanceof String)
3249 uniqueSeqSetId = (String) seqsetobj;
3251 .println("Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
3257 .println("Warning : Collision between sequence set ID string and existing jalview object mapping.");
3263 * indicate that annotation colours are applied across all groups (pre
3264 * Jalview 2.8.1 behaviour)
3266 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan(
3267 "2.8.1", object.getVersion());
3269 AlignmentPanel ap = null;
3270 boolean isnewview = true;
3273 // Check to see if this alignment already has a view id == viewId
3274 jalview.gui.AlignmentPanel views[] = Desktop
3275 .getAlignmentPanels(uniqueSeqSetId);
3276 if (views != null && views.length > 0)
3278 for (int v = 0; v < views.length; v++)
3280 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
3282 // recover the existing alignpanel, alignframe, viewport
3283 af = views[v].alignFrame;
3286 // TODO: could even skip resetting view settings if we don't want to
3287 // change the local settings from other jalview processes
3296 af = loadViewport(file, jseqs, hiddenSeqs, al, jms, view,
3297 uniqueSeqSetId, viewId, autoAlan);
3303 * Load any trees, PDB structures and viewers
3305 * Not done if flag is false (when this method is used for New View)
3307 if (loadTreesAndStructures)
3309 loadTrees(jms, view, af, av, ap);
3310 loadPDBStructures(jprovider, jseqs, af, ap);
3311 loadRnaViewers(jprovider, jseqs, ap);
3313 // and finally return.
3318 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
3319 * panel is restored from separate jar entries, two (gapped and trimmed) per
3320 * sequence and secondary structure.
3322 * Currently each viewer shows just one sequence and structure (gapped and
3323 * trimmed), however this method is designed to support multiple sequences or
3324 * structures in viewers if wanted in future.
3330 private void loadRnaViewers(jarInputStreamProvider jprovider,
3331 JSeq[] jseqs, AlignmentPanel ap)
3334 * scan the sequences for references to viewers; create each one the first
3335 * time it is referenced, add Rna models to existing viewers
3337 for (JSeq jseq : jseqs)
3339 for (int i = 0; i < jseq.getRnaViewerCount(); i++)
3341 RnaViewer viewer = jseq.getRnaViewer(i);
3342 AppVarna appVarna = findOrCreateVarnaViewer(viewer,
3343 uniqueSetSuffix, ap);
3345 for (int j = 0; j < viewer.getSecondaryStructureCount(); j++)
3347 SecondaryStructure ss = viewer.getSecondaryStructure(j);
3348 SequenceI seq = seqRefIds.get(jseq.getId());
3349 AlignmentAnnotation ann = this.annotationIds.get(ss
3350 .getAnnotationId());
3353 * add the structure to the Varna display (with session state copied
3354 * from the jar to a temporary file)
3356 boolean gapped = ss.isGapped();
3357 String rnaTitle = ss.getTitle();
3358 String sessionState = ss.getViewerState();
3359 String tempStateFile = copyJarEntry(jprovider, sessionState,
3361 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
3362 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
3364 appVarna.setInitialSelection(viewer.getSelectedRna());
3370 * Locate and return an already instantiated matching AppVarna, or create one
3374 * @param viewIdSuffix
3378 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
3379 String viewIdSuffix, AlignmentPanel ap)
3382 * on each load a suffix is appended to the saved viewId, to avoid conflicts
3383 * if load is repeated
3385 String postLoadId = viewer.getViewId() + viewIdSuffix;
3386 for (JInternalFrame frame : getAllFrames())
3388 if (frame instanceof AppVarna)
3390 AppVarna varna = (AppVarna) frame;
3391 if (postLoadId.equals(varna.getViewId()))
3393 // this viewer is already instantiated
3394 // could in future here add ap as another 'parent' of the
3395 // AppVarna window; currently just 1-to-many
3402 * viewer not found - make it
3404 RnaViewerModel model = new RnaViewerModel(postLoadId,
3405 viewer.getTitle(), viewer.getXpos(), viewer.getYpos(),
3406 viewer.getWidth(), viewer.getHeight(),
3407 viewer.getDividerLocation());
3408 AppVarna varna = new AppVarna(model, ap);
3414 * Load any saved trees
3422 protected void loadTrees(JalviewModelSequence jms, Viewport view,
3423 AlignFrame af, AlignViewport av, AlignmentPanel ap)
3425 // TODO result of automated refactoring - are all these parameters needed?
3428 for (int t = 0; t < jms.getTreeCount(); t++)
3431 Tree tree = jms.getTree(t);
3433 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
3436 tp = af.ShowNewickTree(
3437 new jalview.io.NewickFile(tree.getNewick()),
3438 tree.getTitle(), tree.getWidth(), tree.getHeight(),
3439 tree.getXpos(), tree.getYpos());
3440 if (tree.getId() != null)
3442 // perhaps bind the tree id to something ?
3447 // update local tree attributes ?
3448 // TODO: should check if tp has been manipulated by user - if so its
3449 // settings shouldn't be modified
3450 tp.setTitle(tree.getTitle());
3451 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(), tree
3452 .getWidth(), tree.getHeight()));
3453 tp.av = av; // af.viewport; // TODO: verify 'associate with all
3456 tp.treeCanvas.av = av; // af.viewport;
3457 tp.treeCanvas.ap = ap; // af.alignPanel;
3462 warn("There was a problem recovering stored Newick tree: \n"
3463 + tree.getNewick());
3467 tp.fitToWindow.setState(tree.getFitToWindow());
3468 tp.fitToWindow_actionPerformed(null);
3470 if (tree.getFontName() != null)
3472 tp.setTreeFont(new java.awt.Font(tree.getFontName(), tree
3473 .getFontStyle(), tree.getFontSize()));
3477 tp.setTreeFont(new java.awt.Font(view.getFontName(), view
3478 .getFontStyle(), tree.getFontSize()));
3481 tp.showPlaceholders(tree.getMarkUnlinked());
3482 tp.showBootstrap(tree.getShowBootstrap());
3483 tp.showDistances(tree.getShowDistances());
3485 tp.treeCanvas.threshold = tree.getThreshold();
3487 if (tree.getCurrentTree())
3489 af.viewport.setCurrentTree(tp.getTree());
3493 } catch (Exception ex)
3495 ex.printStackTrace();
3500 * Load and link any saved structure viewers.
3507 protected void loadPDBStructures(jarInputStreamProvider jprovider,
3508 JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
3511 * Run through all PDB ids on the alignment, and collect mappings between
3512 * distinct view ids and all sequences referring to that view.
3514 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<String, StructureViewerModel>();
3516 for (int i = 0; i < jseqs.length; i++)
3518 if (jseqs[i].getPdbidsCount() > 0)
3520 Pdbids[] ids = jseqs[i].getPdbids();
3521 for (int p = 0; p < ids.length; p++)
3523 final int structureStateCount = ids[p].getStructureStateCount();
3524 for (int s = 0; s < structureStateCount; s++)
3526 // check to see if we haven't already created this structure view
3527 final StructureState structureState = ids[p]
3528 .getStructureState(s);
3529 String sviewid = (structureState.getViewId() == null) ? null
3530 : structureState.getViewId() + uniqueSetSuffix;
3531 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
3532 // Originally : ids[p].getFile()
3533 // : TODO: verify external PDB file recovery still works in normal
3534 // jalview project load
3535 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId()));
3536 jpdb.setId(ids[p].getId());
3538 int x = structureState.getXpos();
3539 int y = structureState.getYpos();
3540 int width = structureState.getWidth();
3541 int height = structureState.getHeight();
3543 // Probably don't need to do this anymore...
3544 // Desktop.desktop.getComponentAt(x, y);
3545 // TODO: NOW: check that this recovers the PDB file correctly.
3546 String pdbFile = loadPDBFile(jprovider, ids[p].getId());
3547 jalview.datamodel.SequenceI seq = seqRefIds.get(jseqs[i]
3549 if (sviewid == null)
3551 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width
3554 if (!structureViewers.containsKey(sviewid))
3556 structureViewers.put(sviewid,
3557 new StructureViewerModel(x, y, width, height, false,
3558 false, true, structureState.getViewId(),
3559 structureState.getType()));
3560 // Legacy pre-2.7 conversion JAL-823 :
3561 // do not assume any view has to be linked for colour by
3565 // assemble String[] { pdb files }, String[] { id for each
3566 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3567 // seqs_file 2}, boolean[] {
3568 // linkAlignPanel,superposeWithAlignpanel}} from hash
3569 StructureViewerModel jmoldat = structureViewers.get(sviewid);
3570 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
3571 | (structureState.hasAlignwithAlignPanel() ? structureState
3572 .getAlignwithAlignPanel() : false));
3575 * Default colour by linked panel to false if not specified (e.g.
3576 * for pre-2.7 projects)
3578 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
3579 colourWithAlignPanel |= (structureState
3580 .hasColourwithAlignPanel() ? structureState
3581 .getColourwithAlignPanel() : false);
3582 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
3585 * Default colour by viewer to true if not specified (e.g. for
3588 boolean colourByViewer = jmoldat.isColourByViewer();
3589 colourByViewer &= structureState.hasColourByJmol() ? structureState
3590 .getColourByJmol() : true;
3591 jmoldat.setColourByViewer(colourByViewer);
3593 if (jmoldat.getStateData().length() < structureState
3594 .getContent().length())
3597 jmoldat.setStateData(structureState.getContent());
3600 if (ids[p].getFile() != null)
3602 File mapkey = new File(ids[p].getFile());
3603 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
3604 if (seqstrmaps == null)
3606 jmoldat.getFileData().put(
3608 seqstrmaps = jmoldat.new StructureData(pdbFile,
3611 if (!seqstrmaps.getSeqList().contains(seq))
3613 seqstrmaps.getSeqList().add(seq);
3619 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");
3626 // Instantiate the associated structure views
3627 for (Entry<String, StructureViewerModel> entry : structureViewers
3632 createOrLinkStructureViewer(entry, af, ap, jprovider);
3633 } catch (Exception e)
3635 System.err.println("Error loading structure viewer: "
3637 // failed - try the next one
3649 protected void createOrLinkStructureViewer(
3650 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3651 AlignmentPanel ap, jarInputStreamProvider jprovider)
3653 final StructureViewerModel stateData = viewerData.getValue();
3656 * Search for any viewer windows already open from other alignment views
3657 * that exactly match the stored structure state
3659 StructureViewerBase comp = findMatchingViewer(viewerData);
3663 linkStructureViewer(ap, comp, stateData);
3668 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
3669 * "viewer_"+stateData.viewId
3671 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
3673 createChimeraViewer(viewerData, af, jprovider);
3678 * else Jmol (if pre-2.9, stateData contains JMOL state string)
3680 createJmolViewer(viewerData, af, jprovider);
3685 * Create a new Chimera viewer.
3691 protected void createChimeraViewer(
3692 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3693 jarInputStreamProvider jprovider)
3695 StructureViewerModel data = viewerData.getValue();
3696 String chimeraSessionFile = data.getStateData();
3699 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
3701 * NB this is the 'saved' viewId as in the project file XML, _not_ the
3702 * 'uniquified' sviewid used to reconstruct the viewer here
3704 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
3705 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
3708 Set<Entry<File, StructureData>> fileData = data.getFileData()
3710 List<PDBEntry> pdbs = new ArrayList<PDBEntry>();
3711 List<SequenceI[]> allseqs = new ArrayList<SequenceI[]>();
3712 for (Entry<File, StructureData> pdb : fileData)
3714 String filePath = pdb.getValue().getFilePath();
3715 String pdbId = pdb.getValue().getPdbId();
3716 // pdbs.add(new PDBEntry(filePath, pdbId));
3717 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
3718 final List<SequenceI> seqList = pdb.getValue().getSeqList();
3719 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
3723 boolean colourByChimera = data.isColourByViewer();
3724 boolean colourBySequence = data.isColourWithAlignPanel();
3726 // TODO use StructureViewer as a factory here, see JAL-1761
3727 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
3728 final SequenceI[][] seqsArray = allseqs.toArray(new SequenceI[allseqs
3730 String newViewId = viewerData.getKey();
3732 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
3733 af.alignPanel, pdbArray, seqsArray, colourByChimera,
3734 colourBySequence, newViewId);
3735 cvf.setSize(data.getWidth(), data.getHeight());
3736 cvf.setLocation(data.getX(), data.getY());
3740 * Create a new Jmol window. First parse the Jmol state to translate filenames
3741 * loaded into the view, and record the order in which files are shown in the
3742 * Jmol view, so we can add the sequence mappings in same order.
3748 protected void createJmolViewer(
3749 final Entry<String, StructureViewerModel> viewerData,
3750 AlignFrame af, jarInputStreamProvider jprovider)
3752 final StructureViewerModel svattrib = viewerData.getValue();
3753 String state = svattrib.getStateData();
3756 * Pre-2.9: state element value is the Jmol state string
3758 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
3761 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
3763 state = readJarEntry(jprovider,
3764 getViewerJarEntryName(svattrib.getViewId()));
3767 List<String> pdbfilenames = new ArrayList<String>();
3768 List<SequenceI[]> seqmaps = new ArrayList<SequenceI[]>();
3769 List<String> pdbids = new ArrayList<String>();
3770 StringBuilder newFileLoc = new StringBuilder(64);
3771 int cp = 0, ncp, ecp;
3772 Map<File, StructureData> oldFiles = svattrib.getFileData();
3773 while ((ncp = state.indexOf("load ", cp)) > -1)
3777 // look for next filename in load statement
3778 newFileLoc.append(state.substring(cp,
3779 ncp = (state.indexOf("\"", ncp + 1) + 1)));
3780 String oldfilenam = state.substring(ncp,
3781 ecp = state.indexOf("\"", ncp));
3782 // recover the new mapping data for this old filename
3783 // have to normalize filename - since Jmol and jalview do
3785 // translation differently.
3786 StructureData filedat = oldFiles.get(new File(oldfilenam));
3787 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
3788 pdbfilenames.add(filedat.getFilePath());
3789 pdbids.add(filedat.getPdbId());
3790 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
3791 newFileLoc.append("\"");
3792 cp = ecp + 1; // advance beyond last \" and set cursor so we can
3793 // look for next file statement.
3794 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
3798 // just append rest of state
3799 newFileLoc.append(state.substring(cp));
3803 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
3804 newFileLoc = new StringBuilder(state);
3805 newFileLoc.append("; load append ");
3806 for (File id : oldFiles.keySet())
3808 // add this and any other pdb files that should be present in
3810 StructureData filedat = oldFiles.get(id);
3811 newFileLoc.append(filedat.getFilePath());
3812 pdbfilenames.add(filedat.getFilePath());
3813 pdbids.add(filedat.getPdbId());
3814 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
3815 newFileLoc.append(" \"");
3816 newFileLoc.append(filedat.getFilePath());
3817 newFileLoc.append("\"");
3820 newFileLoc.append(";");
3823 if (newFileLoc.length() == 0)
3827 int histbug = newFileLoc.indexOf("history = ");
3831 * change "history = [true|false];" to "history = [1|0];"
3834 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
3835 String val = (diff == -1) ? null : newFileLoc
3836 .substring(histbug, diff);
3837 if (val != null && val.length() >= 4)
3839 if (val.contains("e")) // eh? what can it be?
3841 if (val.trim().equals("true"))
3849 newFileLoc.replace(histbug, diff, val);
3854 final String[] pdbf = pdbfilenames.toArray(new String[pdbfilenames
3856 final String[] id = pdbids.toArray(new String[pdbids.size()]);
3857 final SequenceI[][] sq = seqmaps
3858 .toArray(new SequenceI[seqmaps.size()][]);
3859 final String fileloc = newFileLoc.toString();
3860 final String sviewid = viewerData.getKey();
3861 final AlignFrame alf = af;
3862 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
3863 svattrib.getWidth(), svattrib.getHeight());
3866 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
3871 JalviewStructureDisplayI sview = null;
3874 sview = new StructureViewer(alf.alignPanel
3875 .getStructureSelectionManager()).createView(
3876 StructureViewer.ViewerType.JMOL, pdbf, id, sq,
3877 alf.alignPanel, svattrib, fileloc, rect, sviewid);
3878 addNewStructureViewer(sview);
3879 } catch (OutOfMemoryError ex)
3881 new OOMWarning("restoring structure view for PDB id " + id,
3882 (OutOfMemoryError) ex.getCause());
3883 if (sview != null && sview.isVisible())
3885 sview.closeViewer(false);
3886 sview.setVisible(false);
3892 } catch (InvocationTargetException ex)
3894 warn("Unexpected error when opening Jmol view.", ex);
3896 } catch (InterruptedException e)
3898 // e.printStackTrace();
3904 * Generates a name for the entry in the project jar file to hold state
3905 * information for a structure viewer
3910 protected String getViewerJarEntryName(String viewId)
3912 return VIEWER_PREFIX + viewId;
3916 * Returns any open frame that matches given structure viewer data. The match
3917 * is based on the unique viewId, or (for older project versions) the frame's
3923 protected StructureViewerBase findMatchingViewer(
3924 Entry<String, StructureViewerModel> viewerData)
3926 final String sviewid = viewerData.getKey();
3927 final StructureViewerModel svattrib = viewerData.getValue();
3928 StructureViewerBase comp = null;
3929 JInternalFrame[] frames = getAllFrames();
3930 for (JInternalFrame frame : frames)
3932 if (frame instanceof StructureViewerBase)
3935 * Post jalview 2.4 schema includes structure view id
3938 && ((StructureViewerBase) frame).getViewId()
3941 comp = (StructureViewerBase) frame;
3942 break; // break added in 2.9
3945 * Otherwise test for matching position and size of viewer frame
3947 else if (frame.getX() == svattrib.getX()
3948 && frame.getY() == svattrib.getY()
3949 && frame.getHeight() == svattrib.getHeight()
3950 && frame.getWidth() == svattrib.getWidth())
3952 comp = (StructureViewerBase) frame;
3953 // no break in faint hope of an exact match on viewId
3961 * Link an AlignmentPanel to an existing structure viewer.
3966 * @param useinViewerSuperpos
3967 * @param usetoColourbyseq
3968 * @param viewerColouring
3970 protected void linkStructureViewer(AlignmentPanel ap,
3971 StructureViewerBase viewer, StructureViewerModel stateData)
3973 // NOTE: if the jalview project is part of a shared session then
3974 // view synchronization should/could be done here.
3976 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
3977 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
3978 final boolean viewerColouring = stateData.isColourByViewer();
3979 Map<File, StructureData> oldFiles = stateData.getFileData();
3982 * Add mapping for sequences in this view to an already open viewer
3984 final AAStructureBindingModel binding = viewer.getBinding();
3985 for (File id : oldFiles.keySet())
3987 // add this and any other pdb files that should be present in the
3989 StructureData filedat = oldFiles.get(id);
3990 String pdbFile = filedat.getFilePath();
3991 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
3992 binding.getSsm().setMapping(seq, null, pdbFile,
3993 jalview.io.AppletFormatAdapter.FILE);
3994 binding.addSequenceForStructFile(pdbFile, seq);
3996 // and add the AlignmentPanel's reference to the view panel
3997 viewer.addAlignmentPanel(ap);
3998 if (useinViewerSuperpos)
4000 viewer.useAlignmentPanelForSuperposition(ap);
4004 viewer.excludeAlignmentPanelForSuperposition(ap);
4006 if (usetoColourbyseq)
4008 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4012 viewer.excludeAlignmentPanelForColourbyseq(ap);
4017 * Get all frames within the Desktop.
4021 protected JInternalFrame[] getAllFrames()
4023 JInternalFrame[] frames = null;
4024 // TODO is this necessary - is it safe - risk of hanging?
4029 frames = Desktop.desktop.getAllFrames();
4030 } catch (ArrayIndexOutOfBoundsException e)
4032 // occasional No such child exceptions are thrown here...
4036 } catch (InterruptedException f)
4040 } while (frames == null);
4045 * Answers true if 'version' is equal to or later than 'supported', where each
4046 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4047 * changes. Development and test values for 'version' are leniently treated
4051 * - minimum version we are comparing against
4053 * - version of data being processsed
4056 public static boolean isVersionStringLaterThan(String supported,
4059 if (supported == null || version == null
4060 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4061 || version.equalsIgnoreCase("Test")
4062 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4064 System.err.println("Assuming project file with "
4065 + (version == null ? "null" : version)
4066 + " is compatible with Jalview version " + supported);
4071 return StringUtils.compareVersions(version, supported, "b") >= 0;
4075 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4077 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4079 if (newStructureViewers != null)
4081 sview.getBinding().setFinishedLoadingFromArchive(false);
4082 newStructureViewers.add(sview);
4086 protected void setLoadingFinishedForNewStructureViewers()
4088 if (newStructureViewers != null)
4090 for (JalviewStructureDisplayI sview : newStructureViewers)
4092 sview.getBinding().setFinishedLoadingFromArchive(true);
4094 newStructureViewers.clear();
4095 newStructureViewers = null;
4099 AlignFrame loadViewport(String file, JSeq[] JSEQ,
4100 List<SequenceI> hiddenSeqs, Alignment al,
4101 JalviewModelSequence jms, Viewport view, String uniqueSeqSetId,
4102 String viewId, List<JvAnnotRow> autoAlan)
4104 AlignFrame af = null;
4105 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
4106 uniqueSeqSetId, viewId);
4108 af.setFileName(file, "Jalview");
4110 for (int i = 0; i < JSEQ.length; i++)
4112 af.viewport.setSequenceColour(af.viewport.getAlignment()
4113 .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour()));
4118 af.getViewport().setColourByReferenceSeq(true);
4119 af.getViewport().setDisplayReferenceSeq(true);
4122 af.viewport.setGatherViewsHere(view.getGatheredViews());
4124 if (view.getSequenceSetId() != null)
4126 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4128 af.viewport.setSequenceSetId(uniqueSeqSetId);
4131 // propagate shared settings to this new view
4132 af.viewport.setHistoryList(av.getHistoryList());
4133 af.viewport.setRedoList(av.getRedoList());
4137 viewportsAdded.put(uniqueSeqSetId, af.viewport);
4139 // TODO: check if this method can be called repeatedly without
4140 // side-effects if alignpanel already registered.
4141 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4143 // apply Hidden regions to view.
4144 if (hiddenSeqs != null)
4146 for (int s = 0; s < JSEQ.length; s++)
4148 jalview.datamodel.SequenceGroup hidden = new jalview.datamodel.SequenceGroup();
4150 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
4153 al.getSequenceAt(JSEQ[s].getHiddenSequences(r)), false);
4155 af.viewport.hideRepSequences(al.getSequenceAt(s), hidden);
4158 // jalview.datamodel.SequenceI[] hseqs = new
4159 // jalview.datamodel.SequenceI[hiddenSeqs
4162 // for (int s = 0; s < hiddenSeqs.size(); s++)
4164 // hseqs[s] = (jalview.datamodel.SequenceI) hiddenSeqs.elementAt(s);
4167 SequenceI[] hseqs = hiddenSeqs.toArray(new SequenceI[hiddenSeqs
4169 af.viewport.hideSequence(hseqs);
4172 // recover view properties and display parameters
4173 if (view.getViewName() != null)
4175 af.viewport.viewName = view.getViewName();
4176 af.setInitialTabVisible();
4178 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
4181 af.viewport.setShowAnnotation(view.getShowAnnotation());
4182 af.viewport.setAbovePIDThreshold(view.getPidSelected());
4184 af.viewport.setColourText(view.getShowColourText());
4186 af.viewport.setConservationSelected(view.getConservationSelected());
4187 af.viewport.setShowJVSuffix(view.getShowFullId());
4188 af.viewport.setRightAlignIds(view.getRightAlignIds());
4189 af.viewport.setFont(
4190 new java.awt.Font(view.getFontName(), view.getFontStyle(), view
4191 .getFontSize()), true);
4192 ViewStyleI vs = af.viewport.getViewStyle();
4193 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
4194 af.viewport.setViewStyle(vs);
4195 // TODO: allow custom charWidth/Heights to be restored by updating them
4196 // after setting font - which means set above to false
4197 af.viewport.setRenderGaps(view.getRenderGaps());
4198 af.viewport.setWrapAlignment(view.getWrapAlignment());
4199 af.viewport.setShowAnnotation(view.getShowAnnotation());
4201 af.viewport.setShowBoxes(view.getShowBoxes());
4203 af.viewport.setShowText(view.getShowText());
4205 af.viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
4206 af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
4207 af.viewport.setThresholdTextColour(view.getTextColThreshold());
4208 af.viewport.setShowUnconserved(view.hasShowUnconserved() ? view
4209 .isShowUnconserved() : false);
4210 af.viewport.setStartRes(view.getStartRes());
4211 af.viewport.setStartSeq(view.getStartSeq());
4212 af.alignPanel.updateLayout();
4213 ColourSchemeI cs = null;
4214 // apply colourschemes
4215 if (view.getBgColour() != null)
4217 if (view.getBgColour().startsWith("ucs"))
4219 cs = getUserColourScheme(jms, view.getBgColour());
4221 else if (view.getBgColour().startsWith("Annotation"))
4223 AnnotationColours viewAnnColour = view.getAnnotationColours();
4224 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
4231 cs = ColourSchemeProperty.getColour(al, view.getBgColour());
4236 cs.setThreshold(view.getPidThreshold(), true);
4237 cs.setConsensus(af.viewport.getSequenceConsensusHash());
4241 af.viewport.setGlobalColourScheme(cs);
4242 af.viewport.setColourAppliesToAllGroups(false);
4244 if (view.getConservationSelected() && cs != null)
4246 cs.setConservationInc(view.getConsThreshold());
4249 af.changeColour(cs);
4251 af.viewport.setColourAppliesToAllGroups(true);
4253 af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures());
4255 if (view.hasCentreColumnLabels())
4257 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
4259 if (view.hasIgnoreGapsinConsensus())
4261 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
4264 if (view.hasFollowHighlight())
4266 af.viewport.setFollowHighlight(view.getFollowHighlight());
4268 if (view.hasFollowSelection())
4270 af.viewport.followSelection = view.getFollowSelection();
4272 if (view.hasShowConsensusHistogram())
4274 af.viewport.setShowConsensusHistogram(view
4275 .getShowConsensusHistogram());
4279 af.viewport.setShowConsensusHistogram(true);
4281 if (view.hasShowSequenceLogo())
4283 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
4287 af.viewport.setShowSequenceLogo(false);
4289 if (view.hasNormaliseSequenceLogo())
4291 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
4293 if (view.hasShowDbRefTooltip())
4295 af.viewport.setShowDBRefs(view.getShowDbRefTooltip());
4297 if (view.hasShowNPfeatureTooltip())
4299 af.viewport.setShowNPFeats(view.hasShowNPfeatureTooltip());
4301 if (view.hasShowGroupConsensus())
4303 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
4307 af.viewport.setShowGroupConsensus(false);
4309 if (view.hasShowGroupConservation())
4311 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
4315 af.viewport.setShowGroupConservation(false);
4318 // recover featre settings
4319 if (jms.getFeatureSettings() != null)
4321 FeaturesDisplayed fdi;
4322 af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
4323 String[] renderOrder = new String[jms.getFeatureSettings()
4324 .getSettingCount()];
4325 Map<String, FeatureColourI> featureColours = new Hashtable<String, FeatureColourI>();
4326 Map<String, Float> featureOrder = new Hashtable<String, Float>();
4328 for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
4330 Setting setting = jms.getFeatureSettings().getSetting(fs);
4331 if (setting.hasMincolour())
4333 FeatureColourI gc = setting.hasMin() ? new FeatureColour(
4334 new Color(setting.getMincolour()), new Color(
4335 setting.getColour()), setting.getMin(),
4336 setting.getMax()) : new FeatureColour(new Color(
4337 setting.getMincolour()), new Color(setting.getColour()),
4339 if (setting.hasThreshold())
4341 gc.setThreshold(setting.getThreshold());
4342 int threshstate = setting.getThreshstate();
4343 // -1 = None, 0 = Below, 1 = Above threshold
4344 if (threshstate == 0)
4346 gc.setBelowThreshold(true);
4348 else if (threshstate == 1)
4350 gc.setAboveThreshold(true);
4353 gc.setAutoScaled(true); // default
4354 if (setting.hasAutoScale())
4356 gc.setAutoScaled(setting.getAutoScale());
4358 if (setting.hasColourByLabel())
4360 gc.setColourByLabel(setting.getColourByLabel());
4362 // and put in the feature colour table.
4363 featureColours.put(setting.getType(), gc);
4367 featureColours.put(setting.getType(), new FeatureColour(
4368 new Color(setting.getColour())));
4370 renderOrder[fs] = setting.getType();
4371 if (setting.hasOrder())
4373 featureOrder.put(setting.getType(), setting.getOrder());
4377 featureOrder.put(setting.getType(), new Float(fs
4378 / jms.getFeatureSettings().getSettingCount()));
4380 if (setting.getDisplay())
4382 fdi.setVisible(setting.getType());
4385 Map<String, Boolean> fgtable = new Hashtable<String, Boolean>();
4386 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
4388 Group grp = jms.getFeatureSettings().getGroup(gs);
4389 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
4391 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4392 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
4393 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
4394 FeatureRendererSettings frs = new FeatureRendererSettings(
4395 renderOrder, fgtable, featureColours, 1.0f, featureOrder);
4396 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
4397 .transferSettings(frs);
4401 if (view.getHiddenColumnsCount() > 0)
4403 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
4405 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(), view
4406 .getHiddenColumns(c).getEnd() // +1
4410 if (view.getCalcIdParam() != null)
4412 for (CalcIdParam calcIdParam : view.getCalcIdParam())
4414 if (calcIdParam != null)
4416 if (recoverCalcIdParam(calcIdParam, af.viewport))
4421 warn("Couldn't recover parameters for "
4422 + calcIdParam.getCalcId());
4427 af.setMenusFromViewport(af.viewport);
4429 // TODO: we don't need to do this if the viewport is aready visible.
4431 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
4432 * has a 'cdna/protein complement' view, in which case save it in order to
4433 * populate a SplitFrame once all views have been read in.
4435 String complementaryViewId = view.getComplementId();
4436 if (complementaryViewId == null)
4438 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
4440 // recompute any autoannotation
4441 af.alignPanel.updateAnnotation(false, true);
4442 reorderAutoannotation(af, al, autoAlan);
4443 af.alignPanel.alignmentChanged();
4447 splitFrameCandidates.put(view, af);
4452 private ColourSchemeI constructAnnotationColour(
4453 AnnotationColours viewAnnColour, AlignFrame af, Alignment al,
4454 JalviewModelSequence jms, boolean checkGroupAnnColour)
4456 boolean propagateAnnColour = false;
4457 ColourSchemeI cs = null;
4458 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
4459 if (checkGroupAnnColour && al.getGroups() != null
4460 && al.getGroups().size() > 0)
4462 // pre 2.8.1 behaviour
4463 // check to see if we should transfer annotation colours
4464 propagateAnnColour = true;
4465 for (jalview.datamodel.SequenceGroup sg : al.getGroups())
4467 if (sg.cs instanceof AnnotationColourGradient)
4469 propagateAnnColour = false;
4473 // int find annotation
4474 if (annAlignment.getAlignmentAnnotation() != null)
4476 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
4478 if (annAlignment.getAlignmentAnnotation()[i].label
4479 .equals(viewAnnColour.getAnnotation()))
4481 if (annAlignment.getAlignmentAnnotation()[i].getThreshold() == null)
4483 annAlignment.getAlignmentAnnotation()[i]
4484 .setThreshold(new jalview.datamodel.GraphLine(
4485 viewAnnColour.getThreshold(), "Threshold",
4486 java.awt.Color.black)
4491 if (viewAnnColour.getColourScheme().equals("None"))
4493 cs = new AnnotationColourGradient(
4494 annAlignment.getAlignmentAnnotation()[i],
4495 new java.awt.Color(viewAnnColour.getMinColour()),
4496 new java.awt.Color(viewAnnColour.getMaxColour()),
4497 viewAnnColour.getAboveThreshold());
4499 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
4501 cs = new AnnotationColourGradient(
4502 annAlignment.getAlignmentAnnotation()[i],
4503 getUserColourScheme(jms,
4504 viewAnnColour.getColourScheme()),
4505 viewAnnColour.getAboveThreshold());
4509 cs = new AnnotationColourGradient(
4510 annAlignment.getAlignmentAnnotation()[i],
4511 ColourSchemeProperty.getColour(al,
4512 viewAnnColour.getColourScheme()),
4513 viewAnnColour.getAboveThreshold());
4515 if (viewAnnColour.hasPerSequence())
4517 ((AnnotationColourGradient) cs).setSeqAssociated(viewAnnColour
4520 if (viewAnnColour.hasPredefinedColours())
4522 ((AnnotationColourGradient) cs)
4523 .setPredefinedColours(viewAnnColour
4524 .isPredefinedColours());
4526 if (propagateAnnColour && al.getGroups() != null)
4528 // Also use these settings for all the groups
4529 for (int g = 0; g < al.getGroups().size(); g++)
4531 jalview.datamodel.SequenceGroup sg = al.getGroups().get(g);
4539 * if (viewAnnColour.getColourScheme().equals("None" )) { sg.cs =
4540 * new AnnotationColourGradient(
4541 * annAlignment.getAlignmentAnnotation()[i], new
4542 * java.awt.Color(viewAnnColour. getMinColour()), new
4543 * java.awt.Color(viewAnnColour. getMaxColour()),
4544 * viewAnnColour.getAboveThreshold()); } else
4547 sg.cs = new AnnotationColourGradient(
4548 annAlignment.getAlignmentAnnotation()[i], sg.cs,
4549 viewAnnColour.getAboveThreshold());
4550 if (cs instanceof AnnotationColourGradient)
4552 if (viewAnnColour.hasPerSequence())
4554 ((AnnotationColourGradient) cs)
4555 .setSeqAssociated(viewAnnColour.isPerSequence());
4557 if (viewAnnColour.hasPredefinedColours())
4559 ((AnnotationColourGradient) cs)
4560 .setPredefinedColours(viewAnnColour
4561 .isPredefinedColours());
4577 private void reorderAutoannotation(AlignFrame af, Alignment al,
4578 List<JvAnnotRow> autoAlan)
4580 // copy over visualization settings for autocalculated annotation in the
4582 if (al.getAlignmentAnnotation() != null)
4585 * Kludge for magic autoannotation names (see JAL-811)
4587 String[] magicNames = new String[] { "Consensus", "Quality",
4589 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
4590 Hashtable<String, JvAnnotRow> visan = new Hashtable<String, JvAnnotRow>();
4591 for (String nm : magicNames)
4593 visan.put(nm, nullAnnot);
4595 for (JvAnnotRow auan : autoAlan)
4597 visan.put(auan.template.label
4598 + (auan.template.getCalcId() == null ? "" : "\t"
4599 + auan.template.getCalcId()), auan);
4601 int hSize = al.getAlignmentAnnotation().length;
4602 List<JvAnnotRow> reorder = new ArrayList<JvAnnotRow>();
4603 // work through any autoCalculated annotation already on the view
4604 // removing it if it should be placed in a different location on the
4605 // annotation panel.
4606 List<String> remains = new ArrayList<String>(visan.keySet());
4607 for (int h = 0; h < hSize; h++)
4609 jalview.datamodel.AlignmentAnnotation jalan = al
4610 .getAlignmentAnnotation()[h];
4611 if (jalan.autoCalculated)
4614 JvAnnotRow valan = visan.get(k = jalan.label);
4615 if (jalan.getCalcId() != null)
4617 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
4622 // delete the auto calculated row from the alignment
4623 al.deleteAnnotation(jalan, false);
4627 if (valan != nullAnnot)
4629 if (jalan != valan.template)
4631 // newly created autoannotation row instance
4632 // so keep a reference to the visible annotation row
4633 // and copy over all relevant attributes
4634 if (valan.template.graphHeight >= 0)
4637 jalan.graphHeight = valan.template.graphHeight;
4639 jalan.visible = valan.template.visible;
4641 reorder.add(new JvAnnotRow(valan.order, jalan));
4646 // Add any (possibly stale) autocalculated rows that were not appended to
4647 // the view during construction
4648 for (String other : remains)
4650 JvAnnotRow othera = visan.get(other);
4651 if (othera != nullAnnot && othera.template.getCalcId() != null
4652 && othera.template.getCalcId().length() > 0)
4654 reorder.add(othera);
4657 // now put the automatic annotation in its correct place
4658 int s = 0, srt[] = new int[reorder.size()];
4659 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
4660 for (JvAnnotRow jvar : reorder)
4663 srt[s++] = jvar.order;
4666 jalview.util.QuickSort.sort(srt, rws);
4667 // and re-insert the annotation at its correct position
4668 for (JvAnnotRow jvar : rws)
4670 al.addAnnotation(jvar.template, jvar.order);
4672 af.alignPanel.adjustAnnotationHeight();
4676 Hashtable skipList = null;
4679 * TODO remove this method
4682 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
4683 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
4684 * throw new Error("Implementation Error. No skipList defined for this
4685 * Jalview2XML instance."); } return (AlignFrame)
4686 * skipList.get(view.getSequenceSetId()); }
4690 * Check if the Jalview view contained in object should be skipped or not.
4693 * @return true if view's sequenceSetId is a key in skipList
4695 private boolean skipViewport(JalviewModel object)
4697 if (skipList == null)
4702 if (skipList.containsKey(id = object.getJalviewModelSequence()
4703 .getViewport()[0].getSequenceSetId()))
4705 if (Cache.log != null && Cache.log.isDebugEnabled())
4707 Cache.log.debug("Skipping seuqence set id " + id);
4714 public void addToSkipList(AlignFrame af)
4716 if (skipList == null)
4718 skipList = new Hashtable();
4720 skipList.put(af.getViewport().getSequenceSetId(), af);
4723 public void clearSkipList()
4725 if (skipList != null)
4732 private void recoverDatasetFor(SequenceSet vamsasSet, Alignment al,
4733 boolean ignoreUnrefed)
4735 jalview.datamodel.Alignment ds = getDatasetFor(vamsasSet.getDatasetId());
4736 Vector dseqs = null;
4739 // create a list of new dataset sequences
4740 dseqs = new Vector();
4742 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
4744 Sequence vamsasSeq = vamsasSet.getSequence(i);
4745 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed);
4747 // create a new dataset
4750 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
4751 dseqs.copyInto(dsseqs);
4752 ds = new jalview.datamodel.Alignment(dsseqs);
4753 debug("Created new dataset " + vamsasSet.getDatasetId()
4754 + " for alignment " + System.identityHashCode(al));
4755 addDatasetRef(vamsasSet.getDatasetId(), ds);
4757 // set the dataset for the newly imported alignment.
4758 if (al.getDataset() == null && !ignoreUnrefed)
4767 * sequence definition to create/merge dataset sequence for
4771 * vector to add new dataset sequence to
4773 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
4774 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed)
4776 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
4778 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
4779 SequenceI dsq = null;
4780 if (sq != null && sq.getDatasetSequence() != null)
4782 dsq = sq.getDatasetSequence();
4784 if (sq == null && ignoreUnrefed)
4788 String sqid = vamsasSeq.getDsseqid();
4791 // need to create or add a new dataset sequence reference to this sequence
4794 dsq = seqRefIds.get(sqid);
4799 // make a new dataset sequence
4800 dsq = sq.createDatasetSequence();
4803 // make up a new dataset reference for this sequence
4804 sqid = seqHash(dsq);
4806 dsq.setVamsasId(uniqueSetSuffix + sqid);
4807 seqRefIds.put(sqid, dsq);
4812 dseqs.addElement(dsq);
4817 ds.addSequence(dsq);
4823 { // make this dataset sequence sq's dataset sequence
4824 sq.setDatasetSequence(dsq);
4825 // and update the current dataset alignment
4830 if (!dseqs.contains(dsq))
4837 if (ds.findIndex(dsq) < 0)
4839 ds.addSequence(dsq);
4846 // TODO: refactor this as a merge dataset sequence function
4847 // now check that sq (the dataset sequence) sequence really is the union of
4848 // all references to it
4849 // boolean pre = sq.getStart() < dsq.getStart();
4850 // boolean post = sq.getEnd() > dsq.getEnd();
4854 // StringBuffer sb = new StringBuffer();
4855 String newres = jalview.analysis.AlignSeq.extractGaps(
4856 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
4857 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
4858 && newres.length() > dsq.getLength())
4860 // Update with the longer sequence.
4864 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
4865 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
4866 * sb.append(newres.substring(newres.length() - sq.getEnd() -
4867 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
4869 dsq.setSequence(newres);
4871 // TODO: merges will never happen if we 'know' we have the real dataset
4872 // sequence - this should be detected when id==dssid
4874 .println("DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
4875 // + (pre ? "prepended" : "") + " "
4876 // + (post ? "appended" : ""));
4882 * TODO use AlignmentI here and in related methods - needs
4883 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
4885 Hashtable<String, Alignment> datasetIds = null;
4887 IdentityHashMap<Alignment, String> dataset2Ids = null;
4889 private Alignment getDatasetFor(String datasetId)
4891 if (datasetIds == null)
4893 datasetIds = new Hashtable<String, Alignment>();
4896 if (datasetIds.containsKey(datasetId))
4898 return datasetIds.get(datasetId);
4903 private void addDatasetRef(String datasetId, Alignment dataset)
4905 if (datasetIds == null)
4907 datasetIds = new Hashtable<String, Alignment>();
4909 datasetIds.put(datasetId, dataset);
4913 * make a new dataset ID for this jalview dataset alignment
4918 private String getDatasetIdRef(Alignment dataset)
4920 if (dataset.getDataset() != null)
4922 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
4924 String datasetId = makeHashCode(dataset, null);
4925 if (datasetId == null)
4927 // make a new datasetId and record it
4928 if (dataset2Ids == null)
4930 dataset2Ids = new IdentityHashMap<Alignment, String>();
4934 datasetId = dataset2Ids.get(dataset);
4936 if (datasetId == null)
4938 datasetId = "ds" + dataset2Ids.size() + 1;
4939 dataset2Ids.put(dataset, datasetId);
4945 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
4947 for (int d = 0; d < sequence.getDBRefCount(); d++)
4949 DBRef dr = sequence.getDBRef(d);
4950 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
4951 sequence.getDBRef(d).getSource(), sequence.getDBRef(d)
4952 .getVersion(), sequence.getDBRef(d).getAccessionId());
4953 if (dr.getMapping() != null)
4955 entry.setMap(addMapping(dr.getMapping()));
4957 datasetSequence.addDBRef(entry);
4961 private jalview.datamodel.Mapping addMapping(Mapping m)
4963 SequenceI dsto = null;
4964 // Mapping m = dr.getMapping();
4965 int fr[] = new int[m.getMapListFromCount() * 2];
4966 Enumeration f = m.enumerateMapListFrom();
4967 for (int _i = 0; f.hasMoreElements(); _i += 2)
4969 MapListFrom mf = (MapListFrom) f.nextElement();
4970 fr[_i] = mf.getStart();
4971 fr[_i + 1] = mf.getEnd();
4973 int fto[] = new int[m.getMapListToCount() * 2];
4974 f = m.enumerateMapListTo();
4975 for (int _i = 0; f.hasMoreElements(); _i += 2)
4977 MapListTo mf = (MapListTo) f.nextElement();
4978 fto[_i] = mf.getStart();
4979 fto[_i + 1] = mf.getEnd();
4981 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto,
4982 fr, fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
4983 if (m.getMappingChoice() != null)
4985 MappingChoice mc = m.getMappingChoice();
4986 if (mc.getDseqFor() != null)
4988 String dsfor = "" + mc.getDseqFor();
4989 if (seqRefIds.containsKey(dsfor))
4994 jmap.setTo(seqRefIds.get(dsfor));
4998 frefedSequence.add(new Object[] { dsfor, jmap });
5004 * local sequence definition
5006 Sequence ms = mc.getSequence();
5007 SequenceI djs = null;
5008 String sqid = ms.getDsseqid();
5009 if (sqid != null && sqid.length() > 0)
5012 * recover dataset sequence
5014 djs = seqRefIds.get(sqid);
5019 .println("Warning - making up dataset sequence id for DbRef sequence map reference");
5020 sqid = ((Object) ms).toString(); // make up a new hascode for
5021 // undefined dataset sequence hash
5022 // (unlikely to happen)
5028 * make a new dataset sequence and add it to refIds hash
5030 djs = new jalview.datamodel.Sequence(ms.getName(),
5032 djs.setStart(jmap.getMap().getToLowest());
5033 djs.setEnd(jmap.getMap().getToHighest());
5034 djs.setVamsasId(uniqueSetSuffix + sqid);
5036 seqRefIds.put(sqid, djs);
5039 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5048 public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
5049 boolean keepSeqRefs)
5052 JalviewModel jm = saveState(ap, null, null, null);
5057 jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
5061 uniqueSetSuffix = "";
5062 jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
5067 if (this.frefedSequence == null)
5069 frefedSequence = new Vector();
5072 viewportsAdded.clear();
5074 AlignFrame af = loadFromObject(jm, null, false, null);
5075 af.alignPanels.clear();
5076 af.closeMenuItem_actionPerformed(true);
5079 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5080 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5081 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5082 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5083 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5086 return af.alignPanel;
5090 * flag indicating if hashtables should be cleared on finalization TODO this
5091 * flag may not be necessary
5093 private final boolean _cleartables = true;
5095 private Hashtable jvids2vobj;
5100 * @see java.lang.Object#finalize()
5103 protected void finalize() throws Throwable
5105 // really make sure we have no buried refs left.
5110 this.seqRefIds = null;
5111 this.seqsToIds = null;
5115 private void warn(String msg)
5120 private void warn(String msg, Exception e)
5122 if (Cache.log != null)
5126 Cache.log.warn(msg, e);
5130 Cache.log.warn(msg);
5135 System.err.println("Warning: " + msg);
5138 e.printStackTrace();
5143 private void debug(String string)
5145 debug(string, null);
5148 private void debug(String msg, Exception e)
5150 if (Cache.log != null)
5154 Cache.log.debug(msg, e);
5158 Cache.log.debug(msg);
5163 System.err.println("Warning: " + msg);
5166 e.printStackTrace();
5172 * set the object to ID mapping tables used to write/recover objects and XML
5173 * ID strings for the jalview project. If external tables are provided then
5174 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
5175 * object goes out of scope. - also populates the datasetIds hashtable with
5176 * alignment objects containing dataset sequences
5179 * Map from ID strings to jalview datamodel
5181 * Map from jalview datamodel to ID strings
5185 public void setObjectMappingTables(Hashtable vobj2jv,
5186 IdentityHashMap jv2vobj)
5188 this.jv2vobj = jv2vobj;
5189 this.vobj2jv = vobj2jv;
5190 Iterator ds = jv2vobj.keySet().iterator();
5192 while (ds.hasNext())
5194 Object jvobj = ds.next();
5195 id = jv2vobj.get(jvobj).toString();
5196 if (jvobj instanceof jalview.datamodel.Alignment)
5198 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
5200 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
5203 else if (jvobj instanceof jalview.datamodel.Sequence)
5205 // register sequence object so the XML parser can recover it.
5206 if (seqRefIds == null)
5208 seqRefIds = new HashMap<String, SequenceI>();
5210 if (seqsToIds == null)
5212 seqsToIds = new IdentityHashMap<SequenceI, String>();
5214 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
5215 seqsToIds.put((SequenceI) jvobj, id);
5217 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
5220 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
5221 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
5222 if (jvann.annotationId == null)
5224 jvann.annotationId = anid;
5226 if (!jvann.annotationId.equals(anid))
5228 // TODO verify that this is the correct behaviour
5229 this.warn("Overriding Annotation ID for " + anid
5230 + " from different id : " + jvann.annotationId);
5231 jvann.annotationId = anid;
5234 else if (jvobj instanceof String)
5236 if (jvids2vobj == null)
5238 jvids2vobj = new Hashtable();
5239 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
5244 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
5250 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
5251 * objects created from the project archive. If string is null (default for
5252 * construction) then suffix will be set automatically.
5256 public void setUniqueSetSuffix(String string)
5258 uniqueSetSuffix = string;
5263 * uses skipList2 as the skipList for skipping views on sequence sets
5264 * associated with keys in the skipList
5268 public void setSkipList(Hashtable skipList2)
5270 skipList = skipList2;
5274 * Reads the jar entry of given name and returns its contents, or null if the
5275 * entry is not found.
5278 * @param jarEntryName
5281 protected String readJarEntry(jarInputStreamProvider jprovider,
5282 String jarEntryName)
5284 String result = null;
5285 BufferedReader in = null;
5290 * Reopen the jar input stream and traverse its entries to find a matching
5293 JarInputStream jin = jprovider.getJarInputStream();
5294 JarEntry entry = null;
5297 entry = jin.getNextJarEntry();
5298 } while (entry != null && !entry.getName().equals(jarEntryName));
5302 StringBuilder out = new StringBuilder(256);
5303 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
5306 while ((data = in.readLine()) != null)
5310 result = out.toString();
5314 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
5316 } catch (Exception ex)
5318 ex.printStackTrace();
5326 } catch (IOException e)
5337 * Returns an incrementing counter (0, 1, 2...)
5341 private synchronized int nextCounter()