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.
21 package jalview.project;
23 import static jalview.math.RotatableMatrix.Axis.X;
24 import static jalview.math.RotatableMatrix.Axis.Y;
25 import static jalview.math.RotatableMatrix.Axis.Z;
27 import jalview.analysis.Conservation;
28 import jalview.analysis.PCA;
29 import jalview.analysis.scoremodels.ScoreModels;
30 import jalview.analysis.scoremodels.SimilarityParams;
31 import jalview.api.AlignmentViewPanel;
32 import jalview.api.FeatureColourI;
33 import jalview.api.ViewStyleI;
34 import jalview.api.analysis.ScoreModelI;
35 import jalview.api.analysis.SimilarityParamsI;
36 import jalview.api.structures.JalviewStructureDisplayI;
37 import jalview.bin.Cache;
38 import jalview.datamodel.AlignedCodonFrame;
39 import jalview.datamodel.Alignment;
40 import jalview.datamodel.AlignmentAnnotation;
41 import jalview.datamodel.AlignmentI;
42 import jalview.datamodel.DBRefEntry;
43 import jalview.datamodel.GeneLocus;
44 import jalview.datamodel.GraphLine;
45 import jalview.datamodel.PDBEntry;
46 import jalview.datamodel.Point;
47 import jalview.datamodel.RnaViewerModel;
48 import jalview.datamodel.SequenceFeature;
49 import jalview.datamodel.SequenceGroup;
50 import jalview.datamodel.SequenceI;
51 import jalview.datamodel.StructureViewerModel;
52 import jalview.datamodel.StructureViewerModel.StructureData;
53 import jalview.datamodel.features.FeatureMatcher;
54 import jalview.datamodel.features.FeatureMatcherI;
55 import jalview.datamodel.features.FeatureMatcherSet;
56 import jalview.datamodel.features.FeatureMatcherSetI;
57 import jalview.ext.varna.RnaModel;
58 import jalview.gui.AlignFrame;
59 import jalview.gui.AlignViewport;
60 import jalview.gui.AlignmentPanel;
61 import jalview.gui.AppVarna;
62 import jalview.gui.ChimeraViewFrame;
63 import jalview.gui.Desktop;
64 import jalview.gui.FeatureRenderer;
65 import jalview.gui.JvOptionPane;
66 import jalview.gui.OOMWarning;
67 import jalview.gui.PCAPanel;
68 import jalview.gui.PaintRefresher;
69 import jalview.gui.SplitFrame;
70 import jalview.gui.StructureViewer;
71 import jalview.gui.StructureViewer.ViewerType;
72 import jalview.gui.StructureViewerBase;
73 import jalview.gui.TreePanel;
74 import jalview.io.BackupFiles;
75 import jalview.io.DataSourceType;
76 import jalview.io.FileFormat;
77 import jalview.io.NewickFile;
78 import jalview.math.Matrix;
79 import jalview.math.MatrixI;
80 import jalview.renderer.ResidueShaderI;
81 import jalview.schemes.AnnotationColourGradient;
82 import jalview.schemes.ColourSchemeI;
83 import jalview.schemes.ColourSchemeProperty;
84 import jalview.schemes.FeatureColour;
85 import jalview.schemes.ResidueProperties;
86 import jalview.schemes.UserColourScheme;
87 import jalview.structures.models.AAStructureBindingModel;
88 import jalview.util.Format;
89 import jalview.util.MessageManager;
90 import jalview.util.Platform;
91 import jalview.util.StringUtils;
92 import jalview.util.jarInputStreamProvider;
93 import jalview.util.matcher.Condition;
94 import jalview.viewmodel.AlignmentViewport;
95 import jalview.viewmodel.PCAModel;
96 import jalview.viewmodel.ViewportRanges;
97 import jalview.viewmodel.seqfeatures.FeatureRendererModel;
98 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
99 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
100 import jalview.ws.jws2.Jws2Discoverer;
101 import jalview.ws.jws2.dm.AAConSettings;
102 import jalview.ws.jws2.jabaws2.Jws2Instance;
103 import jalview.ws.params.ArgumentI;
104 import jalview.ws.params.AutoCalcSetting;
105 import jalview.ws.params.WsParamSetI;
106 import jalview.xml.binding.jalview.AlcodonFrame;
107 import jalview.xml.binding.jalview.AlcodonFrame.AlcodMap;
108 import jalview.xml.binding.jalview.Annotation;
109 import jalview.xml.binding.jalview.Annotation.ThresholdLine;
110 import jalview.xml.binding.jalview.AnnotationColourScheme;
111 import jalview.xml.binding.jalview.AnnotationElement;
112 import jalview.xml.binding.jalview.DoubleMatrix;
113 import jalview.xml.binding.jalview.DoubleVector;
114 import jalview.xml.binding.jalview.Feature;
115 import jalview.xml.binding.jalview.Feature.OtherData;
116 import jalview.xml.binding.jalview.FeatureMatcherSet.CompoundMatcher;
117 import jalview.xml.binding.jalview.FilterBy;
118 import jalview.xml.binding.jalview.JalviewModel;
119 import jalview.xml.binding.jalview.JalviewModel.FeatureSettings;
120 import jalview.xml.binding.jalview.JalviewModel.FeatureSettings.Group;
121 import jalview.xml.binding.jalview.JalviewModel.FeatureSettings.Setting;
122 import jalview.xml.binding.jalview.JalviewModel.JGroup;
123 import jalview.xml.binding.jalview.JalviewModel.JSeq;
124 import jalview.xml.binding.jalview.JalviewModel.JSeq.Pdbids;
125 import jalview.xml.binding.jalview.JalviewModel.JSeq.Pdbids.StructureState;
126 import jalview.xml.binding.jalview.JalviewModel.JSeq.RnaViewer;
127 import jalview.xml.binding.jalview.JalviewModel.JSeq.RnaViewer.SecondaryStructure;
128 import jalview.xml.binding.jalview.JalviewModel.PcaViewer;
129 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.Axis;
130 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.SeqPointMax;
131 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.SeqPointMin;
132 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.SequencePoint;
133 import jalview.xml.binding.jalview.JalviewModel.Tree;
134 import jalview.xml.binding.jalview.JalviewModel.UserColours;
135 import jalview.xml.binding.jalview.JalviewModel.Viewport;
136 import jalview.xml.binding.jalview.JalviewModel.Viewport.CalcIdParam;
137 import jalview.xml.binding.jalview.JalviewModel.Viewport.HiddenColumns;
138 import jalview.xml.binding.jalview.JalviewUserColours;
139 import jalview.xml.binding.jalview.JalviewUserColours.Colour;
140 import jalview.xml.binding.jalview.MapListType.MapListFrom;
141 import jalview.xml.binding.jalview.MapListType.MapListTo;
142 import jalview.xml.binding.jalview.Mapping;
143 import jalview.xml.binding.jalview.NoValueColour;
144 import jalview.xml.binding.jalview.ObjectFactory;
145 import jalview.xml.binding.jalview.PcaDataType;
146 import jalview.xml.binding.jalview.Pdbentry.Property;
147 import jalview.xml.binding.jalview.Sequence;
148 import jalview.xml.binding.jalview.Sequence.DBRef;
149 import jalview.xml.binding.jalview.SequenceSet;
150 import jalview.xml.binding.jalview.SequenceSet.SequenceSetProperties;
151 import jalview.xml.binding.jalview.ThresholdType;
152 import jalview.xml.binding.jalview.VAMSAS;
154 import java.awt.Color;
155 import java.awt.Dimension;
156 import java.awt.Font;
157 import java.awt.Rectangle;
158 import java.io.BufferedReader;
159 import java.io.ByteArrayInputStream;
160 import java.io.DataInputStream;
161 import java.io.DataOutputStream;
163 import java.io.FileInputStream;
164 import java.io.FileOutputStream;
165 import java.io.IOException;
166 import java.io.InputStream;
167 import java.io.InputStreamReader;
168 import java.io.OutputStreamWriter;
169 import java.io.PrintWriter;
170 import java.math.BigInteger;
171 import java.net.MalformedURLException;
173 import java.util.ArrayList;
174 import java.util.Arrays;
175 import java.util.Collections;
176 import java.util.Enumeration;
177 import java.util.GregorianCalendar;
178 import java.util.HashMap;
179 import java.util.HashSet;
180 import java.util.Hashtable;
181 import java.util.IdentityHashMap;
182 import java.util.Iterator;
183 import java.util.LinkedHashMap;
184 import java.util.List;
185 import java.util.Map;
186 import java.util.Map.Entry;
187 import java.util.Set;
188 import java.util.Vector;
189 import java.util.jar.JarEntry;
190 import java.util.jar.JarInputStream;
191 import java.util.jar.JarOutputStream;
193 import javax.swing.JInternalFrame;
194 import javax.swing.SwingUtilities;
195 import javax.xml.bind.JAXBContext;
196 import javax.xml.bind.JAXBElement;
197 import javax.xml.bind.Marshaller;
198 import javax.xml.datatype.DatatypeConfigurationException;
199 import javax.xml.datatype.DatatypeFactory;
200 import javax.xml.datatype.XMLGregorianCalendar;
201 import javax.xml.stream.XMLInputFactory;
202 import javax.xml.stream.XMLStreamReader;
205 * Write out the current jalview desktop state as a Jalview XML stream.
207 * Note: the vamsas objects referred to here are primitive versions of the
208 * VAMSAS project schema elements - they are not the same and most likely never
212 * @version $Revision: 1.134 $
214 public class Jalview2XML
217 // BH 2018 we add the .jvp binary extension to J2S so that
218 // it will declare that binary when we do the file save from the browser
222 Platform.addJ2SBinaryType(".jvp?");
225 private static final String VIEWER_PREFIX = "viewer_";
227 private static final String RNA_PREFIX = "rna_";
229 private static final String UTF_8 = "UTF-8";
232 * prefix for recovering datasets for alignments with multiple views where
233 * non-existent dataset IDs were written for some views
235 private static final String UNIQSEQSETID = "uniqueSeqSetId.";
237 // use this with nextCounter() to make unique names for entities
238 private int counter = 0;
241 * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
242 * of sequence objects are created.
244 IdentityHashMap<SequenceI, String> seqsToIds = null;
247 * jalview XML Sequence ID to jalview sequence object reference (both dataset
248 * and alignment sequences. Populated as XML reps of sequence objects are
251 Map<String, SequenceI> seqRefIds = null;
253 Map<String, SequenceI> incompleteSeqs = null;
255 List<SeqFref> frefedSequence = null;
257 boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
260 * Map of reconstructed AlignFrame objects that appear to have come from
261 * SplitFrame objects (have a dna/protein complement view).
263 private Map<Viewport, AlignFrame> splitFrameCandidates = new HashMap<>();
266 * Map from displayed rna structure models to their saved session state jar
269 private Map<RnaModel, String> rnaSessions = new HashMap<>();
272 * contains last error message (if any) encountered by XML loader.
274 String errorMessage = null;
277 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
278 * exceptions are raised during project XML parsing
280 public boolean attemptversion1parse = false;
283 * JalviewJS only -- to allow read file bytes to be saved in the
284 * created AlignFrame, allowing File | Reload of a project file to work
288 private File jarFile;
291 * A helper method for safely using the value of an optional attribute that
292 * may be null if not present in the XML. Answers the boolean value, or false
298 public static boolean safeBoolean(Boolean b)
300 return b == null ? false : b.booleanValue();
304 * A helper method for safely using the value of an optional attribute that
305 * may be null if not present in the XML. Answers the integer value, or zero
311 public static int safeInt(Integer i)
313 return i == null ? 0 : i.intValue();
317 * A helper method for safely using the value of an optional attribute that
318 * may be null if not present in the XML. Answers the float value, or zero if
324 public static float safeFloat(Float f)
326 return f == null ? 0f : f.floatValue();
330 * create/return unique hash string for sq
333 * @return new or existing unique string for sq
335 String seqHash(SequenceI sq)
337 if (seqsToIds == null)
341 if (seqsToIds.containsKey(sq))
343 return seqsToIds.get(sq);
347 // create sequential key
348 String key = "sq" + (seqsToIds.size() + 1);
349 key = makeHashCode(sq, key); // check we don't have an external reference
351 seqsToIds.put(sq, key);
358 if (seqsToIds == null)
360 seqsToIds = new IdentityHashMap<>();
362 if (seqRefIds == null)
364 seqRefIds = new HashMap<>();
366 if (incompleteSeqs == null)
368 incompleteSeqs = new HashMap<>();
370 if (frefedSequence == null)
372 frefedSequence = new ArrayList<>();
380 public Jalview2XML(boolean raiseGUI)
382 this.raiseGUI = raiseGUI;
386 * base class for resolving forward references to sequences by their ID
391 abstract class SeqFref
397 public SeqFref(String _sref, String type)
403 public String getSref()
408 public SequenceI getSrefSeq()
410 return seqRefIds.get(sref);
413 public boolean isResolvable()
415 return seqRefIds.get(sref) != null;
418 public SequenceI getSrefDatasetSeq()
420 SequenceI sq = seqRefIds.get(sref);
423 while (sq.getDatasetSequence() != null)
425 sq = sq.getDatasetSequence();
432 * @return true if the forward reference was fully resolved
434 abstract boolean resolve();
437 public String toString()
439 return type + " reference to " + sref;
444 * create forward reference for a mapping
450 protected SeqFref newMappingRef(final String sref,
451 final jalview.datamodel.Mapping _jmap)
453 SeqFref fref = new SeqFref(sref, "Mapping")
455 public jalview.datamodel.Mapping jmap = _jmap;
460 SequenceI seq = getSrefDatasetSeq();
472 protected SeqFref newAlcodMapRef(final String sref,
473 final AlignedCodonFrame _cf,
474 final jalview.datamodel.Mapping _jmap)
477 SeqFref fref = new SeqFref(sref, "Codon Frame")
479 AlignedCodonFrame cf = _cf;
481 public jalview.datamodel.Mapping mp = _jmap;
484 public boolean isResolvable()
486 return super.isResolvable() && mp.getTo() != null;
492 SequenceI seq = getSrefDatasetSeq();
497 cf.addMap(seq, mp.getTo(), mp.getMap());
504 protected void resolveFrefedSequences()
506 Iterator<SeqFref> nextFref = frefedSequence.iterator();
507 int toresolve = frefedSequence.size();
508 int unresolved = 0, failedtoresolve = 0;
509 while (nextFref.hasNext())
511 SeqFref ref = nextFref.next();
512 if (ref.isResolvable())
524 } catch (Exception x)
527 "IMPLEMENTATION ERROR: Failed to resolve forward reference for sequence "
540 System.err.println("Jalview Project Import: There were " + unresolved
541 + " forward references left unresolved on the stack.");
543 if (failedtoresolve > 0)
545 System.err.println("SERIOUS! " + failedtoresolve
546 + " resolvable forward references failed to resolve.");
548 if (incompleteSeqs != null && incompleteSeqs.size() > 0)
551 "Jalview Project Import: There are " + incompleteSeqs.size()
552 + " sequences which may have incomplete metadata.");
553 if (incompleteSeqs.size() < 10)
555 for (SequenceI s : incompleteSeqs.values())
557 System.err.println(s.toString());
563 "Too many to report. Skipping output of incomplete sequences.");
569 * This maintains a map of viewports, the key being the seqSetId. Important to
570 * set historyItem and redoList for multiple views
572 Map<String, AlignViewport> viewportsAdded = new HashMap<>();
574 Map<String, AlignmentAnnotation> annotationIds = new HashMap<>();
576 String uniqueSetSuffix = "";
579 * List of pdbfiles added to Jar
581 List<String> pdbfiles = null;
583 // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
584 public void saveState(File statefile)
586 FileOutputStream fos = null;
591 fos = new FileOutputStream(statefile);
593 JarOutputStream jout = new JarOutputStream(fos);
597 } catch (Exception e)
599 Cache.log.error("Couln't write Jalview state to " + statefile, e);
600 // TODO: inform user of the problem - they need to know if their data was
602 if (errorMessage == null)
604 errorMessage = "Did't write Jalview Archive to output file '"
605 + statefile + "' - See console error log for details";
609 errorMessage += "(Didn't write Jalview Archive to output file '"
620 } catch (IOException e)
630 * Writes a jalview project archive to the given Jar output stream.
634 public void saveState(JarOutputStream jout)
636 AlignFrame[] frames = Desktop.getAlignFrames();
642 saveAllFrames(Arrays.asList(frames), jout);
646 * core method for storing state for a set of AlignFrames.
649 * - frames involving all data to be exported (including those
650 * contained in splitframes, though not the split frames themselves)
652 * - project output stream
654 private void saveAllFrames(List<AlignFrame> frames, JarOutputStream jout)
657 Hashtable<String, AlignFrame> dsses = new Hashtable<>();
660 * ensure cached data is clear before starting
662 // todo tidy up seqRefIds, seqsToIds initialisation / reset
664 splitFrameCandidates.clear();
669 // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
670 // //////////////////////////////////////////////////
672 List<String> shortNames = new ArrayList<>();
673 List<String> viewIds = new ArrayList<>();
676 for (int i = frames.size() - 1; i > -1; i--)
678 AlignFrame af = frames.get(i);
679 AlignViewport vp = af.getViewport();
681 if (skipList != null && skipList
682 .containsKey(vp.getSequenceSetId()))
687 String shortName = makeFilename(af, shortNames);
689 AlignmentI alignment = vp.getAlignment();
690 List<? extends AlignmentViewPanel> panels = af.getAlignPanels();
691 int apSize = panels.size();
692 for (int ap = 0; ap < apSize; ap++)
694 AlignmentPanel apanel = (AlignmentPanel) panels.get(ap);
695 String fileName = apSize == 1 ? shortName : ap + shortName;
696 if (!fileName.endsWith(".xml"))
698 fileName = fileName + ".xml";
701 saveState(apanel, fileName, jout, viewIds);
705 // BH moved next bit out of inner loop, not that it really matters.
706 // so we are testing to make sure we actually have an alignment,
708 String dssid = getDatasetIdRef(alignment.getDataset());
709 if (!dsses.containsKey(dssid))
711 // We have not already covered this data by reference from another
713 dsses.put(dssid, af);
718 writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix,
724 } catch (Exception foo)
728 } catch (Exception ex)
730 // TODO: inform user of the problem - they need to know if their data was
732 if (errorMessage == null)
734 errorMessage = "Couldn't write Jalview Archive - see error output for details";
736 ex.printStackTrace();
741 * Generates a distinct file name, based on the title of the AlignFrame, by
742 * appending _n for increasing n until an unused name is generated. The new
743 * name (without its extension) is added to the list.
747 * @return the generated name, with .xml extension
749 protected String makeFilename(AlignFrame af, List<String> namesUsed)
751 String shortName = af.getTitle();
753 if (shortName.indexOf(File.separatorChar) > -1)
755 shortName = shortName
756 .substring(shortName.lastIndexOf(File.separatorChar) + 1);
761 while (namesUsed.contains(shortName))
763 if (shortName.endsWith("_" + (count - 1)))
765 shortName = shortName.substring(0, shortName.lastIndexOf("_"));
768 shortName = shortName.concat("_" + count);
772 namesUsed.add(shortName);
774 if (!shortName.endsWith(".xml"))
776 shortName = shortName + ".xml";
781 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
782 public boolean saveAlignment(AlignFrame af, String jarFile,
787 // create backupfiles object and get new temp filename destination
788 boolean doBackup = BackupFiles.getEnabled();
789 BackupFiles backupfiles = doBackup ? new BackupFiles(jarFile) : null;
790 FileOutputStream fos = new FileOutputStream(doBackup ?
791 backupfiles.getTempFilePath() : jarFile);
793 JarOutputStream jout = new JarOutputStream(fos);
794 List<AlignFrame> frames = new ArrayList<>();
796 // resolve splitframes
797 if (af.getViewport().getCodingComplement() != null)
799 frames = ((SplitFrame) af.getSplitViewContainer()).getAlignFrames();
805 saveAllFrames(frames, jout);
809 } catch (Exception foo)
813 boolean success = true;
817 backupfiles.setWriteSuccess(success);
818 success = backupfiles.rollBackupsAndRenameTempFile();
822 } catch (Exception ex)
824 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
825 ex.printStackTrace();
831 * Each AlignFrame has a single data set associated with it. Note that none of
832 * these frames are split frames, because Desktop.getAlignFrames() collects
833 * top and bottom separately here.
839 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
840 String fileName, JarOutputStream jout)
843 // Note that in saveAllFrames we have associated each specific dataset to
844 // ONE of its associated frames.
846 for (String dssids : dsses.keySet())
848 AlignFrame _af = dsses.get(dssids);
849 String jfileName = fileName + " Dataset for " + _af.getTitle();
850 if (!jfileName.endsWith(".xml"))
852 jfileName = jfileName + ".xml";
854 saveState(_af.alignPanel, jfileName, true, jout, null);
859 * create a JalviewModel from an alignment view and marshall it to a
863 * panel to create jalview model for
865 * name of alignment panel written to output stream
872 protected JalviewModel saveState(AlignmentPanel ap, String fileName,
873 JarOutputStream jout, List<String> viewIds)
875 return saveState(ap, fileName, false, jout, viewIds);
879 * create a JalviewModel from an alignment view and marshall it to a
883 * panel to create jalview model for
885 * name of alignment panel written to output stream
887 * when true, only write the dataset for the alignment, not the data
888 * associated with the view.
894 protected JalviewModel saveState(AlignmentPanel ap, String fileName,
895 boolean storeDS, JarOutputStream jout, List<String> viewIds)
899 viewIds = new ArrayList<>();
904 List<UserColourScheme> userColours = new ArrayList<>();
906 AlignViewport av = ap.av;
907 ViewportRanges vpRanges = av.getRanges();
909 final ObjectFactory objectFactory = new ObjectFactory();
910 JalviewModel object = objectFactory.createJalviewModel();
911 object.setVamsasModel(new VAMSAS());
913 // object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
916 GregorianCalendar c = new GregorianCalendar();
917 DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
918 XMLGregorianCalendar now = datatypeFactory.newXMLGregorianCalendar(c);// gregorianCalendar);
919 object.setCreationDate(now);
920 } catch (DatatypeConfigurationException e)
922 System.err.println("error writing date: " + e.toString());
925 jalview.bin.Cache.getDefault("VERSION", "Development Build"));
928 * rjal is full height alignment, jal is actual alignment with full metadata
929 * but excludes hidden sequences.
931 jalview.datamodel.AlignmentI rjal = av.getAlignment(), jal = rjal;
933 if (av.hasHiddenRows())
935 rjal = jal.getHiddenSequences().getFullAlignment();
938 SequenceSet vamsasSet = new SequenceSet();
940 // JalviewModelSequence jms = new JalviewModelSequence();
942 vamsasSet.setGapChar(jal.getGapCharacter() + "");
944 if (jal.getDataset() != null)
946 // dataset id is the dataset's hashcode
947 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
950 // switch jal and the dataset
951 jal = jal.getDataset();
955 if (jal.getProperties() != null)
957 Enumeration en = jal.getProperties().keys();
958 while (en.hasMoreElements())
960 String key = en.nextElement().toString();
961 SequenceSetProperties ssp = new SequenceSetProperties();
963 ssp.setValue(jal.getProperties().get(key).toString());
964 // vamsasSet.addSequenceSetProperties(ssp);
965 vamsasSet.getSequenceSetProperties().add(ssp);
970 Set<String> calcIdSet = new HashSet<>();
971 // record the set of vamsas sequence XML POJO we create.
972 HashMap<String, Sequence> vamsasSetIds = new HashMap<>();
974 for (final SequenceI jds : rjal.getSequences())
976 final SequenceI jdatasq = jds.getDatasetSequence() == null ? jds
977 : jds.getDatasetSequence();
978 String id = seqHash(jds);
979 if (vamsasSetIds.get(id) == null)
981 if (seqRefIds.get(id) != null && !storeDS)
983 // This happens for two reasons: 1. multiple views are being
985 // 2. the hashCode has collided with another sequence's code. This
987 // HAPPEN! (PF00072.15.stk does this)
988 // JBPNote: Uncomment to debug writing out of files that do not read
989 // back in due to ArrayOutOfBoundExceptions.
990 // System.err.println("vamsasSeq backref: "+id+"");
991 // System.err.println(jds.getName()+"
992 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
993 // System.err.println("Hashcode: "+seqHash(jds));
994 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
995 // System.err.println(rsq.getName()+"
996 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
997 // System.err.println("Hashcode: "+seqHash(rsq));
1001 vamsasSeq = createVamsasSequence(id, jds);
1002 // vamsasSet.addSequence(vamsasSeq);
1003 vamsasSet.getSequence().add(vamsasSeq);
1004 vamsasSetIds.put(id, vamsasSeq);
1005 seqRefIds.put(id, jds);
1009 jseq.setStart(jds.getStart());
1010 jseq.setEnd(jds.getEnd());
1011 jseq.setColour(av.getSequenceColour(jds).getRGB());
1013 jseq.setId(id); // jseq id should be a string not a number
1016 // Store any sequences this sequence represents
1017 if (av.hasHiddenRows())
1019 // use rjal, contains the full height alignment
1021 av.getAlignment().getHiddenSequences().isHidden(jds));
1023 if (av.isHiddenRepSequence(jds))
1025 jalview.datamodel.SequenceI[] reps = av
1026 .getRepresentedSequences(jds).getSequencesInOrder(rjal);
1028 for (int h = 0; h < reps.length; h++)
1032 // jseq.addHiddenSequences(rjal.findIndex(reps[h]));
1033 jseq.getHiddenSequences().add(rjal.findIndex(reps[h]));
1038 // mark sequence as reference - if it is the reference for this view
1039 if (jal.hasSeqrep())
1041 jseq.setViewreference(jds == jal.getSeqrep());
1045 // TODO: omit sequence features from each alignment view's XML dump if we
1046 // are storing dataset
1047 List<SequenceFeature> sfs = jds.getSequenceFeatures();
1048 for (SequenceFeature sf : sfs)
1050 // Features features = new Features();
1051 Feature features = new Feature();
1053 features.setBegin(sf.getBegin());
1054 features.setEnd(sf.getEnd());
1055 features.setDescription(sf.getDescription());
1056 features.setType(sf.getType());
1057 features.setFeatureGroup(sf.getFeatureGroup());
1058 features.setScore(sf.getScore());
1059 if (sf.links != null)
1061 for (int l = 0; l < sf.links.size(); l++)
1063 OtherData keyValue = new OtherData();
1064 keyValue.setKey("LINK_" + l);
1065 keyValue.setValue(sf.links.elementAt(l).toString());
1066 // features.addOtherData(keyValue);
1067 features.getOtherData().add(keyValue);
1070 if (sf.otherDetails != null)
1073 * save feature attributes, which may be simple strings or
1074 * map valued (have sub-attributes)
1076 for (Entry<String, Object> entry : sf.otherDetails.entrySet())
1078 String key = entry.getKey();
1079 Object value = entry.getValue();
1080 if (value instanceof Map<?, ?>)
1082 for (Entry<String, Object> subAttribute : ((Map<String, Object>) value)
1085 OtherData otherData = new OtherData();
1086 otherData.setKey(key);
1087 otherData.setKey2(subAttribute.getKey());
1088 otherData.setValue(subAttribute.getValue().toString());
1089 // features.addOtherData(otherData);
1090 features.getOtherData().add(otherData);
1095 OtherData otherData = new OtherData();
1096 otherData.setKey(key);
1097 otherData.setValue(value.toString());
1098 // features.addOtherData(otherData);
1099 features.getOtherData().add(otherData);
1104 // jseq.addFeatures(features);
1105 jseq.getFeatures().add(features);
1108 if (jdatasq.getAllPDBEntries() != null)
1110 Enumeration<PDBEntry> en = jdatasq.getAllPDBEntries().elements();
1111 while (en.hasMoreElements())
1113 Pdbids pdb = new Pdbids();
1114 jalview.datamodel.PDBEntry entry = en.nextElement();
1116 String pdbId = entry.getId();
1118 pdb.setType(entry.getType());
1121 * Store any structure views associated with this sequence. This
1122 * section copes with duplicate entries in the project, so a dataset
1123 * only view *should* be coped with sensibly.
1125 // This must have been loaded, is it still visible?
1126 JInternalFrame[] frames = Desktop.getDesktopPane().getAllFrames();
1127 String matchedFile = null;
1128 for (int f = frames.length - 1; f > -1; f--)
1130 if (frames[f] instanceof StructureViewerBase)
1132 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
1133 matchedFile = saveStructureState(ap, jds, pdb, entry, viewIds,
1134 matchedFile, viewFrame);
1136 * Only store each structure viewer's state once in the project
1137 * jar. First time through only (storeDS==false)
1139 String viewId = viewFrame.getViewId();
1140 if (!storeDS && !viewIds.contains(viewId))
1142 viewIds.add(viewId);
1145 String viewerState = viewFrame.getStateInfo();
1146 writeJarEntry(jout, getViewerJarEntryName(viewId),
1147 viewerState.getBytes());
1148 } catch (IOException e)
1151 "Error saving viewer state: " + e.getMessage());
1157 if (matchedFile != null || entry.getFile() != null)
1159 if (entry.getFile() != null)
1162 matchedFile = entry.getFile();
1164 pdb.setFile(matchedFile); // entry.getFile());
1165 if (pdbfiles == null)
1167 pdbfiles = new ArrayList<>();
1170 if (!pdbfiles.contains(pdbId))
1172 pdbfiles.add(pdbId);
1173 copyFileToJar(jout, matchedFile, pdbId);
1177 Enumeration<String> props = entry.getProperties();
1178 if (props.hasMoreElements())
1180 // PdbentryItem item = new PdbentryItem();
1181 while (props.hasMoreElements())
1183 Property prop = new Property();
1184 String key = props.nextElement();
1186 prop.setValue(entry.getProperty(key).toString());
1187 // item.addProperty(prop);
1188 pdb.getProperty().add(prop);
1190 // pdb.addPdbentryItem(item);
1193 // jseq.addPdbids(pdb);
1194 jseq.getPdbids().add(pdb);
1198 saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
1200 // jms.addJSeq(jseq);
1201 object.getJSeq().add(jseq);
1204 if (!storeDS && av.hasHiddenRows())
1206 jal = av.getAlignment();
1210 if (storeDS && jal.getCodonFrames() != null)
1212 List<AlignedCodonFrame> jac = jal.getCodonFrames();
1213 for (AlignedCodonFrame acf : jac)
1215 AlcodonFrame alc = new AlcodonFrame();
1216 if (acf.getProtMappings() != null
1217 && acf.getProtMappings().length > 0)
1219 boolean hasMap = false;
1220 SequenceI[] dnas = acf.getdnaSeqs();
1221 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1222 for (int m = 0; m < pmaps.length; m++)
1224 AlcodMap alcmap = new AlcodMap();
1225 alcmap.setDnasq(seqHash(dnas[m]));
1227 createVamsasMapping(pmaps[m], dnas[m], null, false));
1228 // alc.addAlcodMap(alcmap);
1229 alc.getAlcodMap().add(alcmap);
1234 // vamsasSet.addAlcodonFrame(alc);
1235 vamsasSet.getAlcodonFrame().add(alc);
1238 // TODO: delete this ? dead code from 2.8.3->2.9 ?
1240 // AlcodonFrame alc = new AlcodonFrame();
1241 // vamsasSet.addAlcodonFrame(alc);
1242 // for (int p = 0; p < acf.aaWidth; p++)
1244 // Alcodon cmap = new Alcodon();
1245 // if (acf.codons[p] != null)
1247 // // Null codons indicate a gapped column in the translated peptide
1249 // cmap.setPos1(acf.codons[p][0]);
1250 // cmap.setPos2(acf.codons[p][1]);
1251 // cmap.setPos3(acf.codons[p][2]);
1253 // alc.addAlcodon(cmap);
1255 // if (acf.getProtMappings() != null
1256 // && acf.getProtMappings().length > 0)
1258 // SequenceI[] dnas = acf.getdnaSeqs();
1259 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1260 // for (int m = 0; m < pmaps.length; m++)
1262 // AlcodMap alcmap = new AlcodMap();
1263 // alcmap.setDnasq(seqHash(dnas[m]));
1264 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
1266 // alc.addAlcodMap(alcmap);
1273 // /////////////////////////////////
1274 if (!storeDS && av.getCurrentTree() != null)
1276 // FIND ANY ASSOCIATED TREES
1277 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
1278 if (Desktop.getDesktopPane() != null)
1280 JInternalFrame[] frames = Desktop.getDesktopPane().getAllFrames();
1282 for (int t = 0; t < frames.length; t++)
1284 if (frames[t] instanceof TreePanel)
1286 TreePanel tp = (TreePanel) frames[t];
1288 if (tp.getTreeCanvas().getViewport().getAlignment() == jal)
1290 JalviewModel.Tree tree = new JalviewModel.Tree();
1291 tree.setTitle(tp.getTitle());
1292 tree.setCurrentTree((av.getCurrentTree() == tp.getTree()));
1293 tree.setNewick(tp.getTree().print());
1294 tree.setThreshold(tp.getTreeCanvas().getThreshold());
1296 tree.setFitToWindow(tp.fitToWindow.getState());
1297 tree.setFontName(tp.getTreeFont().getName());
1298 tree.setFontSize(tp.getTreeFont().getSize());
1299 tree.setFontStyle(tp.getTreeFont().getStyle());
1300 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
1302 tree.setShowBootstrap(tp.bootstrapMenu.getState());
1303 tree.setShowDistances(tp.distanceMenu.getState());
1305 tree.setHeight(tp.getHeight());
1306 tree.setWidth(tp.getWidth());
1307 tree.setXpos(tp.getX());
1308 tree.setYpos(tp.getY());
1309 tree.setId(makeHashCode(tp, null));
1310 tree.setLinkToAllViews(
1311 tp.getTreeCanvas().isApplyToAllViews());
1313 // jms.addTree(tree);
1314 object.getTree().add(tree);
1324 if (!storeDS && Desktop.getDesktopPane() != null)
1326 for (JInternalFrame frame : Desktop.getDesktopPane().getAllFrames())
1328 if (frame instanceof PCAPanel)
1330 PCAPanel panel = (PCAPanel) frame;
1331 if (panel.getAlignViewport().getAlignment() == jal)
1333 savePCA(panel, object);
1341 * store forward refs from an annotationRow to any groups
1343 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<>();
1346 for (SequenceI sq : jal.getSequences())
1348 // Store annotation on dataset sequences only
1349 AlignmentAnnotation[] aa = sq.getAnnotation();
1350 if (aa != null && aa.length > 0)
1352 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1359 if (jal.getAlignmentAnnotation() != null)
1361 // Store the annotation shown on the alignment.
1362 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1363 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1368 if (jal.getGroups() != null)
1370 JGroup[] groups = new JGroup[jal.getGroups().size()];
1372 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1374 JGroup jGroup = new JGroup();
1375 groups[++i] = jGroup;
1377 jGroup.setStart(sg.getStartRes());
1378 jGroup.setEnd(sg.getEndRes());
1379 jGroup.setName(sg.getName());
1380 if (groupRefs.containsKey(sg))
1382 // group has references so set its ID field
1383 jGroup.setId(groupRefs.get(sg));
1385 ColourSchemeI colourScheme = sg.getColourScheme();
1386 if (colourScheme != null)
1388 ResidueShaderI groupColourScheme = sg.getGroupColourScheme();
1389 if (groupColourScheme.conservationApplied())
1391 jGroup.setConsThreshold(groupColourScheme.getConservationInc());
1393 if (colourScheme instanceof jalview.schemes.UserColourScheme)
1396 setUserColourScheme(colourScheme, userColours,
1401 jGroup.setColour(colourScheme.getSchemeName());
1404 else if (colourScheme instanceof jalview.schemes.AnnotationColourGradient)
1406 jGroup.setColour("AnnotationColourGradient");
1407 jGroup.setAnnotationColours(constructAnnotationColours(
1408 (jalview.schemes.AnnotationColourGradient) colourScheme,
1409 userColours, object));
1411 else if (colourScheme instanceof jalview.schemes.UserColourScheme)
1414 setUserColourScheme(colourScheme, userColours, object));
1418 jGroup.setColour(colourScheme.getSchemeName());
1421 jGroup.setPidThreshold(groupColourScheme.getThreshold());
1424 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1425 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1426 jGroup.setDisplayText(sg.getDisplayText());
1427 jGroup.setColourText(sg.getColourText());
1428 jGroup.setTextCol1(sg.textColour.getRGB());
1429 jGroup.setTextCol2(sg.textColour2.getRGB());
1430 jGroup.setTextColThreshold(sg.thresholdTextColour);
1431 jGroup.setShowUnconserved(sg.getShowNonconserved());
1432 jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1433 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1434 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1435 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1436 for (SequenceI seq : sg.getSequences())
1438 // jGroup.addSeq(seqHash(seq));
1439 jGroup.getSeq().add(seqHash(seq));
1443 //jms.setJGroup(groups);
1445 for (JGroup grp : groups)
1447 object.getJGroup().add(grp);
1452 // /////////SAVE VIEWPORT
1453 Viewport view = new Viewport();
1454 view.setTitle(ap.alignFrame.getTitle());
1455 view.setSequenceSetId(
1456 makeHashCode(av.getSequenceSetId(), av.getSequenceSetId()));
1457 view.setId(av.getViewId());
1458 if (av.getCodingComplement() != null)
1460 view.setComplementId(av.getCodingComplement().getViewId());
1462 view.setViewName(av.getViewName());
1463 view.setGatheredViews(av.isGatherViewsHere());
1465 Rectangle size = ap.av.getExplodedGeometry();
1466 Rectangle position = size;
1469 size = ap.alignFrame.getBounds();
1470 if (av.getCodingComplement() != null)
1472 position = ((SplitFrame) ap.alignFrame.getSplitViewContainer())
1480 view.setXpos(position.x);
1481 view.setYpos(position.y);
1483 view.setWidth(size.width);
1484 view.setHeight(size.height);
1486 view.setStartRes(vpRanges.getStartRes());
1487 view.setStartSeq(vpRanges.getStartSeq());
1489 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1491 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1492 userColours, object));
1495 .getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1497 AnnotationColourScheme ac = constructAnnotationColours(
1498 (jalview.schemes.AnnotationColourGradient) av
1499 .getGlobalColourScheme(),
1500 userColours, object);
1502 view.setAnnotationColours(ac);
1503 view.setBgColour("AnnotationColourGradient");
1507 view.setBgColour(ColourSchemeProperty
1508 .getColourName(av.getGlobalColourScheme()));
1511 ResidueShaderI vcs = av.getResidueShading();
1512 ColourSchemeI cs = av.getGlobalColourScheme();
1516 if (vcs.conservationApplied())
1518 view.setConsThreshold(vcs.getConservationInc());
1519 if (cs instanceof jalview.schemes.UserColourScheme)
1521 view.setBgColour(setUserColourScheme(cs, userColours, object));
1524 view.setPidThreshold(vcs.getThreshold());
1527 view.setConservationSelected(av.getConservationSelected());
1528 view.setPidSelected(av.getAbovePIDThreshold());
1529 final Font font = av.getFont();
1530 view.setFontName(font.getName());
1531 view.setFontSize(font.getSize());
1532 view.setFontStyle(font.getStyle());
1533 view.setScaleProteinAsCdna(av.getViewStyle().isScaleProteinAsCdna());
1534 view.setRenderGaps(av.isRenderGaps());
1535 view.setShowAnnotation(av.isShowAnnotation());
1536 view.setShowBoxes(av.getShowBoxes());
1537 view.setShowColourText(av.getColourText());
1538 view.setShowFullId(av.getShowJVSuffix());
1539 view.setRightAlignIds(av.isRightAlignIds());
1540 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1541 view.setShowText(av.getShowText());
1542 view.setShowUnconserved(av.getShowUnconserved());
1543 view.setWrapAlignment(av.getWrapAlignment());
1544 view.setTextCol1(av.getTextColour().getRGB());
1545 view.setTextCol2(av.getTextColour2().getRGB());
1546 view.setTextColThreshold(av.getThresholdTextColour());
1547 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1548 view.setShowSequenceLogo(av.isShowSequenceLogo());
1549 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1550 view.setShowGroupConsensus(av.isShowGroupConsensus());
1551 view.setShowGroupConservation(av.isShowGroupConservation());
1552 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1553 view.setShowDbRefTooltip(av.isShowDBRefs());
1554 view.setFollowHighlight(av.isFollowHighlight());
1555 view.setFollowSelection(av.followSelection);
1556 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1557 view.setShowComplementFeatures(av.isShowComplementFeatures());
1558 view.setShowComplementFeaturesOnTop(
1559 av.isShowComplementFeaturesOnTop());
1560 if (av.getFeaturesDisplayed() != null)
1562 FeatureSettings fs = new FeatureSettings();
1564 FeatureRendererModel fr = ap.getSeqPanel().seqCanvas
1565 .getFeatureRenderer();
1566 String[] renderOrder = fr.getRenderOrder().toArray(new String[0]);
1568 Vector<String> settingsAdded = new Vector<>();
1569 if (renderOrder != null)
1571 for (String featureType : renderOrder)
1573 FeatureSettings.Setting setting = new FeatureSettings.Setting();
1574 setting.setType(featureType);
1577 * save any filter for the feature type
1579 FeatureMatcherSetI filter = fr.getFeatureFilter(featureType);
1580 if (filter != null) {
1581 Iterator<FeatureMatcherI> filters = filter.getMatchers().iterator();
1582 FeatureMatcherI firstFilter = filters.next();
1583 setting.setMatcherSet(Jalview2XML.marshalFilter(
1584 firstFilter, filters, filter.isAnded()));
1588 * save colour scheme for the feature type
1590 FeatureColourI fcol = fr.getFeatureStyle(featureType);
1591 if (!fcol.isSimpleColour())
1593 setting.setColour(fcol.getMaxColour().getRGB());
1594 setting.setMincolour(fcol.getMinColour().getRGB());
1595 setting.setMin(fcol.getMin());
1596 setting.setMax(fcol.getMax());
1597 setting.setColourByLabel(fcol.isColourByLabel());
1598 if (fcol.isColourByAttribute())
1600 String[] attName = fcol.getAttributeName();
1601 setting.getAttributeName().add(attName[0]);
1602 if (attName.length > 1)
1604 setting.getAttributeName().add(attName[1]);
1607 setting.setAutoScale(fcol.isAutoScaled());
1608 setting.setThreshold(fcol.getThreshold());
1609 Color noColour = fcol.getNoColour();
1610 if (noColour == null)
1612 setting.setNoValueColour(NoValueColour.NONE);
1614 else if (noColour.equals(fcol.getMaxColour()))
1616 setting.setNoValueColour(NoValueColour.MAX);
1620 setting.setNoValueColour(NoValueColour.MIN);
1622 // -1 = No threshold, 0 = Below, 1 = Above
1623 setting.setThreshstate(fcol.isAboveThreshold() ? 1
1624 : (fcol.isBelowThreshold() ? 0 : -1));
1628 setting.setColour(fcol.getColour().getRGB());
1632 av.getFeaturesDisplayed().isVisible(featureType));
1634 .getOrder(featureType);
1637 setting.setOrder(rorder);
1639 /// fs.addSetting(setting);
1640 fs.getSetting().add(setting);
1641 settingsAdded.addElement(featureType);
1645 // is groups actually supposed to be a map here ?
1646 Iterator<String> en = fr.getFeatureGroups().iterator();
1647 Vector<String> groupsAdded = new Vector<>();
1648 while (en.hasNext())
1650 String grp = en.next();
1651 if (groupsAdded.contains(grp))
1655 Group g = new Group();
1657 g.setDisplay(((Boolean) fr.checkGroupVisibility(grp, false))
1660 fs.getGroup().add(g);
1661 groupsAdded.addElement(grp);
1663 // jms.setFeatureSettings(fs);
1664 object.setFeatureSettings(fs);
1667 if (av.hasHiddenColumns())
1669 jalview.datamodel.HiddenColumns hidden = av.getAlignment()
1670 .getHiddenColumns();
1673 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1677 Iterator<int[]> hiddenRegions = hidden.iterator();
1678 while (hiddenRegions.hasNext())
1680 int[] region = hiddenRegions.next();
1681 HiddenColumns hc = new HiddenColumns();
1682 hc.setStart(region[0]);
1683 hc.setEnd(region[1]);
1684 // view.addHiddenColumns(hc);
1685 view.getHiddenColumns().add(hc);
1689 if (calcIdSet.size() > 0)
1691 for (String calcId : calcIdSet)
1693 if (calcId.trim().length() > 0)
1695 CalcIdParam cidp = createCalcIdParam(calcId, av);
1696 // Some calcIds have no parameters.
1699 // view.addCalcIdParam(cidp);
1700 view.getCalcIdParam().add(cidp);
1706 // jms.addViewport(view);
1707 object.getViewport().add(view);
1709 // object.setJalviewModelSequence(jms);
1710 // object.getVamsasModel().addSequenceSet(vamsasSet);
1711 object.getVamsasModel().getSequenceSet().add(vamsasSet);
1713 if (jout != null && fileName != null)
1715 // We may not want to write the object to disk,
1716 // eg we can copy the alignViewport to a new view object
1717 // using save and then load
1720 fileName = fileName.replace('\\', '/');
1721 System.out.println("Writing jar entry " + fileName);
1722 JarEntry entry = new JarEntry(fileName);
1723 jout.putNextEntry(entry);
1724 PrintWriter pout = new PrintWriter(
1725 new OutputStreamWriter(jout, UTF_8));
1726 JAXBContext jaxbContext = JAXBContext
1727 .newInstance(JalviewModel.class);
1728 Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
1730 // output pretty printed
1731 // jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
1732 jaxbMarshaller.marshal(
1733 new ObjectFactory().createJalviewModel(object), pout);
1735 // jaxbMarshaller.marshal(object, pout);
1736 // marshaller.marshal(object);
1739 } catch (Exception ex)
1741 // TODO: raise error in GUI if marshalling failed.
1742 System.err.println("Error writing Jalview project");
1743 ex.printStackTrace();
1750 * Writes PCA viewer attributes and computed values to an XML model object and
1751 * adds it to the JalviewModel. Any exceptions are reported by logging.
1753 protected void savePCA(PCAPanel panel, JalviewModel object)
1757 PcaViewer viewer = new PcaViewer();
1758 viewer.setHeight(panel.getHeight());
1759 viewer.setWidth(panel.getWidth());
1760 viewer.setXpos(panel.getX());
1761 viewer.setYpos(panel.getY());
1762 viewer.setTitle(panel.getTitle());
1763 PCAModel pcaModel = panel.getPcaModel();
1764 viewer.setScoreModelName(pcaModel.getScoreModelName());
1765 viewer.setXDim(panel.getSelectedDimensionIndex(X));
1766 viewer.setYDim(panel.getSelectedDimensionIndex(Y));
1767 viewer.setZDim(panel.getSelectedDimensionIndex(Z));
1769 panel.getRotatableCanvas().getBackgroundColour().getRGB());
1770 viewer.setScaleFactor(panel.getRotatableCanvas().getScaleFactor());
1771 float[] spMin = panel.getRotatableCanvas().getSeqMin();
1772 SeqPointMin spmin = new SeqPointMin();
1773 spmin.setXPos(spMin[0]);
1774 spmin.setYPos(spMin[1]);
1775 spmin.setZPos(spMin[2]);
1776 viewer.setSeqPointMin(spmin);
1777 float[] spMax = panel.getRotatableCanvas().getSeqMax();
1778 SeqPointMax spmax = new SeqPointMax();
1779 spmax.setXPos(spMax[0]);
1780 spmax.setYPos(spMax[1]);
1781 spmax.setZPos(spMax[2]);
1782 viewer.setSeqPointMax(spmax);
1783 viewer.setShowLabels(panel.getRotatableCanvas().isShowLabels());
1784 viewer.setLinkToAllViews(
1785 panel.getRotatableCanvas().isApplyToAllViews());
1786 SimilarityParamsI sp = pcaModel.getSimilarityParameters();
1787 viewer.setIncludeGaps(sp.includeGaps());
1788 viewer.setMatchGaps(sp.matchGaps());
1789 viewer.setIncludeGappedColumns(sp.includeGappedColumns());
1790 viewer.setDenominateByShortestLength(sp.denominateByShortestLength());
1793 * sequence points on display
1795 for (jalview.datamodel.SequencePoint spt : pcaModel
1796 .getSequencePoints())
1798 SequencePoint point = new SequencePoint();
1799 point.setSequenceRef(seqHash(spt.getSequence()));
1800 point.setXPos(spt.coord.x);
1801 point.setYPos(spt.coord.y);
1802 point.setZPos(spt.coord.z);
1803 viewer.getSequencePoint().add(point);
1807 * (end points of) axes on display
1809 for (Point p : panel.getRotatableCanvas().getAxisEndPoints())
1812 Axis axis = new Axis();
1816 viewer.getAxis().add(axis);
1820 * raw PCA data (note we are not restoring PCA inputs here -
1821 * alignment view, score model, similarity parameters)
1823 PcaDataType data = new PcaDataType();
1824 viewer.setPcaData(data);
1825 PCA pca = pcaModel.getPcaData();
1827 DoubleMatrix pm = new DoubleMatrix();
1828 saveDoubleMatrix(pca.getPairwiseScores(), pm);
1829 data.setPairwiseMatrix(pm);
1831 DoubleMatrix tm = new DoubleMatrix();
1832 saveDoubleMatrix(pca.getTridiagonal(), tm);
1833 data.setTridiagonalMatrix(tm);
1835 DoubleMatrix eigenMatrix = new DoubleMatrix();
1836 data.setEigenMatrix(eigenMatrix);
1837 saveDoubleMatrix(pca.getEigenmatrix(), eigenMatrix);
1839 object.getPcaViewer().add(viewer);
1840 } catch (Throwable t)
1842 Cache.log.error("Error saving PCA: " + t.getMessage());
1847 * Stores values from a matrix into an XML element, including (if present) the
1852 * @see #loadDoubleMatrix(DoubleMatrix)
1854 protected void saveDoubleMatrix(MatrixI m, DoubleMatrix xmlMatrix)
1856 xmlMatrix.setRows(m.height());
1857 xmlMatrix.setColumns(m.width());
1858 for (int i = 0; i < m.height(); i++)
1860 DoubleVector row = new DoubleVector();
1861 for (int j = 0; j < m.width(); j++)
1863 row.getV().add(m.getValue(i, j));
1865 xmlMatrix.getRow().add(row);
1867 if (m.getD() != null)
1869 DoubleVector dVector = new DoubleVector();
1870 for (double d : m.getD())
1872 dVector.getV().add(d);
1874 xmlMatrix.setD(dVector);
1876 if (m.getE() != null)
1878 DoubleVector eVector = new DoubleVector();
1879 for (double e : m.getE())
1881 eVector.getV().add(e);
1883 xmlMatrix.setE(eVector);
1888 * Loads XML matrix data into a new Matrix object, including the D and/or E
1889 * vectors (if present)
1893 * @see Jalview2XML#saveDoubleMatrix(MatrixI, DoubleMatrix)
1895 protected MatrixI loadDoubleMatrix(DoubleMatrix mData)
1897 int rows = mData.getRows();
1898 double[][] vals = new double[rows][];
1900 for (int i = 0; i < rows; i++)
1902 List<Double> dVector = mData.getRow().get(i).getV();
1903 vals[i] = new double[dVector.size()];
1905 for (Double d : dVector)
1911 MatrixI m = new Matrix(vals);
1913 if (mData.getD() != null)
1915 List<Double> dVector = mData.getD().getV();
1916 double[] vec = new double[dVector.size()];
1918 for (Double d : dVector)
1924 if (mData.getE() != null)
1926 List<Double> dVector = mData.getE().getV();
1927 double[] vec = new double[dVector.size()];
1929 for (Double d : dVector)
1940 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1941 * for each viewer, with
1943 * <li>viewer geometry (position, size, split pane divider location)</li>
1944 * <li>index of the selected structure in the viewer (currently shows gapped
1946 * <li>the id of the annotation holding RNA secondary structure</li>
1947 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1949 * Varna viewer state is also written out (in native Varna XML) to separate
1950 * project jar entries. A separate entry is written for each RNA structure
1951 * displayed, with the naming convention
1953 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
1961 * @param storeDataset
1963 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
1964 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
1965 boolean storeDataset)
1967 if (Desktop.getDesktopPane() == null)
1971 JInternalFrame[] frames = Desktop.getDesktopPane().getAllFrames();
1972 for (int f = frames.length - 1; f > -1; f--)
1974 if (frames[f] instanceof AppVarna)
1976 AppVarna varna = (AppVarna) frames[f];
1978 * link the sequence to every viewer that is showing it and is linked to
1979 * its alignment panel
1981 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1983 String viewId = varna.getViewId();
1984 RnaViewer rna = new RnaViewer();
1985 rna.setViewId(viewId);
1986 rna.setTitle(varna.getTitle());
1987 rna.setXpos(varna.getX());
1988 rna.setYpos(varna.getY());
1989 rna.setWidth(varna.getWidth());
1990 rna.setHeight(varna.getHeight());
1991 rna.setDividerLocation(varna.getDividerLocation());
1992 rna.setSelectedRna(varna.getSelectedIndex());
1993 // jseq.addRnaViewer(rna);
1994 jseq.getRnaViewer().add(rna);
1997 * Store each Varna panel's state once in the project per sequence.
1998 * First time through only (storeDataset==false)
2000 // boolean storeSessions = false;
2001 // String sequenceViewId = viewId + seqsToIds.get(jds);
2002 // if (!storeDataset && !viewIds.contains(sequenceViewId))
2004 // viewIds.add(sequenceViewId);
2005 // storeSessions = true;
2007 for (RnaModel model : varna.getModels())
2009 if (model.seq == jds)
2012 * VARNA saves each view (sequence or alignment secondary
2013 * structure, gapped or trimmed) as a separate XML file
2015 String jarEntryName = rnaSessions.get(model);
2016 if (jarEntryName == null)
2019 String varnaStateFile = varna.getStateInfo(model.rna);
2020 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
2021 copyFileToJar(jout, varnaStateFile, jarEntryName);
2022 rnaSessions.put(model, jarEntryName);
2024 SecondaryStructure ss = new SecondaryStructure();
2025 String annotationId = varna.getAnnotation(jds).annotationId;
2026 ss.setAnnotationId(annotationId);
2027 ss.setViewerState(jarEntryName);
2028 ss.setGapped(model.gapped);
2029 ss.setTitle(model.title);
2030 // rna.addSecondaryStructure(ss);
2031 rna.getSecondaryStructure().add(ss);
2040 * Copy the contents of a file to a new entry added to the output jar
2044 * @param jarEntryName
2046 protected void copyFileToJar(JarOutputStream jout, String infilePath,
2047 String jarEntryName)
2049 DataInputStream dis = null;
2052 File file = new File(infilePath);
2053 if (file.exists() && jout != null)
2055 dis = new DataInputStream(new FileInputStream(file));
2056 byte[] data = new byte[(int) file.length()];
2057 dis.readFully(data);
2058 writeJarEntry(jout, jarEntryName, data);
2060 } catch (Exception ex)
2062 ex.printStackTrace();
2070 } catch (IOException e)
2079 * Write the data to a new entry of given name in the output jar file
2082 * @param jarEntryName
2084 * @throws IOException
2086 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
2087 byte[] data) throws IOException
2091 jarEntryName = jarEntryName.replace('\\','/');
2092 System.out.println("Writing jar entry " + jarEntryName);
2093 jout.putNextEntry(new JarEntry(jarEntryName));
2094 DataOutputStream dout = new DataOutputStream(jout);
2095 dout.write(data, 0, data.length);
2102 * Save the state of a structure viewer
2107 * the archive XML element under which to save the state
2110 * @param matchedFile
2114 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
2115 Pdbids pdb, PDBEntry entry, List<String> viewIds,
2116 String matchedFile, StructureViewerBase viewFrame)
2118 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
2121 * Look for any bindings for this viewer to the PDB file of interest
2122 * (including part matches excluding chain id)
2124 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
2126 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
2127 final String pdbId = pdbentry.getId();
2128 if (!pdbId.equals(entry.getId())
2129 && !(entry.getId().length() > 4 && entry.getId().toLowerCase()
2130 .startsWith(pdbId.toLowerCase())))
2133 * not interested in a binding to a different PDB entry here
2137 if (matchedFile == null)
2139 matchedFile = pdbentry.getFile();
2141 else if (!matchedFile.equals(pdbentry.getFile()))
2144 "Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
2145 + pdbentry.getFile());
2149 // can get at it if the ID
2150 // match is ambiguous (e.g.
2153 for (int smap = 0; smap < viewFrame.getBinding()
2154 .getSequence()[peid].length; smap++)
2156 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
2157 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
2159 StructureState state = new StructureState();
2160 state.setVisible(true);
2161 state.setXpos(viewFrame.getX());
2162 state.setYpos(viewFrame.getY());
2163 state.setWidth(viewFrame.getWidth());
2164 state.setHeight(viewFrame.getHeight());
2165 final String viewId = viewFrame.getViewId();
2166 state.setViewId(viewId);
2167 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
2168 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
2169 state.setColourByJmol(viewFrame.isColouredByViewer());
2170 state.setType(viewFrame.getViewerType().toString());
2171 // pdb.addStructureState(state);
2172 pdb.getStructureState().add(state);
2180 * Populates the AnnotationColourScheme xml for save. This captures the
2181 * settings of the options in the 'Colour by Annotation' dialog.
2184 * @param userColours
2188 private AnnotationColourScheme constructAnnotationColours(
2189 AnnotationColourGradient acg, List<UserColourScheme> userColours,
2192 AnnotationColourScheme ac = new AnnotationColourScheme();
2193 ac.setAboveThreshold(acg.getAboveThreshold());
2194 ac.setThreshold(acg.getAnnotationThreshold());
2195 // 2.10.2 save annotationId (unique) not annotation label
2196 ac.setAnnotation(acg.getAnnotation().annotationId);
2197 if (acg.getBaseColour() instanceof UserColourScheme)
2200 setUserColourScheme(acg.getBaseColour(), userColours, jm));
2205 ColourSchemeProperty.getColourName(acg.getBaseColour()));
2208 ac.setMaxColour(acg.getMaxColour().getRGB());
2209 ac.setMinColour(acg.getMinColour().getRGB());
2210 ac.setPerSequence(acg.isSeqAssociated());
2211 ac.setPredefinedColours(acg.isPredefinedColours());
2215 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
2216 IdentityHashMap<SequenceGroup, String> groupRefs,
2217 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
2218 SequenceSet vamsasSet)
2221 for (int i = 0; i < aa.length; i++)
2223 Annotation an = new Annotation();
2225 AlignmentAnnotation annotation = aa[i];
2226 if (annotation.annotationId != null)
2228 annotationIds.put(annotation.annotationId, annotation);
2231 an.setId(annotation.annotationId);
2233 an.setVisible(annotation.visible);
2235 an.setDescription(annotation.description);
2237 if (annotation.sequenceRef != null)
2239 // 2.9 JAL-1781 xref on sequence id rather than name
2240 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
2242 if (annotation.groupRef != null)
2244 String groupIdr = groupRefs.get(annotation.groupRef);
2245 if (groupIdr == null)
2247 // make a locally unique String
2248 groupRefs.put(annotation.groupRef,
2249 groupIdr = ("" + System.currentTimeMillis()
2250 + annotation.groupRef.getName()
2251 + groupRefs.size()));
2253 an.setGroupRef(groupIdr.toString());
2256 // store all visualization attributes for annotation
2257 an.setGraphHeight(annotation.graphHeight);
2258 an.setCentreColLabels(annotation.centreColLabels);
2259 an.setScaleColLabels(annotation.scaleColLabel);
2260 an.setShowAllColLabels(annotation.showAllColLabels);
2261 an.setBelowAlignment(annotation.belowAlignment);
2263 if (annotation.graph > 0)
2266 an.setGraphType(annotation.graph);
2267 an.setGraphGroup(annotation.graphGroup);
2268 if (annotation.getThreshold() != null)
2270 ThresholdLine line = new ThresholdLine();
2271 line.setLabel(annotation.getThreshold().label);
2272 line.setValue(annotation.getThreshold().value);
2273 line.setColour(annotation.getThreshold().colour.getRGB());
2274 an.setThresholdLine(line);
2282 an.setLabel(annotation.label);
2284 if (annotation == av.getAlignmentQualityAnnot()
2285 || annotation == av.getAlignmentConservationAnnotation()
2286 || annotation == av.getAlignmentConsensusAnnotation()
2287 || annotation.autoCalculated)
2289 // new way of indicating autocalculated annotation -
2290 an.setAutoCalculated(annotation.autoCalculated);
2292 if (annotation.hasScore())
2294 an.setScore(annotation.getScore());
2297 if (annotation.getCalcId() != null)
2299 calcIdSet.add(annotation.getCalcId());
2300 an.setCalcId(annotation.getCalcId());
2302 if (annotation.hasProperties())
2304 for (String pr : annotation.getProperties())
2306 jalview.xml.binding.jalview.Annotation.Property prop = new jalview.xml.binding.jalview.Annotation.Property();
2308 prop.setValue(annotation.getProperty(pr));
2309 // an.addProperty(prop);
2310 an.getProperty().add(prop);
2314 AnnotationElement ae;
2315 if (annotation.annotations != null)
2317 an.setScoreOnly(false);
2318 for (int a = 0; a < annotation.annotations.length; a++)
2320 if ((annotation == null) || (annotation.annotations[a] == null))
2325 ae = new AnnotationElement();
2326 if (annotation.annotations[a].description != null)
2328 ae.setDescription(annotation.annotations[a].description);
2330 if (annotation.annotations[a].displayCharacter != null)
2332 ae.setDisplayCharacter(
2333 annotation.annotations[a].displayCharacter);
2336 if (!Float.isNaN(annotation.annotations[a].value))
2338 ae.setValue(annotation.annotations[a].value);
2342 if (annotation.annotations[a].secondaryStructure > ' ')
2344 ae.setSecondaryStructure(
2345 annotation.annotations[a].secondaryStructure + "");
2348 if (annotation.annotations[a].colour != null
2349 && annotation.annotations[a].colour != java.awt.Color.black)
2351 ae.setColour(annotation.annotations[a].colour.getRGB());
2354 // an.addAnnotationElement(ae);
2355 an.getAnnotationElement().add(ae);
2356 if (annotation.autoCalculated)
2358 // only write one non-null entry into the annotation row -
2359 // sufficient to get the visualization attributes necessary to
2367 an.setScoreOnly(true);
2369 if (!storeDS || (storeDS && !annotation.autoCalculated))
2371 // skip autocalculated annotation - these are only provided for
2373 // vamsasSet.addAnnotation(an);
2374 vamsasSet.getAnnotation().add(an);
2380 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
2382 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
2383 if (settings != null)
2385 CalcIdParam vCalcIdParam = new CalcIdParam();
2386 vCalcIdParam.setCalcId(calcId);
2387 // vCalcIdParam.addServiceURL(settings.getServiceURI());
2388 vCalcIdParam.getServiceURL().add(settings.getServiceURI());
2389 // generic URI allowing a third party to resolve another instance of the
2390 // service used for this calculation
2391 for (String url : settings.getServiceURLs())
2393 // vCalcIdParam.addServiceURL(urls);
2394 vCalcIdParam.getServiceURL().add(url);
2396 vCalcIdParam.setVersion("1.0");
2397 if (settings.getPreset() != null)
2399 WsParamSetI setting = settings.getPreset();
2400 vCalcIdParam.setName(setting.getName());
2401 vCalcIdParam.setDescription(setting.getDescription());
2405 vCalcIdParam.setName("");
2406 vCalcIdParam.setDescription("Last used parameters");
2408 // need to be able to recover 1) settings 2) user-defined presets or
2409 // recreate settings from preset 3) predefined settings provided by
2410 // service - or settings that can be transferred (or discarded)
2411 vCalcIdParam.setParameters(
2412 settings.getWsParamFile().replace("\n", "|\\n|"));
2413 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
2414 // todo - decide if updateImmediately is needed for any projects.
2416 return vCalcIdParam;
2421 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
2424 if (calcIdParam.getVersion().equals("1.0"))
2426 final String[] calcIds = calcIdParam.getServiceURL().toArray(new String[0]);
2427 Jws2Instance service = Jws2Discoverer.getInstance()
2428 .getPreferredServiceFor(calcIds);
2429 if (service != null)
2431 WsParamSetI parmSet = null;
2434 parmSet = service.getParamStore().parseServiceParameterFile(
2435 calcIdParam.getName(), calcIdParam.getDescription(),
2437 calcIdParam.getParameters().replace("|\\n|", "\n"));
2438 } catch (IOException x)
2440 warn("Couldn't parse parameter data for "
2441 + calcIdParam.getCalcId(), x);
2444 List<ArgumentI> argList = null;
2445 if (calcIdParam.getName().length() > 0)
2447 parmSet = service.getParamStore()
2448 .getPreset(calcIdParam.getName());
2449 if (parmSet != null)
2451 // TODO : check we have a good match with settings in AACon -
2452 // otherwise we'll need to create a new preset
2457 argList = parmSet.getArguments();
2460 AAConSettings settings = new AAConSettings(
2461 calcIdParam.isAutoUpdate(), service, parmSet, argList);
2462 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
2463 calcIdParam.isNeedsUpdate());
2468 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
2472 throw new Error(MessageManager.formatMessage(
2473 "error.unsupported_version_calcIdparam", new Object[]
2474 { calcIdParam.toString() }));
2478 * External mapping between jalview objects and objects yielding a valid and
2479 * unique object ID string. This is null for normal Jalview project IO, but
2480 * non-null when a jalview project is being read or written as part of a
2483 IdentityHashMap jv2vobj = null;
2486 * Construct a unique ID for jvobj using either existing bindings or if none
2487 * exist, the result of the hashcode call for the object.
2490 * jalview data object
2491 * @return unique ID for referring to jvobj
2493 private String makeHashCode(Object jvobj, String altCode)
2495 if (jv2vobj != null)
2497 Object id = jv2vobj.get(jvobj);
2500 return id.toString();
2502 // check string ID mappings
2503 if (jvids2vobj != null && jvobj instanceof String)
2505 id = jvids2vobj.get(jvobj);
2509 return id.toString();
2511 // give up and warn that something has gone wrong
2512 warn("Cannot find ID for object in external mapping : " + jvobj);
2518 * return local jalview object mapped to ID, if it exists
2522 * @return null or object bound to idcode
2524 private Object retrieveExistingObj(String idcode)
2526 if (idcode != null && vobj2jv != null)
2528 return vobj2jv.get(idcode);
2534 * binding from ID strings from external mapping table to jalview data model
2537 private Hashtable vobj2jv;
2539 private Sequence createVamsasSequence(String id, SequenceI jds)
2541 return createVamsasSequence(true, id, jds, null);
2544 private Sequence createVamsasSequence(boolean recurse, String id,
2545 SequenceI jds, SequenceI parentseq)
2547 Sequence vamsasSeq = new Sequence();
2548 vamsasSeq.setId(id);
2549 vamsasSeq.setName(jds.getName());
2550 vamsasSeq.setSequence(jds.getSequenceAsString());
2551 vamsasSeq.setDescription(jds.getDescription());
2552 List<DBRefEntry> dbrefs = null;
2553 if (jds.getDatasetSequence() != null)
2555 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
2559 // seqId==dsseqid so we can tell which sequences really are
2560 // dataset sequences only
2561 vamsasSeq.setDsseqid(id);
2562 dbrefs = jds.getDBRefs();
2563 if (parentseq == null)
2570 * save any dbrefs; special subclass GeneLocus is flagged as 'locus'
2574 for (int d = 0, nd = dbrefs.size(); d < nd; d++)
2576 DBRef dbref = new DBRef();
2577 DBRefEntry ref = dbrefs.get(d);
2578 dbref.setSource(ref.getSource());
2579 dbref.setVersion(ref.getVersion());
2580 dbref.setAccessionId(ref.getAccessionId());
2581 if (ref instanceof GeneLocus)
2583 dbref.setLocus(true);
2587 Mapping mp = createVamsasMapping(ref.getMap(), parentseq,
2589 dbref.setMapping(mp);
2591 vamsasSeq.getDBRef().add(dbref);
2597 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
2598 SequenceI parentseq, SequenceI jds, boolean recurse)
2601 if (jmp.getMap() != null)
2605 jalview.util.MapList mlst = jmp.getMap();
2606 List<int[]> r = mlst.getFromRanges();
2607 for (int[] range : r)
2609 MapListFrom mfrom = new MapListFrom();
2610 mfrom.setStart(range[0]);
2611 mfrom.setEnd(range[1]);
2612 // mp.addMapListFrom(mfrom);
2613 mp.getMapListFrom().add(mfrom);
2615 r = mlst.getToRanges();
2616 for (int[] range : r)
2618 MapListTo mto = new MapListTo();
2619 mto.setStart(range[0]);
2620 mto.setEnd(range[1]);
2621 // mp.addMapListTo(mto);
2622 mp.getMapListTo().add(mto);
2624 mp.setMapFromUnit(BigInteger.valueOf(mlst.getFromRatio()));
2625 mp.setMapToUnit(BigInteger.valueOf(mlst.getToRatio()));
2626 if (jmp.getTo() != null)
2628 // MappingChoice mpc = new MappingChoice();
2630 // check/create ID for the sequence referenced by getTo()
2633 SequenceI ps = null;
2634 if (parentseq != jmp.getTo()
2635 && parentseq.getDatasetSequence() != jmp.getTo())
2637 // chaining dbref rather than a handshaking one
2638 jmpid = seqHash(ps = jmp.getTo());
2642 jmpid = seqHash(ps = parentseq);
2644 // mpc.setDseqFor(jmpid);
2645 mp.setDseqFor(jmpid);
2646 if (!seqRefIds.containsKey(jmpid))
2648 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2649 seqRefIds.put(jmpid, ps);
2653 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2656 // mp.setMappingChoice(mpc);
2662 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2663 List<UserColourScheme> userColours, JalviewModel jm)
2666 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2667 boolean newucs = false;
2668 if (!userColours.contains(ucs))
2670 userColours.add(ucs);
2673 id = "ucs" + userColours.indexOf(ucs);
2676 // actually create the scheme's entry in the XML model
2677 java.awt.Color[] colours = ucs.getColours();
2678 UserColours uc = new UserColours();
2679 // UserColourScheme jbucs = new UserColourScheme();
2680 JalviewUserColours jbucs = new JalviewUserColours();
2682 for (int i = 0; i < colours.length; i++)
2684 Colour col = new Colour();
2685 col.setName(ResidueProperties.aa[i]);
2686 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2687 // jbucs.addColour(col);
2688 jbucs.getColour().add(col);
2690 if (ucs.getLowerCaseColours() != null)
2692 colours = ucs.getLowerCaseColours();
2693 for (int i = 0; i < colours.length; i++)
2695 Colour col = new Colour();
2696 col.setName(ResidueProperties.aa[i].toLowerCase());
2697 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2698 // jbucs.addColour(col);
2699 jbucs.getColour().add(col);
2704 uc.setUserColourScheme(jbucs);
2705 // jm.addUserColours(uc);
2706 jm.getUserColours().add(uc);
2712 jalview.schemes.UserColourScheme getUserColourScheme(
2713 JalviewModel jm, String id)
2715 List<UserColours> uc = jm.getUserColours();
2716 UserColours colours = null;
2718 for (int i = 0; i < uc.length; i++)
2720 if (uc[i].getId().equals(id))
2727 for (UserColours c : uc)
2729 if (c.getId().equals(id))
2736 java.awt.Color[] newColours = new java.awt.Color[24];
2738 for (int i = 0; i < 24; i++)
2740 newColours[i] = new java.awt.Color(Integer.parseInt(
2741 // colours.getUserColourScheme().getColour(i).getRGB(), 16));
2742 colours.getUserColourScheme().getColour().get(i).getRGB(),
2746 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2749 if (colours.getUserColourScheme().getColour().size()/*Count()*/ > 24)
2751 newColours = new java.awt.Color[23];
2752 for (int i = 0; i < 23; i++)
2754 newColours[i] = new java.awt.Color(Integer.parseInt(
2755 colours.getUserColourScheme().getColour().get(i + 24)
2759 ucs.setLowerCaseColours(newColours);
2766 * Load a jalview project archive from a jar file
2769 * - HTTP URL or filename
2771 public AlignFrame loadJalviewAlign(final Object file)
2774 jalview.gui.AlignFrame af = null;
2778 // create list to store references for any new Jmol viewers created
2779 newStructureViewers = new Vector<>();
2780 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2781 // Workaround is to make sure caller implements the JarInputStreamProvider
2783 // so we can re-open the jar input stream for each entry.
2785 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2786 af = loadJalviewAlign(jprovider);
2789 af.setMenusForViewport();
2791 } catch (MalformedURLException e)
2793 errorMessage = "Invalid URL format for '" + file + "'";
2799 // was invokeAndWait
2801 // BH 2019 -- can't wait
2802 SwingUtilities.invokeLater(new Runnable()
2807 setLoadingFinishedForNewStructureViewers();
2810 } catch (Exception x)
2812 System.err.println("Error loading alignment: " + x.getMessage());
2815 this.jarFile = null;
2819 @SuppressWarnings("unused")
2820 private jarInputStreamProvider createjarInputStreamProvider(
2821 final Object ofile) throws MalformedURLException
2825 String file = (ofile instanceof File
2826 ? ((File) ofile).getCanonicalPath()
2827 : ofile.toString());
2828 byte[] bytes = Platform.isJS() ? Platform.getFileBytes((File) ofile)
2832 this.jarFile = (File) ofile;
2834 errorMessage = null;
2835 uniqueSetSuffix = null;
2837 viewportsAdded.clear();
2838 frefedSequence = null;
2840 URL url = file.startsWith("http://") ? new URL(file) : null;
2841 return new jarInputStreamProvider()
2844 public JarInputStream getJarInputStream() throws IOException
2846 InputStream is = bytes != null ? new ByteArrayInputStream(bytes)
2847 : (url != null ? url.openStream()
2848 : new FileInputStream(file));
2849 return new JarInputStream(is);
2853 public String getFilename()
2858 } catch (IOException e)
2860 e.printStackTrace();
2866 * Recover jalview session from a jalview project archive. Caller may
2867 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2868 * themselves. Any null fields will be initialised with default values,
2869 * non-null fields are left alone.
2874 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2876 errorMessage = null;
2877 if (uniqueSetSuffix == null)
2879 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2881 if (seqRefIds == null)
2885 AlignFrame af = null, _af = null;
2886 IdentityHashMap<AlignmentI, AlignmentI> importedDatasets = new IdentityHashMap<>();
2887 Map<String, AlignFrame> gatherToThisFrame = new HashMap<>();
2888 final String file = jprovider.getFilename();
2890 List<AlignFrame> alignFrames = new ArrayList<>();
2894 JarInputStream jin = null;
2895 JarEntry jarentry = null;
2899 // Look for all the entry names ending with ".xml"
2900 // This includes all panels and at least one frame.
2901 // Platform.timeCheck(null, Platform.TIME_MARK);
2904 jin = jprovider.getJarInputStream();
2905 for (int i = 0; i < entryCount; i++)
2907 jarentry = jin.getNextJarEntry();
2909 String name = (jarentry == null ? null : jarentry.getName());
2911 // System.out.println("Jalview2XML opening " + name);
2912 if (name != null && name.endsWith(".xml"))
2915 // DataSet for.... is read last.
2918 // The question here is what to do with the two
2919 // .xml files in the jvp file.
2920 // Some number of them, "...Dataset for...", will be the
2921 // Only AlignPanels and will have Viewport.
2922 // One or more will be the source data, with the DBRefs.
2924 // JVP file writing (above) ensures tha the AlignPanels are written
2925 // first, then all relevant datasets (which are
2926 // Jalview.datamodel.Alignment).
2929 // Platform.timeCheck("Jalview2XML JAXB " + name, Platform.TIME_MARK);
2930 JAXBContext jc = JAXBContext
2931 .newInstance("jalview.xml.binding.jalview");
2932 XMLStreamReader streamReader = XMLInputFactory.newInstance()
2933 .createXMLStreamReader(jin);
2934 javax.xml.bind.Unmarshaller um = jc.createUnmarshaller();
2935 JAXBElement<JalviewModel> jbe = um
2936 .unmarshal(streamReader, JalviewModel.class);
2937 JalviewModel model = jbe.getValue();
2939 if (true) // !skipViewport(object))
2941 // Q: Do we have to load from the model, even if it
2942 // does not have a viewport, could we discover that early on?
2943 // Q: Do we need to load this object?
2944 _af = loadFromObject(model, file, true, jprovider);
2945 // Platform.timeCheck("Jalview2XML.loadFromObject",
2946 // Platform.TIME_MARK);
2950 alignFrames.add(_af);
2952 if (_af != null && model.getViewport().size() > 0)
2955 // That is, this is one of the AlignmentPanel models
2958 // store a reference to the first view
2961 if (_af.getViewport().isGatherViewsHere())
2963 // if this is a gathered view, keep its reference since
2964 // after gathering views, only this frame will remain
2966 gatherToThisFrame.put(_af.getViewport().getSequenceSetId(),
2969 // Save dataset to register mappings once all resolved
2970 importedDatasets.put(
2971 af.getViewport().getAlignment().getDataset(),
2972 af.getViewport().getAlignment().getDataset());
2977 else if (jarentry != null)
2979 // Some other file here.
2982 } while (jarentry != null);
2983 resolveFrefedSequences();
2984 } catch (IOException ex)
2986 ex.printStackTrace();
2987 errorMessage = "Couldn't locate Jalview XML file : " + file;
2989 "Exception whilst loading jalview XML file : " + ex + "\n");
2990 } catch (Exception ex)
2992 System.err.println("Parsing as Jalview Version 2 file failed.");
2993 ex.printStackTrace(System.err);
2994 if (attemptversion1parse)
2996 // used to attempt to parse as V1 castor-generated xml
2998 if (Desktop.getInstance() != null)
3000 Desktop.getInstance().stopLoading();
3004 System.out.println("Successfully loaded archive file");
3007 ex.printStackTrace();
3010 "Exception whilst loading jalview XML file : " + ex + "\n");
3011 } catch (OutOfMemoryError e)
3013 // Don't use the OOM Window here
3014 errorMessage = "Out of memory loading jalview XML file";
3015 System.err.println("Out of memory whilst loading jalview XML file");
3016 e.printStackTrace();
3019 for (AlignFrame alf : alignFrames)
3021 alf.alignPanel.setHoldRepaint(false);
3027 * Regather multiple views (with the same sequence set id) to the frame (if
3028 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
3029 * views instead of separate frames. Note this doesn't restore a state where
3030 * some expanded views in turn have tabbed views - the last "first tab" read
3031 * in will play the role of gatherer for all.
3033 for (AlignFrame fr : gatherToThisFrame.values())
3035 Desktop.getInstance().gatherViews(fr);
3038 restoreSplitFrames();
3039 for (AlignmentI ds : importedDatasets.keySet())
3041 if (ds.getCodonFrames() != null)
3043 Desktop.getStructureSelectionManager()
3044 .registerMappings(ds.getCodonFrames());
3047 if (errorMessage != null)
3052 if (Desktop.getInstance() != null)
3054 Desktop.getInstance().stopLoading();
3061 * Try to reconstruct and display SplitFrame windows, where each contains
3062 * complementary dna and protein alignments. Done by pairing up AlignFrame
3063 * objects (created earlier) which have complementary viewport ids associated.
3065 protected void restoreSplitFrames()
3067 List<SplitFrame> gatherTo = new ArrayList<>();
3068 List<AlignFrame> addedToSplitFrames = new ArrayList<>();
3069 Map<String, AlignFrame> dna = new HashMap<>();
3072 * Identify the DNA alignments
3074 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
3077 AlignFrame af = candidate.getValue();
3078 if (af.getViewport().getAlignment().isNucleotide())
3080 dna.put(candidate.getKey().getId(), af);
3085 * Try to match up the protein complements
3087 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
3090 AlignFrame af = candidate.getValue();
3091 if (!af.getViewport().getAlignment().isNucleotide())
3093 String complementId = candidate.getKey().getComplementId();
3094 // only non-null complements should be in the Map
3095 if (complementId != null && dna.containsKey(complementId))
3097 final AlignFrame dnaFrame = dna.get(complementId);
3098 SplitFrame sf = createSplitFrame(dnaFrame, af);
3099 addedToSplitFrames.add(dnaFrame);
3100 addedToSplitFrames.add(af);
3101 dnaFrame.setMenusForViewport();
3102 af.setMenusForViewport();
3103 if (af.getViewport().isGatherViewsHere())
3112 * Open any that we failed to pair up (which shouldn't happen!) as
3113 * standalone AlignFrame's.
3115 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
3118 AlignFrame af = candidate.getValue();
3119 if (!addedToSplitFrames.contains(af))
3121 Viewport view = candidate.getKey();
3122 Desktop.addInternalFrame(af, view.getTitle(),
3123 safeInt(view.getWidth()), safeInt(view.getHeight()));
3124 af.setMenusForViewport();
3125 System.err.println("Failed to restore view " + view.getTitle()
3126 + " to split frame");
3131 * Gather back into tabbed views as flagged.
3133 for (SplitFrame sf : gatherTo)
3135 Desktop.getInstance().gatherViews(sf);
3138 splitFrameCandidates.clear();
3142 * Construct and display one SplitFrame holding DNA and protein alignments.
3145 * @param proteinFrame
3148 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
3149 AlignFrame proteinFrame)
3151 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
3152 String title = MessageManager.getString("label.linked_view_title");
3153 int width = (int) dnaFrame.getBounds().getWidth();
3154 int height = (int) (dnaFrame.getBounds().getHeight()
3155 + proteinFrame.getBounds().getHeight() + 50);
3158 * SplitFrame location is saved to both enclosed frames
3160 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
3161 Desktop.addInternalFrame(splitFrame, title, width, height);
3164 * And compute cDNA consensus (couldn't do earlier with consensus as
3165 * mappings were not yet present)
3167 proteinFrame.getViewport().alignmentChanged(proteinFrame.alignPanel);
3173 * check errorMessage for a valid error message and raise an error box in the
3174 * GUI or write the current errorMessage to stderr and then clear the error
3177 protected void reportErrors()
3179 reportErrors(false);
3182 protected void reportErrors(final boolean saving)
3184 if (errorMessage != null)
3186 final String finalErrorMessage = errorMessage;
3189 javax.swing.SwingUtilities.invokeLater(new Runnable()
3194 JvOptionPane.showInternalMessageDialog(Desktop.getDesktopPane(),
3196 "Error " + (saving ? "saving" : "loading")
3198 JvOptionPane.WARNING_MESSAGE);
3204 System.err.println("Problem loading Jalview file: " + errorMessage);
3207 errorMessage = null;
3210 Map<String, String> alreadyLoadedPDB = new HashMap<>();
3213 * when set, local views will be updated from view stored in JalviewXML
3214 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
3215 * sync if this is set to true.
3217 private final boolean updateLocalViews = false;
3220 * Returns the path to a temporary file holding the PDB file for the given PDB
3221 * id. The first time of asking, searches for a file of that name in the
3222 * Jalview project jar, and copies it to a new temporary file. Any repeat
3223 * requests just return the path to the file previously created.
3229 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId,
3232 if (alreadyLoadedPDB.containsKey(pdbId))
3234 return alreadyLoadedPDB.get(pdbId).toString();
3237 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb",
3239 if (tempFile != null)
3241 alreadyLoadedPDB.put(pdbId, tempFile);
3247 * Copies the jar entry of given name to a new temporary file and returns the
3248 * path to the file, or null if the entry is not found.
3251 * @param jarEntryName
3253 * a prefix for the temporary file name, must be at least three
3256 * null or original file - so new file can be given the same suffix
3260 protected String copyJarEntry(jarInputStreamProvider jprovider,
3261 String jarEntryName, String prefix, String origFile)
3263 BufferedReader in = null;
3264 PrintWriter out = null;
3265 String suffix = ".tmp";
3266 if (origFile == null)
3268 origFile = jarEntryName;
3270 int sfpos = origFile.lastIndexOf(".");
3271 if (sfpos > -1 && sfpos < (origFile.length() - 3))
3273 suffix = "." + origFile.substring(sfpos + 1);
3277 JarInputStream jin = jprovider.getJarInputStream();
3279 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
3280 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
3281 * FileInputStream(jprovider)); }
3284 JarEntry entry = null;
3287 entry = jin.getNextJarEntry();
3288 } while (entry != null && !entry.getName().equals(jarEntryName));
3291 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
3292 File outFile = File.createTempFile(prefix, suffix);
3293 outFile.deleteOnExit();
3294 out = new PrintWriter(new FileOutputStream(outFile));
3297 while ((data = in.readLine()) != null)
3302 String t = outFile.getAbsolutePath();
3307 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
3309 } catch (Exception ex)
3311 ex.printStackTrace();
3319 } catch (IOException e)
3333 private class JvAnnotRow
3335 public JvAnnotRow(int i, AlignmentAnnotation jaa)
3342 * persisted version of annotation row from which to take vis properties
3344 public jalview.datamodel.AlignmentAnnotation template;
3347 * original position of the annotation row in the alignment
3353 * Load alignment frame from jalview XML DOM object. For a DOM object that
3354 * includes one or more Viewport elements (one with a title that does NOT
3355 * contain "Dataset for"), create the frame.
3357 * @param jalviewModel
3360 * filename source string
3361 * @param loadTreesAndStructures
3362 * when false only create Viewport
3364 * data source provider
3365 * @return alignment frame created from view stored in DOM
3367 AlignFrame loadFromObject(JalviewModel jalviewModel, String file,
3368 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
3370 SequenceSet vamsasSet = jalviewModel.getVamsasModel().getSequenceSet().get(0);
3371 List<Sequence> vamsasSeqs = vamsasSet.getSequence();
3374 // JalviewModelSequence jms = object.getJalviewModelSequence();
3376 // Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
3378 Viewport view = (jalviewModel.getViewport().size() > 0)
3379 ? jalviewModel.getViewport().get(0)
3382 // ////////////////////////////////
3383 // INITIALISE ALIGNMENT SEQUENCESETID AND VIEWID
3386 // If we just load in the same jar file again, the sequenceSetId
3387 // will be the same, and we end up with multiple references
3388 // to the same sequenceSet. We must modify this id on load
3389 // so that each load of the file gives a unique id
3392 * used to resolve correct alignment dataset for alignments with multiple
3395 String uniqueSeqSetId = null;
3396 String viewId = null;
3399 uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3400 viewId = (view.getId() == null ? null
3401 : view.getId() + uniqueSetSuffix);
3404 // ////////////////////////////////
3407 List<SequenceI> hiddenSeqs = null;
3409 List<SequenceI> tmpseqs = new ArrayList<>();
3411 boolean multipleView = false;
3412 SequenceI referenceseqForView = null;
3413 // JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
3414 List<JSeq> jseqs = jalviewModel.getJSeq();
3415 int vi = 0; // counter in vamsasSeq array
3416 for (int i = 0; i < jseqs.size(); i++)
3418 JSeq jseq = jseqs.get(i);
3419 String seqId = jseq.getId();
3421 SequenceI tmpSeq = seqRefIds.get(seqId);
3424 if (!incompleteSeqs.containsKey(seqId))
3426 // may not need this check, but keep it for at least 2.9,1 release
3427 if (tmpSeq.getStart() != jseq.getStart()
3428 || tmpSeq.getEnd() != jseq.getEnd())
3431 String.format("Warning JAL-2154 regression: updating start/end for sequence %s from %d/%d to %d/%d",
3432 tmpSeq.getName(), tmpSeq.getStart(),
3433 tmpSeq.getEnd(), jseq.getStart(),
3439 incompleteSeqs.remove(seqId);
3441 if (vamsasSeqs.size() > vi
3442 && vamsasSeqs.get(vi).getId().equals(seqId))
3444 // most likely we are reading a dataset XML document so
3445 // update from vamsasSeq section of XML for this sequence
3446 tmpSeq.setName(vamsasSeqs.get(vi).getName());
3447 tmpSeq.setDescription(vamsasSeqs.get(vi).getDescription());
3448 tmpSeq.setSequence(vamsasSeqs.get(vi).getSequence());
3453 // reading multiple views, so vamsasSeq set is a subset of JSeq
3454 multipleView = true;
3456 tmpSeq.setStart(jseq.getStart());
3457 tmpSeq.setEnd(jseq.getEnd());
3458 tmpseqs.add(tmpSeq);
3462 Sequence vamsasSeq = vamsasSeqs.get(vi);
3463 tmpSeq = new jalview.datamodel.Sequence(vamsasSeq.getName(),
3464 vamsasSeq.getSequence());
3465 tmpSeq.setDescription(vamsasSeq.getDescription());
3466 tmpSeq.setStart(jseq.getStart());
3467 tmpSeq.setEnd(jseq.getEnd());
3468 tmpSeq.setVamsasId(uniqueSetSuffix + seqId);
3469 seqRefIds.put(vamsasSeq.getId(), tmpSeq);
3470 tmpseqs.add(tmpSeq);
3474 if (safeBoolean(jseq.isViewreference()))
3476 referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
3479 if (jseq.isHidden() != null && jseq.isHidden().booleanValue())
3481 if (hiddenSeqs == null)
3483 hiddenSeqs = new ArrayList<>();
3486 hiddenSeqs.add(tmpSeq);
3491 // Create the alignment object from the sequence set
3492 // ///////////////////////////////
3493 SequenceI[] orderedSeqs = tmpseqs
3494 .toArray(new SequenceI[tmpseqs.size()]);
3496 AlignmentI al = null;
3497 // so we must create or recover the dataset alignment before going further
3498 // ///////////////////////////////
3499 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
3501 // older jalview projects do not have a dataset - so creat alignment and
3503 al = new Alignment(orderedSeqs);
3504 al.setDataset(null);
3508 boolean isdsal = jalviewModel.getViewport().isEmpty();
3511 // we are importing a dataset record, so
3512 // recover reference to an alignment already materialsed as dataset
3513 al = getDatasetFor(vamsasSet.getDatasetId());
3517 // materialse the alignment
3518 al = new Alignment(orderedSeqs);
3522 addDatasetRef(vamsasSet.getDatasetId(), al);
3525 // finally, verify all data in vamsasSet is actually present in al
3526 // passing on flag indicating if it is actually a stored dataset
3527 recoverDatasetFor(vamsasSet, al, isdsal, uniqueSeqSetId);
3530 if (referenceseqForView != null)
3532 al.setSeqrep(referenceseqForView);
3534 // / Add the alignment properties
3535 for (int i = 0; i < vamsasSet.getSequenceSetProperties().size(); i++)
3537 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties()
3539 al.setProperty(ssp.getKey(), ssp.getValue());
3542 // ///////////////////////////////
3544 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
3547 // load sequence features, database references and any associated PDB
3548 // structures for the alignment
3550 // prior to 2.10, this part would only be executed the first time a
3551 // sequence was encountered, but not afterwards.
3552 // now, for 2.10 projects, this is also done if the xml doc includes
3553 // dataset sequences not actually present in any particular view.
3555 for (int i = 0; i < vamsasSeqs.size(); i++)
3557 JSeq jseq = jseqs.get(i);
3558 if (jseq.getFeatures().size() > 0)
3560 List<Feature> features = jseq.getFeatures();
3561 for (int f = 0; f < features.size(); f++)
3563 Feature feat = features.get(f);
3564 SequenceFeature sf = new SequenceFeature(feat.getType(),
3565 feat.getDescription(), feat.getBegin(), feat.getEnd(),
3566 safeFloat(feat.getScore()), feat.getFeatureGroup());
3567 sf.setStatus(feat.getStatus());
3570 * load any feature attributes - include map-valued attributes
3572 Map<String, Map<String, String>> mapAttributes = new HashMap<>();
3573 for (int od = 0; od < feat.getOtherData().size(); od++)
3575 OtherData keyValue = feat.getOtherData().get(od);
3576 String attributeName = keyValue.getKey();
3577 String attributeValue = keyValue.getValue();
3578 if (attributeName.startsWith("LINK"))
3580 sf.addLink(attributeValue);
3584 String subAttribute = keyValue.getKey2();
3585 if (subAttribute == null)
3587 // simple string-valued attribute
3588 sf.setValue(attributeName, attributeValue);
3592 // attribute 'key' has sub-attribute 'key2'
3593 if (!mapAttributes.containsKey(attributeName))
3595 mapAttributes.put(attributeName, new HashMap<>());
3597 mapAttributes.get(attributeName).put(subAttribute,
3602 for (Entry<String, Map<String, String>> mapAttribute : mapAttributes
3605 sf.setValue(mapAttribute.getKey(), mapAttribute.getValue());
3608 // adds feature to datasequence's feature set (since Jalview 2.10)
3609 al.getSequenceAt(i).addSequenceFeature(sf);
3612 if (vamsasSeqs.get(i).getDBRef().size() > 0)
3614 // adds dbrefs to datasequence's set (since Jalview 2.10)
3616 al.getSequenceAt(i).getDatasetSequence() == null
3617 ? al.getSequenceAt(i)
3618 : al.getSequenceAt(i).getDatasetSequence(),
3621 if (jseq.getPdbids().size() > 0)
3623 List<Pdbids> ids = jseq.getPdbids();
3624 for (int p = 0; p < ids.size(); p++)
3626 Pdbids pdbid = ids.get(p);
3627 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
3628 entry.setId(pdbid.getId());
3629 if (pdbid.getType() != null)
3631 if (PDBEntry.Type.getType(pdbid.getType()) != null)
3633 entry.setType(PDBEntry.Type.getType(pdbid.getType()));
3637 entry.setType(PDBEntry.Type.FILE);
3640 // jprovider is null when executing 'New View'
3641 if (pdbid.getFile() != null && jprovider != null)
3643 if (!pdbloaded.containsKey(pdbid.getFile()))
3645 entry.setFile(loadPDBFile(jprovider, pdbid.getId(),
3650 entry.setFile(pdbloaded.get(pdbid.getId()).toString());
3654 if (pdbid.getPdbentryItem() != null)
3656 for (PdbentryItem item : pdbid.getPdbentryItem())
3658 for (Property pr : item.getProperty())
3660 entry.setProperty(pr.getName(), pr.getValue());
3665 for (Property prop : pdbid.getProperty())
3667 entry.setProperty(prop.getName(), prop.getValue());
3669 Desktop.getStructureSelectionManager()
3670 .registerPDBEntry(entry);
3671 // adds PDBEntry to datasequence's set (since Jalview 2.10)
3672 if (al.getSequenceAt(i).getDatasetSequence() != null)
3674 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
3678 al.getSequenceAt(i).addPDBId(entry);
3684 } // end !multipleview
3686 // ///////////////////////////////
3687 // LOAD SEQUENCE MAPPINGS
3689 if (vamsasSet.getAlcodonFrame().size() > 0)
3691 // TODO Potentially this should only be done once for all views of an
3693 List<AlcodonFrame> alc = vamsasSet.getAlcodonFrame();
3694 for (int i = 0; i < alc.size(); i++)
3696 AlignedCodonFrame cf = new AlignedCodonFrame();
3697 if (alc.get(i).getAlcodMap().size() > 0)
3699 List<AlcodMap> maps = alc.get(i).getAlcodMap();
3700 for (int m = 0; m < maps.size(); m++)
3702 AlcodMap map = maps.get(m);
3703 SequenceI dnaseq = seqRefIds.get(map.getDnasq());
3705 jalview.datamodel.Mapping mapping = null;
3706 // attach to dna sequence reference.
3707 if (map.getMapping() != null)
3709 mapping = addMapping(map.getMapping());
3710 if (dnaseq != null && mapping.getTo() != null)
3712 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
3718 newAlcodMapRef(map.getDnasq(), cf, mapping));
3722 al.addCodonFrame(cf);
3727 // ////////////////////////////////
3729 List<JvAnnotRow> autoAlan = new ArrayList<>();
3732 * store any annotations which forward reference a group's ID
3734 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<>();
3736 if (vamsasSet.getAnnotation().size()/*Count()*/ > 0)
3738 List<Annotation> an = vamsasSet.getAnnotation();
3740 for (int i = 0; i < an.size(); i++)
3742 Annotation annotation = an.get(i);
3745 * test if annotation is automatically calculated for this view only
3747 boolean autoForView = false;
3748 if (annotation.getLabel().equals("Quality")
3749 || annotation.getLabel().equals("Conservation")
3750 || annotation.getLabel().equals("Consensus"))
3752 // Kludge for pre 2.5 projects which lacked the autocalculated flag
3754 // JAXB has no has() test; schema defaults value to false
3755 // if (!annotation.hasAutoCalculated())
3757 // annotation.setAutoCalculated(true);
3760 if (autoForView || annotation.isAutoCalculated())
3762 // remove ID - we don't recover annotation from other views for
3763 // view-specific annotation
3764 annotation.setId(null);
3767 // set visibility for other annotation in this view
3768 String annotationId = annotation.getId();
3769 if (annotationId != null && annotationIds.containsKey(annotationId))
3771 AlignmentAnnotation jda = annotationIds.get(annotationId);
3772 // in principle Visible should always be true for annotation displayed
3773 // in multiple views
3774 if (annotation.isVisible() != null)
3776 jda.visible = annotation.isVisible();
3779 al.addAnnotation(jda);
3783 // Construct new annotation from model.
3784 List<AnnotationElement> ae = annotation.getAnnotationElement();
3785 jalview.datamodel.Annotation[] anot = null;
3786 java.awt.Color firstColour = null;
3788 if (!annotation.isScoreOnly())
3790 anot = new jalview.datamodel.Annotation[al.getWidth()];
3791 for (int aa = 0; aa < ae.size() && aa < anot.length; aa++)
3793 AnnotationElement annElement = ae.get(aa);
3794 anpos = annElement.getPosition();
3796 if (anpos >= anot.length)
3801 float value = safeFloat(annElement.getValue());
3802 anot[anpos] = new jalview.datamodel.Annotation(
3803 annElement.getDisplayCharacter(),
3804 annElement.getDescription(),
3805 (annElement.getSecondaryStructure() == null
3806 || annElement.getSecondaryStructure()
3810 .getSecondaryStructure()
3813 anot[anpos].colour = new Color(safeInt(annElement.getColour()));
3814 if (firstColour == null)
3816 firstColour = anot[anpos].colour;
3820 // create the new AlignmentAnnotation
3821 jalview.datamodel.AlignmentAnnotation jaa = null;
3823 if (annotation.isGraph())
3825 float llim = 0, hlim = 0;
3826 // if (autoForView || an[i].isAutoCalculated()) {
3829 jaa = new jalview.datamodel.AlignmentAnnotation(
3830 annotation.getLabel(), annotation.getDescription(), anot,
3831 llim, hlim, safeInt(annotation.getGraphType()));
3833 jaa.graphGroup = safeInt(annotation.getGraphGroup());
3834 jaa._linecolour = firstColour;
3835 if (annotation.getThresholdLine() != null)
3837 jaa.setThreshold(new jalview.datamodel.GraphLine(
3838 safeFloat(annotation.getThresholdLine().getValue()),
3839 annotation.getThresholdLine().getLabel(),
3840 new java.awt.Color(safeInt(
3841 annotation.getThresholdLine().getColour()))));
3843 if (autoForView || annotation.isAutoCalculated())
3845 // Hardwire the symbol display line to ensure that labels for
3846 // histograms are displayed
3852 jaa = new jalview.datamodel.AlignmentAnnotation(
3853 annotation.getLabel(), annotation.getDescription(), anot);
3854 jaa._linecolour = firstColour;
3856 // register new annotation
3857 // Annotation graphs such as Conservation will not have id.
3858 if (annotation.getId() != null)
3860 annotationIds.put(annotation.getId(), jaa);
3861 jaa.annotationId = annotation.getId();
3863 // recover sequence association
3864 String sequenceRef = annotation.getSequenceRef();
3865 if (sequenceRef != null)
3867 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3868 SequenceI sequence = seqRefIds.get(sequenceRef);
3869 if (sequence == null)
3871 // in pre-2.9 projects sequence ref is to sequence name
3872 sequence = al.findName(sequenceRef);
3874 if (sequence != null)
3876 jaa.createSequenceMapping(sequence, 1, true);
3877 sequence.addAlignmentAnnotation(jaa);
3880 // and make a note of any group association
3881 if (annotation.getGroupRef() != null
3882 && annotation.getGroupRef().length() > 0)
3884 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3885 .get(annotation.getGroupRef());
3888 aal = new ArrayList<>();
3889 groupAnnotRefs.put(annotation.getGroupRef(), aal);
3894 if (annotation.getScore() != null)
3896 jaa.setScore(annotation.getScore().doubleValue());
3898 if (annotation.isVisible() != null)
3900 jaa.visible = annotation.isVisible().booleanValue();
3903 if (annotation.isCentreColLabels() != null)
3905 jaa.centreColLabels = annotation.isCentreColLabels()
3909 if (annotation.isScaleColLabels() != null)
3911 jaa.scaleColLabel = annotation.isScaleColLabels().booleanValue();
3913 if (annotation.isAutoCalculated())
3915 // newer files have an 'autoCalculated' flag and store calculation
3916 // state in viewport properties
3917 jaa.autoCalculated = true; // means annotation will be marked for
3918 // update at end of load.
3920 if (annotation.getGraphHeight() != null)
3922 jaa.graphHeight = annotation.getGraphHeight().intValue();
3924 jaa.belowAlignment = annotation.isBelowAlignment();
3925 jaa.setCalcId(annotation.getCalcId());
3926 if (annotation.getProperty().size() > 0)
3928 for (Annotation.Property prop : annotation
3931 jaa.setProperty(prop.getName(), prop.getValue());
3934 if (jaa.autoCalculated)
3936 autoAlan.add(new JvAnnotRow(i, jaa));
3939 // if (!autoForView)
3941 // add autocalculated group annotation and any user created annotation
3943 al.addAnnotation(jaa);
3947 // ///////////////////////
3949 // Create alignment markup and styles for this view
3950 if (jalviewModel.getJGroup().size() > 0)
3952 List<JGroup> groups = jalviewModel.getJGroup();
3953 boolean addAnnotSchemeGroup = false;
3954 for (int i = 0; i < groups.size(); i++)
3956 JGroup jGroup = groups.get(i);
3957 ColourSchemeI cs = null;
3958 if (jGroup.getColour() != null)
3960 if (jGroup.getColour().startsWith("ucs"))
3962 cs = getUserColourScheme(jalviewModel, jGroup.getColour());
3964 else if (jGroup.getColour().equals("AnnotationColourGradient")
3965 && jGroup.getAnnotationColours() != null)
3967 addAnnotSchemeGroup = true;
3971 cs = ColourSchemeProperty.getColourScheme(null, al,
3972 jGroup.getColour());
3975 int pidThreshold = safeInt(jGroup.getPidThreshold());
3977 Vector<SequenceI> seqs = new Vector<>();
3979 for (int s = 0; s < jGroup.getSeq().size(); s++)
3981 String seqId = jGroup.getSeq().get(s);
3982 SequenceI ts = seqRefIds.get(seqId);
3986 seqs.addElement(ts);
3990 if (seqs.size() < 1)
3995 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3996 safeBoolean(jGroup.isDisplayBoxes()),
3997 safeBoolean(jGroup.isDisplayText()),
3998 safeBoolean(jGroup.isColourText()),
3999 safeInt(jGroup.getStart()), safeInt(jGroup.getEnd()));
4000 sg.getGroupColourScheme().setThreshold(pidThreshold, true);
4001 sg.getGroupColourScheme()
4002 .setConservationInc(safeInt(jGroup.getConsThreshold()));
4003 sg.setOutlineColour(new Color(safeInt(jGroup.getOutlineColour())));
4005 sg.textColour = new Color(safeInt(jGroup.getTextCol1()));
4006 sg.textColour2 = new Color(safeInt(jGroup.getTextCol2()));
4007 sg.setShowNonconserved(safeBoolean(jGroup.isShowUnconserved()));
4008 sg.thresholdTextColour = safeInt(jGroup.getTextColThreshold());
4009 // attributes with a default in the schema are never null
4010 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
4011 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
4012 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
4013 sg.setIgnoreGapsConsensus(jGroup.isIgnoreGapsinConsensus());
4014 if (jGroup.getConsThreshold() != null
4015 && jGroup.getConsThreshold().intValue() != 0)
4017 Conservation c = new Conservation("All", sg.getSequences(null), 0,
4020 c.verdict(false, 25);
4021 sg.cs.setConservation(c);
4024 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
4026 // re-instate unique group/annotation row reference
4027 List<AlignmentAnnotation> jaal = groupAnnotRefs
4028 .get(jGroup.getId());
4031 for (AlignmentAnnotation jaa : jaal)
4034 if (jaa.autoCalculated)
4036 // match up and try to set group autocalc alignment row for this
4038 if (jaa.label.startsWith("Consensus for "))
4040 sg.setConsensus(jaa);
4042 // match up and try to set group autocalc alignment row for this
4044 if (jaa.label.startsWith("Conservation for "))
4046 sg.setConservationRow(jaa);
4053 if (addAnnotSchemeGroup)
4055 // reconstruct the annotation colourscheme
4056 sg.setColourScheme(constructAnnotationColour(
4057 jGroup.getAnnotationColours(), null, al, jalviewModel, false));
4063 // only dataset in this model, so just return.
4066 // ///////////////////////////////
4069 // now check to see if we really need to create a new viewport.
4070 if (multipleView && viewportsAdded.size() == 0)
4072 // We recovered an alignment for which a viewport already exists.
4073 // TODO: fix up any settings necessary for overlaying stored state onto
4074 // state recovered from another document. (may not be necessary).
4075 // we may need a binding from a viewport in memory to one recovered from
4077 // and then recover its containing af to allow the settings to be applied.
4078 // TODO: fix for vamsas demo
4080 "About to recover a viewport for existing alignment: Sequence set ID is "
4082 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
4083 if (seqsetobj != null)
4085 if (seqsetobj instanceof String)
4087 uniqueSeqSetId = (String) seqsetobj;
4089 "Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
4095 "Warning : Collision between sequence set ID string and existing jalview object mapping.");
4101 * indicate that annotation colours are applied across all groups (pre
4102 * Jalview 2.8.1 behaviour)
4104 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan("2.8.1",
4105 jalviewModel.getVersion());
4107 AlignFrame af = null;
4108 AlignmentPanel ap = null;
4109 AlignViewport av = null;
4112 // Check to see if this alignment already has a view id == viewId
4113 jalview.gui.AlignmentPanel views[] = Desktop
4114 .getAlignmentPanels(uniqueSeqSetId);
4115 if (views != null && views.length > 0)
4117 for (int v = 0; v < views.length; v++)
4121 if (av.getViewId().equalsIgnoreCase(viewId))
4123 // recover the existing alignpanel, alignframe, viewport
4126 // TODO: could even skip resetting view settings if we don't want to
4127 // change the local settings from other jalview processes
4135 af = loadViewport(file, jseqs, hiddenSeqs, al, jalviewModel, view,
4136 uniqueSeqSetId, viewId, autoAlan);
4137 av = af.getViewport();
4138 // note that this only retrieves the most recently accessed
4139 // tab of an AlignFrame.
4144 * Load any trees, PDB structures and viewers
4146 * Not done if flag is false (when this method is used for New View)
4148 final AlignFrame af0 = af;
4149 final AlignViewport av0 = av;
4150 final AlignmentPanel ap0 = ap;
4151 // Platform.timeCheck("Jalview2XML.loadFromObject-beforetree",
4152 // Platform.TIME_MARK);
4153 if (loadTreesAndStructures)
4155 if (!jalviewModel.getTree().isEmpty())
4157 SwingUtilities.invokeLater(new Runnable()
4162 // Platform.timeCheck(null, Platform.TIME_MARK);
4163 loadTrees(jalviewModel, view, af0, av0, ap0);
4164 // Platform.timeCheck("Jalview2XML.loadTrees", Platform.TIME_MARK);
4168 if (!jalviewModel.getPcaViewer().isEmpty())
4170 SwingUtilities.invokeLater(new Runnable()
4175 // Platform.timeCheck(null, Platform.TIME_MARK);
4176 loadPCAViewers(jalviewModel, ap0);
4177 // Platform.timeCheck("Jalview2XML.loadPCA", Platform.TIME_MARK);
4181 SwingUtilities.invokeLater(new Runnable()
4186 // Platform.timeCheck(null, Platform.TIME_MARK);
4187 loadPDBStructures(jprovider, jseqs, af0, ap0);
4188 // Platform.timeCheck("Jalview2XML.loadPDB", Platform.TIME_MARK);
4191 SwingUtilities.invokeLater(new Runnable()
4196 loadRnaViewers(jprovider, jseqs, ap0);
4200 // and finally return.
4201 // but do not set holdRepaint true just yet, because this could be the
4202 // initial frame with just its dataset.
4207 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
4208 * panel is restored from separate jar entries, two (gapped and trimmed) per
4209 * sequence and secondary structure.
4211 * Currently each viewer shows just one sequence and structure (gapped and
4212 * trimmed), however this method is designed to support multiple sequences or
4213 * structures in viewers if wanted in future.
4219 protected void loadRnaViewers(jarInputStreamProvider jprovider,
4220 List<JSeq> jseqs, AlignmentPanel ap)
4223 * scan the sequences for references to viewers; create each one the first
4224 * time it is referenced, add Rna models to existing viewers
4226 for (JSeq jseq : jseqs)
4228 for (int i = 0; i < jseq.getRnaViewer().size(); i++)
4230 RnaViewer viewer = jseq.getRnaViewer().get(i);
4231 AppVarna appVarna = findOrCreateVarnaViewer(viewer, uniqueSetSuffix,
4234 for (int j = 0; j < viewer.getSecondaryStructure().size(); j++)
4236 SecondaryStructure ss = viewer.getSecondaryStructure().get(j);
4237 SequenceI seq = seqRefIds.get(jseq.getId());
4238 AlignmentAnnotation ann = this.annotationIds
4239 .get(ss.getAnnotationId());
4242 * add the structure to the Varna display (with session state copied
4243 * from the jar to a temporary file)
4245 boolean gapped = safeBoolean(ss.isGapped());
4246 String rnaTitle = ss.getTitle();
4247 String sessionState = ss.getViewerState();
4248 String tempStateFile = copyJarEntry(jprovider, sessionState,
4250 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
4251 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
4253 appVarna.setInitialSelection(safeInt(viewer.getSelectedRna()));
4259 * Locate and return an already instantiated matching AppVarna, or create one
4263 * @param viewIdSuffix
4267 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
4268 String viewIdSuffix, AlignmentPanel ap)
4271 * on each load a suffix is appended to the saved viewId, to avoid conflicts
4272 * if load is repeated
4274 String postLoadId = viewer.getViewId() + viewIdSuffix;
4275 for (JInternalFrame frame : getAllFrames())
4277 if (frame instanceof AppVarna)
4279 AppVarna varna = (AppVarna) frame;
4280 if (postLoadId.equals(varna.getViewId()))
4282 // this viewer is already instantiated
4283 // could in future here add ap as another 'parent' of the
4284 // AppVarna window; currently just 1-to-many
4291 * viewer not found - make it
4293 RnaViewerModel model = new RnaViewerModel(postLoadId, viewer.getTitle(),
4294 safeInt(viewer.getXpos()), safeInt(viewer.getYpos()),
4295 safeInt(viewer.getWidth()), safeInt(viewer.getHeight()),
4296 safeInt(viewer.getDividerLocation()));
4297 AppVarna varna = new AppVarna(model, ap);
4303 * Load any saved trees
4311 protected void loadTrees(JalviewModel jm, Viewport view,
4312 AlignFrame af, AlignViewport av, AlignmentPanel ap)
4314 // TODO result of automated refactoring - are all these parameters needed?
4317 for (int t = 0; t < jm.getTree().size(); t++)
4320 Tree tree = jm.getTree().get(t);
4322 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
4325 tp = af.showNewickTree(new NewickFile(tree.getNewick()),
4326 tree.getTitle(), safeInt(tree.getWidth()),
4327 safeInt(tree.getHeight()), safeInt(tree.getXpos()),
4328 safeInt(tree.getYpos()));
4331 warn("There was a problem recovering stored Newick tree: \n"
4332 + tree.getNewick());
4335 if (tree.getId() != null)
4337 // perhaps bind the tree id to something ?
4342 // update local tree attributes ?
4343 // TODO: should check if tp has been manipulated by user - if so its
4344 // settings shouldn't be modified
4345 tp.setTitle(tree.getTitle());
4346 tp.setBounds(new Rectangle(safeInt(tree.getXpos()),
4347 safeInt(tree.getYpos()), safeInt(tree.getWidth()),
4348 safeInt(tree.getHeight())));
4349 tp.setViewport(av); // af.viewport;
4350 // TODO: verify 'associate with all views' works still
4351 tp.getTreeCanvas().setViewport(av); // af.viewport;
4352 tp.getTreeCanvas().setAssociatedPanel(ap); // af.alignPanel;
4354 tp.getTreeCanvas().setApplyToAllViews(tree.isLinkToAllViews());
4355 tp.fitToWindow.setState(safeBoolean(tree.isFitToWindow()));
4356 tp.fitToWindow_actionPerformed(null);
4358 if (tree.getFontName() != null)
4361 new Font(tree.getFontName(), safeInt(tree.getFontStyle()),
4362 safeInt(tree.getFontSize())));
4367 new Font(view.getFontName(), safeInt(view.getFontStyle()),
4368 safeInt(view.getFontSize())));
4371 tp.showPlaceholders(safeBoolean(tree.isMarkUnlinked()));
4372 tp.showBootstrap(safeBoolean(tree.isShowBootstrap()));
4373 tp.showDistances(safeBoolean(tree.isShowDistances()));
4375 tp.getTreeCanvas().setThreshold(safeFloat(tree.getThreshold()));
4377 if (safeBoolean(tree.isCurrentTree()))
4379 af.getViewport().setCurrentTree(tp.getTree());
4383 } catch (Exception ex)
4385 ex.printStackTrace();
4390 * Load and link any saved structure viewers.
4397 protected void loadPDBStructures(jarInputStreamProvider jprovider,
4398 List<JSeq> jseqs, AlignFrame af, AlignmentPanel ap)
4401 * Run through all PDB ids on the alignment, and collect mappings between
4402 * distinct view ids and all sequences referring to that view.
4404 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<>();
4406 for (int i = 0; i < jseqs.size(); i++)
4408 JSeq jseq = jseqs.get(i);
4409 if (jseq.getPdbids().size() > 0)
4411 List<Pdbids> ids = jseq.getPdbids();
4412 for (int p = 0; p < ids.size(); p++)
4414 Pdbids pdbid = ids.get(p);
4415 final int structureStateCount = pdbid.getStructureState().size();
4416 for (int s = 0; s < structureStateCount; s++)
4418 // check to see if we haven't already created this structure view
4419 final StructureState structureState = pdbid
4420 .getStructureState().get(s);
4421 String sviewid = (structureState.getViewId() == null) ? null
4422 : structureState.getViewId() + uniqueSetSuffix;
4423 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
4424 // Originally : pdbid.getFile()
4425 // : TODO: verify external PDB file recovery still works in normal
4426 // jalview project load
4428 loadPDBFile(jprovider, pdbid.getId(), pdbid.getFile()));
4429 jpdb.setId(pdbid.getId());
4431 int x = safeInt(structureState.getXpos());
4432 int y = safeInt(structureState.getYpos());
4433 int width = safeInt(structureState.getWidth());
4434 int height = safeInt(structureState.getHeight());
4436 // Probably don't need to do this anymore...
4437 // Desktop.getDesktop().getComponentAt(x, y);
4438 // TODO: NOW: check that this recovers the PDB file correctly.
4439 String pdbFile = loadPDBFile(jprovider, pdbid.getId(),
4441 jalview.datamodel.SequenceI seq = seqRefIds
4442 .get(jseq.getId() + "");
4443 if (sviewid == null)
4445 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width + ","
4448 if (!structureViewers.containsKey(sviewid))
4450 structureViewers.put(sviewid,
4451 new StructureViewerModel(x, y, width, height, false,
4452 false, true, structureState.getViewId(),
4453 structureState.getType()));
4454 // Legacy pre-2.7 conversion JAL-823 :
4455 // do not assume any view has to be linked for colour by
4459 // assemble String[] { pdb files }, String[] { id for each
4460 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
4461 // seqs_file 2}, boolean[] {
4462 // linkAlignPanel,superposeWithAlignpanel}} from hash
4463 StructureViewerModel jmoldat = structureViewers.get(sviewid);
4464 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
4465 || structureState.isAlignwithAlignPanel());
4468 * Default colour by linked panel to false if not specified (e.g.
4469 * for pre-2.7 projects)
4471 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
4472 colourWithAlignPanel |= structureState.isColourwithAlignPanel();
4473 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
4476 * Default colour by viewer to true if not specified (e.g. for
4479 boolean colourByViewer = jmoldat.isColourByViewer();
4480 colourByViewer &= structureState.isColourByJmol();
4481 jmoldat.setColourByViewer(colourByViewer);
4483 if (jmoldat.getStateData().length() < structureState
4484 .getValue()/*Content()*/.length())
4486 jmoldat.setStateData(structureState.getValue());// Content());
4488 if (pdbid.getFile() != null)
4490 File mapkey = new File(pdbid.getFile());
4491 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
4492 if (seqstrmaps == null)
4494 jmoldat.getFileData().put(mapkey,
4495 seqstrmaps = jmoldat.new StructureData(pdbFile,
4498 if (!seqstrmaps.getSeqList().contains(seq))
4500 seqstrmaps.getSeqList().add(seq);
4506 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");
4513 // Instantiate the associated structure views
4514 for (Entry<String, StructureViewerModel> entry : structureViewers
4519 createOrLinkStructureViewer(entry, af, ap, jprovider);
4520 } catch (Exception e)
4523 "Error loading structure viewer: " + e.getMessage());
4524 // failed - try the next one
4536 protected void createOrLinkStructureViewer(
4537 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4538 AlignmentPanel ap, jarInputStreamProvider jprovider)
4540 final StructureViewerModel stateData = viewerData.getValue();
4543 * Search for any viewer windows already open from other alignment views
4544 * that exactly match the stored structure state
4546 StructureViewerBase comp = findMatchingViewer(viewerData);
4550 linkStructureViewer(ap, comp, stateData);
4555 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
4556 * "viewer_"+stateData.viewId
4558 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
4560 createChimeraViewer(viewerData, af, jprovider);
4565 * else Jmol (if pre-2.9, stateData contains JMOL state string)
4567 createJmolViewer(viewerData, af, jprovider);
4572 * Create a new Chimera viewer.
4578 protected void createChimeraViewer(
4579 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4580 jarInputStreamProvider jprovider)
4582 StructureViewerModel data = viewerData.getValue();
4583 String chimeraSessionFile = data.getStateData();
4586 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
4588 * NB this is the 'saved' viewId as in the project file XML, _not_ the
4589 * 'uniquified' sviewid used to reconstruct the viewer here
4591 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
4592 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
4595 Set<Entry<File, StructureData>> fileData = data.getFileData()
4597 List<PDBEntry> pdbs = new ArrayList<>();
4598 List<SequenceI[]> allseqs = new ArrayList<>();
4599 for (Entry<File, StructureData> pdb : fileData)
4601 String filePath = pdb.getValue().getFilePath();
4602 String pdbId = pdb.getValue().getPdbId();
4603 // pdbs.add(new PDBEntry(filePath, pdbId));
4604 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
4605 final List<SequenceI> seqList = pdb.getValue().getSeqList();
4606 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
4610 boolean colourByChimera = data.isColourByViewer();
4611 boolean colourBySequence = data.isColourWithAlignPanel();
4613 // TODO use StructureViewer as a factory here, see JAL-1761
4614 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
4615 final SequenceI[][] seqsArray = allseqs
4616 .toArray(new SequenceI[allseqs.size()][]);
4617 String newViewId = viewerData.getKey();
4619 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
4620 af.alignPanel, pdbArray, seqsArray, colourByChimera,
4621 colourBySequence, newViewId);
4622 cvf.setSize(data.getWidth(), data.getHeight());
4623 cvf.setLocation(data.getX(), data.getY());
4627 * Create a new Jmol window. First parse the Jmol state to translate filenames
4628 * loaded into the view, and record the order in which files are shown in the
4629 * Jmol view, so we can add the sequence mappings in same order.
4635 protected void createJmolViewer(
4636 final Entry<String, StructureViewerModel> viewerData,
4637 AlignFrame af, jarInputStreamProvider jprovider)
4639 final StructureViewerModel svattrib = viewerData.getValue();
4640 String state = svattrib.getStateData();
4643 * Pre-2.9: state element value is the Jmol state string
4645 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
4648 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
4650 state = readJarEntry(jprovider,
4651 getViewerJarEntryName(svattrib.getViewId()));
4654 List<String> pdbfilenames = new ArrayList<>();
4655 List<SequenceI[]> seqmaps = new ArrayList<>();
4656 List<String> pdbids = new ArrayList<>();
4657 StringBuilder newFileLoc = new StringBuilder(64);
4658 int cp = 0, ncp, ecp;
4659 Map<File, StructureData> oldFiles = svattrib.getFileData();
4660 while ((ncp = state.indexOf("load ", cp)) > -1)
4664 // look for next filename in load statement
4665 newFileLoc.append(state.substring(cp,
4666 ncp = (state.indexOf("\"", ncp + 1) + 1)));
4667 String oldfilenam = state.substring(ncp,
4668 ecp = state.indexOf("\"", ncp));
4669 // recover the new mapping data for this old filename
4670 // have to normalize filename - since Jmol and jalview do
4672 // translation differently.
4673 StructureData filedat = oldFiles.get(new File(oldfilenam));
4674 if (filedat == null)
4676 String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\");
4677 filedat = oldFiles.get(new File(reformatedOldFilename));
4680 .append(Platform.escapeBackslashes(filedat.getFilePath()));
4681 pdbfilenames.add(filedat.getFilePath());
4682 pdbids.add(filedat.getPdbId());
4683 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4684 newFileLoc.append("\"");
4685 cp = ecp + 1; // advance beyond last \" and set cursor so we can
4686 // look for next file statement.
4687 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
4691 // just append rest of state
4692 newFileLoc.append(state.substring(cp));
4696 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
4697 newFileLoc = new StringBuilder(state);
4698 newFileLoc.append("; load append ");
4699 for (File id : oldFiles.keySet())
4701 // add this and any other pdb files that should be present in
4703 StructureData filedat = oldFiles.get(id);
4704 newFileLoc.append(filedat.getFilePath());
4705 pdbfilenames.add(filedat.getFilePath());
4706 pdbids.add(filedat.getPdbId());
4707 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4708 newFileLoc.append(" \"");
4709 newFileLoc.append(filedat.getFilePath());
4710 newFileLoc.append("\"");
4713 newFileLoc.append(";");
4716 if (newFileLoc.length() == 0)
4720 int histbug = newFileLoc.indexOf("history = ");
4724 * change "history = [true|false];" to "history = [1|0];"
4727 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
4728 String val = (diff == -1) ? null
4729 : newFileLoc.substring(histbug, diff);
4730 if (val != null && val.length() >= 4)
4732 if (val.contains("e")) // eh? what can it be?
4734 if (val.trim().equals("true"))
4742 newFileLoc.replace(histbug, diff, val);
4747 final String[] pdbf = pdbfilenames
4748 .toArray(new String[pdbfilenames.size()]);
4749 final String[] id = pdbids.toArray(new String[pdbids.size()]);
4750 final SequenceI[][] sq = seqmaps
4751 .toArray(new SequenceI[seqmaps.size()][]);
4752 final String fileloc = newFileLoc.toString();
4753 final String sviewid = viewerData.getKey();
4754 final AlignFrame alf = af;
4755 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
4756 svattrib.getWidth(), svattrib.getHeight());
4758 // BH again was invokeAndWait
4761 javax.swing.SwingUtilities.invokeLater(new Runnable()
4766 JalviewStructureDisplayI sview = null;
4769 sview = new StructureViewer(
4770 alf.alignPanel.getStructureSelectionManager())
4771 .createView(StructureViewer.ViewerType.JMOL,
4772 pdbf, id, sq, alf.alignPanel, svattrib,
4773 fileloc, rect, sviewid);
4774 addNewStructureViewer(sview);
4775 } catch (OutOfMemoryError ex)
4777 new OOMWarning("restoring structure view for PDB id " + id,
4778 (OutOfMemoryError) ex.getCause());
4779 if (sview != null && sview.isVisible())
4781 sview.closeViewer(false);
4782 sview.setVisible(false);
4788 // } catch (InvocationTargetException ex)
4790 // warn("Unexpected error when opening Jmol view.", ex);
4792 // } catch (InterruptedException e)
4794 // // e.printStackTrace();
4800 * Generates a name for the entry in the project jar file to hold state
4801 * information for a structure viewer
4806 protected String getViewerJarEntryName(String viewId)
4808 return VIEWER_PREFIX + viewId;
4812 * Returns any open frame that matches given structure viewer data. The match
4813 * is based on the unique viewId, or (for older project versions) the frame's
4819 protected StructureViewerBase findMatchingViewer(
4820 Entry<String, StructureViewerModel> viewerData)
4822 final String sviewid = viewerData.getKey();
4823 final StructureViewerModel svattrib = viewerData.getValue();
4824 StructureViewerBase comp = null;
4825 JInternalFrame[] frames = getAllFrames();
4826 for (JInternalFrame frame : frames)
4828 if (frame instanceof StructureViewerBase)
4831 * Post jalview 2.4 schema includes structure view id
4833 if (sviewid != null && ((StructureViewerBase) frame).getViewId()
4836 comp = (StructureViewerBase) frame;
4837 break; // break added in 2.9
4840 * Otherwise test for matching position and size of viewer frame
4842 else if (frame.getX() == svattrib.getX()
4843 && frame.getY() == svattrib.getY()
4844 && frame.getHeight() == svattrib.getHeight()
4845 && frame.getWidth() == svattrib.getWidth())
4847 comp = (StructureViewerBase) frame;
4848 // no break in faint hope of an exact match on viewId
4856 * Link an AlignmentPanel to an existing structure viewer.
4861 * @param useinViewerSuperpos
4862 * @param usetoColourbyseq
4863 * @param viewerColouring
4865 protected void linkStructureViewer(AlignmentPanel ap,
4866 StructureViewerBase viewer, StructureViewerModel stateData)
4868 // NOTE: if the jalview project is part of a shared session then
4869 // view synchronization should/could be done here.
4871 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4872 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4873 final boolean viewerColouring = stateData.isColourByViewer();
4874 Map<File, StructureData> oldFiles = stateData.getFileData();
4877 * Add mapping for sequences in this view to an already open viewer
4879 final AAStructureBindingModel binding = viewer.getBinding();
4880 for (File id : oldFiles.keySet())
4882 // add this and any other pdb files that should be present in the
4884 StructureData filedat = oldFiles.get(id);
4885 String pdbFile = filedat.getFilePath();
4886 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4887 binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE,
4889 binding.addSequenceForStructFile(pdbFile, seq);
4891 // and add the AlignmentPanel's reference to the view panel
4892 viewer.addAlignmentPanel(ap);
4893 if (useinViewerSuperpos)
4895 viewer.useAlignmentPanelForSuperposition(ap);
4899 viewer.excludeAlignmentPanelForSuperposition(ap);
4901 if (usetoColourbyseq)
4903 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4907 viewer.excludeAlignmentPanelForColourbyseq(ap);
4912 * Get all frames within the Desktop.
4916 protected JInternalFrame[] getAllFrames()
4918 JInternalFrame[] frames = null;
4919 // TODO is this necessary - is it safe - risk of hanging?
4924 frames = Desktop.getDesktopPane().getAllFrames();
4925 } catch (ArrayIndexOutOfBoundsException e)
4927 // occasional No such child exceptions are thrown here...
4931 } catch (InterruptedException f)
4935 } while (frames == null);
4940 * Answers true if 'version' is equal to or later than 'supported', where each
4941 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4942 * changes. Development and test values for 'version' are leniently treated
4946 * - minimum version we are comparing against
4948 * - version of data being processsed
4951 public static boolean isVersionStringLaterThan(String supported,
4954 if (supported == null || version == null
4955 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4956 || version.equalsIgnoreCase("Test")
4957 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4959 System.err.println("Assuming project file with "
4960 + (version == null ? "null" : version)
4961 + " is compatible with Jalview version " + supported);
4966 return StringUtils.compareVersions(version, supported, "b") >= 0;
4970 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4972 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4974 if (newStructureViewers != null)
4976 sview.getBinding().setFinishedLoadingFromArchive(false);
4977 newStructureViewers.add(sview);
4981 protected void setLoadingFinishedForNewStructureViewers()
4983 if (newStructureViewers != null)
4985 for (JalviewStructureDisplayI sview : newStructureViewers)
4987 sview.getBinding().setFinishedLoadingFromArchive(true);
4989 newStructureViewers.clear();
4990 newStructureViewers = null;
4994 AlignFrame loadViewport(String fileName, List<JSeq> JSEQ,
4995 List<SequenceI> hiddenSeqs, AlignmentI al, JalviewModel jm,
4996 Viewport view, String uniqueSeqSetId, String viewId,
4997 List<JvAnnotRow> autoAlan)
4999 AlignFrame af = null;
5000 af = new AlignFrame(al, safeInt(view.getWidth()),
5001 safeInt(view.getHeight()), uniqueSeqSetId, viewId)
5005 // protected void processKeyEvent(java.awt.event.KeyEvent e) {
5006 // System.out.println("Jalview2XML AF " + e);
5007 // super.processKeyEvent(e);
5013 af.alignPanel.setHoldRepaint(true);
5014 af.setFileName(fileName, FileFormat.Jalview);
5015 af.setFileObject(jarFile); // BH 2019 JAL-3436
5017 final AlignViewport viewport = af.getViewport();
5018 for (int i = 0; i < JSEQ.size(); i++)
5020 int colour = safeInt(JSEQ.get(i).getColour());
5021 viewport.setSequenceColour(viewport.getAlignment().getSequenceAt(i),
5027 viewport.setColourByReferenceSeq(true);
5028 viewport.setDisplayReferenceSeq(true);
5031 viewport.setGatherViewsHere(safeBoolean(view.isGatheredViews()));
5033 if (view.getSequenceSetId() != null)
5035 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
5037 viewport.setSequenceSetId(uniqueSeqSetId);
5040 // propagate shared settings to this new view
5041 viewport.setHistoryList(av.getHistoryList());
5042 viewport.setRedoList(av.getRedoList());
5046 viewportsAdded.put(uniqueSeqSetId, viewport);
5048 // TODO: check if this method can be called repeatedly without
5049 // side-effects if alignpanel already registered.
5050 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
5052 // apply Hidden regions to view.
5053 if (hiddenSeqs != null)
5055 for (int s = 0; s < JSEQ.size(); s++)
5057 SequenceGroup hidden = new SequenceGroup();
5058 boolean isRepresentative = false;
5059 for (int r = 0; r < JSEQ.get(s).getHiddenSequences().size(); r++)
5061 isRepresentative = true;
5062 SequenceI sequenceToHide = al
5063 .getSequenceAt(JSEQ.get(s).getHiddenSequences().get(r));
5064 hidden.addSequence(sequenceToHide, false);
5065 // remove from hiddenSeqs list so we don't try to hide it twice
5066 hiddenSeqs.remove(sequenceToHide);
5068 if (isRepresentative)
5070 SequenceI representativeSequence = al.getSequenceAt(s);
5071 hidden.addSequence(representativeSequence, false);
5072 viewport.hideRepSequences(representativeSequence, hidden);
5076 SequenceI[] hseqs = hiddenSeqs
5077 .toArray(new SequenceI[hiddenSeqs.size()]);
5078 viewport.hideSequence(hseqs);
5081 // recover view properties and display parameters
5083 viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
5084 viewport.setAbovePIDThreshold(safeBoolean(view.isPidSelected()));
5085 final int pidThreshold = safeInt(view.getPidThreshold());
5086 viewport.setThreshold(pidThreshold);
5088 viewport.setColourText(safeBoolean(view.isShowColourText()));
5090 viewport.setConservationSelected(
5091 safeBoolean(view.isConservationSelected()));
5092 viewport.setIncrement(safeInt(view.getConsThreshold()));
5093 viewport.setShowJVSuffix(safeBoolean(view.isShowFullId()));
5094 viewport.setRightAlignIds(safeBoolean(view.isRightAlignIds()));
5095 viewport.setFont(new Font(view.getFontName(),
5096 safeInt(view.getFontStyle()), safeInt(view.getFontSize())),
5098 ViewStyleI vs = viewport.getViewStyle();
5099 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
5100 viewport.setViewStyle(vs);
5101 // TODO: allow custom charWidth/Heights to be restored by updating them
5102 // after setting font - which means set above to false
5103 viewport.setRenderGaps(safeBoolean(view.isRenderGaps()));
5104 viewport.setWrapAlignment(safeBoolean(view.isWrapAlignment()));
5105 viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
5107 viewport.setShowBoxes(safeBoolean(view.isShowBoxes()));
5109 viewport.setShowText(safeBoolean(view.isShowText()));
5111 viewport.setTextColour(new Color(safeInt(view.getTextCol1())));
5112 viewport.setTextColour2(new Color(safeInt(view.getTextCol2())));
5113 viewport.setThresholdTextColour(safeInt(view.getTextColThreshold()));
5114 viewport.setShowUnconserved(view.isShowUnconserved());
5115 viewport.getRanges().setStartRes(safeInt(view.getStartRes()));
5117 if (view.getViewName() != null)
5119 viewport.setViewName(view.getViewName());
5120 af.setInitialTabVisible();
5122 int x = safeInt(view.getXpos());
5123 int y = safeInt(view.getYpos());
5124 int w = safeInt(view.getWidth());
5125 int h = safeInt(view.getHeight());
5126 // // BH we cannot let the title bar go off the top
5127 // if (Platform.isJS())
5129 // x = Math.max(50 - w, x);
5130 // y = Math.max(0, y);
5133 af.setBounds(x, y, w, h);
5134 // startSeq set in af.alignPanel.updateLayout below
5135 af.alignPanel.updateLayout();
5136 ColourSchemeI cs = null;
5137 // apply colourschemes
5138 if (view.getBgColour() != null)
5140 if (view.getBgColour().startsWith("ucs"))
5142 cs = getUserColourScheme(jm, view.getBgColour());
5144 else if (view.getBgColour().startsWith("Annotation"))
5146 AnnotationColourScheme viewAnnColour = view.getAnnotationColours();
5147 cs = constructAnnotationColour(viewAnnColour, af, al, jm, true);
5154 cs = ColourSchemeProperty.getColourScheme(af.getViewport(), al,
5155 view.getBgColour());
5160 * turn off 'alignment colour applies to all groups'
5161 * while restoring global colour scheme
5163 viewport.setColourAppliesToAllGroups(false);
5164 viewport.setGlobalColourScheme(cs);
5165 viewport.getResidueShading().setThreshold(pidThreshold,
5166 view.isIgnoreGapsinConsensus());
5167 viewport.getResidueShading()
5168 .setConsensus(viewport.getSequenceConsensusHash());
5169 if (safeBoolean(view.isConservationSelected()) && cs != null)
5171 viewport.getResidueShading()
5172 .setConservationInc(safeInt(view.getConsThreshold()));
5174 af.changeColour(cs);
5175 viewport.setColourAppliesToAllGroups(true);
5177 viewport.setShowSequenceFeatures(
5178 safeBoolean(view.isShowSequenceFeatures()));
5180 viewport.setCentreColumnLabels(view.isCentreColumnLabels());
5181 viewport.setIgnoreGapsConsensus(view.isIgnoreGapsinConsensus(), null);
5182 viewport.setFollowHighlight(view.isFollowHighlight());
5183 viewport.followSelection = view.isFollowSelection();
5184 viewport.setShowConsensusHistogram(view.isShowConsensusHistogram());
5185 viewport.setShowSequenceLogo(view.isShowSequenceLogo());
5186 viewport.setNormaliseSequenceLogo(view.isNormaliseSequenceLogo());
5187 viewport.setShowDBRefs(safeBoolean(view.isShowDbRefTooltip()));
5188 viewport.setShowNPFeats(safeBoolean(view.isShowNPfeatureTooltip()));
5189 viewport.setShowGroupConsensus(view.isShowGroupConsensus());
5190 viewport.setShowGroupConservation(view.isShowGroupConservation());
5191 viewport.setShowComplementFeatures(view.isShowComplementFeatures());
5192 viewport.setShowComplementFeaturesOnTop(
5193 view.isShowComplementFeaturesOnTop());
5195 // recover feature settings
5196 if (jm.getFeatureSettings() != null)
5198 FeatureRenderer fr = af.alignPanel.getSeqPanel().seqCanvas
5199 .getFeatureRenderer();
5200 FeaturesDisplayed fdi;
5201 viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
5202 String[] renderOrder = new String[jm.getFeatureSettings().getSetting()
5204 Map<String, FeatureColourI> featureColours = new Hashtable<>();
5205 Map<String, Float> featureOrder = new Hashtable<>();
5207 for (int fs = 0; fs < jm.getFeatureSettings().getSetting()
5210 Setting setting = jm.getFeatureSettings().getSetting().get(fs);
5211 String featureType = setting.getType();
5214 * restore feature filters (if any)
5216 jalview.xml.binding.jalview.FeatureMatcherSet filters = setting
5218 if (filters != null)
5220 FeatureMatcherSetI filter = Jalview2XML.parseFilter(featureType,
5222 if (!filter.isEmpty())
5224 fr.setFeatureFilter(featureType, filter);
5229 * restore feature colour scheme
5231 Color maxColour = new Color(setting.getColour());
5232 if (setting.getMincolour() != null)
5235 * minColour is always set unless a simple colour
5236 * (including for colour by label though it doesn't use it)
5238 Color minColour = new Color(setting.getMincolour().intValue());
5239 Color noValueColour = minColour;
5240 NoValueColour noColour = setting.getNoValueColour();
5241 if (noColour == NoValueColour.NONE)
5243 noValueColour = null;
5245 else if (noColour == NoValueColour.MAX)
5247 noValueColour = maxColour;
5249 float min = safeFloat(safeFloat(setting.getMin()));
5250 float max = setting.getMax() == null ? 1f
5251 : setting.getMax().floatValue();
5252 FeatureColourI gc = new FeatureColour(maxColour, minColour,
5253 maxColour, noValueColour, min, max);
5254 if (setting.getAttributeName().size() > 0)
5256 gc.setAttributeName(setting.getAttributeName().toArray(
5257 new String[setting.getAttributeName().size()]));
5259 if (setting.getThreshold() != null)
5261 gc.setThreshold(setting.getThreshold().floatValue());
5262 int threshstate = safeInt(setting.getThreshstate());
5263 // -1 = None, 0 = Below, 1 = Above threshold
5264 if (threshstate == 0)
5266 gc.setBelowThreshold(true);
5268 else if (threshstate == 1)
5270 gc.setAboveThreshold(true);
5273 gc.setAutoScaled(true); // default
5274 if (setting.isAutoScale() != null)
5276 gc.setAutoScaled(setting.isAutoScale());
5278 if (setting.isColourByLabel() != null)
5280 gc.setColourByLabel(setting.isColourByLabel());
5282 // and put in the feature colour table.
5283 featureColours.put(featureType, gc);
5287 featureColours.put(featureType, new FeatureColour(maxColour));
5289 renderOrder[fs] = featureType;
5290 if (setting.getOrder() != null)
5292 featureOrder.put(featureType, setting.getOrder().floatValue());
5296 featureOrder.put(featureType, Float.valueOf(
5297 fs / jm.getFeatureSettings().getSetting().size()));
5299 if (safeBoolean(setting.isDisplay()))
5301 fdi.setVisible(featureType);
5304 Map<String, Boolean> fgtable = new Hashtable<>();
5305 for (int gs = 0; gs < jm.getFeatureSettings().getGroup().size(); gs++)
5307 Group grp = jm.getFeatureSettings().getGroup().get(gs);
5308 fgtable.put(grp.getName(), Boolean.valueOf(grp.isDisplay()));
5310 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
5311 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
5312 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
5313 FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
5314 fgtable, featureColours, 1.0f, featureOrder);
5315 fr.transferSettings(frs);
5318 if (view.getHiddenColumns().size() > 0)
5320 for (int c = 0; c < view.getHiddenColumns().size(); c++)
5322 final HiddenColumns hc = view.getHiddenColumns().get(c);
5323 viewport.hideColumns(safeInt(hc.getStart()),
5324 safeInt(hc.getEnd()) /* +1 */);
5327 if (view.getCalcIdParam() != null)
5329 for (CalcIdParam calcIdParam : view.getCalcIdParam())
5331 if (calcIdParam != null)
5333 if (recoverCalcIdParam(calcIdParam, viewport))
5338 warn("Couldn't recover parameters for "
5339 + calcIdParam.getCalcId());
5344 af.setMenusFromViewport(viewport);
5345 af.setTitle(view.getTitle());
5346 // TODO: we don't need to do this if the viewport is aready visible.
5348 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
5349 * has a 'cdna/protein complement' view, in which case save it in order to
5350 * populate a SplitFrame once all views have been read in.
5352 String complementaryViewId = view.getComplementId();
5353 if (complementaryViewId == null)
5355 Dimension dim = Platform.getDimIfEmbedded(af,
5356 safeInt(view.getWidth()), safeInt(view.getHeight()));
5357 Desktop.addInternalFrame(af, view.getTitle(), dim.width, dim.height);
5358 // recompute any autoannotation
5359 af.alignPanel.updateAnnotation(false, true);
5360 reorderAutoannotation(af, al, autoAlan);
5361 af.alignPanel.alignmentChanged();
5365 splitFrameCandidates.put(view, af);
5371 * Reads saved data to restore Colour by Annotation settings
5373 * @param viewAnnColour
5377 * @param checkGroupAnnColour
5380 private ColourSchemeI constructAnnotationColour(
5381 AnnotationColourScheme viewAnnColour, AlignFrame af,
5382 AlignmentI al, JalviewModel model, boolean checkGroupAnnColour)
5384 boolean propagateAnnColour = false;
5385 AlignmentI annAlignment = af != null ? af.getViewport().getAlignment()
5387 if (checkGroupAnnColour && al.getGroups() != null
5388 && al.getGroups().size() > 0)
5390 // pre 2.8.1 behaviour
5391 // check to see if we should transfer annotation colours
5392 propagateAnnColour = true;
5393 for (SequenceGroup sg : al.getGroups())
5395 if (sg.getColourScheme() instanceof AnnotationColourGradient)
5397 propagateAnnColour = false;
5403 * 2.10.2- : saved annotationId is AlignmentAnnotation.annotationId
5405 String annotationId = viewAnnColour.getAnnotation();
5406 AlignmentAnnotation matchedAnnotation = annotationIds.get(annotationId);
5409 * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
5411 if (matchedAnnotation == null
5412 && annAlignment.getAlignmentAnnotation() != null)
5414 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
5417 .equals(annAlignment.getAlignmentAnnotation()[i].label))
5419 matchedAnnotation = annAlignment.getAlignmentAnnotation()[i];
5424 if (matchedAnnotation == null)
5426 System.err.println("Failed to match annotation colour scheme for "
5430 if (matchedAnnotation.getThreshold() == null)
5432 matchedAnnotation.setThreshold(
5433 new GraphLine(safeFloat(viewAnnColour.getThreshold()),
5434 "Threshold", Color.black));
5437 AnnotationColourGradient cs = null;
5438 if (viewAnnColour.getColourScheme().equals("None"))
5440 cs = new AnnotationColourGradient(matchedAnnotation,
5441 new Color(safeInt(viewAnnColour.getMinColour())),
5442 new Color(safeInt(viewAnnColour.getMaxColour())),
5443 safeInt(viewAnnColour.getAboveThreshold()));
5445 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
5447 cs = new AnnotationColourGradient(matchedAnnotation,
5448 getUserColourScheme(model, viewAnnColour.getColourScheme()),
5449 safeInt(viewAnnColour.getAboveThreshold()));
5453 cs = new AnnotationColourGradient(matchedAnnotation,
5454 ColourSchemeProperty.getColourScheme(af.getViewport(), al,
5455 viewAnnColour.getColourScheme()),
5456 safeInt(viewAnnColour.getAboveThreshold()));
5459 boolean perSequenceOnly = safeBoolean(viewAnnColour.isPerSequence());
5460 boolean useOriginalColours = safeBoolean(
5461 viewAnnColour.isPredefinedColours());
5462 cs.setSeqAssociated(perSequenceOnly);
5463 cs.setPredefinedColours(useOriginalColours);
5465 if (propagateAnnColour && al.getGroups() != null)
5467 // Also use these settings for all the groups
5468 for (int g = 0; g < al.getGroups().size(); g++)
5470 SequenceGroup sg = al.getGroups().get(g);
5471 if (sg.getGroupColourScheme() == null)
5476 AnnotationColourGradient groupScheme = new AnnotationColourGradient(
5477 matchedAnnotation, sg.getColourScheme(),
5478 safeInt(viewAnnColour.getAboveThreshold()));
5479 sg.setColourScheme(groupScheme);
5480 groupScheme.setSeqAssociated(perSequenceOnly);
5481 groupScheme.setPredefinedColours(useOriginalColours);
5487 private void reorderAutoannotation(AlignFrame af, AlignmentI al,
5488 List<JvAnnotRow> autoAlan)
5490 // copy over visualization settings for autocalculated annotation in the
5492 if (al.getAlignmentAnnotation() != null)
5495 * Kludge for magic autoannotation names (see JAL-811)
5497 String[] magicNames = new String[] { "Consensus", "Quality",
5499 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
5500 Hashtable<String, JvAnnotRow> visan = new Hashtable<>();
5501 for (String nm : magicNames)
5503 visan.put(nm, nullAnnot);
5505 for (JvAnnotRow auan : autoAlan)
5507 visan.put(auan.template.label
5508 + (auan.template.getCalcId() == null ? ""
5509 : "\t" + auan.template.getCalcId()),
5512 int hSize = al.getAlignmentAnnotation().length;
5513 List<JvAnnotRow> reorder = new ArrayList<>();
5514 // work through any autoCalculated annotation already on the view
5515 // removing it if it should be placed in a different location on the
5516 // annotation panel.
5517 List<String> remains = new ArrayList<>(visan.keySet());
5518 for (int h = 0; h < hSize; h++)
5520 jalview.datamodel.AlignmentAnnotation jalan = al
5521 .getAlignmentAnnotation()[h];
5522 if (jalan.autoCalculated)
5525 JvAnnotRow valan = visan.get(k = jalan.label);
5526 if (jalan.getCalcId() != null)
5528 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
5533 // delete the auto calculated row from the alignment
5534 al.deleteAnnotation(jalan, false);
5538 if (valan != nullAnnot)
5540 if (jalan != valan.template)
5542 // newly created autoannotation row instance
5543 // so keep a reference to the visible annotation row
5544 // and copy over all relevant attributes
5545 if (valan.template.graphHeight >= 0)
5548 jalan.graphHeight = valan.template.graphHeight;
5550 jalan.visible = valan.template.visible;
5552 reorder.add(new JvAnnotRow(valan.order, jalan));
5557 // Add any (possibly stale) autocalculated rows that were not appended to
5558 // the view during construction
5559 for (String other : remains)
5561 JvAnnotRow othera = visan.get(other);
5562 if (othera != nullAnnot && othera.template.getCalcId() != null
5563 && othera.template.getCalcId().length() > 0)
5565 reorder.add(othera);
5568 // now put the automatic annotation in its correct place
5569 int s = 0, srt[] = new int[reorder.size()];
5570 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
5571 for (JvAnnotRow jvar : reorder)
5574 srt[s++] = jvar.order;
5577 jalview.util.QuickSort.sort(srt, rws);
5578 // and re-insert the annotation at its correct position
5579 for (JvAnnotRow jvar : rws)
5581 al.addAnnotation(jvar.template, jvar.order);
5583 af.alignPanel.adjustAnnotationHeight();
5587 Hashtable skipList = null;
5590 * TODO remove this method
5593 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
5594 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
5595 * throw new Error("Implementation Error. No skipList defined for this
5596 * Jalview2XML instance."); } return (AlignFrame)
5597 * skipList.get(view.getSequenceSetId()); }
5601 * Check if the Jalview view contained in object should be skipped or not.
5604 * @return true if view's sequenceSetId is a key in skipList
5606 private boolean skipViewport(JalviewModel object)
5608 if (skipList == null)
5612 String id = object.getViewport().get(0).getSequenceSetId();
5613 if (skipList.containsKey(id))
5615 if (Cache.log != null && Cache.log.isDebugEnabled())
5617 Cache.log.debug("Skipping seuqence set id " + id);
5624 protected void addToSkipList(AlignFrame af)
5626 if (skipList == null)
5628 skipList = new Hashtable();
5630 skipList.put(af.getViewport().getSequenceSetId(), af);
5633 protected void clearSkipList()
5635 if (skipList != null)
5642 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
5643 boolean ignoreUnrefed, String uniqueSeqSetId)
5645 jalview.datamodel.AlignmentI ds = getDatasetFor(
5646 vamsasSet.getDatasetId());
5647 AlignmentI xtant_ds = ds;
5648 if (xtant_ds == null)
5650 // good chance we are about to create a new dataset, but check if we've
5651 // seen some of the dataset sequence IDs before.
5652 // TODO: skip this check if we are working with project generated by
5653 // version 2.11 or later
5654 xtant_ds = checkIfHasDataset(vamsasSet.getSequence());
5655 if (xtant_ds != null)
5658 addDatasetRef(vamsasSet.getDatasetId(), ds);
5661 Vector dseqs = null;
5664 // recovering an alignment View
5665 AlignmentI seqSetDS = getDatasetFor(UNIQSEQSETID + uniqueSeqSetId);
5666 if (seqSetDS != null)
5668 if (ds != null && ds != seqSetDS)
5670 warn("JAL-3171 regression: Overwriting a dataset reference for an alignment"
5671 + " - CDS/Protein crossreference data may be lost");
5672 if (xtant_ds != null)
5674 // This can only happen if the unique sequence set ID was bound to a
5675 // dataset that did not contain any of the sequences in the view
5676 // currently being restored.
5677 warn("JAL-3171 SERIOUS! TOTAL CONFUSION - please consider contacting the Jalview Development team so they can investigate why your project caused this message to be displayed.");
5681 addDatasetRef(vamsasSet.getDatasetId(), ds);
5686 // try even harder to restore dataset
5687 AlignmentI xtantDS = checkIfHasDataset(vamsasSet.getSequence());
5688 // create a list of new dataset sequences
5689 dseqs = new Vector();
5691 for (int i = 0, iSize = vamsasSet.getSequence().size(); i < iSize; i++)
5693 Sequence vamsasSeq = vamsasSet.getSequence().get(i);
5694 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
5696 // create a new dataset
5699 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
5700 dseqs.copyInto(dsseqs);
5701 ds = new jalview.datamodel.Alignment(dsseqs);
5702 // debug("Jalview2XML Created new dataset " + vamsasSet.getDatasetId()
5703 // + " for alignment " + System.identityHashCode(al));
5704 addDatasetRef(vamsasSet.getDatasetId(), ds);
5706 // set the dataset for the newly imported alignment.
5707 if (al.getDataset() == null && !ignoreUnrefed)
5710 // register dataset for the alignment's uniqueSeqSetId for legacy projects
5711 addDatasetRef(UNIQSEQSETID + uniqueSeqSetId, ds);
5713 updateSeqDatasetBinding(vamsasSet.getSequence(), ds);
5717 * XML dataset sequence ID to materialised dataset reference
5719 HashMap<String, AlignmentI> seqToDataset = new HashMap<>();
5722 * @return the first materialised dataset reference containing a dataset
5723 * sequence referenced in the given view
5725 * - sequences from the view
5727 AlignmentI checkIfHasDataset(List<Sequence> list)
5729 for (Sequence restoredSeq : list)
5731 AlignmentI datasetFor = seqToDataset.get(restoredSeq.getDsseqid());
5732 if (datasetFor != null)
5741 * Register ds as the containing dataset for the dataset sequences referenced
5742 * by sequences in list
5745 * - sequences in a view
5748 void updateSeqDatasetBinding(List<Sequence> list, AlignmentI ds)
5750 for (Sequence restoredSeq : list)
5752 AlignmentI prevDS = seqToDataset.put(restoredSeq.getDsseqid(), ds);
5753 if (prevDS != null && prevDS != ds)
5755 warn("Dataset sequence appears in many datasets: "
5756 + restoredSeq.getDsseqid());
5757 // TODO: try to merge!
5764 * sequence definition to create/merge dataset sequence for
5768 * vector to add new dataset sequence to
5769 * @param ignoreUnrefed
5770 * - when true, don't create new sequences from vamsasSeq if it's id
5771 * doesn't already have an asssociated Jalview sequence.
5773 * - used to reorder the sequence in the alignment according to the
5774 * vamsasSeq array ordering, to preserve ordering of dataset
5776 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
5777 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed, int vseqpos)
5779 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
5781 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
5782 boolean reorder = false;
5783 SequenceI dsq = null;
5784 if (sq != null && sq.getDatasetSequence() != null)
5786 dsq = sq.getDatasetSequence();
5792 if (sq == null && ignoreUnrefed)
5796 String sqid = vamsasSeq.getDsseqid();
5799 // need to create or add a new dataset sequence reference to this sequence
5802 dsq = seqRefIds.get(sqid);
5807 // make a new dataset sequence
5808 dsq = sq.createDatasetSequence();
5811 // make up a new dataset reference for this sequence
5812 sqid = seqHash(dsq);
5814 dsq.setVamsasId(uniqueSetSuffix + sqid);
5815 seqRefIds.put(sqid, dsq);
5820 dseqs.addElement(dsq);
5825 ds.addSequence(dsq);
5831 { // make this dataset sequence sq's dataset sequence
5832 sq.setDatasetSequence(dsq);
5833 // and update the current dataset alignment
5838 if (!dseqs.contains(dsq))
5845 if (ds.findIndex(dsq) < 0)
5847 ds.addSequence(dsq);
5854 // TODO: refactor this as a merge dataset sequence function
5855 // now check that sq (the dataset sequence) sequence really is the union of
5856 // all references to it
5857 // boolean pre = sq.getStart() < dsq.getStart();
5858 // boolean post = sq.getEnd() > dsq.getEnd();
5862 // StringBuffer sb = new StringBuffer();
5863 String newres = jalview.analysis.AlignSeq.extractGaps(
5864 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
5865 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
5866 && newres.length() > dsq.getLength())
5868 // Update with the longer sequence.
5872 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
5873 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
5874 * sb.append(newres.substring(newres.length() - sq.getEnd() -
5875 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
5877 dsq.setSequence(newres);
5879 // TODO: merges will never happen if we 'know' we have the real dataset
5880 // sequence - this should be detected when id==dssid
5882 "DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
5883 // + (pre ? "prepended" : "") + " "
5884 // + (post ? "appended" : ""));
5889 // sequence refs are identical. We may need to update the existing dataset
5890 // alignment with this one, though.
5891 if (ds != null && dseqs == null)
5893 int opos = ds.findIndex(dsq);
5894 SequenceI tseq = null;
5895 if (opos != -1 && vseqpos != opos)
5897 // remove from old position
5898 ds.deleteSequence(dsq);
5900 if (vseqpos < ds.getHeight())
5902 if (vseqpos != opos)
5904 // save sequence at destination position
5905 tseq = ds.getSequenceAt(vseqpos);
5906 ds.replaceSequenceAt(vseqpos, dsq);
5907 ds.addSequence(tseq);
5912 ds.addSequence(dsq);
5919 * TODO use AlignmentI here and in related methods - needs
5920 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
5922 Hashtable<String, AlignmentI> datasetIds = null;
5924 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
5926 private AlignmentI getDatasetFor(String datasetId)
5928 if (datasetIds == null)
5930 datasetIds = new Hashtable<>();
5933 if (datasetIds.containsKey(datasetId))
5935 return datasetIds.get(datasetId);
5940 private void addDatasetRef(String datasetId, AlignmentI dataset)
5942 if (datasetIds == null)
5944 datasetIds = new Hashtable<>();
5946 datasetIds.put(datasetId, dataset);
5950 * make a new dataset ID for this jalview dataset alignment
5955 private String getDatasetIdRef(AlignmentI dataset)
5957 if (dataset.getDataset() != null)
5959 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
5961 String datasetId = makeHashCode(dataset, null);
5962 if (datasetId == null)
5964 // make a new datasetId and record it
5965 if (dataset2Ids == null)
5967 dataset2Ids = new IdentityHashMap<>();
5971 datasetId = dataset2Ids.get(dataset);
5973 if (datasetId == null)
5975 datasetId = "ds" + dataset2Ids.size() + 1;
5976 dataset2Ids.put(dataset, datasetId);
5983 * Add any saved DBRefEntry's to the sequence. An entry flagged as 'locus' is
5984 * constructed as a special subclass GeneLocus.
5986 * @param datasetSequence
5989 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5991 for (int d = 0; d < sequence.getDBRef().size(); d++)
5993 DBRef dr = sequence.getDBRef().get(d);
5997 entry = new GeneLocus(dr.getSource(), dr.getVersion(),
5998 dr.getAccessionId());
6002 entry = new DBRefEntry(dr.getSource(), dr.getVersion(),
6003 dr.getAccessionId());
6005 if (dr.getMapping() != null)
6007 entry.setMap(addMapping(dr.getMapping()));
6009 datasetSequence.addDBRef(entry);
6013 private jalview.datamodel.Mapping addMapping(Mapping m)
6015 SequenceI dsto = null;
6016 // Mapping m = dr.getMapping();
6017 int fr[] = new int[m.getMapListFrom().size() * 2];
6018 Iterator<MapListFrom> from = m.getMapListFrom().iterator();// enumerateMapListFrom();
6019 for (int _i = 0; from.hasNext(); _i += 2)
6021 MapListFrom mf = from.next();
6022 fr[_i] = mf.getStart();
6023 fr[_i + 1] = mf.getEnd();
6025 int fto[] = new int[m.getMapListTo().size() * 2];
6026 Iterator<MapListTo> to = m.getMapListTo().iterator();// enumerateMapListTo();
6027 for (int _i = 0; to.hasNext(); _i += 2)
6029 MapListTo mf = to.next();
6030 fto[_i] = mf.getStart();
6031 fto[_i + 1] = mf.getEnd();
6033 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto, fr,
6034 fto, m.getMapFromUnit().intValue(),
6035 m.getMapToUnit().intValue());
6038 * (optional) choice of dseqFor or Sequence
6040 if (m.getDseqFor() != null)
6042 String dsfor = m.getDseqFor();
6043 if (seqRefIds.containsKey(dsfor))
6048 jmap.setTo(seqRefIds.get(dsfor));
6052 frefedSequence.add(newMappingRef(dsfor, jmap));
6055 else if (m.getSequence() != null)
6058 * local sequence definition
6060 Sequence ms = m.getSequence();
6061 SequenceI djs = null;
6062 String sqid = ms.getDsseqid();
6063 if (sqid != null && sqid.length() > 0)
6066 * recover dataset sequence
6068 djs = seqRefIds.get(sqid);
6073 "Warning - making up dataset sequence id for DbRef sequence map reference");
6074 sqid = ((Object) ms).toString(); // make up a new hascode for
6075 // undefined dataset sequence hash
6076 // (unlikely to happen)
6082 * make a new dataset sequence and add it to refIds hash
6084 djs = new jalview.datamodel.Sequence(ms.getName(),
6086 djs.setStart(jmap.getMap().getToLowest());
6087 djs.setEnd(jmap.getMap().getToHighest());
6088 djs.setVamsasId(uniqueSetSuffix + sqid);
6090 incompleteSeqs.put(sqid, djs);
6091 seqRefIds.put(sqid, djs);
6094 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
6103 * Provides a 'copy' of an alignment view (on action New View) by 'saving' the
6104 * view as XML (but not to file), and then reloading it
6109 public AlignmentPanel copyAlignPanel(AlignmentPanel ap)
6112 JalviewModel jm = saveState(ap, null, null, null);
6115 jm.getVamsasModel().getSequenceSet().get(0).getDatasetId(),
6116 ap.getAlignment().getDataset());
6118 uniqueSetSuffix = "";
6119 // jm.getJalviewModelSequence().getViewport(0).setId(null);
6120 jm.getViewport().get(0).setId(null);
6121 // we don't overwrite the view we just copied
6123 if (this.frefedSequence == null)
6125 frefedSequence = new Vector<>();
6128 viewportsAdded.clear();
6130 AlignFrame af = loadFromObject(jm, null, false, null);
6131 af.getAlignPanels().clear();
6132 af.closeMenuItem_actionPerformed(true);
6133 af.alignPanel.setHoldRepaint(false);
6134 this.jarFile = null;
6137 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
6138 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
6139 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
6140 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
6141 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
6144 return af.alignPanel;
6147 private Hashtable jvids2vobj;
6149 private void warn(String msg)
6154 private void warn(String msg, Exception e)
6156 if (Cache.log != null)
6160 Cache.log.warn(msg, e);
6164 Cache.log.warn(msg);
6169 System.err.println("Warning: " + msg);
6172 e.printStackTrace();
6177 private void debug(String string)
6179 debug(string, null);
6182 private void debug(String msg, Exception e)
6184 if (Cache.log != null)
6188 Cache.log.debug(msg, e);
6192 Cache.log.debug(msg);
6197 System.err.println("Warning: " + msg);
6200 e.printStackTrace();
6206 * set the object to ID mapping tables used to write/recover objects and XML
6207 * ID strings for the jalview project. If external tables are provided then
6208 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
6209 * object goes out of scope. - also populates the datasetIds hashtable with
6210 * alignment objects containing dataset sequences
6213 * Map from ID strings to jalview datamodel
6215 * Map from jalview datamodel to ID strings
6219 public void setObjectMappingTables(Hashtable vobj2jv,
6220 IdentityHashMap jv2vobj)
6222 this.jv2vobj = jv2vobj;
6223 this.vobj2jv = vobj2jv;
6224 Iterator ds = jv2vobj.keySet().iterator();
6226 while (ds.hasNext())
6228 Object jvobj = ds.next();
6229 id = jv2vobj.get(jvobj).toString();
6230 if (jvobj instanceof jalview.datamodel.Alignment)
6232 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
6234 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
6237 else if (jvobj instanceof jalview.datamodel.Sequence)
6239 // register sequence object so the XML parser can recover it.
6240 if (seqRefIds == null)
6242 seqRefIds = new HashMap<>();
6244 if (seqsToIds == null)
6246 seqsToIds = new IdentityHashMap<>();
6248 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
6249 seqsToIds.put((SequenceI) jvobj, id);
6251 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
6254 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
6255 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
6256 if (jvann.annotationId == null)
6258 jvann.annotationId = anid;
6260 if (!jvann.annotationId.equals(anid))
6262 // TODO verify that this is the correct behaviour
6263 this.warn("Overriding Annotation ID for " + anid
6264 + " from different id : " + jvann.annotationId);
6265 jvann.annotationId = anid;
6268 else if (jvobj instanceof String)
6270 if (jvids2vobj == null)
6272 jvids2vobj = new Hashtable();
6273 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
6278 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
6284 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
6285 * objects created from the project archive. If string is null (default for
6286 * construction) then suffix will be set automatically.
6290 public void setUniqueSetSuffix(String string)
6292 uniqueSetSuffix = string;
6297 * uses skipList2 as the skipList for skipping views on sequence sets
6298 * associated with keys in the skipList
6302 public void setSkipList(Hashtable skipList2)
6304 skipList = skipList2;
6308 * Reads the jar entry of given name and returns its contents, or null if the
6309 * entry is not found.
6312 * @param jarEntryName
6315 protected String readJarEntry(jarInputStreamProvider jprovider,
6316 String jarEntryName)
6318 String result = null;
6319 BufferedReader in = null;
6324 * Reopen the jar input stream and traverse its entries to find a matching
6327 JarInputStream jin = jprovider.getJarInputStream();
6328 JarEntry entry = null;
6331 entry = jin.getNextJarEntry();
6332 } while (entry != null && !entry.getName().equals(jarEntryName));
6336 StringBuilder out = new StringBuilder(256);
6337 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
6340 while ((data = in.readLine()) != null)
6344 result = out.toString();
6348 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
6350 } catch (Exception ex)
6352 ex.printStackTrace();
6360 } catch (IOException e)
6371 * Returns an incrementing counter (0, 1, 2...)
6375 private synchronized int nextCounter()
6381 * Loads any saved PCA viewers
6386 protected void loadPCAViewers(JalviewModel model, AlignmentPanel ap)
6390 List<PcaViewer> pcaviewers = model.getPcaViewer();
6391 for (PcaViewer viewer : pcaviewers)
6393 String modelName = viewer.getScoreModelName();
6394 SimilarityParamsI params = new SimilarityParams(
6395 viewer.isIncludeGappedColumns(), viewer.isMatchGaps(),
6396 viewer.isIncludeGaps(),
6397 viewer.isDenominateByShortestLength());
6400 * create the panel (without computing the PCA)
6402 PCAPanel panel = new PCAPanel(ap, modelName, params);
6404 panel.setTitle(viewer.getTitle());
6405 panel.setBounds(new Rectangle(viewer.getXpos(), viewer.getYpos(),
6406 viewer.getWidth(), viewer.getHeight()));
6408 boolean showLabels = viewer.isShowLabels();
6409 panel.setShowLabels(showLabels);
6410 panel.getRotatableCanvas().setShowLabels(showLabels);
6411 panel.getRotatableCanvas()
6412 .setBgColour(new Color(viewer.getBgColour()));
6413 panel.getRotatableCanvas()
6414 .setApplyToAllViews(viewer.isLinkToAllViews());
6417 * load PCA output data
6419 ScoreModelI scoreModel = ScoreModels.getInstance()
6420 .getScoreModel(modelName, ap);
6421 PCA pca = new PCA(null, scoreModel, params);
6422 PcaDataType pcaData = viewer.getPcaData();
6424 MatrixI pairwise = loadDoubleMatrix(pcaData.getPairwiseMatrix());
6425 pca.setPairwiseScores(pairwise);
6427 MatrixI triDiag = loadDoubleMatrix(pcaData.getTridiagonalMatrix());
6428 pca.setTridiagonal(triDiag);
6430 MatrixI result = loadDoubleMatrix(pcaData.getEigenMatrix());
6431 pca.setEigenmatrix(result);
6433 panel.getPcaModel().setPCA(pca);
6436 * we haven't saved the input data! (JAL-2647 to do)
6438 panel.setInputData(null);
6441 * add the sequence points for the PCA display
6443 List<jalview.datamodel.SequencePoint> seqPoints = new ArrayList<>();
6444 for (SequencePoint sp : viewer.getSequencePoint())
6446 String seqId = sp.getSequenceRef();
6447 SequenceI seq = seqRefIds.get(seqId);
6450 throw new IllegalStateException(
6451 "Unmatched seqref for PCA: " + seqId);
6453 Point pt = new Point(sp.getXPos(), sp.getYPos(), sp.getZPos());
6454 jalview.datamodel.SequencePoint seqPoint = new jalview.datamodel.SequencePoint(
6456 seqPoints.add(seqPoint);
6458 panel.getRotatableCanvas().setPoints(seqPoints, seqPoints.size());
6461 * set min-max ranges and scale after setPoints (which recomputes them)
6463 panel.getRotatableCanvas().setScaleFactor(viewer.getScaleFactor());
6464 SeqPointMin spMin = viewer.getSeqPointMin();
6465 float[] min = new float[] { spMin.getXPos(), spMin.getYPos(),
6467 SeqPointMax spMax = viewer.getSeqPointMax();
6468 float[] max = new float[] { spMax.getXPos(), spMax.getYPos(),
6470 panel.getRotatableCanvas().setSeqMinMax(min, max);
6472 // todo: hold points list in PCAModel only
6473 panel.getPcaModel().setSequencePoints(seqPoints);
6475 panel.setSelectedDimensionIndex(viewer.getXDim(), X);
6476 panel.setSelectedDimensionIndex(viewer.getYDim(), Y);
6477 panel.setSelectedDimensionIndex(viewer.getZDim(), Z);
6479 // is this duplication needed?
6480 panel.setTop(seqPoints.size() - 1);
6481 panel.getPcaModel().setTop(seqPoints.size() - 1);
6484 * add the axes' end points for the display
6486 for (int i = 0; i < 3; i++)
6488 Axis axis = viewer.getAxis().get(i);
6489 panel.getRotatableCanvas().getAxisEndPoints()[i] = new Point(
6490 axis.getXPos(), axis.getYPos(), axis.getZPos());
6493 Dimension dim = Platform.getDimIfEmbedded(panel, 475, 450);
6494 Desktop.addInternalFrame(panel, MessageManager.formatMessage(
6495 "label.calc_title", "PCA", modelName), dim.width,
6498 } catch (Exception ex)
6500 Cache.log.error("Error loading PCA: " + ex.toString());
6505 * Populates an XML model of the feature colour scheme for one feature type
6507 * @param featureType
6511 public static Colour marshalColour(
6512 String featureType, FeatureColourI fcol)
6514 Colour col = new Colour();
6515 if (fcol.isSimpleColour())
6517 col.setRGB(Format.getHexString(fcol.getColour()));
6521 col.setRGB(Format.getHexString(fcol.getMaxColour()));
6522 col.setMin(fcol.getMin());
6523 col.setMax(fcol.getMax());
6524 col.setMinRGB(jalview.util.Format.getHexString(fcol.getMinColour()));
6525 col.setAutoScale(fcol.isAutoScaled());
6526 col.setThreshold(fcol.getThreshold());
6527 col.setColourByLabel(fcol.isColourByLabel());
6528 col.setThreshType(fcol.isAboveThreshold() ? ThresholdType.ABOVE
6529 : (fcol.isBelowThreshold() ? ThresholdType.BELOW
6530 : ThresholdType.NONE));
6531 if (fcol.isColourByAttribute())
6533 final String[] attName = fcol.getAttributeName();
6534 col.getAttributeName().add(attName[0]);
6535 if (attName.length > 1)
6537 col.getAttributeName().add(attName[1]);
6540 Color noColour = fcol.getNoColour();
6541 if (noColour == null)
6543 col.setNoValueColour(NoValueColour.NONE);
6545 else if (noColour == fcol.getMaxColour())
6547 col.setNoValueColour(NoValueColour.MAX);
6551 col.setNoValueColour(NoValueColour.MIN);
6554 col.setName(featureType);
6559 * Populates an XML model of the feature filter(s) for one feature type
6561 * @param firstMatcher
6562 * the first (or only) match condition)
6564 * remaining match conditions (if any)
6566 * if true, conditions are and-ed, else or-ed
6568 public static jalview.xml.binding.jalview.FeatureMatcherSet marshalFilter(
6569 FeatureMatcherI firstMatcher, Iterator<FeatureMatcherI> filters,
6572 jalview.xml.binding.jalview.FeatureMatcherSet result = new jalview.xml.binding.jalview.FeatureMatcherSet();
6574 if (filters.hasNext())
6579 CompoundMatcher compound = new CompoundMatcher();
6580 compound.setAnd(and);
6581 jalview.xml.binding.jalview.FeatureMatcherSet matcher1 = marshalFilter(
6582 firstMatcher, Collections.emptyIterator(), and);
6583 // compound.addMatcherSet(matcher1);
6584 compound.getMatcherSet().add(matcher1);
6585 FeatureMatcherI nextMatcher = filters.next();
6586 jalview.xml.binding.jalview.FeatureMatcherSet matcher2 = marshalFilter(
6587 nextMatcher, filters, and);
6588 // compound.addMatcherSet(matcher2);
6589 compound.getMatcherSet().add(matcher2);
6590 result.setCompoundMatcher(compound);
6595 * single condition matcher
6597 // MatchCondition matcherModel = new MatchCondition();
6598 jalview.xml.binding.jalview.FeatureMatcher matcherModel = new jalview.xml.binding.jalview.FeatureMatcher();
6599 matcherModel.setCondition(
6600 firstMatcher.getMatcher().getCondition().getStableName());
6601 matcherModel.setValue(firstMatcher.getMatcher().getPattern());
6602 if (firstMatcher.isByAttribute())
6604 matcherModel.setBy(FilterBy.BY_ATTRIBUTE);
6605 // matcherModel.setAttributeName(firstMatcher.getAttribute());
6606 String[] attName = firstMatcher.getAttribute();
6607 matcherModel.getAttributeName().add(attName[0]); // attribute
6608 if (attName.length > 1)
6610 matcherModel.getAttributeName().add(attName[1]); // sub-attribute
6613 else if (firstMatcher.isByLabel())
6615 matcherModel.setBy(FilterBy.BY_LABEL);
6617 else if (firstMatcher.isByScore())
6619 matcherModel.setBy(FilterBy.BY_SCORE);
6621 result.setMatchCondition(matcherModel);
6628 * Loads one XML model of a feature filter to a Jalview object
6630 * @param featureType
6631 * @param matcherSetModel
6634 public static FeatureMatcherSetI parseFilter(
6636 jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel)
6638 FeatureMatcherSetI result = new FeatureMatcherSet();
6641 parseFilterConditions(result, matcherSetModel, true);
6642 } catch (IllegalStateException e)
6644 // mixing AND and OR conditions perhaps
6646 String.format("Error reading filter conditions for '%s': %s",
6647 featureType, e.getMessage()));
6648 // return as much as was parsed up to the error
6655 * Adds feature match conditions to matcherSet as unmarshalled from XML
6656 * (possibly recursively for compound conditions)
6659 * @param matcherSetModel
6661 * if true, multiple conditions are AND-ed, else they are OR-ed
6662 * @throws IllegalStateException
6663 * if AND and OR conditions are mixed
6665 protected static void parseFilterConditions(
6666 FeatureMatcherSetI matcherSet,
6667 jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel,
6670 jalview.xml.binding.jalview.FeatureMatcher mc = matcherSetModel
6671 .getMatchCondition();
6677 FilterBy filterBy = mc.getBy();
6678 Condition cond = Condition.fromString(mc.getCondition());
6679 String pattern = mc.getValue();
6680 FeatureMatcherI matchCondition = null;
6681 if (filterBy == FilterBy.BY_LABEL)
6683 matchCondition = FeatureMatcher.byLabel(cond, pattern);
6685 else if (filterBy == FilterBy.BY_SCORE)
6687 matchCondition = FeatureMatcher.byScore(cond, pattern);
6690 else if (filterBy == FilterBy.BY_ATTRIBUTE)
6692 final List<String> attributeName = mc.getAttributeName();
6693 String[] attNames = attributeName
6694 .toArray(new String[attributeName.size()]);
6695 matchCondition = FeatureMatcher.byAttribute(cond, pattern,
6700 * note this throws IllegalStateException if AND-ing to a
6701 * previously OR-ed compound condition, or vice versa
6705 matcherSet.and(matchCondition);
6709 matcherSet.or(matchCondition);
6715 * compound condition
6717 List<jalview.xml.binding.jalview.FeatureMatcherSet> matchers = matcherSetModel
6718 .getCompoundMatcher().getMatcherSet();
6719 boolean anded = matcherSetModel.getCompoundMatcher().isAnd();
6720 if (matchers.size() == 2)
6722 parseFilterConditions(matcherSet, matchers.get(0), anded);
6723 parseFilterConditions(matcherSet, matchers.get(1), anded);
6727 System.err.println("Malformed compound filter condition");
6733 * Loads one XML model of a feature colour to a Jalview object
6735 * @param colourModel
6738 public static FeatureColourI parseColour(Colour colourModel)
6740 FeatureColourI colour = null;
6742 if (colourModel.getMax() != null)
6744 Color mincol = null;
6745 Color maxcol = null;
6746 Color noValueColour = null;
6750 mincol = new Color(Integer.parseInt(colourModel.getMinRGB(), 16));
6751 maxcol = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6752 } catch (Exception e)
6754 Cache.log.warn("Couldn't parse out graduated feature color.", e);
6757 NoValueColour noCol = colourModel.getNoValueColour();
6758 if (noCol == NoValueColour.MIN)
6760 noValueColour = mincol;
6762 else if (noCol == NoValueColour.MAX)
6764 noValueColour = maxcol;
6767 colour = new FeatureColour(maxcol, mincol, maxcol, noValueColour,
6768 safeFloat(colourModel.getMin()),
6769 safeFloat(colourModel.getMax()));
6770 final List<String> attributeName = colourModel.getAttributeName();
6771 String[] attributes = attributeName
6772 .toArray(new String[attributeName.size()]);
6773 if (attributes != null && attributes.length > 0)
6775 colour.setAttributeName(attributes);
6777 if (colourModel.isAutoScale() != null)
6779 colour.setAutoScaled(colourModel.isAutoScale().booleanValue());
6781 if (colourModel.isColourByLabel() != null)
6783 colour.setColourByLabel(
6784 colourModel.isColourByLabel().booleanValue());
6786 if (colourModel.getThreshold() != null)
6788 colour.setThreshold(colourModel.getThreshold().floatValue());
6790 ThresholdType ttyp = colourModel.getThreshType();
6791 if (ttyp == ThresholdType.ABOVE)
6793 colour.setAboveThreshold(true);
6795 else if (ttyp == ThresholdType.BELOW)
6797 colour.setBelowThreshold(true);
6802 Color color = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6803 colour = new FeatureColour(color);