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.GraphLine;
44 import jalview.datamodel.PDBEntry;
45 import jalview.datamodel.Point;
46 import jalview.datamodel.RnaViewerModel;
47 import jalview.datamodel.SequenceFeature;
48 import jalview.datamodel.SequenceGroup;
49 import jalview.datamodel.SequenceI;
50 import jalview.datamodel.StructureViewerModel;
51 import jalview.datamodel.StructureViewerModel.StructureData;
52 import jalview.datamodel.features.FeatureMatcher;
53 import jalview.datamodel.features.FeatureMatcherI;
54 import jalview.datamodel.features.FeatureMatcherSet;
55 import jalview.datamodel.features.FeatureMatcherSetI;
56 import jalview.ext.varna.RnaModel;
57 import jalview.gui.AlignFrame;
58 import jalview.gui.AlignViewport;
59 import jalview.gui.AlignmentPanel;
60 import jalview.gui.AppVarna;
61 import jalview.gui.ChimeraViewFrame;
62 import jalview.gui.Desktop;
63 import jalview.gui.FeatureRenderer;
64 import jalview.gui.JvOptionPane;
65 import jalview.gui.OOMWarning;
66 import jalview.gui.PCAPanel;
67 import jalview.gui.PaintRefresher;
68 import jalview.gui.SplitFrame;
69 import jalview.gui.StructureViewer;
70 import jalview.gui.StructureViewer.ViewerType;
71 import jalview.gui.StructureViewerBase;
72 import jalview.gui.TreePanel;
73 import jalview.io.BackupFiles;
74 import jalview.io.DataSourceType;
75 import jalview.io.FileFormat;
76 import jalview.io.NewickFile;
77 import jalview.math.Matrix;
78 import jalview.math.MatrixI;
79 import jalview.renderer.ResidueShaderI;
80 import jalview.schemes.AnnotationColourGradient;
81 import jalview.schemes.ColourSchemeI;
82 import jalview.schemes.ColourSchemeProperty;
83 import jalview.schemes.FeatureColour;
84 import jalview.schemes.ResidueProperties;
85 import jalview.schemes.UserColourScheme;
86 import jalview.structures.models.AAStructureBindingModel;
87 import jalview.util.Format;
88 import jalview.util.MessageManager;
89 import jalview.util.Platform;
90 import jalview.util.StringUtils;
91 import jalview.util.jarInputStreamProvider;
92 import jalview.util.matcher.Condition;
93 import jalview.viewmodel.AlignmentViewport;
94 import jalview.viewmodel.PCAModel;
95 import jalview.viewmodel.ViewportRanges;
96 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
97 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
98 import jalview.ws.jws2.Jws2Discoverer;
99 import jalview.ws.jws2.dm.AAConSettings;
100 import jalview.ws.jws2.jabaws2.Jws2Instance;
101 import jalview.ws.params.ArgumentI;
102 import jalview.ws.params.AutoCalcSetting;
103 import jalview.ws.params.WsParamSetI;
104 import jalview.xml.binding.jalview.AlcodonFrame;
105 import jalview.xml.binding.jalview.AlcodonFrame.AlcodMap;
106 import jalview.xml.binding.jalview.Annotation;
107 import jalview.xml.binding.jalview.Annotation.ThresholdLine;
108 import jalview.xml.binding.jalview.AnnotationColourScheme;
109 import jalview.xml.binding.jalview.AnnotationElement;
110 import jalview.xml.binding.jalview.DoubleMatrix;
111 import jalview.xml.binding.jalview.DoubleVector;
112 import jalview.xml.binding.jalview.Feature;
113 import jalview.xml.binding.jalview.Feature.OtherData;
114 import jalview.xml.binding.jalview.FeatureMatcherSet.CompoundMatcher;
115 import jalview.xml.binding.jalview.FilterBy;
116 import jalview.xml.binding.jalview.JalviewModel;
117 import jalview.xml.binding.jalview.JalviewModel.FeatureSettings;
118 import jalview.xml.binding.jalview.JalviewModel.FeatureSettings.Group;
119 import jalview.xml.binding.jalview.JalviewModel.FeatureSettings.Setting;
120 import jalview.xml.binding.jalview.JalviewModel.JGroup;
121 import jalview.xml.binding.jalview.JalviewModel.JSeq;
122 import jalview.xml.binding.jalview.JalviewModel.JSeq.Pdbids;
123 import jalview.xml.binding.jalview.JalviewModel.JSeq.Pdbids.StructureState;
124 import jalview.xml.binding.jalview.JalviewModel.JSeq.RnaViewer;
125 import jalview.xml.binding.jalview.JalviewModel.JSeq.RnaViewer.SecondaryStructure;
126 import jalview.xml.binding.jalview.JalviewModel.PcaViewer;
127 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.Axis;
128 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.SeqPointMax;
129 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.SeqPointMin;
130 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.SequencePoint;
131 import jalview.xml.binding.jalview.JalviewModel.Tree;
132 import jalview.xml.binding.jalview.JalviewModel.UserColours;
133 import jalview.xml.binding.jalview.JalviewModel.Viewport;
134 import jalview.xml.binding.jalview.JalviewModel.Viewport.CalcIdParam;
135 import jalview.xml.binding.jalview.JalviewModel.Viewport.HiddenColumns;
136 import jalview.xml.binding.jalview.JalviewUserColours;
137 import jalview.xml.binding.jalview.JalviewUserColours.Colour;
138 import jalview.xml.binding.jalview.MapListType.MapListFrom;
139 import jalview.xml.binding.jalview.MapListType.MapListTo;
140 import jalview.xml.binding.jalview.Mapping;
141 import jalview.xml.binding.jalview.NoValueColour;
142 import jalview.xml.binding.jalview.ObjectFactory;
143 import jalview.xml.binding.jalview.PcaDataType;
144 import jalview.xml.binding.jalview.Pdbentry.Property;
145 import jalview.xml.binding.jalview.Sequence;
146 import jalview.xml.binding.jalview.Sequence.DBRef;
147 import jalview.xml.binding.jalview.SequenceSet;
148 import jalview.xml.binding.jalview.SequenceSet.SequenceSetProperties;
149 import jalview.xml.binding.jalview.ThresholdType;
150 import jalview.xml.binding.jalview.VAMSAS;
152 import java.awt.Color;
153 import java.awt.Font;
154 import java.awt.Rectangle;
155 import java.io.BufferedReader;
156 import java.io.ByteArrayInputStream;
157 import java.io.DataInputStream;
158 import java.io.DataOutputStream;
160 import java.io.FileInputStream;
161 import java.io.FileOutputStream;
162 import java.io.IOException;
163 import java.io.InputStreamReader;
164 import java.io.OutputStreamWriter;
165 import java.io.PrintWriter;
166 import java.math.BigInteger;
167 import java.net.MalformedURLException;
169 import java.util.ArrayList;
170 import java.util.Arrays;
171 import java.util.Collections;
172 import java.util.Enumeration;
173 import java.util.GregorianCalendar;
174 import java.util.HashMap;
175 import java.util.HashSet;
176 import java.util.Hashtable;
177 import java.util.IdentityHashMap;
178 import java.util.Iterator;
179 import java.util.LinkedHashMap;
180 import java.util.List;
181 import java.util.Map;
182 import java.util.Map.Entry;
183 import java.util.Set;
184 import java.util.Vector;
185 import java.util.jar.JarEntry;
186 import java.util.jar.JarInputStream;
187 import java.util.jar.JarOutputStream;
189 import javax.swing.JInternalFrame;
190 import javax.swing.SwingUtilities;
191 import javax.xml.bind.JAXBContext;
192 import javax.xml.bind.JAXBElement;
193 import javax.xml.bind.Marshaller;
194 import javax.xml.datatype.DatatypeConfigurationException;
195 import javax.xml.datatype.DatatypeFactory;
196 import javax.xml.datatype.XMLGregorianCalendar;
197 import javax.xml.stream.XMLInputFactory;
198 import javax.xml.stream.XMLStreamReader;
201 * Write out the current jalview desktop state as a Jalview XML stream.
203 * Note: the vamsas objects referred to here are primitive versions of the
204 * VAMSAS project schema elements - they are not the same and most likely never
208 * @version $Revision: 1.134 $
210 public class Jalview2XML
213 // BH 2018 we add the .jvp binary extension to J2S so that
214 // it will declare that binary when we do the file save from the browser
218 Platform.addJ2SBinaryType(".jvp?");
221 private static final String VIEWER_PREFIX = "viewer_";
223 private static final String RNA_PREFIX = "rna_";
225 private static final String UTF_8 = "UTF-8";
228 * prefix for recovering datasets for alignments with multiple views where
229 * non-existent dataset IDs were written for some views
231 private static final String UNIQSEQSETID = "uniqueSeqSetId.";
233 // use this with nextCounter() to make unique names for entities
234 private int counter = 0;
237 * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
238 * of sequence objects are created.
240 IdentityHashMap<SequenceI, String> seqsToIds = null;
243 * jalview XML Sequence ID to jalview sequence object reference (both dataset
244 * and alignment sequences. Populated as XML reps of sequence objects are
247 Map<String, SequenceI> seqRefIds = null;
249 Map<String, SequenceI> incompleteSeqs = null;
251 List<SeqFref> frefedSequence = null;
253 boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
256 * Map of reconstructed AlignFrame objects that appear to have come from
257 * SplitFrame objects (have a dna/protein complement view).
259 private Map<Viewport, AlignFrame> splitFrameCandidates = new HashMap<>();
262 * Map from displayed rna structure models to their saved session state jar
265 private Map<RnaModel, String> rnaSessions = new HashMap<>();
268 * A helper method for safely using the value of an optional attribute that
269 * may be null if not present in the XML. Answers the boolean value, or false
275 public static boolean safeBoolean(Boolean b)
277 return b == null ? false : b.booleanValue();
281 * A helper method for safely using the value of an optional attribute that
282 * may be null if not present in the XML. Answers the integer value, or zero
288 public static int safeInt(Integer i)
290 return i == null ? 0 : i.intValue();
294 * A helper method for safely using the value of an optional attribute that
295 * may be null if not present in the XML. Answers the float value, or zero if
301 public static float safeFloat(Float f)
303 return f == null ? 0f : f.floatValue();
307 * create/return unique hash string for sq
310 * @return new or existing unique string for sq
312 String seqHash(SequenceI sq)
314 if (seqsToIds == null)
318 if (seqsToIds.containsKey(sq))
320 return seqsToIds.get(sq);
324 // create sequential key
325 String key = "sq" + (seqsToIds.size() + 1);
326 key = makeHashCode(sq, key); // check we don't have an external reference
328 seqsToIds.put(sq, key);
335 if (seqsToIds == null)
337 seqsToIds = new IdentityHashMap<>();
339 if (seqRefIds == null)
341 seqRefIds = new HashMap<>();
343 if (incompleteSeqs == null)
345 incompleteSeqs = new HashMap<>();
347 if (frefedSequence == null)
349 frefedSequence = new ArrayList<>();
357 public Jalview2XML(boolean raiseGUI)
359 this.raiseGUI = raiseGUI;
363 * base class for resolving forward references to sequences by their ID
368 abstract class SeqFref
374 public SeqFref(String _sref, String type)
380 public String getSref()
385 public SequenceI getSrefSeq()
387 return seqRefIds.get(sref);
390 public boolean isResolvable()
392 return seqRefIds.get(sref) != null;
395 public SequenceI getSrefDatasetSeq()
397 SequenceI sq = seqRefIds.get(sref);
400 while (sq.getDatasetSequence() != null)
402 sq = sq.getDatasetSequence();
409 * @return true if the forward reference was fully resolved
411 abstract boolean resolve();
414 public String toString()
416 return type + " reference to " + sref;
421 * create forward reference for a mapping
427 public SeqFref newMappingRef(final String sref,
428 final jalview.datamodel.Mapping _jmap)
430 SeqFref fref = new SeqFref(sref, "Mapping")
432 public jalview.datamodel.Mapping jmap = _jmap;
437 SequenceI seq = getSrefDatasetSeq();
449 public SeqFref newAlcodMapRef(final String sref,
450 final AlignedCodonFrame _cf,
451 final jalview.datamodel.Mapping _jmap)
454 SeqFref fref = new SeqFref(sref, "Codon Frame")
456 AlignedCodonFrame cf = _cf;
458 public jalview.datamodel.Mapping mp = _jmap;
461 public boolean isResolvable()
463 return super.isResolvable() && mp.getTo() != null;
469 SequenceI seq = getSrefDatasetSeq();
474 cf.addMap(seq, mp.getTo(), mp.getMap());
481 public void resolveFrefedSequences()
483 Iterator<SeqFref> nextFref = frefedSequence.iterator();
484 int toresolve = frefedSequence.size();
485 int unresolved = 0, failedtoresolve = 0;
486 while (nextFref.hasNext())
488 SeqFref ref = nextFref.next();
489 if (ref.isResolvable())
501 } catch (Exception x)
504 "IMPLEMENTATION ERROR: Failed to resolve forward reference for sequence "
517 System.err.println("Jalview Project Import: There were " + unresolved
518 + " forward references left unresolved on the stack.");
520 if (failedtoresolve > 0)
522 System.err.println("SERIOUS! " + failedtoresolve
523 + " resolvable forward references failed to resolve.");
525 if (incompleteSeqs != null && incompleteSeqs.size() > 0)
528 "Jalview Project Import: There are " + incompleteSeqs.size()
529 + " sequences which may have incomplete metadata.");
530 if (incompleteSeqs.size() < 10)
532 for (SequenceI s : incompleteSeqs.values())
534 System.err.println(s.toString());
540 "Too many to report. Skipping output of incomplete sequences.");
546 * This maintains a map of viewports, the key being the seqSetId. Important to
547 * set historyItem and redoList for multiple views
549 Map<String, AlignViewport> viewportsAdded = new HashMap<>();
551 Map<String, AlignmentAnnotation> annotationIds = new HashMap<>();
553 String uniqueSetSuffix = "";
556 * List of pdbfiles added to Jar
558 List<String> pdbfiles = null;
560 // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
561 public void saveState(File statefile)
563 FileOutputStream fos = null;
568 fos = new FileOutputStream(statefile);
570 JarOutputStream jout = new JarOutputStream(fos);
574 } catch (Exception e)
576 Cache.log.error("Couln't write Jalview state to " + statefile, e);
577 // TODO: inform user of the problem - they need to know if their data was
579 if (errorMessage == null)
581 errorMessage = "Did't write Jalview Archive to output file '"
582 + statefile + "' - See console error log for details";
586 errorMessage += "(Didn't write Jalview Archive to output file '"
597 } catch (IOException e)
607 * Writes a jalview project archive to the given Jar output stream.
611 public void saveState(JarOutputStream jout)
613 AlignFrame[] frames = Desktop.getAlignFrames();
619 saveAllFrames(Arrays.asList(frames), jout);
623 * core method for storing state for a set of AlignFrames.
626 * - frames involving all data to be exported (including those
627 * contained in splitframes, though not the split frames themselves)
629 * - project output stream
631 private void saveAllFrames(List<AlignFrame> frames, JarOutputStream jout)
634 Hashtable<String, AlignFrame> dsses = new Hashtable<>();
637 * ensure cached data is clear before starting
639 // todo tidy up seqRefIds, seqsToIds initialisation / reset
641 splitFrameCandidates.clear();
646 // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
647 // //////////////////////////////////////////////////
649 List<String> shortNames = new ArrayList<>();
650 List<String> viewIds = new ArrayList<>();
653 for (int i = frames.size() - 1; i > -1; i--)
655 AlignFrame af = frames.get(i);
656 AlignViewport vp = af.getViewport();
658 if (skipList != null && skipList
659 .containsKey(vp.getSequenceSetId()))
664 String shortName = makeFilename(af, shortNames);
666 AlignmentI alignment = vp.getAlignment();
667 List<? extends AlignmentViewPanel> panels = af.getAlignPanels();
668 int apSize = panels.size();
669 for (int ap = 0; ap < apSize; ap++)
671 AlignmentPanel apanel = (AlignmentPanel) panels.get(ap);
672 String fileName = apSize == 1 ? shortName : ap + shortName;
673 if (!fileName.endsWith(".xml"))
675 fileName = fileName + ".xml";
678 saveState(apanel, fileName, jout, viewIds);
682 // BH moved next bit out of inner loop, not that it really matters.
683 // so we are testing to make sure we actually have an alignment,
685 String dssid = getDatasetIdRef(alignment.getDataset());
686 if (!dsses.containsKey(dssid))
688 // We have not already covered this data by reference from another
690 dsses.put(dssid, af);
695 writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix,
701 } catch (Exception foo)
705 } catch (Exception ex)
707 // TODO: inform user of the problem - they need to know if their data was
709 if (errorMessage == null)
711 errorMessage = "Couldn't write Jalview Archive - see error output for details";
713 ex.printStackTrace();
718 * Generates a distinct file name, based on the title of the AlignFrame, by
719 * appending _n for increasing n until an unused name is generated. The new
720 * name (without its extension) is added to the list.
724 * @return the generated name, with .xml extension
726 protected String makeFilename(AlignFrame af, List<String> namesUsed)
728 String shortName = af.getTitle();
730 if (shortName.indexOf(File.separatorChar) > -1)
732 shortName = shortName
733 .substring(shortName.lastIndexOf(File.separatorChar) + 1);
738 while (namesUsed.contains(shortName))
740 if (shortName.endsWith("_" + (count - 1)))
742 shortName = shortName.substring(0, shortName.lastIndexOf("_"));
745 shortName = shortName.concat("_" + count);
749 namesUsed.add(shortName);
751 if (!shortName.endsWith(".xml"))
753 shortName = shortName + ".xml";
758 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
759 public boolean saveAlignment(AlignFrame af, String jarFile,
764 // create backupfiles object and get new temp filename destination
765 boolean doBackup = BackupFiles.getEnabled();
766 BackupFiles backupfiles = doBackup ? new BackupFiles(jarFile) : null;
767 FileOutputStream fos = new FileOutputStream(doBackup ?
768 backupfiles.getTempFilePath() : jarFile);
770 JarOutputStream jout = new JarOutputStream(fos);
771 List<AlignFrame> frames = new ArrayList<>();
773 // resolve splitframes
774 if (af.getViewport().getCodingComplement() != null)
776 frames = ((SplitFrame) af.getSplitViewContainer()).getAlignFrames();
782 saveAllFrames(frames, jout);
786 } catch (Exception foo)
790 boolean success = true;
794 backupfiles.setWriteSuccess(success);
795 success = backupfiles.rollBackupsAndRenameTempFile();
799 } catch (Exception ex)
801 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
802 ex.printStackTrace();
808 * Each AlignFrame has a single data set associated with it. Note that none of
809 * these frames are split frames, because Desktop.getAlignFrames() collects
810 * top and bottom separately here.
816 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
817 String fileName, JarOutputStream jout)
820 // Note that in saveAllFrames we have associated each specific dataset to
821 // ONE of its associated frames.
823 for (String dssids : dsses.keySet())
825 AlignFrame _af = dsses.get(dssids);
826 String jfileName = fileName + " Dataset for " + _af.getTitle();
827 if (!jfileName.endsWith(".xml"))
829 jfileName = jfileName + ".xml";
831 saveState(_af.alignPanel, jfileName, true, jout, null);
836 * create a JalviewModel from an alignment view and marshall it to a
840 * panel to create jalview model for
842 * name of alignment panel written to output stream
849 public JalviewModel saveState(AlignmentPanel ap, String fileName,
850 JarOutputStream jout, List<String> viewIds)
852 return saveState(ap, fileName, false, jout, viewIds);
856 * create a JalviewModel from an alignment view and marshall it to a
860 * panel to create jalview model for
862 * name of alignment panel written to output stream
864 * when true, only write the dataset for the alignment, not the data
865 * associated with the view.
871 public JalviewModel saveState(AlignmentPanel ap, String fileName,
872 boolean storeDS, JarOutputStream jout, List<String> viewIds)
876 viewIds = new ArrayList<>();
881 List<UserColourScheme> userColours = new ArrayList<>();
883 AlignViewport av = ap.av;
884 ViewportRanges vpRanges = av.getRanges();
886 final ObjectFactory objectFactory = new ObjectFactory();
887 JalviewModel object = objectFactory.createJalviewModel();
888 object.setVamsasModel(new VAMSAS());
890 // object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
893 GregorianCalendar c = new GregorianCalendar();
894 DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
895 XMLGregorianCalendar now = datatypeFactory.newXMLGregorianCalendar(c);// gregorianCalendar);
896 object.setCreationDate(now);
897 } catch (DatatypeConfigurationException e)
899 System.err.println("error writing date: " + e.toString());
902 jalview.bin.Cache.getDefault("VERSION", "Development Build"));
905 * rjal is full height alignment, jal is actual alignment with full metadata
906 * but excludes hidden sequences.
908 jalview.datamodel.AlignmentI rjal = av.getAlignment(), jal = rjal;
910 if (av.hasHiddenRows())
912 rjal = jal.getHiddenSequences().getFullAlignment();
915 SequenceSet vamsasSet = new SequenceSet();
917 // JalviewModelSequence jms = new JalviewModelSequence();
919 vamsasSet.setGapChar(jal.getGapCharacter() + "");
921 if (jal.getDataset() != null)
923 // dataset id is the dataset's hashcode
924 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
927 // switch jal and the dataset
928 jal = jal.getDataset();
932 if (jal.getProperties() != null)
934 Enumeration en = jal.getProperties().keys();
935 while (en.hasMoreElements())
937 String key = en.nextElement().toString();
938 SequenceSetProperties ssp = new SequenceSetProperties();
940 ssp.setValue(jal.getProperties().get(key).toString());
941 // vamsasSet.addSequenceSetProperties(ssp);
942 vamsasSet.getSequenceSetProperties().add(ssp);
947 Set<String> calcIdSet = new HashSet<>();
948 // record the set of vamsas sequence XML POJO we create.
949 HashMap<String, Sequence> vamsasSetIds = new HashMap<>();
951 for (final SequenceI jds : rjal.getSequences())
953 final SequenceI jdatasq = jds.getDatasetSequence() == null ? jds
954 : jds.getDatasetSequence();
955 String id = seqHash(jds);
956 if (vamsasSetIds.get(id) == null)
958 if (seqRefIds.get(id) != null && !storeDS)
960 // This happens for two reasons: 1. multiple views are being
962 // 2. the hashCode has collided with another sequence's code. This
964 // HAPPEN! (PF00072.15.stk does this)
965 // JBPNote: Uncomment to debug writing out of files that do not read
966 // back in due to ArrayOutOfBoundExceptions.
967 // System.err.println("vamsasSeq backref: "+id+"");
968 // System.err.println(jds.getName()+"
969 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
970 // System.err.println("Hashcode: "+seqHash(jds));
971 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
972 // System.err.println(rsq.getName()+"
973 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
974 // System.err.println("Hashcode: "+seqHash(rsq));
978 vamsasSeq = createVamsasSequence(id, jds);
979 // vamsasSet.addSequence(vamsasSeq);
980 vamsasSet.getSequence().add(vamsasSeq);
981 vamsasSetIds.put(id, vamsasSeq);
982 seqRefIds.put(id, jds);
986 jseq.setStart(jds.getStart());
987 jseq.setEnd(jds.getEnd());
988 jseq.setColour(av.getSequenceColour(jds).getRGB());
990 jseq.setId(id); // jseq id should be a string not a number
993 // Store any sequences this sequence represents
994 if (av.hasHiddenRows())
996 // use rjal, contains the full height alignment
998 av.getAlignment().getHiddenSequences().isHidden(jds));
1000 if (av.isHiddenRepSequence(jds))
1002 jalview.datamodel.SequenceI[] reps = av
1003 .getRepresentedSequences(jds).getSequencesInOrder(rjal);
1005 for (int h = 0; h < reps.length; h++)
1009 // jseq.addHiddenSequences(rjal.findIndex(reps[h]));
1010 jseq.getHiddenSequences().add(rjal.findIndex(reps[h]));
1015 // mark sequence as reference - if it is the reference for this view
1016 if (jal.hasSeqrep())
1018 jseq.setViewreference(jds == jal.getSeqrep());
1022 // TODO: omit sequence features from each alignment view's XML dump if we
1023 // are storing dataset
1024 List<SequenceFeature> sfs = jds.getSequenceFeatures();
1025 for (SequenceFeature sf : sfs)
1027 // Features features = new Features();
1028 Feature features = new Feature();
1030 features.setBegin(sf.getBegin());
1031 features.setEnd(sf.getEnd());
1032 features.setDescription(sf.getDescription());
1033 features.setType(sf.getType());
1034 features.setFeatureGroup(sf.getFeatureGroup());
1035 features.setScore(sf.getScore());
1036 if (sf.links != null)
1038 for (int l = 0; l < sf.links.size(); l++)
1040 OtherData keyValue = new OtherData();
1041 keyValue.setKey("LINK_" + l);
1042 keyValue.setValue(sf.links.elementAt(l).toString());
1043 // features.addOtherData(keyValue);
1044 features.getOtherData().add(keyValue);
1047 if (sf.otherDetails != null)
1050 * save feature attributes, which may be simple strings or
1051 * map valued (have sub-attributes)
1053 for (Entry<String, Object> entry : sf.otherDetails.entrySet())
1055 String key = entry.getKey();
1056 Object value = entry.getValue();
1057 if (value instanceof Map<?, ?>)
1059 for (Entry<String, Object> subAttribute : ((Map<String, Object>) value)
1062 OtherData otherData = new OtherData();
1063 otherData.setKey(key);
1064 otherData.setKey2(subAttribute.getKey());
1065 otherData.setValue(subAttribute.getValue().toString());
1066 // features.addOtherData(otherData);
1067 features.getOtherData().add(otherData);
1072 OtherData otherData = new OtherData();
1073 otherData.setKey(key);
1074 otherData.setValue(value.toString());
1075 // features.addOtherData(otherData);
1076 features.getOtherData().add(otherData);
1081 // jseq.addFeatures(features);
1082 jseq.getFeatures().add(features);
1085 if (jdatasq.getAllPDBEntries() != null)
1087 Enumeration<PDBEntry> en = jdatasq.getAllPDBEntries().elements();
1088 while (en.hasMoreElements())
1090 Pdbids pdb = new Pdbids();
1091 jalview.datamodel.PDBEntry entry = en.nextElement();
1093 String pdbId = entry.getId();
1095 pdb.setType(entry.getType());
1098 * Store any structure views associated with this sequence. This
1099 * section copes with duplicate entries in the project, so a dataset
1100 * only view *should* be coped with sensibly.
1102 // This must have been loaded, is it still visible?
1103 JInternalFrame[] frames = Desktop.getDesktopPane().getAllFrames();
1104 String matchedFile = null;
1105 for (int f = frames.length - 1; f > -1; f--)
1107 if (frames[f] instanceof StructureViewerBase)
1109 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
1110 matchedFile = saveStructureState(ap, jds, pdb, entry, viewIds,
1111 matchedFile, viewFrame);
1113 * Only store each structure viewer's state once in the project
1114 * jar. First time through only (storeDS==false)
1116 String viewId = viewFrame.getViewId();
1117 if (!storeDS && !viewIds.contains(viewId))
1119 viewIds.add(viewId);
1122 String viewerState = viewFrame.getStateInfo();
1123 writeJarEntry(jout, getViewerJarEntryName(viewId),
1124 viewerState.getBytes());
1125 } catch (IOException e)
1128 "Error saving viewer state: " + e.getMessage());
1134 if (matchedFile != null || entry.getFile() != null)
1136 if (entry.getFile() != null)
1139 matchedFile = entry.getFile();
1141 pdb.setFile(matchedFile); // entry.getFile());
1142 if (pdbfiles == null)
1144 pdbfiles = new ArrayList<>();
1147 if (!pdbfiles.contains(pdbId))
1149 pdbfiles.add(pdbId);
1150 copyFileToJar(jout, matchedFile, pdbId);
1154 Enumeration<String> props = entry.getProperties();
1155 if (props.hasMoreElements())
1157 // PdbentryItem item = new PdbentryItem();
1158 while (props.hasMoreElements())
1160 Property prop = new Property();
1161 String key = props.nextElement();
1163 prop.setValue(entry.getProperty(key).toString());
1164 // item.addProperty(prop);
1165 pdb.getProperty().add(prop);
1167 // pdb.addPdbentryItem(item);
1170 // jseq.addPdbids(pdb);
1171 jseq.getPdbids().add(pdb);
1175 saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
1177 // jms.addJSeq(jseq);
1178 object.getJSeq().add(jseq);
1181 if (!storeDS && av.hasHiddenRows())
1183 jal = av.getAlignment();
1187 if (storeDS && jal.getCodonFrames() != null)
1189 List<AlignedCodonFrame> jac = jal.getCodonFrames();
1190 for (AlignedCodonFrame acf : jac)
1192 AlcodonFrame alc = new AlcodonFrame();
1193 if (acf.getProtMappings() != null
1194 && acf.getProtMappings().length > 0)
1196 boolean hasMap = false;
1197 SequenceI[] dnas = acf.getdnaSeqs();
1198 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1199 for (int m = 0; m < pmaps.length; m++)
1201 AlcodMap alcmap = new AlcodMap();
1202 alcmap.setDnasq(seqHash(dnas[m]));
1204 createVamsasMapping(pmaps[m], dnas[m], null, false));
1205 // alc.addAlcodMap(alcmap);
1206 alc.getAlcodMap().add(alcmap);
1211 // vamsasSet.addAlcodonFrame(alc);
1212 vamsasSet.getAlcodonFrame().add(alc);
1215 // TODO: delete this ? dead code from 2.8.3->2.9 ?
1217 // AlcodonFrame alc = new AlcodonFrame();
1218 // vamsasSet.addAlcodonFrame(alc);
1219 // for (int p = 0; p < acf.aaWidth; p++)
1221 // Alcodon cmap = new Alcodon();
1222 // if (acf.codons[p] != null)
1224 // // Null codons indicate a gapped column in the translated peptide
1226 // cmap.setPos1(acf.codons[p][0]);
1227 // cmap.setPos2(acf.codons[p][1]);
1228 // cmap.setPos3(acf.codons[p][2]);
1230 // alc.addAlcodon(cmap);
1232 // if (acf.getProtMappings() != null
1233 // && acf.getProtMappings().length > 0)
1235 // SequenceI[] dnas = acf.getdnaSeqs();
1236 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1237 // for (int m = 0; m < pmaps.length; m++)
1239 // AlcodMap alcmap = new AlcodMap();
1240 // alcmap.setDnasq(seqHash(dnas[m]));
1241 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
1243 // alc.addAlcodMap(alcmap);
1250 // /////////////////////////////////
1251 if (!storeDS && av.getCurrentTree() != null)
1253 // FIND ANY ASSOCIATED TREES
1254 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
1255 if (Desktop.getDesktopPane() != null)
1257 JInternalFrame[] frames = Desktop.getDesktopPane().getAllFrames();
1259 for (int t = 0; t < frames.length; t++)
1261 if (frames[t] instanceof TreePanel)
1263 TreePanel tp = (TreePanel) frames[t];
1265 if (tp.getTreeCanvas().getViewport().getAlignment() == jal)
1267 JalviewModel.Tree tree = new JalviewModel.Tree();
1268 tree.setTitle(tp.getTitle());
1269 tree.setCurrentTree((av.getCurrentTree() == tp.getTree()));
1270 tree.setNewick(tp.getTree().print());
1271 tree.setThreshold(tp.getTreeCanvas().getThreshold());
1273 tree.setFitToWindow(tp.fitToWindow.getState());
1274 tree.setFontName(tp.getTreeFont().getName());
1275 tree.setFontSize(tp.getTreeFont().getSize());
1276 tree.setFontStyle(tp.getTreeFont().getStyle());
1277 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
1279 tree.setShowBootstrap(tp.bootstrapMenu.getState());
1280 tree.setShowDistances(tp.distanceMenu.getState());
1282 tree.setHeight(tp.getHeight());
1283 tree.setWidth(tp.getWidth());
1284 tree.setXpos(tp.getX());
1285 tree.setYpos(tp.getY());
1286 tree.setId(makeHashCode(tp, null));
1287 tree.setLinkToAllViews(
1288 tp.getTreeCanvas().isApplyToAllViews());
1290 // jms.addTree(tree);
1291 object.getTree().add(tree);
1301 if (!storeDS && Desktop.getDesktopPane() != null)
1303 for (JInternalFrame frame : Desktop.getDesktopPane().getAllFrames())
1305 if (frame instanceof PCAPanel)
1307 PCAPanel panel = (PCAPanel) frame;
1308 if (panel.getAlignViewport().getAlignment() == jal)
1310 savePCA(panel, object);
1318 * store forward refs from an annotationRow to any groups
1320 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<>();
1323 for (SequenceI sq : jal.getSequences())
1325 // Store annotation on dataset sequences only
1326 AlignmentAnnotation[] aa = sq.getAnnotation();
1327 if (aa != null && aa.length > 0)
1329 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1336 if (jal.getAlignmentAnnotation() != null)
1338 // Store the annotation shown on the alignment.
1339 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1340 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1345 if (jal.getGroups() != null)
1347 JGroup[] groups = new JGroup[jal.getGroups().size()];
1349 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1351 JGroup jGroup = new JGroup();
1352 groups[++i] = jGroup;
1354 jGroup.setStart(sg.getStartRes());
1355 jGroup.setEnd(sg.getEndRes());
1356 jGroup.setName(sg.getName());
1357 if (groupRefs.containsKey(sg))
1359 // group has references so set its ID field
1360 jGroup.setId(groupRefs.get(sg));
1362 ColourSchemeI colourScheme = sg.getColourScheme();
1363 if (colourScheme != null)
1365 ResidueShaderI groupColourScheme = sg.getGroupColourScheme();
1366 if (groupColourScheme.conservationApplied())
1368 jGroup.setConsThreshold(groupColourScheme.getConservationInc());
1370 if (colourScheme instanceof jalview.schemes.UserColourScheme)
1373 setUserColourScheme(colourScheme, userColours,
1378 jGroup.setColour(colourScheme.getSchemeName());
1381 else if (colourScheme instanceof jalview.schemes.AnnotationColourGradient)
1383 jGroup.setColour("AnnotationColourGradient");
1384 jGroup.setAnnotationColours(constructAnnotationColours(
1385 (jalview.schemes.AnnotationColourGradient) colourScheme,
1386 userColours, object));
1388 else if (colourScheme instanceof jalview.schemes.UserColourScheme)
1391 setUserColourScheme(colourScheme, userColours, object));
1395 jGroup.setColour(colourScheme.getSchemeName());
1398 jGroup.setPidThreshold(groupColourScheme.getThreshold());
1401 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1402 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1403 jGroup.setDisplayText(sg.getDisplayText());
1404 jGroup.setColourText(sg.getColourText());
1405 jGroup.setTextCol1(sg.textColour.getRGB());
1406 jGroup.setTextCol2(sg.textColour2.getRGB());
1407 jGroup.setTextColThreshold(sg.thresholdTextColour);
1408 jGroup.setShowUnconserved(sg.getShowNonconserved());
1409 jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1410 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1411 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1412 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1413 for (SequenceI seq : sg.getSequences())
1415 // jGroup.addSeq(seqHash(seq));
1416 jGroup.getSeq().add(seqHash(seq));
1420 //jms.setJGroup(groups);
1422 for (JGroup grp : groups)
1424 object.getJGroup().add(grp);
1429 // /////////SAVE VIEWPORT
1430 Viewport view = new Viewport();
1431 view.setTitle(ap.alignFrame.getTitle());
1432 view.setSequenceSetId(
1433 makeHashCode(av.getSequenceSetId(), av.getSequenceSetId()));
1434 view.setId(av.getViewId());
1435 if (av.getCodingComplement() != null)
1437 view.setComplementId(av.getCodingComplement().getViewId());
1439 view.setViewName(av.getViewName());
1440 view.setGatheredViews(av.isGatherViewsHere());
1442 Rectangle size = ap.av.getExplodedGeometry();
1443 Rectangle position = size;
1446 size = ap.alignFrame.getBounds();
1447 if (av.getCodingComplement() != null)
1449 position = ((SplitFrame) ap.alignFrame.getSplitViewContainer())
1457 view.setXpos(position.x);
1458 view.setYpos(position.y);
1460 view.setWidth(size.width);
1461 view.setHeight(size.height);
1463 view.setStartRes(vpRanges.getStartRes());
1464 view.setStartSeq(vpRanges.getStartSeq());
1466 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1468 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1469 userColours, object));
1472 .getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1474 AnnotationColourScheme ac = constructAnnotationColours(
1475 (jalview.schemes.AnnotationColourGradient) av
1476 .getGlobalColourScheme(),
1477 userColours, object);
1479 view.setAnnotationColours(ac);
1480 view.setBgColour("AnnotationColourGradient");
1484 view.setBgColour(ColourSchemeProperty
1485 .getColourName(av.getGlobalColourScheme()));
1488 ResidueShaderI vcs = av.getResidueShading();
1489 ColourSchemeI cs = av.getGlobalColourScheme();
1493 if (vcs.conservationApplied())
1495 view.setConsThreshold(vcs.getConservationInc());
1496 if (cs instanceof jalview.schemes.UserColourScheme)
1498 view.setBgColour(setUserColourScheme(cs, userColours, object));
1501 view.setPidThreshold(vcs.getThreshold());
1504 view.setConservationSelected(av.getConservationSelected());
1505 view.setPidSelected(av.getAbovePIDThreshold());
1506 final Font font = av.getFont();
1507 view.setFontName(font.getName());
1508 view.setFontSize(font.getSize());
1509 view.setFontStyle(font.getStyle());
1510 view.setScaleProteinAsCdna(av.getViewStyle().isScaleProteinAsCdna());
1511 view.setRenderGaps(av.isRenderGaps());
1512 view.setShowAnnotation(av.isShowAnnotation());
1513 view.setShowBoxes(av.getShowBoxes());
1514 view.setShowColourText(av.getColourText());
1515 view.setShowFullId(av.getShowJVSuffix());
1516 view.setRightAlignIds(av.isRightAlignIds());
1517 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1518 view.setShowText(av.getShowText());
1519 view.setShowUnconserved(av.getShowUnconserved());
1520 view.setWrapAlignment(av.getWrapAlignment());
1521 view.setTextCol1(av.getTextColour().getRGB());
1522 view.setTextCol2(av.getTextColour2().getRGB());
1523 view.setTextColThreshold(av.getThresholdTextColour());
1524 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1525 view.setShowSequenceLogo(av.isShowSequenceLogo());
1526 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1527 view.setShowGroupConsensus(av.isShowGroupConsensus());
1528 view.setShowGroupConservation(av.isShowGroupConservation());
1529 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1530 view.setShowDbRefTooltip(av.isShowDBRefs());
1531 view.setFollowHighlight(av.isFollowHighlight());
1532 view.setFollowSelection(av.followSelection);
1533 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1534 if (av.getFeaturesDisplayed() != null)
1536 FeatureSettings fs = new FeatureSettings();
1538 FeatureRenderer fr = ap.getSeqPanel().seqCanvas
1539 .getFeatureRenderer();
1540 String[] renderOrder = fr.getRenderOrder().toArray(new String[0]);
1542 Vector<String> settingsAdded = new Vector<>();
1543 if (renderOrder != null)
1545 for (String featureType : renderOrder)
1547 FeatureSettings.Setting setting = new FeatureSettings.Setting();
1548 setting.setType(featureType);
1551 * save any filter for the feature type
1553 FeatureMatcherSetI filter = fr.getFeatureFilter(featureType);
1554 if (filter != null) {
1555 Iterator<FeatureMatcherI> filters = filter.getMatchers().iterator();
1556 FeatureMatcherI firstFilter = filters.next();
1557 setting.setMatcherSet(Jalview2XML.marshalFilter(
1558 firstFilter, filters, filter.isAnded()));
1562 * save colour scheme for the feature type
1564 FeatureColourI fcol = fr.getFeatureStyle(featureType);
1565 if (!fcol.isSimpleColour())
1567 setting.setColour(fcol.getMaxColour().getRGB());
1568 setting.setMincolour(fcol.getMinColour().getRGB());
1569 setting.setMin(fcol.getMin());
1570 setting.setMax(fcol.getMax());
1571 setting.setColourByLabel(fcol.isColourByLabel());
1572 if (fcol.isColourByAttribute())
1574 String[] attName = fcol.getAttributeName();
1575 setting.getAttributeName().add(attName[0]);
1576 if (attName.length > 1)
1578 setting.getAttributeName().add(attName[1]);
1581 setting.setAutoScale(fcol.isAutoScaled());
1582 setting.setThreshold(fcol.getThreshold());
1583 Color noColour = fcol.getNoColour();
1584 if (noColour == null)
1586 setting.setNoValueColour(NoValueColour.NONE);
1588 else if (noColour.equals(fcol.getMaxColour()))
1590 setting.setNoValueColour(NoValueColour.MAX);
1594 setting.setNoValueColour(NoValueColour.MIN);
1596 // -1 = No threshold, 0 = Below, 1 = Above
1597 setting.setThreshstate(fcol.isAboveThreshold() ? 1
1598 : (fcol.isBelowThreshold() ? 0 : -1));
1602 setting.setColour(fcol.getColour().getRGB());
1606 av.getFeaturesDisplayed().isVisible(featureType));
1608 .getOrder(featureType);
1611 setting.setOrder(rorder);
1613 /// fs.addSetting(setting);
1614 fs.getSetting().add(setting);
1615 settingsAdded.addElement(featureType);
1619 // is groups actually supposed to be a map here ?
1620 Iterator<String> en = fr.getFeatureGroups().iterator();
1621 Vector<String> groupsAdded = new Vector<>();
1622 while (en.hasNext())
1624 String grp = en.next();
1625 if (groupsAdded.contains(grp))
1629 Group g = new Group();
1631 g.setDisplay(((Boolean) fr.checkGroupVisibility(grp, false))
1634 fs.getGroup().add(g);
1635 groupsAdded.addElement(grp);
1637 // jms.setFeatureSettings(fs);
1638 object.setFeatureSettings(fs);
1641 if (av.hasHiddenColumns())
1643 jalview.datamodel.HiddenColumns hidden = av.getAlignment()
1644 .getHiddenColumns();
1647 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1651 Iterator<int[]> hiddenRegions = hidden.iterator();
1652 while (hiddenRegions.hasNext())
1654 int[] region = hiddenRegions.next();
1655 HiddenColumns hc = new HiddenColumns();
1656 hc.setStart(region[0]);
1657 hc.setEnd(region[1]);
1658 // view.addHiddenColumns(hc);
1659 view.getHiddenColumns().add(hc);
1663 if (calcIdSet.size() > 0)
1665 for (String calcId : calcIdSet)
1667 if (calcId.trim().length() > 0)
1669 CalcIdParam cidp = createCalcIdParam(calcId, av);
1670 // Some calcIds have no parameters.
1673 // view.addCalcIdParam(cidp);
1674 view.getCalcIdParam().add(cidp);
1680 // jms.addViewport(view);
1681 object.getViewport().add(view);
1683 // object.setJalviewModelSequence(jms);
1684 // object.getVamsasModel().addSequenceSet(vamsasSet);
1685 object.getVamsasModel().getSequenceSet().add(vamsasSet);
1687 if (jout != null && fileName != null)
1689 // We may not want to write the object to disk,
1690 // eg we can copy the alignViewport to a new view object
1691 // using save and then load
1694 fileName = fileName.replace('\\', '/');
1695 System.out.println("Writing jar entry " + fileName);
1696 JarEntry entry = new JarEntry(fileName);
1697 jout.putNextEntry(entry);
1698 PrintWriter pout = new PrintWriter(
1699 new OutputStreamWriter(jout, UTF_8));
1700 JAXBContext jaxbContext = JAXBContext
1701 .newInstance(JalviewModel.class);
1702 Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
1704 // output pretty printed
1705 // jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
1706 jaxbMarshaller.marshal(
1707 new ObjectFactory().createJalviewModel(object), pout);
1709 // jaxbMarshaller.marshal(object, pout);
1710 // marshaller.marshal(object);
1713 } catch (Exception ex)
1715 // TODO: raise error in GUI if marshalling failed.
1716 System.err.println("Error writing Jalview project");
1717 ex.printStackTrace();
1724 * Writes PCA viewer attributes and computed values to an XML model object and
1725 * adds it to the JalviewModel. Any exceptions are reported by logging.
1727 protected void savePCA(PCAPanel panel, JalviewModel object)
1731 PcaViewer viewer = new PcaViewer();
1732 viewer.setHeight(panel.getHeight());
1733 viewer.setWidth(panel.getWidth());
1734 viewer.setXpos(panel.getX());
1735 viewer.setYpos(panel.getY());
1736 viewer.setTitle(panel.getTitle());
1737 PCAModel pcaModel = panel.getPcaModel();
1738 viewer.setScoreModelName(pcaModel.getScoreModelName());
1739 viewer.setXDim(panel.getSelectedDimensionIndex(X));
1740 viewer.setYDim(panel.getSelectedDimensionIndex(Y));
1741 viewer.setZDim(panel.getSelectedDimensionIndex(Z));
1743 panel.getRotatableCanvas().getBackgroundColour().getRGB());
1744 viewer.setScaleFactor(panel.getRotatableCanvas().getScaleFactor());
1745 float[] spMin = panel.getRotatableCanvas().getSeqMin();
1746 SeqPointMin spmin = new SeqPointMin();
1747 spmin.setXPos(spMin[0]);
1748 spmin.setYPos(spMin[1]);
1749 spmin.setZPos(spMin[2]);
1750 viewer.setSeqPointMin(spmin);
1751 float[] spMax = panel.getRotatableCanvas().getSeqMax();
1752 SeqPointMax spmax = new SeqPointMax();
1753 spmax.setXPos(spMax[0]);
1754 spmax.setYPos(spMax[1]);
1755 spmax.setZPos(spMax[2]);
1756 viewer.setSeqPointMax(spmax);
1757 viewer.setShowLabels(panel.getRotatableCanvas().isShowLabels());
1758 viewer.setLinkToAllViews(
1759 panel.getRotatableCanvas().isApplyToAllViews());
1760 SimilarityParamsI sp = pcaModel.getSimilarityParameters();
1761 viewer.setIncludeGaps(sp.includeGaps());
1762 viewer.setMatchGaps(sp.matchGaps());
1763 viewer.setIncludeGappedColumns(sp.includeGappedColumns());
1764 viewer.setDenominateByShortestLength(sp.denominateByShortestLength());
1767 * sequence points on display
1769 for (jalview.datamodel.SequencePoint spt : pcaModel
1770 .getSequencePoints())
1772 SequencePoint point = new SequencePoint();
1773 point.setSequenceRef(seqHash(spt.getSequence()));
1774 point.setXPos(spt.coord.x);
1775 point.setYPos(spt.coord.y);
1776 point.setZPos(spt.coord.z);
1777 viewer.getSequencePoint().add(point);
1781 * (end points of) axes on display
1783 for (Point p : panel.getRotatableCanvas().getAxisEndPoints())
1786 Axis axis = new Axis();
1790 viewer.getAxis().add(axis);
1794 * raw PCA data (note we are not restoring PCA inputs here -
1795 * alignment view, score model, similarity parameters)
1797 PcaDataType data = new PcaDataType();
1798 viewer.setPcaData(data);
1799 PCA pca = pcaModel.getPcaData();
1801 DoubleMatrix pm = new DoubleMatrix();
1802 saveDoubleMatrix(pca.getPairwiseScores(), pm);
1803 data.setPairwiseMatrix(pm);
1805 DoubleMatrix tm = new DoubleMatrix();
1806 saveDoubleMatrix(pca.getTridiagonal(), tm);
1807 data.setTridiagonalMatrix(tm);
1809 DoubleMatrix eigenMatrix = new DoubleMatrix();
1810 data.setEigenMatrix(eigenMatrix);
1811 saveDoubleMatrix(pca.getEigenmatrix(), eigenMatrix);
1813 object.getPcaViewer().add(viewer);
1814 } catch (Throwable t)
1816 Cache.log.error("Error saving PCA: " + t.getMessage());
1821 * Stores values from a matrix into an XML element, including (if present) the
1826 * @see #loadDoubleMatrix(DoubleMatrix)
1828 protected void saveDoubleMatrix(MatrixI m, DoubleMatrix xmlMatrix)
1830 xmlMatrix.setRows(m.height());
1831 xmlMatrix.setColumns(m.width());
1832 for (int i = 0; i < m.height(); i++)
1834 DoubleVector row = new DoubleVector();
1835 for (int j = 0; j < m.width(); j++)
1837 row.getV().add(m.getValue(i, j));
1839 xmlMatrix.getRow().add(row);
1841 if (m.getD() != null)
1843 DoubleVector dVector = new DoubleVector();
1844 for (double d : m.getD())
1846 dVector.getV().add(d);
1848 xmlMatrix.setD(dVector);
1850 if (m.getE() != null)
1852 DoubleVector eVector = new DoubleVector();
1853 for (double e : m.getE())
1855 eVector.getV().add(e);
1857 xmlMatrix.setE(eVector);
1862 * Loads XML matrix data into a new Matrix object, including the D and/or E
1863 * vectors (if present)
1867 * @see Jalview2XML#saveDoubleMatrix(MatrixI, DoubleMatrix)
1869 protected MatrixI loadDoubleMatrix(DoubleMatrix mData)
1871 int rows = mData.getRows();
1872 double[][] vals = new double[rows][];
1874 for (int i = 0; i < rows; i++)
1876 List<Double> dVector = mData.getRow().get(i).getV();
1877 vals[i] = new double[dVector.size()];
1879 for (Double d : dVector)
1885 MatrixI m = new Matrix(vals);
1887 if (mData.getD() != null)
1889 List<Double> dVector = mData.getD().getV();
1890 double[] vec = new double[dVector.size()];
1892 for (Double d : dVector)
1898 if (mData.getE() != null)
1900 List<Double> dVector = mData.getE().getV();
1901 double[] vec = new double[dVector.size()];
1903 for (Double d : dVector)
1914 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1915 * for each viewer, with
1917 * <li>viewer geometry (position, size, split pane divider location)</li>
1918 * <li>index of the selected structure in the viewer (currently shows gapped
1920 * <li>the id of the annotation holding RNA secondary structure</li>
1921 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1923 * Varna viewer state is also written out (in native Varna XML) to separate
1924 * project jar entries. A separate entry is written for each RNA structure
1925 * displayed, with the naming convention
1927 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
1935 * @param storeDataset
1937 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
1938 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
1939 boolean storeDataset)
1941 if (Desktop.getDesktopPane() == null)
1945 JInternalFrame[] frames = Desktop.getDesktopPane().getAllFrames();
1946 for (int f = frames.length - 1; f > -1; f--)
1948 if (frames[f] instanceof AppVarna)
1950 AppVarna varna = (AppVarna) frames[f];
1952 * link the sequence to every viewer that is showing it and is linked to
1953 * its alignment panel
1955 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1957 String viewId = varna.getViewId();
1958 RnaViewer rna = new RnaViewer();
1959 rna.setViewId(viewId);
1960 rna.setTitle(varna.getTitle());
1961 rna.setXpos(varna.getX());
1962 rna.setYpos(varna.getY());
1963 rna.setWidth(varna.getWidth());
1964 rna.setHeight(varna.getHeight());
1965 rna.setDividerLocation(varna.getDividerLocation());
1966 rna.setSelectedRna(varna.getSelectedIndex());
1967 // jseq.addRnaViewer(rna);
1968 jseq.getRnaViewer().add(rna);
1971 * Store each Varna panel's state once in the project per sequence.
1972 * First time through only (storeDataset==false)
1974 // boolean storeSessions = false;
1975 // String sequenceViewId = viewId + seqsToIds.get(jds);
1976 // if (!storeDataset && !viewIds.contains(sequenceViewId))
1978 // viewIds.add(sequenceViewId);
1979 // storeSessions = true;
1981 for (RnaModel model : varna.getModels())
1983 if (model.seq == jds)
1986 * VARNA saves each view (sequence or alignment secondary
1987 * structure, gapped or trimmed) as a separate XML file
1989 String jarEntryName = rnaSessions.get(model);
1990 if (jarEntryName == null)
1993 String varnaStateFile = varna.getStateInfo(model.rna);
1994 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
1995 copyFileToJar(jout, varnaStateFile, jarEntryName);
1996 rnaSessions.put(model, jarEntryName);
1998 SecondaryStructure ss = new SecondaryStructure();
1999 String annotationId = varna.getAnnotation(jds).annotationId;
2000 ss.setAnnotationId(annotationId);
2001 ss.setViewerState(jarEntryName);
2002 ss.setGapped(model.gapped);
2003 ss.setTitle(model.title);
2004 // rna.addSecondaryStructure(ss);
2005 rna.getSecondaryStructure().add(ss);
2014 * Copy the contents of a file to a new entry added to the output jar
2018 * @param jarEntryName
2020 protected void copyFileToJar(JarOutputStream jout, String infilePath,
2021 String jarEntryName)
2023 DataInputStream dis = null;
2026 File file = new File(infilePath);
2027 if (file.exists() && jout != null)
2029 dis = new DataInputStream(new FileInputStream(file));
2030 byte[] data = new byte[(int) file.length()];
2031 dis.readFully(data);
2032 writeJarEntry(jout, jarEntryName, data);
2034 } catch (Exception ex)
2036 ex.printStackTrace();
2044 } catch (IOException e)
2053 * Write the data to a new entry of given name in the output jar file
2056 * @param jarEntryName
2058 * @throws IOException
2060 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
2061 byte[] data) throws IOException
2065 jarEntryName = jarEntryName.replace('\\','/');
2066 System.out.println("Writing jar entry " + jarEntryName);
2067 jout.putNextEntry(new JarEntry(jarEntryName));
2068 DataOutputStream dout = new DataOutputStream(jout);
2069 dout.write(data, 0, data.length);
2076 * Save the state of a structure viewer
2081 * the archive XML element under which to save the state
2084 * @param matchedFile
2088 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
2089 Pdbids pdb, PDBEntry entry, List<String> viewIds,
2090 String matchedFile, StructureViewerBase viewFrame)
2092 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
2095 * Look for any bindings for this viewer to the PDB file of interest
2096 * (including part matches excluding chain id)
2098 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
2100 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
2101 final String pdbId = pdbentry.getId();
2102 if (!pdbId.equals(entry.getId())
2103 && !(entry.getId().length() > 4 && entry.getId().toLowerCase()
2104 .startsWith(pdbId.toLowerCase())))
2107 * not interested in a binding to a different PDB entry here
2111 if (matchedFile == null)
2113 matchedFile = pdbentry.getFile();
2115 else if (!matchedFile.equals(pdbentry.getFile()))
2118 "Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
2119 + pdbentry.getFile());
2123 // can get at it if the ID
2124 // match is ambiguous (e.g.
2127 for (int smap = 0; smap < viewFrame.getBinding()
2128 .getSequence()[peid].length; smap++)
2130 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
2131 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
2133 StructureState state = new StructureState();
2134 state.setVisible(true);
2135 state.setXpos(viewFrame.getX());
2136 state.setYpos(viewFrame.getY());
2137 state.setWidth(viewFrame.getWidth());
2138 state.setHeight(viewFrame.getHeight());
2139 final String viewId = viewFrame.getViewId();
2140 state.setViewId(viewId);
2141 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
2142 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
2143 state.setColourByJmol(viewFrame.isColouredByViewer());
2144 state.setType(viewFrame.getViewerType().toString());
2145 // pdb.addStructureState(state);
2146 pdb.getStructureState().add(state);
2154 * Populates the AnnotationColourScheme xml for save. This captures the
2155 * settings of the options in the 'Colour by Annotation' dialog.
2158 * @param userColours
2162 private AnnotationColourScheme constructAnnotationColours(
2163 AnnotationColourGradient acg, List<UserColourScheme> userColours,
2166 AnnotationColourScheme ac = new AnnotationColourScheme();
2167 ac.setAboveThreshold(acg.getAboveThreshold());
2168 ac.setThreshold(acg.getAnnotationThreshold());
2169 // 2.10.2 save annotationId (unique) not annotation label
2170 ac.setAnnotation(acg.getAnnotation().annotationId);
2171 if (acg.getBaseColour() instanceof UserColourScheme)
2174 setUserColourScheme(acg.getBaseColour(), userColours, jm));
2179 ColourSchemeProperty.getColourName(acg.getBaseColour()));
2182 ac.setMaxColour(acg.getMaxColour().getRGB());
2183 ac.setMinColour(acg.getMinColour().getRGB());
2184 ac.setPerSequence(acg.isSeqAssociated());
2185 ac.setPredefinedColours(acg.isPredefinedColours());
2189 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
2190 IdentityHashMap<SequenceGroup, String> groupRefs,
2191 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
2192 SequenceSet vamsasSet)
2195 for (int i = 0; i < aa.length; i++)
2197 Annotation an = new Annotation();
2199 AlignmentAnnotation annotation = aa[i];
2200 if (annotation.annotationId != null)
2202 annotationIds.put(annotation.annotationId, annotation);
2205 an.setId(annotation.annotationId);
2207 an.setVisible(annotation.visible);
2209 an.setDescription(annotation.description);
2211 if (annotation.sequenceRef != null)
2213 // 2.9 JAL-1781 xref on sequence id rather than name
2214 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
2216 if (annotation.groupRef != null)
2218 String groupIdr = groupRefs.get(annotation.groupRef);
2219 if (groupIdr == null)
2221 // make a locally unique String
2222 groupRefs.put(annotation.groupRef,
2223 groupIdr = ("" + System.currentTimeMillis()
2224 + annotation.groupRef.getName()
2225 + groupRefs.size()));
2227 an.setGroupRef(groupIdr.toString());
2230 // store all visualization attributes for annotation
2231 an.setGraphHeight(annotation.graphHeight);
2232 an.setCentreColLabels(annotation.centreColLabels);
2233 an.setScaleColLabels(annotation.scaleColLabel);
2234 an.setShowAllColLabels(annotation.showAllColLabels);
2235 an.setBelowAlignment(annotation.belowAlignment);
2237 if (annotation.graph > 0)
2240 an.setGraphType(annotation.graph);
2241 an.setGraphGroup(annotation.graphGroup);
2242 if (annotation.getThreshold() != null)
2244 ThresholdLine line = new ThresholdLine();
2245 line.setLabel(annotation.getThreshold().label);
2246 line.setValue(annotation.getThreshold().value);
2247 line.setColour(annotation.getThreshold().colour.getRGB());
2248 an.setThresholdLine(line);
2256 an.setLabel(annotation.label);
2258 if (annotation == av.getAlignmentQualityAnnot()
2259 || annotation == av.getAlignmentConservationAnnotation()
2260 || annotation == av.getAlignmentConsensusAnnotation()
2261 || annotation.autoCalculated)
2263 // new way of indicating autocalculated annotation -
2264 an.setAutoCalculated(annotation.autoCalculated);
2266 if (annotation.hasScore())
2268 an.setScore(annotation.getScore());
2271 if (annotation.getCalcId() != null)
2273 calcIdSet.add(annotation.getCalcId());
2274 an.setCalcId(annotation.getCalcId());
2276 if (annotation.hasProperties())
2278 for (String pr : annotation.getProperties())
2280 jalview.xml.binding.jalview.Annotation.Property prop = new jalview.xml.binding.jalview.Annotation.Property();
2282 prop.setValue(annotation.getProperty(pr));
2283 // an.addProperty(prop);
2284 an.getProperty().add(prop);
2288 AnnotationElement ae;
2289 if (annotation.annotations != null)
2291 an.setScoreOnly(false);
2292 for (int a = 0; a < annotation.annotations.length; a++)
2294 if ((annotation == null) || (annotation.annotations[a] == null))
2299 ae = new AnnotationElement();
2300 if (annotation.annotations[a].description != null)
2302 ae.setDescription(annotation.annotations[a].description);
2304 if (annotation.annotations[a].displayCharacter != null)
2306 ae.setDisplayCharacter(
2307 annotation.annotations[a].displayCharacter);
2310 if (!Float.isNaN(annotation.annotations[a].value))
2312 ae.setValue(annotation.annotations[a].value);
2316 if (annotation.annotations[a].secondaryStructure > ' ')
2318 ae.setSecondaryStructure(
2319 annotation.annotations[a].secondaryStructure + "");
2322 if (annotation.annotations[a].colour != null
2323 && annotation.annotations[a].colour != java.awt.Color.black)
2325 ae.setColour(annotation.annotations[a].colour.getRGB());
2328 // an.addAnnotationElement(ae);
2329 an.getAnnotationElement().add(ae);
2330 if (annotation.autoCalculated)
2332 // only write one non-null entry into the annotation row -
2333 // sufficient to get the visualization attributes necessary to
2341 an.setScoreOnly(true);
2343 if (!storeDS || (storeDS && !annotation.autoCalculated))
2345 // skip autocalculated annotation - these are only provided for
2347 // vamsasSet.addAnnotation(an);
2348 vamsasSet.getAnnotation().add(an);
2354 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
2356 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
2357 if (settings != null)
2359 CalcIdParam vCalcIdParam = new CalcIdParam();
2360 vCalcIdParam.setCalcId(calcId);
2361 // vCalcIdParam.addServiceURL(settings.getServiceURI());
2362 vCalcIdParam.getServiceURL().add(settings.getServiceURI());
2363 // generic URI allowing a third party to resolve another instance of the
2364 // service used for this calculation
2365 for (String url : settings.getServiceURLs())
2367 // vCalcIdParam.addServiceURL(urls);
2368 vCalcIdParam.getServiceURL().add(url);
2370 vCalcIdParam.setVersion("1.0");
2371 if (settings.getPreset() != null)
2373 WsParamSetI setting = settings.getPreset();
2374 vCalcIdParam.setName(setting.getName());
2375 vCalcIdParam.setDescription(setting.getDescription());
2379 vCalcIdParam.setName("");
2380 vCalcIdParam.setDescription("Last used parameters");
2382 // need to be able to recover 1) settings 2) user-defined presets or
2383 // recreate settings from preset 3) predefined settings provided by
2384 // service - or settings that can be transferred (or discarded)
2385 vCalcIdParam.setParameters(
2386 settings.getWsParamFile().replace("\n", "|\\n|"));
2387 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
2388 // todo - decide if updateImmediately is needed for any projects.
2390 return vCalcIdParam;
2395 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
2398 if (calcIdParam.getVersion().equals("1.0"))
2400 final String[] calcIds = calcIdParam.getServiceURL().toArray(new String[0]);
2401 Jws2Instance service = Jws2Discoverer.getInstance()
2402 .getPreferredServiceFor(calcIds);
2403 if (service != null)
2405 WsParamSetI parmSet = null;
2408 parmSet = service.getParamStore().parseServiceParameterFile(
2409 calcIdParam.getName(), calcIdParam.getDescription(),
2411 calcIdParam.getParameters().replace("|\\n|", "\n"));
2412 } catch (IOException x)
2414 warn("Couldn't parse parameter data for "
2415 + calcIdParam.getCalcId(), x);
2418 List<ArgumentI> argList = null;
2419 if (calcIdParam.getName().length() > 0)
2421 parmSet = service.getParamStore()
2422 .getPreset(calcIdParam.getName());
2423 if (parmSet != null)
2425 // TODO : check we have a good match with settings in AACon -
2426 // otherwise we'll need to create a new preset
2431 argList = parmSet.getArguments();
2434 AAConSettings settings = new AAConSettings(
2435 calcIdParam.isAutoUpdate(), service, parmSet, argList);
2436 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
2437 calcIdParam.isNeedsUpdate());
2442 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
2446 throw new Error(MessageManager.formatMessage(
2447 "error.unsupported_version_calcIdparam", new Object[]
2448 { calcIdParam.toString() }));
2452 * External mapping between jalview objects and objects yielding a valid and
2453 * unique object ID string. This is null for normal Jalview project IO, but
2454 * non-null when a jalview project is being read or written as part of a
2457 IdentityHashMap jv2vobj = null;
2460 * Construct a unique ID for jvobj using either existing bindings or if none
2461 * exist, the result of the hashcode call for the object.
2464 * jalview data object
2465 * @return unique ID for referring to jvobj
2467 private String makeHashCode(Object jvobj, String altCode)
2469 if (jv2vobj != null)
2471 Object id = jv2vobj.get(jvobj);
2474 return id.toString();
2476 // check string ID mappings
2477 if (jvids2vobj != null && jvobj instanceof String)
2479 id = jvids2vobj.get(jvobj);
2483 return id.toString();
2485 // give up and warn that something has gone wrong
2486 warn("Cannot find ID for object in external mapping : " + jvobj);
2492 * return local jalview object mapped to ID, if it exists
2496 * @return null or object bound to idcode
2498 private Object retrieveExistingObj(String idcode)
2500 if (idcode != null && vobj2jv != null)
2502 return vobj2jv.get(idcode);
2508 * binding from ID strings from external mapping table to jalview data model
2511 private Hashtable vobj2jv;
2513 private Sequence createVamsasSequence(String id, SequenceI jds)
2515 return createVamsasSequence(true, id, jds, null);
2518 private Sequence createVamsasSequence(boolean recurse, String id,
2519 SequenceI jds, SequenceI parentseq)
2521 Sequence vamsasSeq = new Sequence();
2522 vamsasSeq.setId(id);
2523 vamsasSeq.setName(jds.getName());
2524 vamsasSeq.setSequence(jds.getSequenceAsString());
2525 vamsasSeq.setDescription(jds.getDescription());
2526 List<DBRefEntry> dbrefs = null;
2527 if (jds.getDatasetSequence() != null)
2529 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
2533 // seqId==dsseqid so we can tell which sequences really are
2534 // dataset sequences only
2535 vamsasSeq.setDsseqid(id);
2536 dbrefs = jds.getDBRefs();
2537 if (parentseq == null)
2544 for (int d = 0, nd = dbrefs.size(); d < nd; d++)
2546 DBRef dbref = new DBRef();
2547 DBRefEntry ref = dbrefs.get(d);
2548 dbref.setSource(ref.getSource());
2549 dbref.setVersion(ref.getVersion());
2550 dbref.setAccessionId(ref.getAccessionId());
2553 Mapping mp = createVamsasMapping(ref.getMap(), parentseq,
2555 dbref.setMapping(mp);
2557 // vamsasSeq.addDBRef(dbref);
2558 vamsasSeq.getDBRef().add(dbref);
2564 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
2565 SequenceI parentseq, SequenceI jds, boolean recurse)
2568 if (jmp.getMap() != null)
2572 jalview.util.MapList mlst = jmp.getMap();
2573 List<int[]> r = mlst.getFromRanges();
2574 for (int[] range : r)
2576 MapListFrom mfrom = new MapListFrom();
2577 mfrom.setStart(range[0]);
2578 mfrom.setEnd(range[1]);
2579 // mp.addMapListFrom(mfrom);
2580 mp.getMapListFrom().add(mfrom);
2582 r = mlst.getToRanges();
2583 for (int[] range : r)
2585 MapListTo mto = new MapListTo();
2586 mto.setStart(range[0]);
2587 mto.setEnd(range[1]);
2588 // mp.addMapListTo(mto);
2589 mp.getMapListTo().add(mto);
2591 mp.setMapFromUnit(BigInteger.valueOf(mlst.getFromRatio()));
2592 mp.setMapToUnit(BigInteger.valueOf(mlst.getToRatio()));
2593 if (jmp.getTo() != null)
2595 // MappingChoice mpc = new MappingChoice();
2597 // check/create ID for the sequence referenced by getTo()
2600 SequenceI ps = null;
2601 if (parentseq != jmp.getTo()
2602 && parentseq.getDatasetSequence() != jmp.getTo())
2604 // chaining dbref rather than a handshaking one
2605 jmpid = seqHash(ps = jmp.getTo());
2609 jmpid = seqHash(ps = parentseq);
2611 // mpc.setDseqFor(jmpid);
2612 mp.setDseqFor(jmpid);
2613 if (!seqRefIds.containsKey(jmpid))
2615 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2616 seqRefIds.put(jmpid, ps);
2620 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2623 // mp.setMappingChoice(mpc);
2629 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2630 List<UserColourScheme> userColours, JalviewModel jm)
2633 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2634 boolean newucs = false;
2635 if (!userColours.contains(ucs))
2637 userColours.add(ucs);
2640 id = "ucs" + userColours.indexOf(ucs);
2643 // actually create the scheme's entry in the XML model
2644 java.awt.Color[] colours = ucs.getColours();
2645 UserColours uc = new UserColours();
2646 // UserColourScheme jbucs = new UserColourScheme();
2647 JalviewUserColours jbucs = new JalviewUserColours();
2649 for (int i = 0; i < colours.length; i++)
2651 Colour col = new Colour();
2652 col.setName(ResidueProperties.aa[i]);
2653 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2654 // jbucs.addColour(col);
2655 jbucs.getColour().add(col);
2657 if (ucs.getLowerCaseColours() != null)
2659 colours = ucs.getLowerCaseColours();
2660 for (int i = 0; i < colours.length; i++)
2662 Colour col = new Colour();
2663 col.setName(ResidueProperties.aa[i].toLowerCase());
2664 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2665 // jbucs.addColour(col);
2666 jbucs.getColour().add(col);
2671 uc.setUserColourScheme(jbucs);
2672 // jm.addUserColours(uc);
2673 jm.getUserColours().add(uc);
2679 jalview.schemes.UserColourScheme getUserColourScheme(
2680 JalviewModel jm, String id)
2682 List<UserColours> uc = jm.getUserColours();
2683 UserColours colours = null;
2685 for (int i = 0; i < uc.length; i++)
2687 if (uc[i].getId().equals(id))
2694 for (UserColours c : uc)
2696 if (c.getId().equals(id))
2703 java.awt.Color[] newColours = new java.awt.Color[24];
2705 for (int i = 0; i < 24; i++)
2707 newColours[i] = new java.awt.Color(Integer.parseInt(
2708 // colours.getUserColourScheme().getColour(i).getRGB(), 16));
2709 colours.getUserColourScheme().getColour().get(i).getRGB(),
2713 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2716 if (colours.getUserColourScheme().getColour().size()/*Count()*/ > 24)
2718 newColours = new java.awt.Color[23];
2719 for (int i = 0; i < 23; i++)
2721 newColours[i] = new java.awt.Color(Integer.parseInt(
2722 colours.getUserColourScheme().getColour().get(i + 24)
2726 ucs.setLowerCaseColours(newColours);
2733 * contains last error message (if any) encountered by XML loader.
2735 String errorMessage = null;
2738 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2739 * exceptions are raised during project XML parsing
2741 public boolean attemptversion1parse = false;
2744 * Load a jalview project archive from a jar file
2747 * - HTTP URL or filename
2749 public AlignFrame loadJalviewAlign(final Object file)
2752 jalview.gui.AlignFrame af = null;
2756 // create list to store references for any new Jmol viewers created
2757 newStructureViewers = new Vector<>();
2758 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2759 // Workaround is to make sure caller implements the JarInputStreamProvider
2761 // so we can re-open the jar input stream for each entry.
2763 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2764 af = loadJalviewAlign(jprovider);
2767 af.setMenusForViewport();
2769 } catch (MalformedURLException e)
2771 errorMessage = "Invalid URL format for '" + file + "'";
2777 // BH 2019 -- can't wait
2778 SwingUtilities.invokeLater(new Runnable()
2783 setLoadingFinishedForNewStructureViewers();
2786 } catch (Exception x)
2788 System.err.println("Error loading alignment: " + x.getMessage());
2794 @SuppressWarnings("unused")
2795 private jarInputStreamProvider createjarInputStreamProvider(final Object ofile) throws MalformedURLException {
2797 // BH 2018 allow for bytes already attached to File object
2799 String file = (ofile instanceof File ? ((File) ofile).getCanonicalPath() : ofile.toString());
2800 byte[] bytes = Platform.isJS() ? Platform.getFileBytes((File) ofile)
2803 errorMessage = null;
2804 uniqueSetSuffix = null;
2806 viewportsAdded.clear();
2807 frefedSequence = null;
2809 if (file.startsWith("http://")) {
2810 url = new URL(file);
2812 final URL _url = url;
2813 return new jarInputStreamProvider() {
2816 public JarInputStream getJarInputStream() throws IOException {
2817 if (bytes != null) {
2818 // System.out.println("Jalview2XML: opening byte jarInputStream for bytes.length=" + bytes.length);
2819 return new JarInputStream(new ByteArrayInputStream(bytes));
2822 // System.out.println("Jalview2XML: opening url jarInputStream for " + _url);
2823 return new JarInputStream(_url.openStream());
2825 // System.out.println("Jalview2XML: opening file jarInputStream for " + file);
2826 return new JarInputStream(new FileInputStream(file));
2831 public String getFilename() {
2835 } catch (IOException e) {
2836 e.printStackTrace();
2842 * Recover jalview session from a jalview project archive. Caller may
2843 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2844 * themselves. Any null fields will be initialised with default values,
2845 * non-null fields are left alone.
2850 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2852 errorMessage = null;
2853 if (uniqueSetSuffix == null)
2855 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2857 if (seqRefIds == null)
2861 AlignFrame af = null, _af = null;
2862 IdentityHashMap<AlignmentI, AlignmentI> importedDatasets = new IdentityHashMap<>();
2863 Map<String, AlignFrame> gatherToThisFrame = new HashMap<>();
2864 final String file = jprovider.getFilename();
2867 JarInputStream jin = null;
2868 JarEntry jarentry = null;
2871 // Look for all the entry names ending with ".xml"
2872 // This includes all panels and at least one frame.
2873 // Platform.timeCheck(null, Platform.TIME_MARK);
2876 jin = jprovider.getJarInputStream();
2877 for (int i = 0; i < entryCount; i++)
2879 jarentry = jin.getNextJarEntry();
2881 String name = (jarentry == null ? null : jarentry.getName());
2882 if (name != null && name.endsWith(".xml"))
2885 // The question here is what to do with the two
2886 // .xml files in the jvp file.
2887 // Some number of them, "...Dataset for...", will be the
2888 // Only AlignPanels and will have Viewport.
2889 // One or more will be the source data, with the DBRefs.
2891 // JVP file writing (above) ensures tha the AlignPanels are written
2892 // first, then all relevant datasets (which are
2893 // Jalview.datamodel.Alignment).
2896 // Platform.timeCheck("Jalview2XML JAXB " + name, Platform.TIME_MARK);
2897 JAXBContext jc = JAXBContext
2898 .newInstance("jalview.xml.binding.jalview");
2899 XMLStreamReader streamReader = XMLInputFactory.newInstance()
2900 .createXMLStreamReader(jin);
2901 javax.xml.bind.Unmarshaller um = jc.createUnmarshaller();
2902 JAXBElement<JalviewModel> jbe = um
2903 .unmarshal(streamReader, JalviewModel.class);
2904 JalviewModel model = jbe.getValue();
2906 if (true) // !skipViewport(object))
2908 // Q: Do we have to load from the model, even if it
2909 // does not have a viewport, could we discover that early on?
2910 // Q: Do we need to load this object?
2911 _af = loadFromObject(model, file, true, jprovider);
2912 // Platform.timeCheck("Jalview2XML.loadFromObject",
2913 // Platform.TIME_MARK);
2914 if (_af != null && model.getViewport().size() > 0)
2916 // That is, this is one of the AlignmentPanel models
2919 // store a reference to the first view
2922 if (_af.getViewport().isGatherViewsHere())
2924 // if this is a gathered view, keep its reference since
2925 // after gathering views, only this frame will remain
2927 gatherToThisFrame.put(_af.getViewport().getSequenceSetId(),
2930 // Save dataset to register mappings once all resolved
2931 importedDatasets.put(
2932 af.getViewport().getAlignment().getDataset(),
2933 af.getViewport().getAlignment().getDataset());
2936 // Platform.timeCheck("JAXB " + name, Platform.TIME_MARK);
2939 else if (jarentry != null)
2941 // Some other file here.
2944 } while (jarentry != null);
2945 // Platform.timeCheck("JAXB loop exit", Platform.TIME_MARK);
2946 resolveFrefedSequences();
2947 // Platform.timeCheck("JAXB resolveFrefed", Platform.TIME_MARK);
2949 } catch (IOException ex)
2951 ex.printStackTrace();
2952 errorMessage = "Couldn't locate Jalview XML file : " + file;
2954 "Exception whilst loading jalview XML file : " + ex + "\n");
2955 } catch (Exception ex)
2957 System.err.println("Parsing as Jalview Version 2 file failed.");
2958 ex.printStackTrace(System.err);
2959 if (attemptversion1parse)
2961 // used to attempt to parse as V1 castor-generated xml
2963 if (Desktop.getInstance() != null)
2965 Desktop.getInstance().stopLoading();
2969 System.out.println("Successfully loaded archive file");
2972 ex.printStackTrace();
2975 "Exception whilst loading jalview XML file : " + ex + "\n");
2976 } catch (OutOfMemoryError e)
2978 // Don't use the OOM Window here
2979 errorMessage = "Out of memory loading jalview XML file";
2980 System.err.println("Out of memory whilst loading jalview XML file");
2981 e.printStackTrace();
2985 * Regather multiple views (with the same sequence set id) to the frame (if
2986 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2987 * views instead of separate frames. Note this doesn't restore a state where
2988 * some expanded views in turn have tabbed views - the last "first tab" read
2989 * in will play the role of gatherer for all.
2991 for (AlignFrame fr : gatherToThisFrame.values())
2993 Desktop.getInstance().gatherViews(fr);
2996 restoreSplitFrames();
2997 for (AlignmentI ds : importedDatasets.keySet())
2999 if (ds.getCodonFrames() != null)
3001 Desktop.getInstance().getStructureSelectionManager()
3002 .registerMappings(ds.getCodonFrames());
3005 if (errorMessage != null)
3010 if (Desktop.getInstance() != null)
3012 Desktop.getInstance().stopLoading();
3019 * Try to reconstruct and display SplitFrame windows, where each contains
3020 * complementary dna and protein alignments. Done by pairing up AlignFrame
3021 * objects (created earlier) which have complementary viewport ids associated.
3023 protected void restoreSplitFrames()
3025 List<SplitFrame> gatherTo = new ArrayList<>();
3026 List<AlignFrame> addedToSplitFrames = new ArrayList<>();
3027 Map<String, AlignFrame> dna = new HashMap<>();
3030 * Identify the DNA alignments
3032 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
3035 AlignFrame af = candidate.getValue();
3036 if (af.getViewport().getAlignment().isNucleotide())
3038 dna.put(candidate.getKey().getId(), af);
3043 * Try to match up the protein complements
3045 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
3048 AlignFrame af = candidate.getValue();
3049 if (!af.getViewport().getAlignment().isNucleotide())
3051 String complementId = candidate.getKey().getComplementId();
3052 // only non-null complements should be in the Map
3053 if (complementId != null && dna.containsKey(complementId))
3055 final AlignFrame dnaFrame = dna.get(complementId);
3056 SplitFrame sf = createSplitFrame(dnaFrame, af);
3057 addedToSplitFrames.add(dnaFrame);
3058 addedToSplitFrames.add(af);
3059 dnaFrame.setMenusForViewport();
3060 af.setMenusForViewport();
3061 if (af.getViewport().isGatherViewsHere())
3070 * Open any that we failed to pair up (which shouldn't happen!) as
3071 * standalone AlignFrame's.
3073 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
3076 AlignFrame af = candidate.getValue();
3077 if (!addedToSplitFrames.contains(af))
3079 Viewport view = candidate.getKey();
3080 Desktop.addInternalFrame(af, view.getTitle(),
3081 safeInt(view.getWidth()), safeInt(view.getHeight()));
3082 af.setMenusForViewport();
3083 System.err.println("Failed to restore view " + view.getTitle()
3084 + " to split frame");
3089 * Gather back into tabbed views as flagged.
3091 for (SplitFrame sf : gatherTo)
3093 Desktop.getInstance().gatherViews(sf);
3096 splitFrameCandidates.clear();
3100 * Construct and display one SplitFrame holding DNA and protein alignments.
3103 * @param proteinFrame
3106 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
3107 AlignFrame proteinFrame)
3109 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
3110 String title = MessageManager.getString("label.linked_view_title");
3111 int width = (int) dnaFrame.getBounds().getWidth();
3112 int height = (int) (dnaFrame.getBounds().getHeight()
3113 + proteinFrame.getBounds().getHeight() + 50);
3116 * SplitFrame location is saved to both enclosed frames
3118 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
3119 Desktop.addInternalFrame(splitFrame, title, width, height);
3122 * And compute cDNA consensus (couldn't do earlier with consensus as
3123 * mappings were not yet present)
3125 proteinFrame.getViewport().alignmentChanged(proteinFrame.alignPanel);
3131 * check errorMessage for a valid error message and raise an error box in the
3132 * GUI or write the current errorMessage to stderr and then clear the error
3135 protected void reportErrors()
3137 reportErrors(false);
3140 protected void reportErrors(final boolean saving)
3142 if (errorMessage != null)
3144 final String finalErrorMessage = errorMessage;
3147 javax.swing.SwingUtilities.invokeLater(new Runnable()
3152 JvOptionPane.showInternalMessageDialog(Desktop.getDesktopPane(),
3154 "Error " + (saving ? "saving" : "loading")
3156 JvOptionPane.WARNING_MESSAGE);
3162 System.err.println("Problem loading Jalview file: " + errorMessage);
3165 errorMessage = null;
3168 Map<String, String> alreadyLoadedPDB = new HashMap<>();
3171 * when set, local views will be updated from view stored in JalviewXML
3172 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
3173 * sync if this is set to true.
3175 private final boolean updateLocalViews = false;
3178 * Returns the path to a temporary file holding the PDB file for the given PDB
3179 * id. The first time of asking, searches for a file of that name in the
3180 * Jalview project jar, and copies it to a new temporary file. Any repeat
3181 * requests just return the path to the file previously created.
3187 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId,
3190 if (alreadyLoadedPDB.containsKey(pdbId))
3192 return alreadyLoadedPDB.get(pdbId).toString();
3195 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb",
3197 if (tempFile != null)
3199 alreadyLoadedPDB.put(pdbId, tempFile);
3205 * Copies the jar entry of given name to a new temporary file and returns the
3206 * path to the file, or null if the entry is not found.
3209 * @param jarEntryName
3211 * a prefix for the temporary file name, must be at least three
3214 * null or original file - so new file can be given the same suffix
3218 protected String copyJarEntry(jarInputStreamProvider jprovider,
3219 String jarEntryName, String prefix, String origFile)
3221 BufferedReader in = null;
3222 PrintWriter out = null;
3223 String suffix = ".tmp";
3224 if (origFile == null)
3226 origFile = jarEntryName;
3228 int sfpos = origFile.lastIndexOf(".");
3229 if (sfpos > -1 && sfpos < (origFile.length() - 3))
3231 suffix = "." + origFile.substring(sfpos + 1);
3235 JarInputStream jin = jprovider.getJarInputStream();
3237 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
3238 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
3239 * FileInputStream(jprovider)); }
3242 JarEntry entry = null;
3245 entry = jin.getNextJarEntry();
3246 } while (entry != null && !entry.getName().equals(jarEntryName));
3249 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
3250 File outFile = File.createTempFile(prefix, suffix);
3251 outFile.deleteOnExit();
3252 out = new PrintWriter(new FileOutputStream(outFile));
3255 while ((data = in.readLine()) != null)
3260 String t = outFile.getAbsolutePath();
3265 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
3267 } catch (Exception ex)
3269 ex.printStackTrace();
3277 } catch (IOException e)
3291 private class JvAnnotRow
3293 public JvAnnotRow(int i, AlignmentAnnotation jaa)
3300 * persisted version of annotation row from which to take vis properties
3302 public jalview.datamodel.AlignmentAnnotation template;
3305 * original position of the annotation row in the alignment
3311 * Load alignment frame from jalview XML DOM object. For a DOM object that
3312 * includes one or more Viewport elements (one with a title that does NOT
3313 * contain "Dataset for"), create the frame.
3315 * @param jalviewModel
3318 * filename source string
3319 * @param loadTreesAndStructures
3320 * when false only create Viewport
3322 * data source provider
3323 * @return alignment frame created from view stored in DOM
3325 AlignFrame loadFromObject(JalviewModel jalviewModel, String file,
3326 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
3329 // Platform.timeCheck("Jalview2XML.loadFromObject0", Platform.TIME_MARK);
3331 SequenceSet vamsasSet = jalviewModel.getVamsasModel().getSequenceSet().get(0);
3332 List<Sequence> vamsasSeqs = vamsasSet.getSequence();
3335 // JalviewModelSequence jms = object.getJalviewModelSequence();
3337 // Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
3339 Viewport view = (jalviewModel.getViewport().size() > 0)
3340 ? jalviewModel.getViewport().get(0)
3343 // ////////////////////////////////
3344 // INITIALISE ALIGNMENT SEQUENCESETID AND VIEWID
3347 // If we just load in the same jar file again, the sequenceSetId
3348 // will be the same, and we end up with multiple references
3349 // to the same sequenceSet. We must modify this id on load
3350 // so that each load of the file gives a unique id
3353 * used to resolve correct alignment dataset for alignments with multiple
3356 String uniqueSeqSetId = null;
3357 String viewId = null;
3360 uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3361 viewId = (view.getId() == null ? null
3362 : view.getId() + uniqueSetSuffix);
3365 // Platform.timeCheck("Jalview2XML.loadFromObject1", Platform.TIME_MARK);
3366 // ////////////////////////////////
3369 List<SequenceI> hiddenSeqs = null;
3371 List<SequenceI> tmpseqs = new ArrayList<>();
3373 boolean multipleView = false;
3374 SequenceI referenceseqForView = null;
3375 // JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
3376 List<JSeq> jseqs = jalviewModel.getJSeq();
3377 int vi = 0; // counter in vamsasSeq array
3378 for (int i = 0; i < jseqs.size(); i++)
3380 JSeq jseq = jseqs.get(i);
3381 String seqId = jseq.getId();
3383 SequenceI tmpSeq = seqRefIds.get(seqId);
3387 if (!incompleteSeqs.containsKey(seqId))
3389 // may not need this check, but keep it for at least 2.9,1 release
3390 if (tmpSeq.getStart() != jseq.getStart()
3391 || tmpSeq.getEnd() != jseq.getEnd())
3394 "Warning JAL-2154 regression: updating start/end for sequence "
3395 + tmpSeq.toString() + " to " + jseq);
3400 incompleteSeqs.remove(seqId);
3402 if (vamsasSeqs.size() > vi
3403 && vamsasSeqs.get(vi).getId().equals(seqId))
3405 // most likely we are reading a dataset XML document so
3406 // update from vamsasSeq section of XML for this sequence
3407 tmpSeq.setName(vamsasSeqs.get(vi).getName());
3408 tmpSeq.setDescription(vamsasSeqs.get(vi).getDescription());
3409 tmpSeq.setSequence(vamsasSeqs.get(vi).getSequence());
3414 // reading multiple views, so vamsasSeq set is a subset of JSeq
3415 multipleView = true;
3417 tmpSeq.setStart(jseq.getStart());
3418 tmpSeq.setEnd(jseq.getEnd());
3419 tmpseqs.add(tmpSeq);
3423 Sequence vamsasSeq = vamsasSeqs.get(vi);
3424 tmpSeq = new jalview.datamodel.Sequence(vamsasSeq.getName(),
3425 vamsasSeq.getSequence());
3426 tmpSeq.setDescription(vamsasSeq.getDescription());
3427 tmpSeq.setStart(jseq.getStart());
3428 tmpSeq.setEnd(jseq.getEnd());
3429 tmpSeq.setVamsasId(uniqueSetSuffix + seqId);
3430 seqRefIds.put(vamsasSeq.getId(), tmpSeq);
3431 tmpseqs.add(tmpSeq);
3435 if (safeBoolean(jseq.isViewreference()))
3437 referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
3440 if (jseq.isHidden() != null && jseq.isHidden().booleanValue())
3442 if (hiddenSeqs == null)
3444 hiddenSeqs = new ArrayList<>();
3447 hiddenSeqs.add(tmpSeq);
3451 // Platform.timeCheck("Jalview2XML.loadFromObject-seq",
3452 // Platform.TIME_MARK);
3454 // Create the alignment object from the sequence set
3455 // ///////////////////////////////
3456 SequenceI[] orderedSeqs = tmpseqs
3457 .toArray(new SequenceI[tmpseqs.size()]);
3459 AlignmentI al = null;
3460 // so we must create or recover the dataset alignment before going further
3461 // ///////////////////////////////
3462 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
3464 // older jalview projects do not have a dataset - so creat alignment and
3466 al = new Alignment(orderedSeqs);
3467 al.setDataset(null);
3471 boolean isdsal = jalviewModel.getViewport().isEmpty();
3474 // we are importing a dataset record, so
3475 // recover reference to an alignment already materialsed as dataset
3476 al = getDatasetFor(vamsasSet.getDatasetId());
3480 // materialse the alignment
3481 al = new Alignment(orderedSeqs);
3485 addDatasetRef(vamsasSet.getDatasetId(), al);
3488 // finally, verify all data in vamsasSet is actually present in al
3489 // passing on flag indicating if it is actually a stored dataset
3490 recoverDatasetFor(vamsasSet, al, isdsal, uniqueSeqSetId);
3493 // Platform.timeCheck("Jalview2XML.loadFromObject-align",
3494 // Platform.TIME_MARK);
3495 if (referenceseqForView != null)
3497 al.setSeqrep(referenceseqForView);
3499 // / Add the alignment properties
3500 for (int i = 0; i < vamsasSet.getSequenceSetProperties().size(); i++)
3502 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties()
3504 al.setProperty(ssp.getKey(), ssp.getValue());
3507 // Platform.timeCheck("Jalview2XML.loadFromObject-setseqprop",
3508 // Platform.TIME_MARK);
3509 // ///////////////////////////////
3511 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
3514 // load sequence features, database references and any associated PDB
3515 // structures for the alignment
3517 // prior to 2.10, this part would only be executed the first time a
3518 // sequence was encountered, but not afterwards.
3519 // now, for 2.10 projects, this is also done if the xml doc includes
3520 // dataset sequences not actually present in any particular view.
3522 Platform.timeCheck("J2XML features0", Platform.TIME_MARK);
3523 for (int i = 0; i < vamsasSeqs.size(); i++)
3525 JSeq jseq = jseqs.get(i);
3526 if (jseq.getFeatures().size() > 0)
3528 List<Feature> features = jseq.getFeatures();
3529 for (int f = 0; f < features.size(); f++)
3531 Feature feat = features.get(f);
3532 SequenceFeature sf = new SequenceFeature(feat.getType(),
3533 feat.getDescription(), feat.getBegin(), feat.getEnd(),
3534 safeFloat(feat.getScore()), feat.getFeatureGroup());
3535 sf.setStatus(feat.getStatus());
3538 * load any feature attributes - include map-valued attributes
3540 Map<String, Map<String, String>> mapAttributes = new HashMap<>();
3541 for (int od = 0; od < feat.getOtherData().size(); od++)
3543 OtherData keyValue = feat.getOtherData().get(od);
3544 String attributeName = keyValue.getKey();
3545 String attributeValue = keyValue.getValue();
3546 if (attributeName.startsWith("LINK"))
3548 sf.addLink(attributeValue);
3552 String subAttribute = keyValue.getKey2();
3553 if (subAttribute == null)
3555 // simple string-valued attribute
3556 sf.setValue(attributeName, attributeValue);
3560 // attribute 'key' has sub-attribute 'key2'
3561 if (!mapAttributes.containsKey(attributeName))
3563 mapAttributes.put(attributeName, new HashMap<>());
3565 mapAttributes.get(attributeName).put(subAttribute,
3570 for (Entry<String, Map<String, String>> mapAttribute : mapAttributes
3573 sf.setValue(mapAttribute.getKey(), mapAttribute.getValue());
3576 // adds feature to datasequence's feature set (since Jalview 2.10)
3577 al.getSequenceAt(i).addSequenceFeature(sf);
3580 Platform.timeCheck("J2XML features done", Platform.TIME_MARK);
3582 if (vamsasSeqs.get(i).getDBRef().size() > 0)
3584 // adds dbrefs to datasequence's set (since Jalview 2.10)
3586 al.getSequenceAt(i).getDatasetSequence() == null
3587 ? al.getSequenceAt(i)
3588 : al.getSequenceAt(i).getDatasetSequence(),
3591 if (jseq.getPdbids().size() > 0)
3593 List<Pdbids> ids = jseq.getPdbids();
3594 for (int p = 0; p < ids.size(); p++)
3596 Pdbids pdbid = ids.get(p);
3597 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
3598 entry.setId(pdbid.getId());
3599 if (pdbid.getType() != null)
3601 if (PDBEntry.Type.getType(pdbid.getType()) != null)
3603 entry.setType(PDBEntry.Type.getType(pdbid.getType()));
3607 entry.setType(PDBEntry.Type.FILE);
3610 // jprovider is null when executing 'New View'
3611 if (pdbid.getFile() != null && jprovider != null)
3613 if (!pdbloaded.containsKey(pdbid.getFile()))
3615 entry.setFile(loadPDBFile(jprovider, pdbid.getId(),
3620 entry.setFile(pdbloaded.get(pdbid.getId()).toString());
3624 if (pdbid.getPdbentryItem() != null)
3626 for (PdbentryItem item : pdbid.getPdbentryItem())
3628 for (Property pr : item.getProperty())
3630 entry.setProperty(pr.getName(), pr.getValue());
3635 for (Property prop : pdbid.getProperty())
3637 entry.setProperty(prop.getName(), prop.getValue());
3639 Desktop.getInstance().getStructureSelectionManager()
3640 .registerPDBEntry(entry);
3641 // adds PDBEntry to datasequence's set (since Jalview 2.10)
3642 if (al.getSequenceAt(i).getDatasetSequence() != null)
3644 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
3648 al.getSequenceAt(i).addPDBId(entry);
3653 // Platform.timeCheck("Jalview2XML.loadFromObject-endmultiview",
3654 // Platform.TIME_MARK);
3655 } // end !multipleview
3657 // ///////////////////////////////
3658 // LOAD SEQUENCE MAPPINGS
3660 if (vamsasSet.getAlcodonFrame().size() > 0)
3662 // TODO Potentially this should only be done once for all views of an
3664 List<AlcodonFrame> alc = vamsasSet.getAlcodonFrame();
3665 for (int i = 0; i < alc.size(); i++)
3667 AlignedCodonFrame cf = new AlignedCodonFrame();
3668 if (alc.get(i).getAlcodMap().size() > 0)
3670 List<AlcodMap> maps = alc.get(i).getAlcodMap();
3671 for (int m = 0; m < maps.size(); m++)
3673 AlcodMap map = maps.get(m);
3674 SequenceI dnaseq = seqRefIds.get(map.getDnasq());
3676 jalview.datamodel.Mapping mapping = null;
3677 // attach to dna sequence reference.
3678 if (map.getMapping() != null)
3680 mapping = addMapping(map.getMapping());
3681 if (dnaseq != null && mapping.getTo() != null)
3683 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
3689 newAlcodMapRef(map.getDnasq(), cf, mapping));
3693 al.addCodonFrame(cf);
3696 // Platform.timeCheck("Jalview2XML.loadFromObject-seqmap",
3697 // Platform.TIME_MARK);
3700 // ////////////////////////////////
3702 List<JvAnnotRow> autoAlan = new ArrayList<>();
3705 * store any annotations which forward reference a group's ID
3707 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<>();
3709 if (vamsasSet.getAnnotation().size()/*Count()*/ > 0)
3711 List<Annotation> an = vamsasSet.getAnnotation();
3713 for (int i = 0; i < an.size(); i++)
3715 Annotation annotation = an.get(i);
3718 * test if annotation is automatically calculated for this view only
3720 boolean autoForView = false;
3721 if (annotation.getLabel().equals("Quality")
3722 || annotation.getLabel().equals("Conservation")
3723 || annotation.getLabel().equals("Consensus"))
3725 // Kludge for pre 2.5 projects which lacked the autocalculated flag
3727 // JAXB has no has() test; schema defaults value to false
3728 // if (!annotation.hasAutoCalculated())
3730 // annotation.setAutoCalculated(true);
3733 if (autoForView || annotation.isAutoCalculated())
3735 // remove ID - we don't recover annotation from other views for
3736 // view-specific annotation
3737 annotation.setId(null);
3740 // set visibility for other annotation in this view
3741 String annotationId = annotation.getId();
3742 if (annotationId != null && annotationIds.containsKey(annotationId))
3744 AlignmentAnnotation jda = annotationIds.get(annotationId);
3745 // in principle Visible should always be true for annotation displayed
3746 // in multiple views
3747 if (annotation.isVisible() != null)
3749 jda.visible = annotation.isVisible();
3752 al.addAnnotation(jda);
3756 // Construct new annotation from model.
3757 List<AnnotationElement> ae = annotation.getAnnotationElement();
3758 // System.err.println(
3759 // "Jalview2XML processing " + ae.size() + " annotations");
3761 jalview.datamodel.Annotation[] anot = null;
3762 java.awt.Color firstColour = null;
3764 if (!annotation.isScoreOnly())
3766 anot = new jalview.datamodel.Annotation[al.getWidth()];
3767 for (int aa = 0; aa < ae.size() && aa < anot.length; aa++)
3769 AnnotationElement annElement = ae.get(aa);
3770 anpos = annElement.getPosition();
3772 if (anpos >= anot.length)
3777 float value = safeFloat(annElement.getValue());
3778 anot[anpos] = new jalview.datamodel.Annotation(
3779 annElement.getDisplayCharacter(),
3780 annElement.getDescription(),
3781 (annElement.getSecondaryStructure() == null
3782 || annElement.getSecondaryStructure()
3786 .getSecondaryStructure()
3789 anot[anpos].colour = new Color(safeInt(annElement.getColour()));
3790 if (firstColour == null)
3792 firstColour = anot[anpos].colour;
3796 // create the new AlignmentAnnotation
3797 jalview.datamodel.AlignmentAnnotation jaa = null;
3799 if (annotation.isGraph())
3801 float llim = 0, hlim = 0;
3802 // if (autoForView || an[i].isAutoCalculated()) {
3805 jaa = new jalview.datamodel.AlignmentAnnotation(
3806 annotation.getLabel(), annotation.getDescription(), anot,
3807 llim, hlim, safeInt(annotation.getGraphType()));
3809 jaa.graphGroup = safeInt(annotation.getGraphGroup());
3810 jaa._linecolour = firstColour;
3811 if (annotation.getThresholdLine() != null)
3813 jaa.setThreshold(new jalview.datamodel.GraphLine(
3814 safeFloat(annotation.getThresholdLine().getValue()),
3815 annotation.getThresholdLine().getLabel(),
3816 new java.awt.Color(safeInt(
3817 annotation.getThresholdLine().getColour()))));
3819 if (autoForView || annotation.isAutoCalculated())
3821 // Hardwire the symbol display line to ensure that labels for
3822 // histograms are displayed
3828 jaa = new jalview.datamodel.AlignmentAnnotation(
3829 annotation.getLabel(), annotation.getDescription(), anot);
3830 jaa._linecolour = firstColour;
3832 // register new annotation
3833 // Annotation graphs such as Conservation will not have id.
3834 if (annotation.getId() != null)
3836 annotationIds.put(annotation.getId(), jaa);
3837 jaa.annotationId = annotation.getId();
3839 // recover sequence association
3840 String sequenceRef = annotation.getSequenceRef();
3841 if (sequenceRef != null)
3843 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3844 SequenceI sequence = seqRefIds.get(sequenceRef);
3845 if (sequence == null)
3847 // in pre-2.9 projects sequence ref is to sequence name
3848 sequence = al.findName(sequenceRef);
3850 if (sequence != null)
3852 jaa.createSequenceMapping(sequence, 1, true);
3853 sequence.addAlignmentAnnotation(jaa);
3856 // and make a note of any group association
3857 if (annotation.getGroupRef() != null
3858 && annotation.getGroupRef().length() > 0)
3860 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3861 .get(annotation.getGroupRef());
3864 aal = new ArrayList<>();
3865 groupAnnotRefs.put(annotation.getGroupRef(), aal);
3870 if (annotation.getScore() != null)
3872 jaa.setScore(annotation.getScore().doubleValue());
3874 if (annotation.isVisible() != null)
3876 jaa.visible = annotation.isVisible().booleanValue();
3879 if (annotation.isCentreColLabels() != null)
3881 jaa.centreColLabels = annotation.isCentreColLabels()
3885 if (annotation.isScaleColLabels() != null)
3887 jaa.scaleColLabel = annotation.isScaleColLabels().booleanValue();
3889 if (annotation.isAutoCalculated())
3891 // newer files have an 'autoCalculated' flag and store calculation
3892 // state in viewport properties
3893 jaa.autoCalculated = true; // means annotation will be marked for
3894 // update at end of load.
3896 if (annotation.getGraphHeight() != null)
3898 jaa.graphHeight = annotation.getGraphHeight().intValue();
3900 jaa.belowAlignment = annotation.isBelowAlignment();
3901 jaa.setCalcId(annotation.getCalcId());
3902 if (annotation.getProperty().size() > 0)
3904 for (Annotation.Property prop : annotation
3907 jaa.setProperty(prop.getName(), prop.getValue());
3910 if (jaa.autoCalculated)
3912 autoAlan.add(new JvAnnotRow(i, jaa));
3915 // if (!autoForView)
3917 // add autocalculated group annotation and any user created annotation
3919 al.addAnnotation(jaa);
3922 // Platform.timeCheck("Jalview2XML.loadFromObject-annot",
3923 // Platform.TIME_MARK);
3925 // ///////////////////////
3927 // Create alignment markup and styles for this view
3928 if (jalviewModel.getJGroup().size() > 0)
3930 List<JGroup> groups = jalviewModel.getJGroup();
3931 boolean addAnnotSchemeGroup = false;
3932 for (int i = 0; i < groups.size(); i++)
3934 JGroup jGroup = groups.get(i);
3935 ColourSchemeI cs = null;
3936 if (jGroup.getColour() != null)
3938 if (jGroup.getColour().startsWith("ucs"))
3940 cs = getUserColourScheme(jalviewModel, jGroup.getColour());
3942 else if (jGroup.getColour().equals("AnnotationColourGradient")
3943 && jGroup.getAnnotationColours() != null)
3945 addAnnotSchemeGroup = true;
3949 cs = ColourSchemeProperty.getColourScheme(null, al,
3950 jGroup.getColour());
3953 int pidThreshold = safeInt(jGroup.getPidThreshold());
3955 Vector<SequenceI> seqs = new Vector<>();
3957 for (int s = 0; s < jGroup.getSeq().size(); s++)
3959 String seqId = jGroup.getSeq().get(s);
3960 SequenceI ts = seqRefIds.get(seqId);
3964 seqs.addElement(ts);
3968 if (seqs.size() < 1)
3973 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3974 safeBoolean(jGroup.isDisplayBoxes()),
3975 safeBoolean(jGroup.isDisplayText()),
3976 safeBoolean(jGroup.isColourText()),
3977 safeInt(jGroup.getStart()), safeInt(jGroup.getEnd()));
3978 sg.getGroupColourScheme().setThreshold(pidThreshold, true);
3979 sg.getGroupColourScheme()
3980 .setConservationInc(safeInt(jGroup.getConsThreshold()));
3981 sg.setOutlineColour(new Color(safeInt(jGroup.getOutlineColour())));
3983 sg.textColour = new Color(safeInt(jGroup.getTextCol1()));
3984 sg.textColour2 = new Color(safeInt(jGroup.getTextCol2()));
3985 sg.setShowNonconserved(safeBoolean(jGroup.isShowUnconserved()));
3986 sg.thresholdTextColour = safeInt(jGroup.getTextColThreshold());
3987 // attributes with a default in the schema are never null
3988 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3989 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3990 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3991 sg.setIgnoreGapsConsensus(jGroup.isIgnoreGapsinConsensus());
3992 if (jGroup.getConsThreshold() != null
3993 && jGroup.getConsThreshold().intValue() != 0)
3995 Conservation c = new Conservation("All", sg.getSequences(null), 0,
3998 c.verdict(false, 25);
3999 sg.cs.setConservation(c);
4002 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
4004 // re-instate unique group/annotation row reference
4005 List<AlignmentAnnotation> jaal = groupAnnotRefs
4006 .get(jGroup.getId());
4009 for (AlignmentAnnotation jaa : jaal)
4012 if (jaa.autoCalculated)
4014 // match up and try to set group autocalc alignment row for this
4016 if (jaa.label.startsWith("Consensus for "))
4018 sg.setConsensus(jaa);
4020 // match up and try to set group autocalc alignment row for this
4022 if (jaa.label.startsWith("Conservation for "))
4024 sg.setConservationRow(jaa);
4031 if (addAnnotSchemeGroup)
4033 // reconstruct the annotation colourscheme
4034 sg.setColourScheme(constructAnnotationColour(
4035 jGroup.getAnnotationColours(), null, al, jalviewModel, false));
4038 // Platform.timeCheck("Jalview2XML.loadFromObject-groups",
4039 // Platform.TIME_MARK);
4043 // only dataset in this model, so just return.
4046 // ///////////////////////////////
4049 // now check to see if we really need to create a new viewport.
4050 if (multipleView && viewportsAdded.size() == 0)
4052 // We recovered an alignment for which a viewport already exists.
4053 // TODO: fix up any settings necessary for overlaying stored state onto
4054 // state recovered from another document. (may not be necessary).
4055 // we may need a binding from a viewport in memory to one recovered from
4057 // and then recover its containing af to allow the settings to be applied.
4058 // TODO: fix for vamsas demo
4060 "About to recover a viewport for existing alignment: Sequence set ID is "
4062 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
4063 if (seqsetobj != null)
4065 if (seqsetobj instanceof String)
4067 uniqueSeqSetId = (String) seqsetobj;
4069 "Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
4075 "Warning : Collision between sequence set ID string and existing jalview object mapping.");
4079 // Platform.timeCheck("Jalview2XML.loadFromObject-viewport",
4080 // Platform.TIME_MARK);
4083 * indicate that annotation colours are applied across all groups (pre
4084 * Jalview 2.8.1 behaviour)
4086 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan("2.8.1",
4087 jalviewModel.getVersion());
4089 AlignFrame af = null;
4090 AlignmentPanel ap = null;
4091 AlignViewport av = null;
4094 // Check to see if this alignment already has a view id == viewId
4095 jalview.gui.AlignmentPanel views[] = Desktop
4096 .getAlignmentPanels(uniqueSeqSetId);
4097 if (views != null && views.length > 0)
4099 for (int v = 0; v < views.length; v++)
4103 if (av.getViewId().equalsIgnoreCase(viewId))
4105 // recover the existing alignpanel, alignframe, viewport
4108 // TODO: could even skip resetting view settings if we don't want to
4109 // change the local settings from other jalview processes
4117 af = loadViewport(file, jseqs, hiddenSeqs, al, jalviewModel, view,
4118 uniqueSeqSetId, viewId, autoAlan);
4119 av = af.getViewport();
4120 // note that this only retrieves the most recently accessed
4121 // tab of an AlignFrame.
4126 * Load any trees, PDB structures and viewers
4128 * Not done if flag is false (when this method is used for New View)
4130 final AlignFrame af0 = af;
4131 final AlignViewport av0 = av;
4132 final AlignmentPanel ap0 = ap;
4133 // Platform.timeCheck("Jalview2XML.loadFromObject-beforetree",
4134 // Platform.TIME_MARK);
4135 if (loadTreesAndStructures)
4137 if (!jalviewModel.getTree().isEmpty())
4139 SwingUtilities.invokeLater(new Runnable()
4144 // Platform.timeCheck(null, Platform.TIME_MARK);
4145 loadTrees(jalviewModel, view, af0, av0, ap0);
4146 // Platform.timeCheck("Jalview2XML.loadTrees", Platform.TIME_MARK);
4150 if (!jalviewModel.getPcaViewer().isEmpty())
4152 SwingUtilities.invokeLater(new Runnable()
4157 // Platform.timeCheck(null, Platform.TIME_MARK);
4158 loadPCAViewers(jalviewModel, ap0);
4159 // Platform.timeCheck("Jalview2XML.loadPCA", Platform.TIME_MARK);
4163 SwingUtilities.invokeLater(new Runnable()
4168 // Platform.timeCheck(null, Platform.TIME_MARK);
4169 loadPDBStructures(jprovider, jseqs, af0, ap0);
4170 // Platform.timeCheck("Jalview2XML.loadPDB", Platform.TIME_MARK);
4173 SwingUtilities.invokeLater(new Runnable()
4178 loadRnaViewers(jprovider, jseqs, ap0);
4182 // and finally return.
4187 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
4188 * panel is restored from separate jar entries, two (gapped and trimmed) per
4189 * sequence and secondary structure.
4191 * Currently each viewer shows just one sequence and structure (gapped and
4192 * trimmed), however this method is designed to support multiple sequences or
4193 * structures in viewers if wanted in future.
4199 protected void loadRnaViewers(jarInputStreamProvider jprovider,
4200 List<JSeq> jseqs, AlignmentPanel ap)
4203 * scan the sequences for references to viewers; create each one the first
4204 * time it is referenced, add Rna models to existing viewers
4206 for (JSeq jseq : jseqs)
4208 for (int i = 0; i < jseq.getRnaViewer().size(); i++)
4210 RnaViewer viewer = jseq.getRnaViewer().get(i);
4211 AppVarna appVarna = findOrCreateVarnaViewer(viewer, uniqueSetSuffix,
4214 for (int j = 0; j < viewer.getSecondaryStructure().size(); j++)
4216 SecondaryStructure ss = viewer.getSecondaryStructure().get(j);
4217 SequenceI seq = seqRefIds.get(jseq.getId());
4218 AlignmentAnnotation ann = this.annotationIds
4219 .get(ss.getAnnotationId());
4222 * add the structure to the Varna display (with session state copied
4223 * from the jar to a temporary file)
4225 boolean gapped = safeBoolean(ss.isGapped());
4226 String rnaTitle = ss.getTitle();
4227 String sessionState = ss.getViewerState();
4228 String tempStateFile = copyJarEntry(jprovider, sessionState,
4230 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
4231 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
4233 appVarna.setInitialSelection(safeInt(viewer.getSelectedRna()));
4239 * Locate and return an already instantiated matching AppVarna, or create one
4243 * @param viewIdSuffix
4247 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
4248 String viewIdSuffix, AlignmentPanel ap)
4251 * on each load a suffix is appended to the saved viewId, to avoid conflicts
4252 * if load is repeated
4254 String postLoadId = viewer.getViewId() + viewIdSuffix;
4255 for (JInternalFrame frame : getAllFrames())
4257 if (frame instanceof AppVarna)
4259 AppVarna varna = (AppVarna) frame;
4260 if (postLoadId.equals(varna.getViewId()))
4262 // this viewer is already instantiated
4263 // could in future here add ap as another 'parent' of the
4264 // AppVarna window; currently just 1-to-many
4271 * viewer not found - make it
4273 RnaViewerModel model = new RnaViewerModel(postLoadId, viewer.getTitle(),
4274 safeInt(viewer.getXpos()), safeInt(viewer.getYpos()),
4275 safeInt(viewer.getWidth()), safeInt(viewer.getHeight()),
4276 safeInt(viewer.getDividerLocation()));
4277 AppVarna varna = new AppVarna(model, ap);
4283 * Load any saved trees
4291 protected void loadTrees(JalviewModel jm, Viewport view,
4292 AlignFrame af, AlignViewport av, AlignmentPanel ap)
4294 // TODO result of automated refactoring - are all these parameters needed?
4297 for (int t = 0; t < jm.getTree().size(); t++)
4300 Tree tree = jm.getTree().get(t);
4302 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
4305 tp = af.showNewickTree(new NewickFile(tree.getNewick()),
4306 tree.getTitle(), safeInt(tree.getWidth()),
4307 safeInt(tree.getHeight()), safeInt(tree.getXpos()),
4308 safeInt(tree.getYpos()));
4309 if (tree.getId() != null)
4311 // perhaps bind the tree id to something ?
4316 // update local tree attributes ?
4317 // TODO: should check if tp has been manipulated by user - if so its
4318 // settings shouldn't be modified
4319 tp.setTitle(tree.getTitle());
4320 tp.setBounds(new Rectangle(safeInt(tree.getXpos()),
4321 safeInt(tree.getYpos()), safeInt(tree.getWidth()),
4322 safeInt(tree.getHeight())));
4323 tp.setViewport(av); // af.viewport;
4324 // TODO: verify 'associate with all views' works still
4325 tp.getTreeCanvas().setViewport(av); // af.viewport;
4326 tp.getTreeCanvas().setAssociatedPanel(ap); // af.alignPanel;
4328 tp.getTreeCanvas().setApplyToAllViews(tree.isLinkToAllViews());
4331 warn("There was a problem recovering stored Newick tree: \n"
4332 + tree.getNewick());
4336 tp.fitToWindow.setState(safeBoolean(tree.isFitToWindow()));
4337 tp.fitToWindow_actionPerformed(null);
4339 if (tree.getFontName() != null)
4342 new Font(tree.getFontName(), safeInt(tree.getFontStyle()),
4343 safeInt(tree.getFontSize())));
4348 new Font(view.getFontName(), safeInt(view.getFontStyle()),
4349 safeInt(view.getFontSize())));
4352 tp.showPlaceholders(safeBoolean(tree.isMarkUnlinked()));
4353 tp.showBootstrap(safeBoolean(tree.isShowBootstrap()));
4354 tp.showDistances(safeBoolean(tree.isShowDistances()));
4356 tp.getTreeCanvas().setThreshold(safeFloat(tree.getThreshold()));
4358 if (safeBoolean(tree.isCurrentTree()))
4360 af.getViewport().setCurrentTree(tp.getTree());
4364 } catch (Exception ex)
4366 ex.printStackTrace();
4371 * Load and link any saved structure viewers.
4378 protected void loadPDBStructures(jarInputStreamProvider jprovider,
4379 List<JSeq> jseqs, AlignFrame af, AlignmentPanel ap)
4382 * Run through all PDB ids on the alignment, and collect mappings between
4383 * distinct view ids and all sequences referring to that view.
4385 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<>();
4387 for (int i = 0; i < jseqs.size(); i++)
4389 JSeq jseq = jseqs.get(i);
4390 if (jseq.getPdbids().size() > 0)
4392 List<Pdbids> ids = jseq.getPdbids();
4393 for (int p = 0; p < ids.size(); p++)
4395 Pdbids pdbid = ids.get(p);
4396 final int structureStateCount = pdbid.getStructureState().size();
4397 for (int s = 0; s < structureStateCount; s++)
4399 // check to see if we haven't already created this structure view
4400 final StructureState structureState = pdbid
4401 .getStructureState().get(s);
4402 String sviewid = (structureState.getViewId() == null) ? null
4403 : structureState.getViewId() + uniqueSetSuffix;
4404 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
4405 // Originally : pdbid.getFile()
4406 // : TODO: verify external PDB file recovery still works in normal
4407 // jalview project load
4409 loadPDBFile(jprovider, pdbid.getId(), pdbid.getFile()));
4410 jpdb.setId(pdbid.getId());
4412 int x = safeInt(structureState.getXpos());
4413 int y = safeInt(structureState.getYpos());
4414 int width = safeInt(structureState.getWidth());
4415 int height = safeInt(structureState.getHeight());
4417 // Probably don't need to do this anymore...
4418 // Desktop.getDesktop().getComponentAt(x, y);
4419 // TODO: NOW: check that this recovers the PDB file correctly.
4420 String pdbFile = loadPDBFile(jprovider, pdbid.getId(),
4422 jalview.datamodel.SequenceI seq = seqRefIds
4423 .get(jseq.getId() + "");
4424 if (sviewid == null)
4426 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width + ","
4429 if (!structureViewers.containsKey(sviewid))
4431 structureViewers.put(sviewid,
4432 new StructureViewerModel(x, y, width, height, false,
4433 false, true, structureState.getViewId(),
4434 structureState.getType()));
4435 // Legacy pre-2.7 conversion JAL-823 :
4436 // do not assume any view has to be linked for colour by
4440 // assemble String[] { pdb files }, String[] { id for each
4441 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
4442 // seqs_file 2}, boolean[] {
4443 // linkAlignPanel,superposeWithAlignpanel}} from hash
4444 StructureViewerModel jmoldat = structureViewers.get(sviewid);
4445 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
4446 || structureState.isAlignwithAlignPanel());
4449 * Default colour by linked panel to false if not specified (e.g.
4450 * for pre-2.7 projects)
4452 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
4453 colourWithAlignPanel |= structureState.isColourwithAlignPanel();
4454 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
4457 * Default colour by viewer to true if not specified (e.g. for
4460 boolean colourByViewer = jmoldat.isColourByViewer();
4461 colourByViewer &= structureState.isColourByJmol();
4462 jmoldat.setColourByViewer(colourByViewer);
4464 if (jmoldat.getStateData().length() < structureState
4465 .getValue()/*Content()*/.length())
4467 jmoldat.setStateData(structureState.getValue());// Content());
4469 if (pdbid.getFile() != null)
4471 File mapkey = new File(pdbid.getFile());
4472 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
4473 if (seqstrmaps == null)
4475 jmoldat.getFileData().put(mapkey,
4476 seqstrmaps = jmoldat.new StructureData(pdbFile,
4479 if (!seqstrmaps.getSeqList().contains(seq))
4481 seqstrmaps.getSeqList().add(seq);
4487 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");
4494 // Instantiate the associated structure views
4495 for (Entry<String, StructureViewerModel> entry : structureViewers
4500 createOrLinkStructureViewer(entry, af, ap, jprovider);
4501 } catch (Exception e)
4504 "Error loading structure viewer: " + e.getMessage());
4505 // failed - try the next one
4517 protected void createOrLinkStructureViewer(
4518 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4519 AlignmentPanel ap, jarInputStreamProvider jprovider)
4521 final StructureViewerModel stateData = viewerData.getValue();
4524 * Search for any viewer windows already open from other alignment views
4525 * that exactly match the stored structure state
4527 StructureViewerBase comp = findMatchingViewer(viewerData);
4531 linkStructureViewer(ap, comp, stateData);
4536 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
4537 * "viewer_"+stateData.viewId
4539 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
4541 createChimeraViewer(viewerData, af, jprovider);
4546 * else Jmol (if pre-2.9, stateData contains JMOL state string)
4548 createJmolViewer(viewerData, af, jprovider);
4553 * Create a new Chimera viewer.
4559 protected void createChimeraViewer(
4560 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4561 jarInputStreamProvider jprovider)
4563 StructureViewerModel data = viewerData.getValue();
4564 String chimeraSessionFile = data.getStateData();
4567 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
4569 * NB this is the 'saved' viewId as in the project file XML, _not_ the
4570 * 'uniquified' sviewid used to reconstruct the viewer here
4572 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
4573 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
4576 Set<Entry<File, StructureData>> fileData = data.getFileData()
4578 List<PDBEntry> pdbs = new ArrayList<>();
4579 List<SequenceI[]> allseqs = new ArrayList<>();
4580 for (Entry<File, StructureData> pdb : fileData)
4582 String filePath = pdb.getValue().getFilePath();
4583 String pdbId = pdb.getValue().getPdbId();
4584 // pdbs.add(new PDBEntry(filePath, pdbId));
4585 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
4586 final List<SequenceI> seqList = pdb.getValue().getSeqList();
4587 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
4591 boolean colourByChimera = data.isColourByViewer();
4592 boolean colourBySequence = data.isColourWithAlignPanel();
4594 // TODO use StructureViewer as a factory here, see JAL-1761
4595 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
4596 final SequenceI[][] seqsArray = allseqs
4597 .toArray(new SequenceI[allseqs.size()][]);
4598 String newViewId = viewerData.getKey();
4600 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
4601 af.alignPanel, pdbArray, seqsArray, colourByChimera,
4602 colourBySequence, newViewId);
4603 cvf.setSize(data.getWidth(), data.getHeight());
4604 cvf.setLocation(data.getX(), data.getY());
4608 * Create a new Jmol window. First parse the Jmol state to translate filenames
4609 * loaded into the view, and record the order in which files are shown in the
4610 * Jmol view, so we can add the sequence mappings in same order.
4616 protected void createJmolViewer(
4617 final Entry<String, StructureViewerModel> viewerData,
4618 AlignFrame af, jarInputStreamProvider jprovider)
4620 final StructureViewerModel svattrib = viewerData.getValue();
4621 String state = svattrib.getStateData();
4624 * Pre-2.9: state element value is the Jmol state string
4626 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
4629 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
4631 state = readJarEntry(jprovider,
4632 getViewerJarEntryName(svattrib.getViewId()));
4635 List<String> pdbfilenames = new ArrayList<>();
4636 List<SequenceI[]> seqmaps = new ArrayList<>();
4637 List<String> pdbids = new ArrayList<>();
4638 StringBuilder newFileLoc = new StringBuilder(64);
4639 int cp = 0, ncp, ecp;
4640 Map<File, StructureData> oldFiles = svattrib.getFileData();
4641 while ((ncp = state.indexOf("load ", cp)) > -1)
4645 // look for next filename in load statement
4646 newFileLoc.append(state.substring(cp,
4647 ncp = (state.indexOf("\"", ncp + 1) + 1)));
4648 String oldfilenam = state.substring(ncp,
4649 ecp = state.indexOf("\"", ncp));
4650 // recover the new mapping data for this old filename
4651 // have to normalize filename - since Jmol and jalview do
4653 // translation differently.
4654 StructureData filedat = oldFiles.get(new File(oldfilenam));
4655 if (filedat == null)
4657 String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\");
4658 filedat = oldFiles.get(new File(reformatedOldFilename));
4660 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
4661 pdbfilenames.add(filedat.getFilePath());
4662 pdbids.add(filedat.getPdbId());
4663 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4664 newFileLoc.append("\"");
4665 cp = ecp + 1; // advance beyond last \" and set cursor so we can
4666 // look for next file statement.
4667 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
4671 // just append rest of state
4672 newFileLoc.append(state.substring(cp));
4676 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
4677 newFileLoc = new StringBuilder(state);
4678 newFileLoc.append("; load append ");
4679 for (File id : oldFiles.keySet())
4681 // add this and any other pdb files that should be present in
4683 StructureData filedat = oldFiles.get(id);
4684 newFileLoc.append(filedat.getFilePath());
4685 pdbfilenames.add(filedat.getFilePath());
4686 pdbids.add(filedat.getPdbId());
4687 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4688 newFileLoc.append(" \"");
4689 newFileLoc.append(filedat.getFilePath());
4690 newFileLoc.append("\"");
4693 newFileLoc.append(";");
4696 if (newFileLoc.length() == 0)
4700 int histbug = newFileLoc.indexOf("history = ");
4704 * change "history = [true|false];" to "history = [1|0];"
4707 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
4708 String val = (diff == -1) ? null
4709 : newFileLoc.substring(histbug, diff);
4710 if (val != null && val.length() >= 4)
4712 if (val.contains("e")) // eh? what can it be?
4714 if (val.trim().equals("true"))
4722 newFileLoc.replace(histbug, diff, val);
4727 final String[] pdbf = pdbfilenames
4728 .toArray(new String[pdbfilenames.size()]);
4729 final String[] id = pdbids.toArray(new String[pdbids.size()]);
4730 final SequenceI[][] sq = seqmaps
4731 .toArray(new SequenceI[seqmaps.size()][]);
4732 final String fileloc = newFileLoc.toString();
4733 final String sviewid = viewerData.getKey();
4734 final AlignFrame alf = af;
4735 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
4736 svattrib.getWidth(), svattrib.getHeight());
4739 javax.swing.SwingUtilities.invokeLater(new Runnable()
4744 JalviewStructureDisplayI sview = null;
4747 sview = new StructureViewer(
4748 alf.alignPanel.getStructureSelectionManager())
4749 .createView(StructureViewer.ViewerType.JMOL,
4750 pdbf, id, sq, alf.alignPanel, svattrib,
4751 fileloc, rect, sviewid);
4752 addNewStructureViewer(sview);
4753 } catch (OutOfMemoryError ex)
4755 new OOMWarning("restoring structure view for PDB id " + id,
4756 (OutOfMemoryError) ex.getCause());
4757 if (sview != null && sview.isVisible())
4759 sview.closeViewer(false);
4760 sview.setVisible(false);
4766 // } catch (InvocationTargetException ex)
4768 // warn("Unexpected error when opening Jmol view.", ex);
4770 // } catch (InterruptedException e)
4772 // // e.printStackTrace();
4778 * Generates a name for the entry in the project jar file to hold state
4779 * information for a structure viewer
4784 protected String getViewerJarEntryName(String viewId)
4786 return VIEWER_PREFIX + viewId;
4790 * Returns any open frame that matches given structure viewer data. The match
4791 * is based on the unique viewId, or (for older project versions) the frame's
4797 protected StructureViewerBase findMatchingViewer(
4798 Entry<String, StructureViewerModel> viewerData)
4800 final String sviewid = viewerData.getKey();
4801 final StructureViewerModel svattrib = viewerData.getValue();
4802 StructureViewerBase comp = null;
4803 JInternalFrame[] frames = getAllFrames();
4804 for (JInternalFrame frame : frames)
4806 if (frame instanceof StructureViewerBase)
4809 * Post jalview 2.4 schema includes structure view id
4811 if (sviewid != null && ((StructureViewerBase) frame).getViewId()
4814 comp = (StructureViewerBase) frame;
4815 break; // break added in 2.9
4818 * Otherwise test for matching position and size of viewer frame
4820 else if (frame.getX() == svattrib.getX()
4821 && frame.getY() == svattrib.getY()
4822 && frame.getHeight() == svattrib.getHeight()
4823 && frame.getWidth() == svattrib.getWidth())
4825 comp = (StructureViewerBase) frame;
4826 // no break in faint hope of an exact match on viewId
4834 * Link an AlignmentPanel to an existing structure viewer.
4839 * @param useinViewerSuperpos
4840 * @param usetoColourbyseq
4841 * @param viewerColouring
4843 protected void linkStructureViewer(AlignmentPanel ap,
4844 StructureViewerBase viewer, StructureViewerModel stateData)
4846 // NOTE: if the jalview project is part of a shared session then
4847 // view synchronization should/could be done here.
4849 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4850 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4851 final boolean viewerColouring = stateData.isColourByViewer();
4852 Map<File, StructureData> oldFiles = stateData.getFileData();
4855 * Add mapping for sequences in this view to an already open viewer
4857 final AAStructureBindingModel binding = viewer.getBinding();
4858 for (File id : oldFiles.keySet())
4860 // add this and any other pdb files that should be present in the
4862 StructureData filedat = oldFiles.get(id);
4863 String pdbFile = filedat.getFilePath();
4864 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4865 binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE,
4867 binding.addSequenceForStructFile(pdbFile, seq);
4869 // and add the AlignmentPanel's reference to the view panel
4870 viewer.addAlignmentPanel(ap);
4871 if (useinViewerSuperpos)
4873 viewer.useAlignmentPanelForSuperposition(ap);
4877 viewer.excludeAlignmentPanelForSuperposition(ap);
4879 if (usetoColourbyseq)
4881 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4885 viewer.excludeAlignmentPanelForColourbyseq(ap);
4890 * Get all frames within the Desktop.
4894 protected JInternalFrame[] getAllFrames()
4896 JInternalFrame[] frames = null;
4897 // TODO is this necessary - is it safe - risk of hanging?
4902 frames = Desktop.getDesktopPane().getAllFrames();
4903 } catch (ArrayIndexOutOfBoundsException e)
4905 // occasional No such child exceptions are thrown here...
4909 } catch (InterruptedException f)
4913 } while (frames == null);
4918 * Answers true if 'version' is equal to or later than 'supported', where each
4919 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4920 * changes. Development and test values for 'version' are leniently treated
4924 * - minimum version we are comparing against
4926 * - version of data being processsed
4929 public static boolean isVersionStringLaterThan(String supported,
4932 if (supported == null || version == null
4933 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4934 || version.equalsIgnoreCase("Test")
4935 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4937 System.err.println("Assuming project file with "
4938 + (version == null ? "null" : version)
4939 + " is compatible with Jalview version " + supported);
4944 return StringUtils.compareVersions(version, supported, "b") >= 0;
4948 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4950 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4952 if (newStructureViewers != null)
4954 sview.getBinding().setFinishedLoadingFromArchive(false);
4955 newStructureViewers.add(sview);
4959 protected void setLoadingFinishedForNewStructureViewers()
4961 if (newStructureViewers != null)
4963 for (JalviewStructureDisplayI sview : newStructureViewers)
4965 sview.getBinding().setFinishedLoadingFromArchive(true);
4967 newStructureViewers.clear();
4968 newStructureViewers = null;
4972 AlignFrame loadViewport(String file, List<JSeq> JSEQ,
4973 List<SequenceI> hiddenSeqs, AlignmentI al,
4974 JalviewModel jm, Viewport view, String uniqueSeqSetId,
4975 String viewId, List<JvAnnotRow> autoAlan)
4977 AlignFrame af = null;
4978 af = new AlignFrame(al, safeInt(view.getWidth()),
4979 safeInt(view.getHeight()), uniqueSeqSetId, viewId)
4983 // protected void processKeyEvent(java.awt.event.KeyEvent e) {
4984 // System.out.println("Jalview2XML AF " + e);
4985 // super.processKeyEvent(e);
4992 af.setFileName(file, FileFormat.Jalview);
4994 final AlignViewport viewport = af.getViewport();
4995 for (int i = 0; i < JSEQ.size(); i++)
4997 int colour = safeInt(JSEQ.get(i).getColour());
4998 viewport.setSequenceColour(viewport.getAlignment().getSequenceAt(i),
5004 viewport.setColourByReferenceSeq(true);
5005 viewport.setDisplayReferenceSeq(true);
5008 viewport.setGatherViewsHere(safeBoolean(view.isGatheredViews()));
5010 if (view.getSequenceSetId() != null)
5012 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
5014 viewport.setSequenceSetId(uniqueSeqSetId);
5017 // propagate shared settings to this new view
5018 viewport.setHistoryList(av.getHistoryList());
5019 viewport.setRedoList(av.getRedoList());
5023 viewportsAdded.put(uniqueSeqSetId, viewport);
5025 // TODO: check if this method can be called repeatedly without
5026 // side-effects if alignpanel already registered.
5027 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
5029 // apply Hidden regions to view.
5030 if (hiddenSeqs != null)
5032 for (int s = 0; s < JSEQ.size(); s++)
5034 SequenceGroup hidden = new SequenceGroup();
5035 boolean isRepresentative = false;
5036 for (int r = 0; r < JSEQ.get(s).getHiddenSequences().size(); r++)
5038 isRepresentative = true;
5039 SequenceI sequenceToHide = al
5040 .getSequenceAt(JSEQ.get(s).getHiddenSequences().get(r));
5041 hidden.addSequence(sequenceToHide, false);
5042 // remove from hiddenSeqs list so we don't try to hide it twice
5043 hiddenSeqs.remove(sequenceToHide);
5045 if (isRepresentative)
5047 SequenceI representativeSequence = al.getSequenceAt(s);
5048 hidden.addSequence(representativeSequence, false);
5049 viewport.hideRepSequences(representativeSequence, hidden);
5053 SequenceI[] hseqs = hiddenSeqs
5054 .toArray(new SequenceI[hiddenSeqs.size()]);
5055 viewport.hideSequence(hseqs);
5058 // recover view properties and display parameters
5060 viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
5061 viewport.setAbovePIDThreshold(safeBoolean(view.isPidSelected()));
5062 final int pidThreshold = safeInt(view.getPidThreshold());
5063 viewport.setThreshold(pidThreshold);
5065 viewport.setColourText(safeBoolean(view.isShowColourText()));
5068 .setConservationSelected(
5069 safeBoolean(view.isConservationSelected()));
5070 viewport.setIncrement(safeInt(view.getConsThreshold()));
5071 viewport.setShowJVSuffix(safeBoolean(view.isShowFullId()));
5072 viewport.setRightAlignIds(safeBoolean(view.isRightAlignIds()));
5073 viewport.setFont(new Font(view.getFontName(),
5074 safeInt(view.getFontStyle()), safeInt(view.getFontSize())),
5076 ViewStyleI vs = viewport.getViewStyle();
5077 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
5078 viewport.setViewStyle(vs);
5079 // TODO: allow custom charWidth/Heights to be restored by updating them
5080 // after setting font - which means set above to false
5081 viewport.setRenderGaps(safeBoolean(view.isRenderGaps()));
5082 viewport.setWrapAlignment(safeBoolean(view.isWrapAlignment()));
5083 viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
5085 viewport.setShowBoxes(safeBoolean(view.isShowBoxes()));
5087 viewport.setShowText(safeBoolean(view.isShowText()));
5089 viewport.setTextColour(new Color(safeInt(view.getTextCol1())));
5090 viewport.setTextColour2(new Color(safeInt(view.getTextCol2())));
5091 viewport.setThresholdTextColour(safeInt(view.getTextColThreshold()));
5092 viewport.setShowUnconserved(view.isShowUnconserved());
5093 viewport.getRanges().setStartRes(safeInt(view.getStartRes()));
5095 if (view.getViewName() != null)
5097 viewport.setViewName(view.getViewName());
5098 af.setInitialTabVisible();
5100 int x = safeInt(view.getXpos());
5101 int y = safeInt(view.getYpos());
5102 int w = safeInt(view.getWidth());
5103 int h = safeInt(view.getHeight());
5104 // // BH we cannot let the title bar go off the top
5105 // if (Platform.isJS())
5107 // x = Math.max(50 - w, x);
5108 // y = Math.max(0, y);
5111 af.setBounds(x, y, w, h);
5112 // startSeq set in af.alignPanel.updateLayout below
5113 af.alignPanel.updateLayout();
5114 ColourSchemeI cs = null;
5115 // apply colourschemes
5116 if (view.getBgColour() != null)
5118 if (view.getBgColour().startsWith("ucs"))
5120 cs = getUserColourScheme(jm, view.getBgColour());
5122 else if (view.getBgColour().startsWith("Annotation"))
5124 AnnotationColourScheme viewAnnColour = view.getAnnotationColours();
5125 cs = constructAnnotationColour(viewAnnColour, af, al, jm, true);
5132 cs = ColourSchemeProperty.getColourScheme(af.getViewport(), al,
5133 view.getBgColour());
5138 * turn off 'alignment colour applies to all groups'
5139 * while restoring global colour scheme
5141 viewport.setColourAppliesToAllGroups(false);
5142 viewport.setGlobalColourScheme(cs);
5143 viewport.getResidueShading().setThreshold(pidThreshold,
5144 view.isIgnoreGapsinConsensus());
5145 viewport.getResidueShading()
5146 .setConsensus(viewport.getSequenceConsensusHash());
5147 if (safeBoolean(view.isConservationSelected()) && cs != null)
5149 viewport.getResidueShading()
5150 .setConservationInc(safeInt(view.getConsThreshold()));
5152 af.changeColour(cs);
5153 viewport.setColourAppliesToAllGroups(true);
5156 .setShowSequenceFeatures(
5157 safeBoolean(view.isShowSequenceFeatures()));
5159 viewport.setCentreColumnLabels(view.isCentreColumnLabels());
5160 viewport.setIgnoreGapsConsensus(view.isIgnoreGapsinConsensus(), null);
5161 viewport.setFollowHighlight(view.isFollowHighlight());
5162 viewport.followSelection = view.isFollowSelection();
5163 viewport.setShowConsensusHistogram(view.isShowConsensusHistogram());
5164 viewport.setShowSequenceLogo(view.isShowSequenceLogo());
5165 viewport.setNormaliseSequenceLogo(view.isNormaliseSequenceLogo());
5166 viewport.setShowDBRefs(safeBoolean(view.isShowDbRefTooltip()));
5167 viewport.setShowNPFeats(safeBoolean(view.isShowNPfeatureTooltip()));
5168 viewport.setShowGroupConsensus(view.isShowGroupConsensus());
5169 viewport.setShowGroupConservation(view.isShowGroupConservation());
5171 // recover feature settings
5172 if (jm.getFeatureSettings() != null)
5174 FeatureRenderer fr = af.alignPanel.getSeqPanel().seqCanvas
5175 .getFeatureRenderer();
5176 FeaturesDisplayed fdi;
5177 viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
5178 String[] renderOrder = new String[jm.getFeatureSettings()
5179 .getSetting().size()];
5180 Map<String, FeatureColourI> featureColours = new Hashtable<>();
5181 Map<String, Float> featureOrder = new Hashtable<>();
5183 for (int fs = 0; fs < jm.getFeatureSettings()
5184 .getSetting().size(); fs++)
5186 Setting setting = jm.getFeatureSettings().getSetting().get(fs);
5187 String featureType = setting.getType();
5190 * restore feature filters (if any)
5192 jalview.xml.binding.jalview.FeatureMatcherSet filters = setting
5194 if (filters != null)
5196 FeatureMatcherSetI filter = Jalview2XML
5197 .parseFilter(featureType, filters);
5198 if (!filter.isEmpty())
5200 fr.setFeatureFilter(featureType, filter);
5205 * restore feature colour scheme
5207 Color maxColour = new Color(setting.getColour());
5208 if (setting.getMincolour() != null)
5211 * minColour is always set unless a simple colour
5212 * (including for colour by label though it doesn't use it)
5214 Color minColour = new Color(setting.getMincolour().intValue());
5215 Color noValueColour = minColour;
5216 NoValueColour noColour = setting.getNoValueColour();
5217 if (noColour == NoValueColour.NONE)
5219 noValueColour = null;
5221 else if (noColour == NoValueColour.MAX)
5223 noValueColour = maxColour;
5225 float min = safeFloat(safeFloat(setting.getMin()));
5226 float max = setting.getMax() == null ? 1f
5227 : setting.getMax().floatValue();
5228 FeatureColourI gc = new FeatureColour(maxColour, minColour,
5230 noValueColour, min, max);
5231 if (setting.getAttributeName().size() > 0)
5233 gc.setAttributeName(setting.getAttributeName().toArray(
5234 new String[setting.getAttributeName().size()]));
5236 if (setting.getThreshold() != null)
5238 gc.setThreshold(setting.getThreshold().floatValue());
5239 int threshstate = safeInt(setting.getThreshstate());
5240 // -1 = None, 0 = Below, 1 = Above threshold
5241 if (threshstate == 0)
5243 gc.setBelowThreshold(true);
5245 else if (threshstate == 1)
5247 gc.setAboveThreshold(true);
5250 gc.setAutoScaled(true); // default
5251 if (setting.isAutoScale() != null)
5253 gc.setAutoScaled(setting.isAutoScale());
5255 if (setting.isColourByLabel() != null)
5257 gc.setColourByLabel(setting.isColourByLabel());
5259 // and put in the feature colour table.
5260 featureColours.put(featureType, gc);
5264 featureColours.put(featureType,
5265 new FeatureColour(maxColour));
5267 renderOrder[fs] = featureType;
5268 if (setting.getOrder() != null)
5270 featureOrder.put(featureType, setting.getOrder().floatValue());
5274 featureOrder.put(featureType, new Float(
5275 fs / jm.getFeatureSettings().getSetting().size()));
5277 if (safeBoolean(setting.isDisplay()))
5279 fdi.setVisible(featureType);
5282 Map<String, Boolean> fgtable = new Hashtable<>();
5283 for (int gs = 0; gs < jm.getFeatureSettings().getGroup().size(); gs++)
5285 Group grp = jm.getFeatureSettings().getGroup().get(gs);
5286 fgtable.put(grp.getName(), new Boolean(grp.isDisplay()));
5288 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
5289 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
5290 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
5291 FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
5292 fgtable, featureColours, 1.0f, featureOrder);
5293 fr.transferSettings(frs);
5296 if (view.getHiddenColumns().size() > 0)
5298 for (int c = 0; c < view.getHiddenColumns().size(); c++)
5300 final HiddenColumns hc = view.getHiddenColumns().get(c);
5301 viewport.hideColumns(safeInt(hc.getStart()),
5302 safeInt(hc.getEnd()) /* +1 */);
5305 if (view.getCalcIdParam() != null)
5307 for (CalcIdParam calcIdParam : view.getCalcIdParam())
5309 if (calcIdParam != null)
5311 if (recoverCalcIdParam(calcIdParam, viewport))
5316 warn("Couldn't recover parameters for "
5317 + calcIdParam.getCalcId());
5322 af.setMenusFromViewport(viewport);
5323 af.setTitle(view.getTitle());
5324 // TODO: we don't need to do this if the viewport is aready visible.
5326 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
5327 * has a 'cdna/protein complement' view, in which case save it in order to
5328 * populate a SplitFrame once all views have been read in.
5330 String complementaryViewId = view.getComplementId();
5331 if (complementaryViewId == null)
5333 Desktop.addInternalFrame(af, view.getTitle(),
5334 safeInt(view.getWidth()), safeInt(view.getHeight()));
5335 // recompute any autoannotation
5336 af.alignPanel.updateAnnotation(false, true);
5337 reorderAutoannotation(af, al, autoAlan);
5338 af.alignPanel.alignmentChanged();
5342 splitFrameCandidates.put(view, af);
5348 * Reads saved data to restore Colour by Annotation settings
5350 * @param viewAnnColour
5354 * @param checkGroupAnnColour
5357 private ColourSchemeI constructAnnotationColour(
5358 AnnotationColourScheme viewAnnColour, AlignFrame af,
5359 AlignmentI al, JalviewModel model, boolean checkGroupAnnColour)
5361 boolean propagateAnnColour = false;
5362 AlignmentI annAlignment = af != null ? af.getViewport().getAlignment()
5364 if (checkGroupAnnColour && al.getGroups() != null
5365 && al.getGroups().size() > 0)
5367 // pre 2.8.1 behaviour
5368 // check to see if we should transfer annotation colours
5369 propagateAnnColour = true;
5370 for (SequenceGroup sg : al.getGroups())
5372 if (sg.getColourScheme() instanceof AnnotationColourGradient)
5374 propagateAnnColour = false;
5380 * 2.10.2- : saved annotationId is AlignmentAnnotation.annotationId
5382 String annotationId = viewAnnColour.getAnnotation();
5383 AlignmentAnnotation matchedAnnotation = annotationIds.get(annotationId);
5386 * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
5388 if (matchedAnnotation == null
5389 && annAlignment.getAlignmentAnnotation() != null)
5391 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
5394 .equals(annAlignment.getAlignmentAnnotation()[i].label))
5396 matchedAnnotation = annAlignment.getAlignmentAnnotation()[i];
5401 if (matchedAnnotation == null)
5403 System.err.println("Failed to match annotation colour scheme for "
5407 if (matchedAnnotation.getThreshold() == null)
5409 matchedAnnotation.setThreshold(
5410 new GraphLine(safeFloat(viewAnnColour.getThreshold()),
5411 "Threshold", Color.black));
5414 AnnotationColourGradient cs = null;
5415 if (viewAnnColour.getColourScheme().equals("None"))
5417 cs = new AnnotationColourGradient(matchedAnnotation,
5418 new Color(safeInt(viewAnnColour.getMinColour())),
5419 new Color(safeInt(viewAnnColour.getMaxColour())),
5420 safeInt(viewAnnColour.getAboveThreshold()));
5422 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
5424 cs = new AnnotationColourGradient(matchedAnnotation,
5425 getUserColourScheme(model, viewAnnColour.getColourScheme()),
5426 safeInt(viewAnnColour.getAboveThreshold()));
5430 cs = new AnnotationColourGradient(matchedAnnotation,
5431 ColourSchemeProperty.getColourScheme(af.getViewport(), al,
5432 viewAnnColour.getColourScheme()),
5433 safeInt(viewAnnColour.getAboveThreshold()));
5436 boolean perSequenceOnly = safeBoolean(viewAnnColour.isPerSequence());
5437 boolean useOriginalColours = safeBoolean(
5438 viewAnnColour.isPredefinedColours());
5439 cs.setSeqAssociated(perSequenceOnly);
5440 cs.setPredefinedColours(useOriginalColours);
5442 if (propagateAnnColour && al.getGroups() != null)
5444 // Also use these settings for all the groups
5445 for (int g = 0; g < al.getGroups().size(); g++)
5447 SequenceGroup sg = al.getGroups().get(g);
5448 if (sg.getGroupColourScheme() == null)
5453 AnnotationColourGradient groupScheme = new AnnotationColourGradient(
5454 matchedAnnotation, sg.getColourScheme(),
5455 safeInt(viewAnnColour.getAboveThreshold()));
5456 sg.setColourScheme(groupScheme);
5457 groupScheme.setSeqAssociated(perSequenceOnly);
5458 groupScheme.setPredefinedColours(useOriginalColours);
5464 private void reorderAutoannotation(AlignFrame af, AlignmentI al,
5465 List<JvAnnotRow> autoAlan)
5467 // copy over visualization settings for autocalculated annotation in the
5469 if (al.getAlignmentAnnotation() != null)
5472 * Kludge for magic autoannotation names (see JAL-811)
5474 String[] magicNames = new String[] { "Consensus", "Quality",
5476 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
5477 Hashtable<String, JvAnnotRow> visan = new Hashtable<>();
5478 for (String nm : magicNames)
5480 visan.put(nm, nullAnnot);
5482 for (JvAnnotRow auan : autoAlan)
5484 visan.put(auan.template.label
5485 + (auan.template.getCalcId() == null ? ""
5486 : "\t" + auan.template.getCalcId()),
5489 int hSize = al.getAlignmentAnnotation().length;
5490 List<JvAnnotRow> reorder = new ArrayList<>();
5491 // work through any autoCalculated annotation already on the view
5492 // removing it if it should be placed in a different location on the
5493 // annotation panel.
5494 List<String> remains = new ArrayList<>(visan.keySet());
5495 for (int h = 0; h < hSize; h++)
5497 jalview.datamodel.AlignmentAnnotation jalan = al
5498 .getAlignmentAnnotation()[h];
5499 if (jalan.autoCalculated)
5502 JvAnnotRow valan = visan.get(k = jalan.label);
5503 if (jalan.getCalcId() != null)
5505 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
5510 // delete the auto calculated row from the alignment
5511 al.deleteAnnotation(jalan, false);
5515 if (valan != nullAnnot)
5517 if (jalan != valan.template)
5519 // newly created autoannotation row instance
5520 // so keep a reference to the visible annotation row
5521 // and copy over all relevant attributes
5522 if (valan.template.graphHeight >= 0)
5525 jalan.graphHeight = valan.template.graphHeight;
5527 jalan.visible = valan.template.visible;
5529 reorder.add(new JvAnnotRow(valan.order, jalan));
5534 // Add any (possibly stale) autocalculated rows that were not appended to
5535 // the view during construction
5536 for (String other : remains)
5538 JvAnnotRow othera = visan.get(other);
5539 if (othera != nullAnnot && othera.template.getCalcId() != null
5540 && othera.template.getCalcId().length() > 0)
5542 reorder.add(othera);
5545 // now put the automatic annotation in its correct place
5546 int s = 0, srt[] = new int[reorder.size()];
5547 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
5548 for (JvAnnotRow jvar : reorder)
5551 srt[s++] = jvar.order;
5554 jalview.util.QuickSort.sort(srt, rws);
5555 // and re-insert the annotation at its correct position
5556 for (JvAnnotRow jvar : rws)
5558 al.addAnnotation(jvar.template, jvar.order);
5560 af.alignPanel.adjustAnnotationHeight();
5564 Hashtable skipList = null;
5567 * TODO remove this method
5570 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
5571 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
5572 * throw new Error("Implementation Error. No skipList defined for this
5573 * Jalview2XML instance."); } return (AlignFrame)
5574 * skipList.get(view.getSequenceSetId()); }
5578 * Check if the Jalview view contained in object should be skipped or not.
5581 * @return true if view's sequenceSetId is a key in skipList
5583 private boolean skipViewport(JalviewModel object)
5585 if (skipList == null)
5589 String id = object.getViewport().get(0).getSequenceSetId();
5590 if (skipList.containsKey(id))
5592 if (Cache.log != null && Cache.log.isDebugEnabled())
5594 Cache.log.debug("Skipping seuqence set id " + id);
5601 public void addToSkipList(AlignFrame af)
5603 if (skipList == null)
5605 skipList = new Hashtable();
5607 skipList.put(af.getViewport().getSequenceSetId(), af);
5610 public void clearSkipList()
5612 if (skipList != null)
5619 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
5620 boolean ignoreUnrefed, String uniqueSeqSetId)
5622 jalview.datamodel.AlignmentI ds = getDatasetFor(
5623 vamsasSet.getDatasetId());
5624 AlignmentI xtant_ds = ds;
5625 if (xtant_ds == null)
5627 // good chance we are about to create a new dataset, but check if we've
5628 // seen some of the dataset sequence IDs before.
5629 // TODO: skip this check if we are working with project generated by
5630 // version 2.11 or later
5631 xtant_ds = checkIfHasDataset(vamsasSet.getSequence());
5632 if (xtant_ds != null)
5635 addDatasetRef(vamsasSet.getDatasetId(), ds);
5638 Vector dseqs = null;
5641 // recovering an alignment View
5642 AlignmentI seqSetDS = getDatasetFor(UNIQSEQSETID + uniqueSeqSetId);
5643 if (seqSetDS != null)
5645 if (ds != null && ds != seqSetDS)
5647 warn("JAL-3171 regression: Overwriting a dataset reference for an alignment"
5648 + " - CDS/Protein crossreference data may be lost");
5649 if (xtant_ds != null)
5651 // This can only happen if the unique sequence set ID was bound to a
5652 // dataset that did not contain any of the sequences in the view
5653 // currently being restored.
5654 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.");
5658 addDatasetRef(vamsasSet.getDatasetId(), ds);
5663 // try even harder to restore dataset
5664 AlignmentI xtantDS = checkIfHasDataset(vamsasSet.getSequence());
5665 // create a list of new dataset sequences
5666 dseqs = new Vector();
5668 for (int i = 0, iSize = vamsasSet.getSequence().size(); i < iSize; i++)
5670 Sequence vamsasSeq = vamsasSet.getSequence().get(i);
5671 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
5673 // create a new dataset
5676 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
5677 dseqs.copyInto(dsseqs);
5678 ds = new jalview.datamodel.Alignment(dsseqs);
5679 debug("Created new dataset " + vamsasSet.getDatasetId()
5680 + " for alignment " + System.identityHashCode(al));
5681 addDatasetRef(vamsasSet.getDatasetId(), ds);
5683 // set the dataset for the newly imported alignment.
5684 if (al.getDataset() == null && !ignoreUnrefed)
5687 // register dataset for the alignment's uniqueSeqSetId for legacy projects
5688 addDatasetRef(UNIQSEQSETID + uniqueSeqSetId, ds);
5690 updateSeqDatasetBinding(vamsasSet.getSequence(), ds);
5694 * XML dataset sequence ID to materialised dataset reference
5696 HashMap<String, AlignmentI> seqToDataset = new HashMap<>();
5699 * @return the first materialised dataset reference containing a dataset
5700 * sequence referenced in the given view
5702 * - sequences from the view
5704 AlignmentI checkIfHasDataset(List<Sequence> list)
5706 for (Sequence restoredSeq : list)
5708 AlignmentI datasetFor = seqToDataset.get(restoredSeq.getDsseqid());
5709 if (datasetFor != null)
5718 * Register ds as the containing dataset for the dataset sequences referenced
5719 * by sequences in list
5722 * - sequences in a view
5725 void updateSeqDatasetBinding(List<Sequence> list, AlignmentI ds)
5727 for (Sequence restoredSeq : list)
5729 AlignmentI prevDS = seqToDataset.put(restoredSeq.getDsseqid(), ds);
5730 if (prevDS != null && prevDS != ds)
5732 warn("Dataset sequence appears in many datasets: "
5733 + restoredSeq.getDsseqid());
5734 // TODO: try to merge!
5741 * sequence definition to create/merge dataset sequence for
5745 * vector to add new dataset sequence to
5746 * @param ignoreUnrefed
5747 * - when true, don't create new sequences from vamsasSeq if it's id
5748 * doesn't already have an asssociated Jalview sequence.
5750 * - used to reorder the sequence in the alignment according to the
5751 * vamsasSeq array ordering, to preserve ordering of dataset
5753 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
5754 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed, int vseqpos)
5756 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
5758 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
5759 boolean reorder = false;
5760 SequenceI dsq = null;
5761 if (sq != null && sq.getDatasetSequence() != null)
5763 dsq = sq.getDatasetSequence();
5769 if (sq == null && ignoreUnrefed)
5773 String sqid = vamsasSeq.getDsseqid();
5776 // need to create or add a new dataset sequence reference to this sequence
5779 dsq = seqRefIds.get(sqid);
5784 // make a new dataset sequence
5785 dsq = sq.createDatasetSequence();
5788 // make up a new dataset reference for this sequence
5789 sqid = seqHash(dsq);
5791 dsq.setVamsasId(uniqueSetSuffix + sqid);
5792 seqRefIds.put(sqid, dsq);
5797 dseqs.addElement(dsq);
5802 ds.addSequence(dsq);
5808 { // make this dataset sequence sq's dataset sequence
5809 sq.setDatasetSequence(dsq);
5810 // and update the current dataset alignment
5815 if (!dseqs.contains(dsq))
5822 if (ds.findIndex(dsq) < 0)
5824 ds.addSequence(dsq);
5831 // TODO: refactor this as a merge dataset sequence function
5832 // now check that sq (the dataset sequence) sequence really is the union of
5833 // all references to it
5834 // boolean pre = sq.getStart() < dsq.getStart();
5835 // boolean post = sq.getEnd() > dsq.getEnd();
5839 // StringBuffer sb = new StringBuffer();
5840 String newres = jalview.analysis.AlignSeq.extractGaps(
5841 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
5842 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
5843 && newres.length() > dsq.getLength())
5845 // Update with the longer sequence.
5849 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
5850 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
5851 * sb.append(newres.substring(newres.length() - sq.getEnd() -
5852 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
5854 dsq.setSequence(newres);
5856 // TODO: merges will never happen if we 'know' we have the real dataset
5857 // sequence - this should be detected when id==dssid
5859 "DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
5860 // + (pre ? "prepended" : "") + " "
5861 // + (post ? "appended" : ""));
5866 // sequence refs are identical. We may need to update the existing dataset
5867 // alignment with this one, though.
5868 if (ds != null && dseqs == null)
5870 int opos = ds.findIndex(dsq);
5871 SequenceI tseq = null;
5872 if (opos != -1 && vseqpos != opos)
5874 // remove from old position
5875 ds.deleteSequence(dsq);
5877 if (vseqpos < ds.getHeight())
5879 if (vseqpos != opos)
5881 // save sequence at destination position
5882 tseq = ds.getSequenceAt(vseqpos);
5883 ds.replaceSequenceAt(vseqpos, dsq);
5884 ds.addSequence(tseq);
5889 ds.addSequence(dsq);
5896 * TODO use AlignmentI here and in related methods - needs
5897 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
5899 Hashtable<String, AlignmentI> datasetIds = null;
5901 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
5903 private AlignmentI getDatasetFor(String datasetId)
5905 if (datasetIds == null)
5907 datasetIds = new Hashtable<>();
5910 if (datasetIds.containsKey(datasetId))
5912 return datasetIds.get(datasetId);
5917 private void addDatasetRef(String datasetId, AlignmentI dataset)
5919 if (datasetIds == null)
5921 datasetIds = new Hashtable<>();
5923 datasetIds.put(datasetId, dataset);
5927 * make a new dataset ID for this jalview dataset alignment
5932 private String getDatasetIdRef(AlignmentI dataset)
5934 if (dataset.getDataset() != null)
5936 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
5938 String datasetId = makeHashCode(dataset, null);
5939 if (datasetId == null)
5941 // make a new datasetId and record it
5942 if (dataset2Ids == null)
5944 dataset2Ids = new IdentityHashMap<>();
5948 datasetId = dataset2Ids.get(dataset);
5950 if (datasetId == null)
5952 datasetId = "ds" + dataset2Ids.size() + 1;
5953 dataset2Ids.put(dataset, datasetId);
5959 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5961 for (int d = 0; d < sequence.getDBRef().size(); d++)
5963 DBRef dr = sequence.getDBRef().get(d);
5964 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
5965 dr.getSource(), dr.getVersion(), dr.getAccessionId());
5966 if (dr.getMapping() != null)
5968 entry.setMap(addMapping(dr.getMapping()));
5970 datasetSequence.addDBRef(entry);
5974 private jalview.datamodel.Mapping addMapping(Mapping m)
5976 SequenceI dsto = null;
5977 // Mapping m = dr.getMapping();
5978 int fr[] = new int[m.getMapListFrom().size() * 2];
5979 Iterator<MapListFrom> from = m.getMapListFrom().iterator();// enumerateMapListFrom();
5980 for (int _i = 0; from.hasNext(); _i += 2)
5982 MapListFrom mf = from.next();
5983 fr[_i] = mf.getStart();
5984 fr[_i + 1] = mf.getEnd();
5986 int fto[] = new int[m.getMapListTo().size() * 2];
5987 Iterator<MapListTo> to = m.getMapListTo().iterator();// enumerateMapListTo();
5988 for (int _i = 0; to.hasNext(); _i += 2)
5990 MapListTo mf = to.next();
5991 fto[_i] = mf.getStart();
5992 fto[_i + 1] = mf.getEnd();
5994 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto, fr,
5995 fto, m.getMapFromUnit().intValue(),
5996 m.getMapToUnit().intValue());
5999 * (optional) choice of dseqFor or Sequence
6001 if (m.getDseqFor() != null)
6003 String dsfor = m.getDseqFor();
6004 if (seqRefIds.containsKey(dsfor))
6009 jmap.setTo(seqRefIds.get(dsfor));
6013 frefedSequence.add(newMappingRef(dsfor, jmap));
6016 else if (m.getSequence() != null)
6019 * local sequence definition
6021 Sequence ms = m.getSequence();
6022 SequenceI djs = null;
6023 String sqid = ms.getDsseqid();
6024 if (sqid != null && sqid.length() > 0)
6027 * recover dataset sequence
6029 djs = seqRefIds.get(sqid);
6034 "Warning - making up dataset sequence id for DbRef sequence map reference");
6035 sqid = ((Object) ms).toString(); // make up a new hascode for
6036 // undefined dataset sequence hash
6037 // (unlikely to happen)
6043 * make a new dataset sequence and add it to refIds hash
6045 djs = new jalview.datamodel.Sequence(ms.getName(),
6047 djs.setStart(jmap.getMap().getToLowest());
6048 djs.setEnd(jmap.getMap().getToHighest());
6049 djs.setVamsasId(uniqueSetSuffix + sqid);
6051 incompleteSeqs.put(sqid, djs);
6052 seqRefIds.put(sqid, djs);
6055 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
6064 * Provides a 'copy' of an alignment view (on action New View) by 'saving' the
6065 * view as XML (but not to file), and then reloading it
6070 public AlignmentPanel copyAlignPanel(AlignmentPanel ap)
6073 JalviewModel jm = saveState(ap, null, null, null);
6076 jm.getVamsasModel().getSequenceSet().get(0).getDatasetId(),
6077 ap.getAlignment().getDataset());
6079 uniqueSetSuffix = "";
6080 // jm.getJalviewModelSequence().getViewport(0).setId(null);
6081 jm.getViewport().get(0).setId(null);
6082 // we don't overwrite the view we just copied
6084 if (this.frefedSequence == null)
6086 frefedSequence = new Vector<>();
6089 viewportsAdded.clear();
6091 AlignFrame af = loadFromObject(jm, null, false, null);
6092 af.getAlignPanels().clear();
6093 af.closeMenuItem_actionPerformed(true);
6096 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
6097 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
6098 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
6099 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
6100 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
6103 return af.alignPanel;
6106 private Hashtable jvids2vobj;
6108 private void warn(String msg)
6113 private void warn(String msg, Exception e)
6115 if (Cache.log != null)
6119 Cache.log.warn(msg, e);
6123 Cache.log.warn(msg);
6128 System.err.println("Warning: " + msg);
6131 e.printStackTrace();
6136 private void debug(String string)
6138 debug(string, null);
6141 private void debug(String msg, Exception e)
6143 if (Cache.log != null)
6147 Cache.log.debug(msg, e);
6151 Cache.log.debug(msg);
6156 System.err.println("Warning: " + msg);
6159 e.printStackTrace();
6165 * set the object to ID mapping tables used to write/recover objects and XML
6166 * ID strings for the jalview project. If external tables are provided then
6167 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
6168 * object goes out of scope. - also populates the datasetIds hashtable with
6169 * alignment objects containing dataset sequences
6172 * Map from ID strings to jalview datamodel
6174 * Map from jalview datamodel to ID strings
6178 public void setObjectMappingTables(Hashtable vobj2jv,
6179 IdentityHashMap jv2vobj)
6181 this.jv2vobj = jv2vobj;
6182 this.vobj2jv = vobj2jv;
6183 Iterator ds = jv2vobj.keySet().iterator();
6185 while (ds.hasNext())
6187 Object jvobj = ds.next();
6188 id = jv2vobj.get(jvobj).toString();
6189 if (jvobj instanceof jalview.datamodel.Alignment)
6191 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
6193 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
6196 else if (jvobj instanceof jalview.datamodel.Sequence)
6198 // register sequence object so the XML parser can recover it.
6199 if (seqRefIds == null)
6201 seqRefIds = new HashMap<>();
6203 if (seqsToIds == null)
6205 seqsToIds = new IdentityHashMap<>();
6207 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
6208 seqsToIds.put((SequenceI) jvobj, id);
6210 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
6213 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
6214 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
6215 if (jvann.annotationId == null)
6217 jvann.annotationId = anid;
6219 if (!jvann.annotationId.equals(anid))
6221 // TODO verify that this is the correct behaviour
6222 this.warn("Overriding Annotation ID for " + anid
6223 + " from different id : " + jvann.annotationId);
6224 jvann.annotationId = anid;
6227 else if (jvobj instanceof String)
6229 if (jvids2vobj == null)
6231 jvids2vobj = new Hashtable();
6232 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
6237 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
6243 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
6244 * objects created from the project archive. If string is null (default for
6245 * construction) then suffix will be set automatically.
6249 public void setUniqueSetSuffix(String string)
6251 uniqueSetSuffix = string;
6256 * uses skipList2 as the skipList for skipping views on sequence sets
6257 * associated with keys in the skipList
6261 public void setSkipList(Hashtable skipList2)
6263 skipList = skipList2;
6267 * Reads the jar entry of given name and returns its contents, or null if the
6268 * entry is not found.
6271 * @param jarEntryName
6274 protected String readJarEntry(jarInputStreamProvider jprovider,
6275 String jarEntryName)
6277 String result = null;
6278 BufferedReader in = null;
6283 * Reopen the jar input stream and traverse its entries to find a matching
6286 JarInputStream jin = jprovider.getJarInputStream();
6287 JarEntry entry = null;
6290 entry = jin.getNextJarEntry();
6291 } while (entry != null && !entry.getName().equals(jarEntryName));
6295 StringBuilder out = new StringBuilder(256);
6296 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
6299 while ((data = in.readLine()) != null)
6303 result = out.toString();
6307 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
6309 } catch (Exception ex)
6311 ex.printStackTrace();
6319 } catch (IOException e)
6330 * Returns an incrementing counter (0, 1, 2...)
6334 private synchronized int nextCounter()
6340 * Loads any saved PCA viewers
6345 protected void loadPCAViewers(JalviewModel model, AlignmentPanel ap)
6349 List<PcaViewer> pcaviewers = model.getPcaViewer();
6350 for (PcaViewer viewer : pcaviewers)
6352 String modelName = viewer.getScoreModelName();
6353 SimilarityParamsI params = new SimilarityParams(
6354 viewer.isIncludeGappedColumns(), viewer.isMatchGaps(),
6355 viewer.isIncludeGaps(),
6356 viewer.isDenominateByShortestLength());
6359 * create the panel (without computing the PCA)
6361 PCAPanel panel = new PCAPanel(ap, modelName, params);
6363 panel.setTitle(viewer.getTitle());
6364 panel.setBounds(new Rectangle(viewer.getXpos(), viewer.getYpos(),
6365 viewer.getWidth(), viewer.getHeight()));
6367 boolean showLabels = viewer.isShowLabels();
6368 panel.setShowLabels(showLabels);
6369 panel.getRotatableCanvas().setShowLabels(showLabels);
6370 panel.getRotatableCanvas()
6371 .setBgColour(new Color(viewer.getBgColour()));
6372 panel.getRotatableCanvas()
6373 .setApplyToAllViews(viewer.isLinkToAllViews());
6376 * load PCA output data
6378 ScoreModelI scoreModel = ScoreModels.getInstance()
6379 .getScoreModel(modelName, ap);
6380 PCA pca = new PCA(null, scoreModel, params);
6381 PcaDataType pcaData = viewer.getPcaData();
6383 MatrixI pairwise = loadDoubleMatrix(pcaData.getPairwiseMatrix());
6384 pca.setPairwiseScores(pairwise);
6386 MatrixI triDiag = loadDoubleMatrix(pcaData.getTridiagonalMatrix());
6387 pca.setTridiagonal(triDiag);
6389 MatrixI result = loadDoubleMatrix(pcaData.getEigenMatrix());
6390 pca.setEigenmatrix(result);
6392 panel.getPcaModel().setPCA(pca);
6395 * we haven't saved the input data! (JAL-2647 to do)
6397 panel.setInputData(null);
6400 * add the sequence points for the PCA display
6402 List<jalview.datamodel.SequencePoint> seqPoints = new ArrayList<>();
6403 for (SequencePoint sp : viewer.getSequencePoint())
6405 String seqId = sp.getSequenceRef();
6406 SequenceI seq = seqRefIds.get(seqId);
6409 throw new IllegalStateException(
6410 "Unmatched seqref for PCA: " + seqId);
6412 Point pt = new Point(sp.getXPos(), sp.getYPos(), sp.getZPos());
6413 jalview.datamodel.SequencePoint seqPoint = new jalview.datamodel.SequencePoint(
6415 seqPoints.add(seqPoint);
6417 panel.getRotatableCanvas().setPoints(seqPoints, seqPoints.size());
6420 * set min-max ranges and scale after setPoints (which recomputes them)
6422 panel.getRotatableCanvas().setScaleFactor(viewer.getScaleFactor());
6423 SeqPointMin spMin = viewer.getSeqPointMin();
6424 float[] min = new float[] { spMin.getXPos(), spMin.getYPos(),
6426 SeqPointMax spMax = viewer.getSeqPointMax();
6427 float[] max = new float[] { spMax.getXPos(), spMax.getYPos(),
6429 panel.getRotatableCanvas().setSeqMinMax(min, max);
6431 // todo: hold points list in PCAModel only
6432 panel.getPcaModel().setSequencePoints(seqPoints);
6434 panel.setSelectedDimensionIndex(viewer.getXDim(), X);
6435 panel.setSelectedDimensionIndex(viewer.getYDim(), Y);
6436 panel.setSelectedDimensionIndex(viewer.getZDim(), Z);
6438 // is this duplication needed?
6439 panel.setTop(seqPoints.size() - 1);
6440 panel.getPcaModel().setTop(seqPoints.size() - 1);
6443 * add the axes' end points for the display
6445 for (int i = 0; i < 3; i++)
6447 Axis axis = viewer.getAxis().get(i);
6448 panel.getRotatableCanvas().getAxisEndPoints()[i] = new Point(
6449 axis.getXPos(), axis.getYPos(), axis.getZPos());
6452 Desktop.addInternalFrame(panel, MessageManager.formatMessage(
6453 "label.calc_title", "PCA", modelName), 475, 450);
6455 } catch (Exception ex)
6457 Cache.log.error("Error loading PCA: " + ex.toString());
6462 * Populates an XML model of the feature colour scheme for one feature type
6464 * @param featureType
6468 public static Colour marshalColour(
6469 String featureType, FeatureColourI fcol)
6471 Colour col = new Colour();
6472 if (fcol.isSimpleColour())
6474 col.setRGB(Format.getHexString(fcol.getColour()));
6478 col.setRGB(Format.getHexString(fcol.getMaxColour()));
6479 col.setMin(fcol.getMin());
6480 col.setMax(fcol.getMax());
6481 col.setMinRGB(jalview.util.Format.getHexString(fcol.getMinColour()));
6482 col.setAutoScale(fcol.isAutoScaled());
6483 col.setThreshold(fcol.getThreshold());
6484 col.setColourByLabel(fcol.isColourByLabel());
6485 col.setThreshType(fcol.isAboveThreshold() ? ThresholdType.ABOVE
6486 : (fcol.isBelowThreshold() ? ThresholdType.BELOW
6487 : ThresholdType.NONE));
6488 if (fcol.isColourByAttribute())
6490 final String[] attName = fcol.getAttributeName();
6491 col.getAttributeName().add(attName[0]);
6492 if (attName.length > 1)
6494 col.getAttributeName().add(attName[1]);
6497 Color noColour = fcol.getNoColour();
6498 if (noColour == null)
6500 col.setNoValueColour(NoValueColour.NONE);
6502 else if (noColour == fcol.getMaxColour())
6504 col.setNoValueColour(NoValueColour.MAX);
6508 col.setNoValueColour(NoValueColour.MIN);
6511 col.setName(featureType);
6516 * Populates an XML model of the feature filter(s) for one feature type
6518 * @param firstMatcher
6519 * the first (or only) match condition)
6521 * remaining match conditions (if any)
6523 * if true, conditions are and-ed, else or-ed
6525 public static jalview.xml.binding.jalview.FeatureMatcherSet marshalFilter(
6526 FeatureMatcherI firstMatcher, Iterator<FeatureMatcherI> filters,
6529 jalview.xml.binding.jalview.FeatureMatcherSet result = new jalview.xml.binding.jalview.FeatureMatcherSet();
6531 if (filters.hasNext())
6536 CompoundMatcher compound = new CompoundMatcher();
6537 compound.setAnd(and);
6538 jalview.xml.binding.jalview.FeatureMatcherSet matcher1 = marshalFilter(
6539 firstMatcher, Collections.emptyIterator(), and);
6540 // compound.addMatcherSet(matcher1);
6541 compound.getMatcherSet().add(matcher1);
6542 FeatureMatcherI nextMatcher = filters.next();
6543 jalview.xml.binding.jalview.FeatureMatcherSet matcher2 = marshalFilter(
6544 nextMatcher, filters, and);
6545 // compound.addMatcherSet(matcher2);
6546 compound.getMatcherSet().add(matcher2);
6547 result.setCompoundMatcher(compound);
6552 * single condition matcher
6554 // MatchCondition matcherModel = new MatchCondition();
6555 jalview.xml.binding.jalview.FeatureMatcher matcherModel = new jalview.xml.binding.jalview.FeatureMatcher();
6556 matcherModel.setCondition(
6557 firstMatcher.getMatcher().getCondition().getStableName());
6558 matcherModel.setValue(firstMatcher.getMatcher().getPattern());
6559 if (firstMatcher.isByAttribute())
6561 matcherModel.setBy(FilterBy.BY_ATTRIBUTE);
6562 // matcherModel.setAttributeName(firstMatcher.getAttribute());
6563 String[] attName = firstMatcher.getAttribute();
6564 matcherModel.getAttributeName().add(attName[0]); // attribute
6565 if (attName.length > 1)
6567 matcherModel.getAttributeName().add(attName[1]); // sub-attribute
6570 else if (firstMatcher.isByLabel())
6572 matcherModel.setBy(FilterBy.BY_LABEL);
6574 else if (firstMatcher.isByScore())
6576 matcherModel.setBy(FilterBy.BY_SCORE);
6578 result.setMatchCondition(matcherModel);
6585 * Loads one XML model of a feature filter to a Jalview object
6587 * @param featureType
6588 * @param matcherSetModel
6591 public static FeatureMatcherSetI parseFilter(
6593 jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel)
6595 FeatureMatcherSetI result = new FeatureMatcherSet();
6598 parseFilterConditions(result, matcherSetModel, true);
6599 } catch (IllegalStateException e)
6601 // mixing AND and OR conditions perhaps
6603 String.format("Error reading filter conditions for '%s': %s",
6604 featureType, e.getMessage()));
6605 // return as much as was parsed up to the error
6612 * Adds feature match conditions to matcherSet as unmarshalled from XML
6613 * (possibly recursively for compound conditions)
6616 * @param matcherSetModel
6618 * if true, multiple conditions are AND-ed, else they are OR-ed
6619 * @throws IllegalStateException
6620 * if AND and OR conditions are mixed
6622 protected static void parseFilterConditions(
6623 FeatureMatcherSetI matcherSet,
6624 jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel,
6627 jalview.xml.binding.jalview.FeatureMatcher mc = matcherSetModel
6628 .getMatchCondition();
6634 FilterBy filterBy = mc.getBy();
6635 Condition cond = Condition.fromString(mc.getCondition());
6636 String pattern = mc.getValue();
6637 FeatureMatcherI matchCondition = null;
6638 if (filterBy == FilterBy.BY_LABEL)
6640 matchCondition = FeatureMatcher.byLabel(cond, pattern);
6642 else if (filterBy == FilterBy.BY_SCORE)
6644 matchCondition = FeatureMatcher.byScore(cond, pattern);
6647 else if (filterBy == FilterBy.BY_ATTRIBUTE)
6649 final List<String> attributeName = mc.getAttributeName();
6650 String[] attNames = attributeName
6651 .toArray(new String[attributeName.size()]);
6652 matchCondition = FeatureMatcher.byAttribute(cond, pattern,
6657 * note this throws IllegalStateException if AND-ing to a
6658 * previously OR-ed compound condition, or vice versa
6662 matcherSet.and(matchCondition);
6666 matcherSet.or(matchCondition);
6672 * compound condition
6674 List<jalview.xml.binding.jalview.FeatureMatcherSet> matchers = matcherSetModel
6675 .getCompoundMatcher().getMatcherSet();
6676 boolean anded = matcherSetModel.getCompoundMatcher().isAnd();
6677 if (matchers.size() == 2)
6679 parseFilterConditions(matcherSet, matchers.get(0), anded);
6680 parseFilterConditions(matcherSet, matchers.get(1), anded);
6684 System.err.println("Malformed compound filter condition");
6690 * Loads one XML model of a feature colour to a Jalview object
6692 * @param colourModel
6695 public static FeatureColourI parseColour(Colour colourModel)
6697 FeatureColourI colour = null;
6699 if (colourModel.getMax() != null)
6701 Color mincol = null;
6702 Color maxcol = null;
6703 Color noValueColour = null;
6707 mincol = new Color(Integer.parseInt(colourModel.getMinRGB(), 16));
6708 maxcol = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6709 } catch (Exception e)
6711 Cache.log.warn("Couldn't parse out graduated feature color.", e);
6714 NoValueColour noCol = colourModel.getNoValueColour();
6715 if (noCol == NoValueColour.MIN)
6717 noValueColour = mincol;
6719 else if (noCol == NoValueColour.MAX)
6721 noValueColour = maxcol;
6724 colour = new FeatureColour(maxcol, mincol, maxcol, noValueColour,
6725 safeFloat(colourModel.getMin()),
6726 safeFloat(colourModel.getMax()));
6727 final List<String> attributeName = colourModel.getAttributeName();
6728 String[] attributes = attributeName
6729 .toArray(new String[attributeName.size()]);
6730 if (attributes != null && attributes.length > 0)
6732 colour.setAttributeName(attributes);
6734 if (colourModel.isAutoScale() != null)
6736 colour.setAutoScaled(colourModel.isAutoScale().booleanValue());
6738 if (colourModel.isColourByLabel() != null)
6740 colour.setColourByLabel(
6741 colourModel.isColourByLabel().booleanValue());
6743 if (colourModel.getThreshold() != null)
6745 colour.setThreshold(colourModel.getThreshold().floatValue());
6747 ThresholdType ttyp = colourModel.getThreshType();
6748 if (ttyp == ThresholdType.ABOVE)
6750 colour.setAboveThreshold(true);
6752 else if (ttyp == ThresholdType.BELOW)
6754 colour.setBelowThreshold(true);
6759 Color color = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6760 colour = new FeatureColour(color);