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();
2866 List<AlignFrame> alignFrames = new ArrayList<>();
2870 JarInputStream jin = null;
2871 JarEntry jarentry = null;
2875 // Look for all the entry names ending with ".xml"
2876 // This includes all panels and at least one frame.
2877 // Platform.timeCheck(null, Platform.TIME_MARK);
2880 jin = jprovider.getJarInputStream();
2881 for (int i = 0; i < entryCount; i++)
2883 jarentry = jin.getNextJarEntry();
2885 String name = (jarentry == null ? null : jarentry.getName());
2887 // System.out.println("Jalview2XML opening " + name);
2888 if (name != null && name.endsWith(".xml"))
2891 // DataSet for.... is read last.
2894 // The question here is what to do with the two
2895 // .xml files in the jvp file.
2896 // Some number of them, "...Dataset for...", will be the
2897 // Only AlignPanels and will have Viewport.
2898 // One or more will be the source data, with the DBRefs.
2900 // JVP file writing (above) ensures tha the AlignPanels are written
2901 // first, then all relevant datasets (which are
2902 // Jalview.datamodel.Alignment).
2905 // Platform.timeCheck("Jalview2XML JAXB " + name, Platform.TIME_MARK);
2906 JAXBContext jc = JAXBContext
2907 .newInstance("jalview.xml.binding.jalview");
2908 XMLStreamReader streamReader = XMLInputFactory.newInstance()
2909 .createXMLStreamReader(jin);
2910 javax.xml.bind.Unmarshaller um = jc.createUnmarshaller();
2911 JAXBElement<JalviewModel> jbe = um
2912 .unmarshal(streamReader, JalviewModel.class);
2913 JalviewModel model = jbe.getValue();
2915 if (true) // !skipViewport(object))
2917 // Q: Do we have to load from the model, even if it
2918 // does not have a viewport, could we discover that early on?
2919 // Q: Do we need to load this object?
2920 _af = loadFromObject(model, file, true, jprovider);
2921 // Platform.timeCheck("Jalview2XML.loadFromObject",
2922 // Platform.TIME_MARK);
2926 alignFrames.add(_af);
2928 if (_af != null && model.getViewport().size() > 0)
2931 // That is, this is one of the AlignmentPanel models
2934 // store a reference to the first view
2937 if (_af.getViewport().isGatherViewsHere())
2939 // if this is a gathered view, keep its reference since
2940 // after gathering views, only this frame will remain
2942 gatherToThisFrame.put(_af.getViewport().getSequenceSetId(),
2945 // Save dataset to register mappings once all resolved
2946 importedDatasets.put(
2947 af.getViewport().getAlignment().getDataset(),
2948 af.getViewport().getAlignment().getDataset());
2951 // Platform.timeCheck("JAXB " + name, Platform.TIME_MARK);
2954 else if (jarentry != null)
2956 // Some other file here.
2959 } while (jarentry != null);
2960 // Platform.timeCheck("JAXB loop exit", Platform.TIME_MARK);
2961 resolveFrefedSequences();
2962 // Platform.timeCheck("JAXB resolveFrefed", Platform.TIME_MARK);
2964 } catch (IOException ex)
2966 ex.printStackTrace();
2967 errorMessage = "Couldn't locate Jalview XML file : " + file;
2969 "Exception whilst loading jalview XML file : " + ex + "\n");
2970 } catch (Exception ex)
2972 System.err.println("Parsing as Jalview Version 2 file failed.");
2973 ex.printStackTrace(System.err);
2974 if (attemptversion1parse)
2976 // used to attempt to parse as V1 castor-generated xml
2978 if (Desktop.getInstance() != null)
2980 Desktop.getInstance().stopLoading();
2984 System.out.println("Successfully loaded archive file");
2987 ex.printStackTrace();
2990 "Exception whilst loading jalview XML file : " + ex + "\n");
2991 } catch (OutOfMemoryError e)
2993 // Don't use the OOM Window here
2994 errorMessage = "Out of memory loading jalview XML file";
2995 System.err.println("Out of memory whilst loading jalview XML file");
2996 e.printStackTrace();
2999 for (AlignFrame alf : alignFrames)
3001 alf.alignPanel.setHoldRepaint(false);
3007 * Regather multiple views (with the same sequence set id) to the frame (if
3008 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
3009 * views instead of separate frames. Note this doesn't restore a state where
3010 * some expanded views in turn have tabbed views - the last "first tab" read
3011 * in will play the role of gatherer for all.
3013 for (AlignFrame fr : gatherToThisFrame.values())
3015 Desktop.getInstance().gatherViews(fr);
3018 restoreSplitFrames();
3019 for (AlignmentI ds : importedDatasets.keySet())
3021 if (ds.getCodonFrames() != null)
3023 Desktop.getInstance().getStructureSelectionManager()
3024 .registerMappings(ds.getCodonFrames());
3027 if (errorMessage != null)
3032 if (Desktop.getInstance() != null)
3034 Desktop.getInstance().stopLoading();
3041 * Try to reconstruct and display SplitFrame windows, where each contains
3042 * complementary dna and protein alignments. Done by pairing up AlignFrame
3043 * objects (created earlier) which have complementary viewport ids associated.
3045 protected void restoreSplitFrames()
3047 List<SplitFrame> gatherTo = new ArrayList<>();
3048 List<AlignFrame> addedToSplitFrames = new ArrayList<>();
3049 Map<String, AlignFrame> dna = new HashMap<>();
3052 * Identify the DNA alignments
3054 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
3057 AlignFrame af = candidate.getValue();
3058 if (af.getViewport().getAlignment().isNucleotide())
3060 dna.put(candidate.getKey().getId(), af);
3065 * Try to match up the protein complements
3067 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
3070 AlignFrame af = candidate.getValue();
3071 if (!af.getViewport().getAlignment().isNucleotide())
3073 String complementId = candidate.getKey().getComplementId();
3074 // only non-null complements should be in the Map
3075 if (complementId != null && dna.containsKey(complementId))
3077 final AlignFrame dnaFrame = dna.get(complementId);
3078 SplitFrame sf = createSplitFrame(dnaFrame, af);
3079 addedToSplitFrames.add(dnaFrame);
3080 addedToSplitFrames.add(af);
3081 dnaFrame.setMenusForViewport();
3082 af.setMenusForViewport();
3083 if (af.getViewport().isGatherViewsHere())
3092 * Open any that we failed to pair up (which shouldn't happen!) as
3093 * standalone AlignFrame's.
3095 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
3098 AlignFrame af = candidate.getValue();
3099 if (!addedToSplitFrames.contains(af))
3101 Viewport view = candidate.getKey();
3102 Desktop.addInternalFrame(af, view.getTitle(),
3103 safeInt(view.getWidth()), safeInt(view.getHeight()));
3104 af.setMenusForViewport();
3105 System.err.println("Failed to restore view " + view.getTitle()
3106 + " to split frame");
3111 * Gather back into tabbed views as flagged.
3113 for (SplitFrame sf : gatherTo)
3115 Desktop.getInstance().gatherViews(sf);
3118 splitFrameCandidates.clear();
3122 * Construct and display one SplitFrame holding DNA and protein alignments.
3125 * @param proteinFrame
3128 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
3129 AlignFrame proteinFrame)
3131 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
3132 String title = MessageManager.getString("label.linked_view_title");
3133 int width = (int) dnaFrame.getBounds().getWidth();
3134 int height = (int) (dnaFrame.getBounds().getHeight()
3135 + proteinFrame.getBounds().getHeight() + 50);
3138 * SplitFrame location is saved to both enclosed frames
3140 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
3141 Desktop.addInternalFrame(splitFrame, title, width, height);
3144 * And compute cDNA consensus (couldn't do earlier with consensus as
3145 * mappings were not yet present)
3147 proteinFrame.getViewport().alignmentChanged(proteinFrame.alignPanel);
3153 * check errorMessage for a valid error message and raise an error box in the
3154 * GUI or write the current errorMessage to stderr and then clear the error
3157 protected void reportErrors()
3159 reportErrors(false);
3162 protected void reportErrors(final boolean saving)
3164 if (errorMessage != null)
3166 final String finalErrorMessage = errorMessage;
3169 javax.swing.SwingUtilities.invokeLater(new Runnable()
3174 JvOptionPane.showInternalMessageDialog(Desktop.getDesktopPane(),
3176 "Error " + (saving ? "saving" : "loading")
3178 JvOptionPane.WARNING_MESSAGE);
3184 System.err.println("Problem loading Jalview file: " + errorMessage);
3187 errorMessage = null;
3190 Map<String, String> alreadyLoadedPDB = new HashMap<>();
3193 * when set, local views will be updated from view stored in JalviewXML
3194 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
3195 * sync if this is set to true.
3197 private final boolean updateLocalViews = false;
3200 * Returns the path to a temporary file holding the PDB file for the given PDB
3201 * id. The first time of asking, searches for a file of that name in the
3202 * Jalview project jar, and copies it to a new temporary file. Any repeat
3203 * requests just return the path to the file previously created.
3209 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId,
3212 if (alreadyLoadedPDB.containsKey(pdbId))
3214 return alreadyLoadedPDB.get(pdbId).toString();
3217 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb",
3219 if (tempFile != null)
3221 alreadyLoadedPDB.put(pdbId, tempFile);
3227 * Copies the jar entry of given name to a new temporary file and returns the
3228 * path to the file, or null if the entry is not found.
3231 * @param jarEntryName
3233 * a prefix for the temporary file name, must be at least three
3236 * null or original file - so new file can be given the same suffix
3240 protected String copyJarEntry(jarInputStreamProvider jprovider,
3241 String jarEntryName, String prefix, String origFile)
3243 BufferedReader in = null;
3244 PrintWriter out = null;
3245 String suffix = ".tmp";
3246 if (origFile == null)
3248 origFile = jarEntryName;
3250 int sfpos = origFile.lastIndexOf(".");
3251 if (sfpos > -1 && sfpos < (origFile.length() - 3))
3253 suffix = "." + origFile.substring(sfpos + 1);
3257 JarInputStream jin = jprovider.getJarInputStream();
3259 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
3260 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
3261 * FileInputStream(jprovider)); }
3264 JarEntry entry = null;
3267 entry = jin.getNextJarEntry();
3268 } while (entry != null && !entry.getName().equals(jarEntryName));
3271 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
3272 File outFile = File.createTempFile(prefix, suffix);
3273 outFile.deleteOnExit();
3274 out = new PrintWriter(new FileOutputStream(outFile));
3277 while ((data = in.readLine()) != null)
3282 String t = outFile.getAbsolutePath();
3287 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
3289 } catch (Exception ex)
3291 ex.printStackTrace();
3299 } catch (IOException e)
3313 private class JvAnnotRow
3315 public JvAnnotRow(int i, AlignmentAnnotation jaa)
3322 * persisted version of annotation row from which to take vis properties
3324 public jalview.datamodel.AlignmentAnnotation template;
3327 * original position of the annotation row in the alignment
3333 * Load alignment frame from jalview XML DOM object. For a DOM object that
3334 * includes one or more Viewport elements (one with a title that does NOT
3335 * contain "Dataset for"), create the frame.
3337 * @param jalviewModel
3340 * filename source string
3341 * @param loadTreesAndStructures
3342 * when false only create Viewport
3344 * data source provider
3345 * @return alignment frame created from view stored in DOM
3347 AlignFrame loadFromObject(JalviewModel jalviewModel, String file,
3348 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
3351 // Platform.timeCheck("Jalview2XML.loadFromObject0", Platform.TIME_MARK);
3353 SequenceSet vamsasSet = jalviewModel.getVamsasModel().getSequenceSet().get(0);
3354 List<Sequence> vamsasSeqs = vamsasSet.getSequence();
3357 // JalviewModelSequence jms = object.getJalviewModelSequence();
3359 // Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
3361 Viewport view = (jalviewModel.getViewport().size() > 0)
3362 ? jalviewModel.getViewport().get(0)
3365 // ////////////////////////////////
3366 // INITIALISE ALIGNMENT SEQUENCESETID AND VIEWID
3369 // If we just load in the same jar file again, the sequenceSetId
3370 // will be the same, and we end up with multiple references
3371 // to the same sequenceSet. We must modify this id on load
3372 // so that each load of the file gives a unique id
3375 * used to resolve correct alignment dataset for alignments with multiple
3378 String uniqueSeqSetId = null;
3379 String viewId = null;
3382 uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3383 viewId = (view.getId() == null ? null
3384 : view.getId() + uniqueSetSuffix);
3387 // Platform.timeCheck("Jalview2XML.loadFromObject1", Platform.TIME_MARK);
3388 // ////////////////////////////////
3391 List<SequenceI> hiddenSeqs = null;
3393 List<SequenceI> tmpseqs = new ArrayList<>();
3395 boolean multipleView = false;
3396 SequenceI referenceseqForView = null;
3397 // JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
3398 List<JSeq> jseqs = jalviewModel.getJSeq();
3399 int vi = 0; // counter in vamsasSeq array
3400 for (int i = 0; i < jseqs.size(); i++)
3402 JSeq jseq = jseqs.get(i);
3403 String seqId = jseq.getId();
3405 SequenceI tmpSeq = seqRefIds.get(seqId);
3409 if (!incompleteSeqs.containsKey(seqId))
3411 // may not need this check, but keep it for at least 2.9,1 release
3412 if (tmpSeq.getStart() != jseq.getStart()
3413 || tmpSeq.getEnd() != jseq.getEnd())
3416 "Warning JAL-2154 regression: updating start/end for sequence "
3417 + tmpSeq.toString() + " to " + jseq);
3422 incompleteSeqs.remove(seqId);
3424 if (vamsasSeqs.size() > vi
3425 && vamsasSeqs.get(vi).getId().equals(seqId))
3427 // most likely we are reading a dataset XML document so
3428 // update from vamsasSeq section of XML for this sequence
3429 tmpSeq.setName(vamsasSeqs.get(vi).getName());
3430 tmpSeq.setDescription(vamsasSeqs.get(vi).getDescription());
3431 tmpSeq.setSequence(vamsasSeqs.get(vi).getSequence());
3436 // reading multiple views, so vamsasSeq set is a subset of JSeq
3437 multipleView = true;
3439 tmpSeq.setStart(jseq.getStart());
3440 tmpSeq.setEnd(jseq.getEnd());
3441 tmpseqs.add(tmpSeq);
3445 Sequence vamsasSeq = vamsasSeqs.get(vi);
3446 tmpSeq = new jalview.datamodel.Sequence(vamsasSeq.getName(),
3447 vamsasSeq.getSequence());
3448 tmpSeq.setDescription(vamsasSeq.getDescription());
3449 tmpSeq.setStart(jseq.getStart());
3450 tmpSeq.setEnd(jseq.getEnd());
3451 tmpSeq.setVamsasId(uniqueSetSuffix + seqId);
3452 seqRefIds.put(vamsasSeq.getId(), tmpSeq);
3453 tmpseqs.add(tmpSeq);
3457 if (safeBoolean(jseq.isViewreference()))
3459 referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
3462 if (jseq.isHidden() != null && jseq.isHidden().booleanValue())
3464 if (hiddenSeqs == null)
3466 hiddenSeqs = new ArrayList<>();
3469 hiddenSeqs.add(tmpSeq);
3473 // Platform.timeCheck("Jalview2XML.loadFromObject-seq",
3474 // Platform.TIME_MARK);
3476 // Create the alignment object from the sequence set
3477 // ///////////////////////////////
3478 SequenceI[] orderedSeqs = tmpseqs
3479 .toArray(new SequenceI[tmpseqs.size()]);
3481 AlignmentI al = null;
3482 // so we must create or recover the dataset alignment before going further
3483 // ///////////////////////////////
3484 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
3486 // older jalview projects do not have a dataset - so creat alignment and
3488 al = new Alignment(orderedSeqs);
3489 al.setDataset(null);
3493 boolean isdsal = jalviewModel.getViewport().isEmpty();
3496 // we are importing a dataset record, so
3497 // recover reference to an alignment already materialsed as dataset
3498 al = getDatasetFor(vamsasSet.getDatasetId());
3502 // materialse the alignment
3503 al = new Alignment(orderedSeqs);
3507 addDatasetRef(vamsasSet.getDatasetId(), al);
3510 // finally, verify all data in vamsasSet is actually present in al
3511 // passing on flag indicating if it is actually a stored dataset
3512 recoverDatasetFor(vamsasSet, al, isdsal, uniqueSeqSetId);
3515 // Platform.timeCheck("Jalview2XML.loadFromObject-align",
3516 // Platform.TIME_MARK);
3517 if (referenceseqForView != null)
3519 al.setSeqrep(referenceseqForView);
3521 // / Add the alignment properties
3522 for (int i = 0; i < vamsasSet.getSequenceSetProperties().size(); i++)
3524 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties()
3526 al.setProperty(ssp.getKey(), ssp.getValue());
3529 // Platform.timeCheck("Jalview2XML.loadFromObject-setseqprop",
3530 // Platform.TIME_MARK);
3531 // ///////////////////////////////
3533 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
3536 // load sequence features, database references and any associated PDB
3537 // structures for the alignment
3539 // prior to 2.10, this part would only be executed the first time a
3540 // sequence was encountered, but not afterwards.
3541 // now, for 2.10 projects, this is also done if the xml doc includes
3542 // dataset sequences not actually present in any particular view.
3544 // Platform.timeCheck("J2XML features0", Platform.TIME_RESET);
3545 for (int i = 0; i < vamsasSeqs.size(); i++)
3547 JSeq jseq = jseqs.get(i);
3548 if (jseq.getFeatures().size() > 0)
3550 List<Feature> features = jseq.getFeatures();
3551 for (int f = 0; f < features.size(); f++)
3553 Feature feat = features.get(f);
3554 SequenceFeature sf = new SequenceFeature(feat.getType(),
3555 feat.getDescription(), feat.getBegin(), feat.getEnd(),
3556 safeFloat(feat.getScore()), feat.getFeatureGroup());
3557 sf.setStatus(feat.getStatus());
3560 * load any feature attributes - include map-valued attributes
3562 Map<String, Map<String, String>> mapAttributes = new HashMap<>();
3563 for (int od = 0; od < feat.getOtherData().size(); od++)
3565 OtherData keyValue = feat.getOtherData().get(od);
3566 String attributeName = keyValue.getKey();
3567 String attributeValue = keyValue.getValue();
3568 if (attributeName.startsWith("LINK"))
3570 sf.addLink(attributeValue);
3574 String subAttribute = keyValue.getKey2();
3575 if (subAttribute == null)
3577 // simple string-valued attribute
3578 sf.setValue(attributeName, attributeValue);
3582 // attribute 'key' has sub-attribute 'key2'
3583 if (!mapAttributes.containsKey(attributeName))
3585 mapAttributes.put(attributeName, new HashMap<>());
3587 mapAttributes.get(attributeName).put(subAttribute,
3592 for (Entry<String, Map<String, String>> mapAttribute : mapAttributes
3595 sf.setValue(mapAttribute.getKey(), mapAttribute.getValue());
3598 // adds feature to datasequence's feature set (since Jalview 2.10)
3599 // Platform.timeCheck(null, Platform.TIME_SET);
3600 al.getSequenceAt(i).addSequenceFeature(sf);
3601 // Platform.timeCheck(null, Platform.TIME_MARK);
3604 if (vamsasSeqs.get(i).getDBRef().size() > 0)
3606 // adds dbrefs to datasequence's set (since Jalview 2.10)
3608 al.getSequenceAt(i).getDatasetSequence() == null
3609 ? al.getSequenceAt(i)
3610 : al.getSequenceAt(i).getDatasetSequence(),
3613 if (jseq.getPdbids().size() > 0)
3615 List<Pdbids> ids = jseq.getPdbids();
3616 for (int p = 0; p < ids.size(); p++)
3618 Pdbids pdbid = ids.get(p);
3619 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
3620 entry.setId(pdbid.getId());
3621 if (pdbid.getType() != null)
3623 if (PDBEntry.Type.getType(pdbid.getType()) != null)
3625 entry.setType(PDBEntry.Type.getType(pdbid.getType()));
3629 entry.setType(PDBEntry.Type.FILE);
3632 // jprovider is null when executing 'New View'
3633 if (pdbid.getFile() != null && jprovider != null)
3635 if (!pdbloaded.containsKey(pdbid.getFile()))
3637 entry.setFile(loadPDBFile(jprovider, pdbid.getId(),
3642 entry.setFile(pdbloaded.get(pdbid.getId()).toString());
3646 if (pdbid.getPdbentryItem() != null)
3648 for (PdbentryItem item : pdbid.getPdbentryItem())
3650 for (Property pr : item.getProperty())
3652 entry.setProperty(pr.getName(), pr.getValue());
3657 for (Property prop : pdbid.getProperty())
3659 entry.setProperty(prop.getName(), prop.getValue());
3661 Desktop.getInstance().getStructureSelectionManager()
3662 .registerPDBEntry(entry);
3663 // adds PDBEntry to datasequence's set (since Jalview 2.10)
3664 if (al.getSequenceAt(i).getDatasetSequence() != null)
3666 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
3670 al.getSequenceAt(i).addPDBId(entry);
3677 // Platform.timeCheck("features done", Platform.TIME_GET);
3678 // Platform.timeCheck("Jalview2XML.loadFromObject-endmultiview",
3679 // Platform.TIME_MARK);
3680 } // end !multipleview
3682 // ///////////////////////////////
3683 // LOAD SEQUENCE MAPPINGS
3685 if (vamsasSet.getAlcodonFrame().size() > 0)
3687 // TODO Potentially this should only be done once for all views of an
3689 List<AlcodonFrame> alc = vamsasSet.getAlcodonFrame();
3690 for (int i = 0; i < alc.size(); i++)
3692 AlignedCodonFrame cf = new AlignedCodonFrame();
3693 if (alc.get(i).getAlcodMap().size() > 0)
3695 List<AlcodMap> maps = alc.get(i).getAlcodMap();
3696 for (int m = 0; m < maps.size(); m++)
3698 AlcodMap map = maps.get(m);
3699 SequenceI dnaseq = seqRefIds.get(map.getDnasq());
3701 jalview.datamodel.Mapping mapping = null;
3702 // attach to dna sequence reference.
3703 if (map.getMapping() != null)
3705 mapping = addMapping(map.getMapping());
3706 if (dnaseq != null && mapping.getTo() != null)
3708 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
3714 newAlcodMapRef(map.getDnasq(), cf, mapping));
3718 al.addCodonFrame(cf);
3721 // Platform.timeCheck("Jalview2XML.loadFromObject-seqmap",
3722 // Platform.TIME_MARK);
3725 // ////////////////////////////////
3727 List<JvAnnotRow> autoAlan = new ArrayList<>();
3730 * store any annotations which forward reference a group's ID
3732 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<>();
3734 if (vamsasSet.getAnnotation().size()/*Count()*/ > 0)
3736 List<Annotation> an = vamsasSet.getAnnotation();
3738 for (int i = 0; i < an.size(); i++)
3740 Annotation annotation = an.get(i);
3743 * test if annotation is automatically calculated for this view only
3745 boolean autoForView = false;
3746 if (annotation.getLabel().equals("Quality")
3747 || annotation.getLabel().equals("Conservation")
3748 || annotation.getLabel().equals("Consensus"))
3750 // Kludge for pre 2.5 projects which lacked the autocalculated flag
3752 // JAXB has no has() test; schema defaults value to false
3753 // if (!annotation.hasAutoCalculated())
3755 // annotation.setAutoCalculated(true);
3758 if (autoForView || annotation.isAutoCalculated())
3760 // remove ID - we don't recover annotation from other views for
3761 // view-specific annotation
3762 annotation.setId(null);
3765 // set visibility for other annotation in this view
3766 String annotationId = annotation.getId();
3767 if (annotationId != null && annotationIds.containsKey(annotationId))
3769 AlignmentAnnotation jda = annotationIds.get(annotationId);
3770 // in principle Visible should always be true for annotation displayed
3771 // in multiple views
3772 if (annotation.isVisible() != null)
3774 jda.visible = annotation.isVisible();
3777 al.addAnnotation(jda);
3781 // Construct new annotation from model.
3782 List<AnnotationElement> ae = annotation.getAnnotationElement();
3783 // System.err.println(
3784 // "Jalview2XML processing " + ae.size() + " annotations");
3786 jalview.datamodel.Annotation[] anot = null;
3787 java.awt.Color firstColour = null;
3789 if (!annotation.isScoreOnly())
3791 anot = new jalview.datamodel.Annotation[al.getWidth()];
3792 for (int aa = 0; aa < ae.size() && aa < anot.length; aa++)
3794 AnnotationElement annElement = ae.get(aa);
3795 anpos = annElement.getPosition();
3797 if (anpos >= anot.length)
3802 float value = safeFloat(annElement.getValue());
3803 anot[anpos] = new jalview.datamodel.Annotation(
3804 annElement.getDisplayCharacter(),
3805 annElement.getDescription(),
3806 (annElement.getSecondaryStructure() == null
3807 || annElement.getSecondaryStructure()
3811 .getSecondaryStructure()
3814 anot[anpos].colour = new Color(safeInt(annElement.getColour()));
3815 if (firstColour == null)
3817 firstColour = anot[anpos].colour;
3821 // create the new AlignmentAnnotation
3822 jalview.datamodel.AlignmentAnnotation jaa = null;
3824 if (annotation.isGraph())
3826 float llim = 0, hlim = 0;
3827 // if (autoForView || an[i].isAutoCalculated()) {
3830 jaa = new jalview.datamodel.AlignmentAnnotation(
3831 annotation.getLabel(), annotation.getDescription(), anot,
3832 llim, hlim, safeInt(annotation.getGraphType()));
3834 jaa.graphGroup = safeInt(annotation.getGraphGroup());
3835 jaa._linecolour = firstColour;
3836 if (annotation.getThresholdLine() != null)
3838 jaa.setThreshold(new jalview.datamodel.GraphLine(
3839 safeFloat(annotation.getThresholdLine().getValue()),
3840 annotation.getThresholdLine().getLabel(),
3841 new java.awt.Color(safeInt(
3842 annotation.getThresholdLine().getColour()))));
3844 if (autoForView || annotation.isAutoCalculated())
3846 // Hardwire the symbol display line to ensure that labels for
3847 // histograms are displayed
3853 jaa = new jalview.datamodel.AlignmentAnnotation(
3854 annotation.getLabel(), annotation.getDescription(), anot);
3855 jaa._linecolour = firstColour;
3857 // register new annotation
3858 // Annotation graphs such as Conservation will not have id.
3859 if (annotation.getId() != null)
3861 annotationIds.put(annotation.getId(), jaa);
3862 jaa.annotationId = annotation.getId();
3864 // recover sequence association
3865 String sequenceRef = annotation.getSequenceRef();
3866 if (sequenceRef != null)
3868 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3869 SequenceI sequence = seqRefIds.get(sequenceRef);
3870 if (sequence == null)
3872 // in pre-2.9 projects sequence ref is to sequence name
3873 sequence = al.findName(sequenceRef);
3875 if (sequence != null)
3877 jaa.createSequenceMapping(sequence, 1, true);
3878 sequence.addAlignmentAnnotation(jaa);
3881 // and make a note of any group association
3882 if (annotation.getGroupRef() != null
3883 && annotation.getGroupRef().length() > 0)
3885 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3886 .get(annotation.getGroupRef());
3889 aal = new ArrayList<>();
3890 groupAnnotRefs.put(annotation.getGroupRef(), aal);
3895 if (annotation.getScore() != null)
3897 jaa.setScore(annotation.getScore().doubleValue());
3899 if (annotation.isVisible() != null)
3901 jaa.visible = annotation.isVisible().booleanValue();
3904 if (annotation.isCentreColLabels() != null)
3906 jaa.centreColLabels = annotation.isCentreColLabels()
3910 if (annotation.isScaleColLabels() != null)
3912 jaa.scaleColLabel = annotation.isScaleColLabels().booleanValue();
3914 if (annotation.isAutoCalculated())
3916 // newer files have an 'autoCalculated' flag and store calculation
3917 // state in viewport properties
3918 jaa.autoCalculated = true; // means annotation will be marked for
3919 // update at end of load.
3921 if (annotation.getGraphHeight() != null)
3923 jaa.graphHeight = annotation.getGraphHeight().intValue();
3925 jaa.belowAlignment = annotation.isBelowAlignment();
3926 jaa.setCalcId(annotation.getCalcId());
3927 if (annotation.getProperty().size() > 0)
3929 for (Annotation.Property prop : annotation
3932 jaa.setProperty(prop.getName(), prop.getValue());
3935 if (jaa.autoCalculated)
3937 autoAlan.add(new JvAnnotRow(i, jaa));
3940 // if (!autoForView)
3942 // add autocalculated group annotation and any user created annotation
3944 al.addAnnotation(jaa);
3947 // Platform.timeCheck("Jalview2XML.loadFromObject-annot",
3948 // Platform.TIME_MARK);
3950 // ///////////////////////
3952 // Create alignment markup and styles for this view
3953 if (jalviewModel.getJGroup().size() > 0)
3955 List<JGroup> groups = jalviewModel.getJGroup();
3956 boolean addAnnotSchemeGroup = false;
3957 for (int i = 0; i < groups.size(); i++)
3959 JGroup jGroup = groups.get(i);
3960 ColourSchemeI cs = null;
3961 if (jGroup.getColour() != null)
3963 if (jGroup.getColour().startsWith("ucs"))
3965 cs = getUserColourScheme(jalviewModel, jGroup.getColour());
3967 else if (jGroup.getColour().equals("AnnotationColourGradient")
3968 && jGroup.getAnnotationColours() != null)
3970 addAnnotSchemeGroup = true;
3974 cs = ColourSchemeProperty.getColourScheme(null, al,
3975 jGroup.getColour());
3978 int pidThreshold = safeInt(jGroup.getPidThreshold());
3980 Vector<SequenceI> seqs = new Vector<>();
3982 for (int s = 0; s < jGroup.getSeq().size(); s++)
3984 String seqId = jGroup.getSeq().get(s);
3985 SequenceI ts = seqRefIds.get(seqId);
3989 seqs.addElement(ts);
3993 if (seqs.size() < 1)
3998 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3999 safeBoolean(jGroup.isDisplayBoxes()),
4000 safeBoolean(jGroup.isDisplayText()),
4001 safeBoolean(jGroup.isColourText()),
4002 safeInt(jGroup.getStart()), safeInt(jGroup.getEnd()));
4003 sg.getGroupColourScheme().setThreshold(pidThreshold, true);
4004 sg.getGroupColourScheme()
4005 .setConservationInc(safeInt(jGroup.getConsThreshold()));
4006 sg.setOutlineColour(new Color(safeInt(jGroup.getOutlineColour())));
4008 sg.textColour = new Color(safeInt(jGroup.getTextCol1()));
4009 sg.textColour2 = new Color(safeInt(jGroup.getTextCol2()));
4010 sg.setShowNonconserved(safeBoolean(jGroup.isShowUnconserved()));
4011 sg.thresholdTextColour = safeInt(jGroup.getTextColThreshold());
4012 // attributes with a default in the schema are never null
4013 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
4014 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
4015 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
4016 sg.setIgnoreGapsConsensus(jGroup.isIgnoreGapsinConsensus());
4017 if (jGroup.getConsThreshold() != null
4018 && jGroup.getConsThreshold().intValue() != 0)
4020 Conservation c = new Conservation("All", sg.getSequences(null), 0,
4023 c.verdict(false, 25);
4024 sg.cs.setConservation(c);
4027 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
4029 // re-instate unique group/annotation row reference
4030 List<AlignmentAnnotation> jaal = groupAnnotRefs
4031 .get(jGroup.getId());
4034 for (AlignmentAnnotation jaa : jaal)
4037 if (jaa.autoCalculated)
4039 // match up and try to set group autocalc alignment row for this
4041 if (jaa.label.startsWith("Consensus for "))
4043 sg.setConsensus(jaa);
4045 // match up and try to set group autocalc alignment row for this
4047 if (jaa.label.startsWith("Conservation for "))
4049 sg.setConservationRow(jaa);
4056 if (addAnnotSchemeGroup)
4058 // reconstruct the annotation colourscheme
4059 sg.setColourScheme(constructAnnotationColour(
4060 jGroup.getAnnotationColours(), null, al, jalviewModel, false));
4063 // Platform.timeCheck("Jalview2XML.loadFromObject-groups",
4064 // Platform.TIME_MARK);
4068 // only dataset in this model, so just return.
4071 // ///////////////////////////////
4074 // now check to see if we really need to create a new viewport.
4075 if (multipleView && viewportsAdded.size() == 0)
4077 // We recovered an alignment for which a viewport already exists.
4078 // TODO: fix up any settings necessary for overlaying stored state onto
4079 // state recovered from another document. (may not be necessary).
4080 // we may need a binding from a viewport in memory to one recovered from
4082 // and then recover its containing af to allow the settings to be applied.
4083 // TODO: fix for vamsas demo
4085 "About to recover a viewport for existing alignment: Sequence set ID is "
4087 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
4088 if (seqsetobj != null)
4090 if (seqsetobj instanceof String)
4092 uniqueSeqSetId = (String) seqsetobj;
4094 "Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
4100 "Warning : Collision between sequence set ID string and existing jalview object mapping.");
4104 // Platform.timeCheck("Jalview2XML.loadFromObject-viewport",
4105 // Platform.TIME_MARK);
4108 * indicate that annotation colours are applied across all groups (pre
4109 * Jalview 2.8.1 behaviour)
4111 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan("2.8.1",
4112 jalviewModel.getVersion());
4114 AlignFrame af = null;
4115 AlignmentPanel ap = null;
4116 AlignViewport av = null;
4119 // Check to see if this alignment already has a view id == viewId
4120 jalview.gui.AlignmentPanel views[] = Desktop
4121 .getAlignmentPanels(uniqueSeqSetId);
4122 if (views != null && views.length > 0)
4124 for (int v = 0; v < views.length; v++)
4128 if (av.getViewId().equalsIgnoreCase(viewId))
4130 // recover the existing alignpanel, alignframe, viewport
4133 // TODO: could even skip resetting view settings if we don't want to
4134 // change the local settings from other jalview processes
4142 af = loadViewport(file, jseqs, hiddenSeqs, al, jalviewModel, view,
4143 uniqueSeqSetId, viewId, autoAlan);
4144 av = af.getViewport();
4145 // note that this only retrieves the most recently accessed
4146 // tab of an AlignFrame.
4151 * Load any trees, PDB structures and viewers
4153 * Not done if flag is false (when this method is used for New View)
4155 final AlignFrame af0 = af;
4156 final AlignViewport av0 = av;
4157 final AlignmentPanel ap0 = ap;
4158 // Platform.timeCheck("Jalview2XML.loadFromObject-beforetree",
4159 // Platform.TIME_MARK);
4160 if (loadTreesAndStructures)
4162 if (!jalviewModel.getTree().isEmpty())
4164 SwingUtilities.invokeLater(new Runnable()
4169 // Platform.timeCheck(null, Platform.TIME_MARK);
4170 loadTrees(jalviewModel, view, af0, av0, ap0);
4171 // Platform.timeCheck("Jalview2XML.loadTrees", Platform.TIME_MARK);
4175 if (!jalviewModel.getPcaViewer().isEmpty())
4177 SwingUtilities.invokeLater(new Runnable()
4182 // Platform.timeCheck(null, Platform.TIME_MARK);
4183 loadPCAViewers(jalviewModel, ap0);
4184 // Platform.timeCheck("Jalview2XML.loadPCA", Platform.TIME_MARK);
4188 SwingUtilities.invokeLater(new Runnable()
4193 // Platform.timeCheck(null, Platform.TIME_MARK);
4194 loadPDBStructures(jprovider, jseqs, af0, ap0);
4195 // Platform.timeCheck("Jalview2XML.loadPDB", Platform.TIME_MARK);
4198 SwingUtilities.invokeLater(new Runnable()
4203 loadRnaViewers(jprovider, jseqs, ap0);
4207 // and finally return.
4208 // but do not set holdRepaint true just yet, because this could be the
4209 // initial frame with just its dataset.
4214 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
4215 * panel is restored from separate jar entries, two (gapped and trimmed) per
4216 * sequence and secondary structure.
4218 * Currently each viewer shows just one sequence and structure (gapped and
4219 * trimmed), however this method is designed to support multiple sequences or
4220 * structures in viewers if wanted in future.
4226 protected void loadRnaViewers(jarInputStreamProvider jprovider,
4227 List<JSeq> jseqs, AlignmentPanel ap)
4230 * scan the sequences for references to viewers; create each one the first
4231 * time it is referenced, add Rna models to existing viewers
4233 for (JSeq jseq : jseqs)
4235 for (int i = 0; i < jseq.getRnaViewer().size(); i++)
4237 RnaViewer viewer = jseq.getRnaViewer().get(i);
4238 AppVarna appVarna = findOrCreateVarnaViewer(viewer, uniqueSetSuffix,
4241 for (int j = 0; j < viewer.getSecondaryStructure().size(); j++)
4243 SecondaryStructure ss = viewer.getSecondaryStructure().get(j);
4244 SequenceI seq = seqRefIds.get(jseq.getId());
4245 AlignmentAnnotation ann = this.annotationIds
4246 .get(ss.getAnnotationId());
4249 * add the structure to the Varna display (with session state copied
4250 * from the jar to a temporary file)
4252 boolean gapped = safeBoolean(ss.isGapped());
4253 String rnaTitle = ss.getTitle();
4254 String sessionState = ss.getViewerState();
4255 String tempStateFile = copyJarEntry(jprovider, sessionState,
4257 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
4258 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
4260 appVarna.setInitialSelection(safeInt(viewer.getSelectedRna()));
4266 * Locate and return an already instantiated matching AppVarna, or create one
4270 * @param viewIdSuffix
4274 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
4275 String viewIdSuffix, AlignmentPanel ap)
4278 * on each load a suffix is appended to the saved viewId, to avoid conflicts
4279 * if load is repeated
4281 String postLoadId = viewer.getViewId() + viewIdSuffix;
4282 for (JInternalFrame frame : getAllFrames())
4284 if (frame instanceof AppVarna)
4286 AppVarna varna = (AppVarna) frame;
4287 if (postLoadId.equals(varna.getViewId()))
4289 // this viewer is already instantiated
4290 // could in future here add ap as another 'parent' of the
4291 // AppVarna window; currently just 1-to-many
4298 * viewer not found - make it
4300 RnaViewerModel model = new RnaViewerModel(postLoadId, viewer.getTitle(),
4301 safeInt(viewer.getXpos()), safeInt(viewer.getYpos()),
4302 safeInt(viewer.getWidth()), safeInt(viewer.getHeight()),
4303 safeInt(viewer.getDividerLocation()));
4304 AppVarna varna = new AppVarna(model, ap);
4310 * Load any saved trees
4318 protected void loadTrees(JalviewModel jm, Viewport view,
4319 AlignFrame af, AlignViewport av, AlignmentPanel ap)
4321 // TODO result of automated refactoring - are all these parameters needed?
4324 for (int t = 0; t < jm.getTree().size(); t++)
4327 Tree tree = jm.getTree().get(t);
4329 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
4332 tp = af.showNewickTree(new NewickFile(tree.getNewick()),
4333 tree.getTitle(), safeInt(tree.getWidth()),
4334 safeInt(tree.getHeight()), safeInt(tree.getXpos()),
4335 safeInt(tree.getYpos()));
4336 if (tree.getId() != null)
4338 // perhaps bind the tree id to something ?
4343 // update local tree attributes ?
4344 // TODO: should check if tp has been manipulated by user - if so its
4345 // settings shouldn't be modified
4346 tp.setTitle(tree.getTitle());
4347 tp.setBounds(new Rectangle(safeInt(tree.getXpos()),
4348 safeInt(tree.getYpos()), safeInt(tree.getWidth()),
4349 safeInt(tree.getHeight())));
4350 tp.setViewport(av); // af.viewport;
4351 // TODO: verify 'associate with all views' works still
4352 tp.getTreeCanvas().setViewport(av); // af.viewport;
4353 tp.getTreeCanvas().setAssociatedPanel(ap); // af.alignPanel;
4355 tp.getTreeCanvas().setApplyToAllViews(tree.isLinkToAllViews());
4358 warn("There was a problem recovering stored Newick tree: \n"
4359 + tree.getNewick());
4363 tp.fitToWindow.setState(safeBoolean(tree.isFitToWindow()));
4364 tp.fitToWindow_actionPerformed(null);
4366 if (tree.getFontName() != null)
4369 new Font(tree.getFontName(), safeInt(tree.getFontStyle()),
4370 safeInt(tree.getFontSize())));
4375 new Font(view.getFontName(), safeInt(view.getFontStyle()),
4376 safeInt(view.getFontSize())));
4379 tp.showPlaceholders(safeBoolean(tree.isMarkUnlinked()));
4380 tp.showBootstrap(safeBoolean(tree.isShowBootstrap()));
4381 tp.showDistances(safeBoolean(tree.isShowDistances()));
4383 tp.getTreeCanvas().setThreshold(safeFloat(tree.getThreshold()));
4385 if (safeBoolean(tree.isCurrentTree()))
4387 af.getViewport().setCurrentTree(tp.getTree());
4391 } catch (Exception ex)
4393 ex.printStackTrace();
4398 * Load and link any saved structure viewers.
4405 protected void loadPDBStructures(jarInputStreamProvider jprovider,
4406 List<JSeq> jseqs, AlignFrame af, AlignmentPanel ap)
4409 * Run through all PDB ids on the alignment, and collect mappings between
4410 * distinct view ids and all sequences referring to that view.
4412 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<>();
4414 for (int i = 0; i < jseqs.size(); i++)
4416 JSeq jseq = jseqs.get(i);
4417 if (jseq.getPdbids().size() > 0)
4419 List<Pdbids> ids = jseq.getPdbids();
4420 for (int p = 0; p < ids.size(); p++)
4422 Pdbids pdbid = ids.get(p);
4423 final int structureStateCount = pdbid.getStructureState().size();
4424 for (int s = 0; s < structureStateCount; s++)
4426 // check to see if we haven't already created this structure view
4427 final StructureState structureState = pdbid
4428 .getStructureState().get(s);
4429 String sviewid = (structureState.getViewId() == null) ? null
4430 : structureState.getViewId() + uniqueSetSuffix;
4431 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
4432 // Originally : pdbid.getFile()
4433 // : TODO: verify external PDB file recovery still works in normal
4434 // jalview project load
4436 loadPDBFile(jprovider, pdbid.getId(), pdbid.getFile()));
4437 jpdb.setId(pdbid.getId());
4439 int x = safeInt(structureState.getXpos());
4440 int y = safeInt(structureState.getYpos());
4441 int width = safeInt(structureState.getWidth());
4442 int height = safeInt(structureState.getHeight());
4444 // Probably don't need to do this anymore...
4445 // Desktop.getDesktop().getComponentAt(x, y);
4446 // TODO: NOW: check that this recovers the PDB file correctly.
4447 String pdbFile = loadPDBFile(jprovider, pdbid.getId(),
4449 jalview.datamodel.SequenceI seq = seqRefIds
4450 .get(jseq.getId() + "");
4451 if (sviewid == null)
4453 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width + ","
4456 if (!structureViewers.containsKey(sviewid))
4458 structureViewers.put(sviewid,
4459 new StructureViewerModel(x, y, width, height, false,
4460 false, true, structureState.getViewId(),
4461 structureState.getType()));
4462 // Legacy pre-2.7 conversion JAL-823 :
4463 // do not assume any view has to be linked for colour by
4467 // assemble String[] { pdb files }, String[] { id for each
4468 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
4469 // seqs_file 2}, boolean[] {
4470 // linkAlignPanel,superposeWithAlignpanel}} from hash
4471 StructureViewerModel jmoldat = structureViewers.get(sviewid);
4472 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
4473 || structureState.isAlignwithAlignPanel());
4476 * Default colour by linked panel to false if not specified (e.g.
4477 * for pre-2.7 projects)
4479 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
4480 colourWithAlignPanel |= structureState.isColourwithAlignPanel();
4481 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
4484 * Default colour by viewer to true if not specified (e.g. for
4487 boolean colourByViewer = jmoldat.isColourByViewer();
4488 colourByViewer &= structureState.isColourByJmol();
4489 jmoldat.setColourByViewer(colourByViewer);
4491 if (jmoldat.getStateData().length() < structureState
4492 .getValue()/*Content()*/.length())
4494 jmoldat.setStateData(structureState.getValue());// Content());
4496 if (pdbid.getFile() != null)
4498 File mapkey = new File(pdbid.getFile());
4499 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
4500 if (seqstrmaps == null)
4502 jmoldat.getFileData().put(mapkey,
4503 seqstrmaps = jmoldat.new StructureData(pdbFile,
4506 if (!seqstrmaps.getSeqList().contains(seq))
4508 seqstrmaps.getSeqList().add(seq);
4514 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");
4521 // Instantiate the associated structure views
4522 for (Entry<String, StructureViewerModel> entry : structureViewers
4527 createOrLinkStructureViewer(entry, af, ap, jprovider);
4528 } catch (Exception e)
4531 "Error loading structure viewer: " + e.getMessage());
4532 // failed - try the next one
4544 protected void createOrLinkStructureViewer(
4545 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4546 AlignmentPanel ap, jarInputStreamProvider jprovider)
4548 final StructureViewerModel stateData = viewerData.getValue();
4551 * Search for any viewer windows already open from other alignment views
4552 * that exactly match the stored structure state
4554 StructureViewerBase comp = findMatchingViewer(viewerData);
4558 linkStructureViewer(ap, comp, stateData);
4563 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
4564 * "viewer_"+stateData.viewId
4566 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
4568 createChimeraViewer(viewerData, af, jprovider);
4573 * else Jmol (if pre-2.9, stateData contains JMOL state string)
4575 createJmolViewer(viewerData, af, jprovider);
4580 * Create a new Chimera viewer.
4586 protected void createChimeraViewer(
4587 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4588 jarInputStreamProvider jprovider)
4590 StructureViewerModel data = viewerData.getValue();
4591 String chimeraSessionFile = data.getStateData();
4594 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
4596 * NB this is the 'saved' viewId as in the project file XML, _not_ the
4597 * 'uniquified' sviewid used to reconstruct the viewer here
4599 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
4600 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
4603 Set<Entry<File, StructureData>> fileData = data.getFileData()
4605 List<PDBEntry> pdbs = new ArrayList<>();
4606 List<SequenceI[]> allseqs = new ArrayList<>();
4607 for (Entry<File, StructureData> pdb : fileData)
4609 String filePath = pdb.getValue().getFilePath();
4610 String pdbId = pdb.getValue().getPdbId();
4611 // pdbs.add(new PDBEntry(filePath, pdbId));
4612 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
4613 final List<SequenceI> seqList = pdb.getValue().getSeqList();
4614 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
4618 boolean colourByChimera = data.isColourByViewer();
4619 boolean colourBySequence = data.isColourWithAlignPanel();
4621 // TODO use StructureViewer as a factory here, see JAL-1761
4622 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
4623 final SequenceI[][] seqsArray = allseqs
4624 .toArray(new SequenceI[allseqs.size()][]);
4625 String newViewId = viewerData.getKey();
4627 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
4628 af.alignPanel, pdbArray, seqsArray, colourByChimera,
4629 colourBySequence, newViewId);
4630 cvf.setSize(data.getWidth(), data.getHeight());
4631 cvf.setLocation(data.getX(), data.getY());
4635 * Create a new Jmol window. First parse the Jmol state to translate filenames
4636 * loaded into the view, and record the order in which files are shown in the
4637 * Jmol view, so we can add the sequence mappings in same order.
4643 protected void createJmolViewer(
4644 final Entry<String, StructureViewerModel> viewerData,
4645 AlignFrame af, jarInputStreamProvider jprovider)
4647 final StructureViewerModel svattrib = viewerData.getValue();
4648 String state = svattrib.getStateData();
4651 * Pre-2.9: state element value is the Jmol state string
4653 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
4656 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
4658 state = readJarEntry(jprovider,
4659 getViewerJarEntryName(svattrib.getViewId()));
4662 List<String> pdbfilenames = new ArrayList<>();
4663 List<SequenceI[]> seqmaps = new ArrayList<>();
4664 List<String> pdbids = new ArrayList<>();
4665 StringBuilder newFileLoc = new StringBuilder(64);
4666 int cp = 0, ncp, ecp;
4667 Map<File, StructureData> oldFiles = svattrib.getFileData();
4668 while ((ncp = state.indexOf("load ", cp)) > -1)
4672 // look for next filename in load statement
4673 newFileLoc.append(state.substring(cp,
4674 ncp = (state.indexOf("\"", ncp + 1) + 1)));
4675 String oldfilenam = state.substring(ncp,
4676 ecp = state.indexOf("\"", ncp));
4677 // recover the new mapping data for this old filename
4678 // have to normalize filename - since Jmol and jalview do
4680 // translation differently.
4681 StructureData filedat = oldFiles.get(new File(oldfilenam));
4682 if (filedat == null)
4684 String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\");
4685 filedat = oldFiles.get(new File(reformatedOldFilename));
4687 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
4688 pdbfilenames.add(filedat.getFilePath());
4689 pdbids.add(filedat.getPdbId());
4690 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4691 newFileLoc.append("\"");
4692 cp = ecp + 1; // advance beyond last \" and set cursor so we can
4693 // look for next file statement.
4694 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
4698 // just append rest of state
4699 newFileLoc.append(state.substring(cp));
4703 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
4704 newFileLoc = new StringBuilder(state);
4705 newFileLoc.append("; load append ");
4706 for (File id : oldFiles.keySet())
4708 // add this and any other pdb files that should be present in
4710 StructureData filedat = oldFiles.get(id);
4711 newFileLoc.append(filedat.getFilePath());
4712 pdbfilenames.add(filedat.getFilePath());
4713 pdbids.add(filedat.getPdbId());
4714 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4715 newFileLoc.append(" \"");
4716 newFileLoc.append(filedat.getFilePath());
4717 newFileLoc.append("\"");
4720 newFileLoc.append(";");
4723 if (newFileLoc.length() == 0)
4727 int histbug = newFileLoc.indexOf("history = ");
4731 * change "history = [true|false];" to "history = [1|0];"
4734 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
4735 String val = (diff == -1) ? null
4736 : newFileLoc.substring(histbug, diff);
4737 if (val != null && val.length() >= 4)
4739 if (val.contains("e")) // eh? what can it be?
4741 if (val.trim().equals("true"))
4749 newFileLoc.replace(histbug, diff, val);
4754 final String[] pdbf = pdbfilenames
4755 .toArray(new String[pdbfilenames.size()]);
4756 final String[] id = pdbids.toArray(new String[pdbids.size()]);
4757 final SequenceI[][] sq = seqmaps
4758 .toArray(new SequenceI[seqmaps.size()][]);
4759 final String fileloc = newFileLoc.toString();
4760 final String sviewid = viewerData.getKey();
4761 final AlignFrame alf = af;
4762 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
4763 svattrib.getWidth(), svattrib.getHeight());
4766 javax.swing.SwingUtilities.invokeLater(new Runnable()
4771 JalviewStructureDisplayI sview = null;
4774 sview = new StructureViewer(
4775 alf.alignPanel.getStructureSelectionManager())
4776 .createView(StructureViewer.ViewerType.JMOL,
4777 pdbf, id, sq, alf.alignPanel, svattrib,
4778 fileloc, rect, sviewid);
4779 addNewStructureViewer(sview);
4780 } catch (OutOfMemoryError ex)
4782 new OOMWarning("restoring structure view for PDB id " + id,
4783 (OutOfMemoryError) ex.getCause());
4784 if (sview != null && sview.isVisible())
4786 sview.closeViewer(false);
4787 sview.setVisible(false);
4793 // } catch (InvocationTargetException ex)
4795 // warn("Unexpected error when opening Jmol view.", ex);
4797 // } catch (InterruptedException e)
4799 // // e.printStackTrace();
4805 * Generates a name for the entry in the project jar file to hold state
4806 * information for a structure viewer
4811 protected String getViewerJarEntryName(String viewId)
4813 return VIEWER_PREFIX + viewId;
4817 * Returns any open frame that matches given structure viewer data. The match
4818 * is based on the unique viewId, or (for older project versions) the frame's
4824 protected StructureViewerBase findMatchingViewer(
4825 Entry<String, StructureViewerModel> viewerData)
4827 final String sviewid = viewerData.getKey();
4828 final StructureViewerModel svattrib = viewerData.getValue();
4829 StructureViewerBase comp = null;
4830 JInternalFrame[] frames = getAllFrames();
4831 for (JInternalFrame frame : frames)
4833 if (frame instanceof StructureViewerBase)
4836 * Post jalview 2.4 schema includes structure view id
4838 if (sviewid != null && ((StructureViewerBase) frame).getViewId()
4841 comp = (StructureViewerBase) frame;
4842 break; // break added in 2.9
4845 * Otherwise test for matching position and size of viewer frame
4847 else if (frame.getX() == svattrib.getX()
4848 && frame.getY() == svattrib.getY()
4849 && frame.getHeight() == svattrib.getHeight()
4850 && frame.getWidth() == svattrib.getWidth())
4852 comp = (StructureViewerBase) frame;
4853 // no break in faint hope of an exact match on viewId
4861 * Link an AlignmentPanel to an existing structure viewer.
4866 * @param useinViewerSuperpos
4867 * @param usetoColourbyseq
4868 * @param viewerColouring
4870 protected void linkStructureViewer(AlignmentPanel ap,
4871 StructureViewerBase viewer, StructureViewerModel stateData)
4873 // NOTE: if the jalview project is part of a shared session then
4874 // view synchronization should/could be done here.
4876 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4877 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4878 final boolean viewerColouring = stateData.isColourByViewer();
4879 Map<File, StructureData> oldFiles = stateData.getFileData();
4882 * Add mapping for sequences in this view to an already open viewer
4884 final AAStructureBindingModel binding = viewer.getBinding();
4885 for (File id : oldFiles.keySet())
4887 // add this and any other pdb files that should be present in the
4889 StructureData filedat = oldFiles.get(id);
4890 String pdbFile = filedat.getFilePath();
4891 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4892 binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE,
4894 binding.addSequenceForStructFile(pdbFile, seq);
4896 // and add the AlignmentPanel's reference to the view panel
4897 viewer.addAlignmentPanel(ap);
4898 if (useinViewerSuperpos)
4900 viewer.useAlignmentPanelForSuperposition(ap);
4904 viewer.excludeAlignmentPanelForSuperposition(ap);
4906 if (usetoColourbyseq)
4908 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4912 viewer.excludeAlignmentPanelForColourbyseq(ap);
4917 * Get all frames within the Desktop.
4921 protected JInternalFrame[] getAllFrames()
4923 JInternalFrame[] frames = null;
4924 // TODO is this necessary - is it safe - risk of hanging?
4929 frames = Desktop.getDesktopPane().getAllFrames();
4930 } catch (ArrayIndexOutOfBoundsException e)
4932 // occasional No such child exceptions are thrown here...
4936 } catch (InterruptedException f)
4940 } while (frames == null);
4945 * Answers true if 'version' is equal to or later than 'supported', where each
4946 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4947 * changes. Development and test values for 'version' are leniently treated
4951 * - minimum version we are comparing against
4953 * - version of data being processsed
4956 public static boolean isVersionStringLaterThan(String supported,
4959 if (supported == null || version == null
4960 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4961 || version.equalsIgnoreCase("Test")
4962 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4964 System.err.println("Assuming project file with "
4965 + (version == null ? "null" : version)
4966 + " is compatible with Jalview version " + supported);
4971 return StringUtils.compareVersions(version, supported, "b") >= 0;
4975 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4977 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4979 if (newStructureViewers != null)
4981 sview.getBinding().setFinishedLoadingFromArchive(false);
4982 newStructureViewers.add(sview);
4986 protected void setLoadingFinishedForNewStructureViewers()
4988 if (newStructureViewers != null)
4990 for (JalviewStructureDisplayI sview : newStructureViewers)
4992 sview.getBinding().setFinishedLoadingFromArchive(true);
4994 newStructureViewers.clear();
4995 newStructureViewers = null;
4999 AlignFrame loadViewport(String file, List<JSeq> JSEQ,
5000 List<SequenceI> hiddenSeqs, AlignmentI al,
5001 JalviewModel jm, Viewport view, String uniqueSeqSetId,
5002 String viewId, List<JvAnnotRow> autoAlan)
5004 AlignFrame af = null;
5005 af = new AlignFrame(al, safeInt(view.getWidth()),
5006 safeInt(view.getHeight()), uniqueSeqSetId, viewId)
5010 // protected void processKeyEvent(java.awt.event.KeyEvent e) {
5011 // System.out.println("Jalview2XML AF " + e);
5012 // super.processKeyEvent(e);
5018 af.alignPanel.setHoldRepaint(true);
5019 af.setFileName(file, FileFormat.Jalview);
5021 final AlignViewport viewport = af.getViewport();
5022 for (int i = 0; i < JSEQ.size(); i++)
5024 int colour = safeInt(JSEQ.get(i).getColour());
5025 viewport.setSequenceColour(viewport.getAlignment().getSequenceAt(i),
5031 viewport.setColourByReferenceSeq(true);
5032 viewport.setDisplayReferenceSeq(true);
5035 viewport.setGatherViewsHere(safeBoolean(view.isGatheredViews()));
5037 if (view.getSequenceSetId() != null)
5039 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
5041 viewport.setSequenceSetId(uniqueSeqSetId);
5044 // propagate shared settings to this new view
5045 viewport.setHistoryList(av.getHistoryList());
5046 viewport.setRedoList(av.getRedoList());
5050 viewportsAdded.put(uniqueSeqSetId, viewport);
5052 // TODO: check if this method can be called repeatedly without
5053 // side-effects if alignpanel already registered.
5054 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
5056 // apply Hidden regions to view.
5057 if (hiddenSeqs != null)
5059 for (int s = 0; s < JSEQ.size(); s++)
5061 SequenceGroup hidden = new SequenceGroup();
5062 boolean isRepresentative = false;
5063 for (int r = 0; r < JSEQ.get(s).getHiddenSequences().size(); r++)
5065 isRepresentative = true;
5066 SequenceI sequenceToHide = al
5067 .getSequenceAt(JSEQ.get(s).getHiddenSequences().get(r));
5068 hidden.addSequence(sequenceToHide, false);
5069 // remove from hiddenSeqs list so we don't try to hide it twice
5070 hiddenSeqs.remove(sequenceToHide);
5072 if (isRepresentative)
5074 SequenceI representativeSequence = al.getSequenceAt(s);
5075 hidden.addSequence(representativeSequence, false);
5076 viewport.hideRepSequences(representativeSequence, hidden);
5080 SequenceI[] hseqs = hiddenSeqs
5081 .toArray(new SequenceI[hiddenSeqs.size()]);
5082 viewport.hideSequence(hseqs);
5085 // recover view properties and display parameters
5087 viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
5088 viewport.setAbovePIDThreshold(safeBoolean(view.isPidSelected()));
5089 final int pidThreshold = safeInt(view.getPidThreshold());
5090 viewport.setThreshold(pidThreshold);
5092 viewport.setColourText(safeBoolean(view.isShowColourText()));
5095 .setConservationSelected(
5096 safeBoolean(view.isConservationSelected()));
5097 viewport.setIncrement(safeInt(view.getConsThreshold()));
5098 viewport.setShowJVSuffix(safeBoolean(view.isShowFullId()));
5099 viewport.setRightAlignIds(safeBoolean(view.isRightAlignIds()));
5100 viewport.setFont(new Font(view.getFontName(),
5101 safeInt(view.getFontStyle()), safeInt(view.getFontSize())),
5103 ViewStyleI vs = viewport.getViewStyle();
5104 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
5105 viewport.setViewStyle(vs);
5106 // TODO: allow custom charWidth/Heights to be restored by updating them
5107 // after setting font - which means set above to false
5108 viewport.setRenderGaps(safeBoolean(view.isRenderGaps()));
5109 viewport.setWrapAlignment(safeBoolean(view.isWrapAlignment()));
5110 viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
5112 viewport.setShowBoxes(safeBoolean(view.isShowBoxes()));
5114 viewport.setShowText(safeBoolean(view.isShowText()));
5116 viewport.setTextColour(new Color(safeInt(view.getTextCol1())));
5117 viewport.setTextColour2(new Color(safeInt(view.getTextCol2())));
5118 viewport.setThresholdTextColour(safeInt(view.getTextColThreshold()));
5119 viewport.setShowUnconserved(view.isShowUnconserved());
5120 viewport.getRanges().setStartRes(safeInt(view.getStartRes()));
5122 if (view.getViewName() != null)
5124 viewport.setViewName(view.getViewName());
5125 af.setInitialTabVisible();
5127 int x = safeInt(view.getXpos());
5128 int y = safeInt(view.getYpos());
5129 int w = safeInt(view.getWidth());
5130 int h = safeInt(view.getHeight());
5131 // // BH we cannot let the title bar go off the top
5132 // if (Platform.isJS())
5134 // x = Math.max(50 - w, x);
5135 // y = Math.max(0, y);
5138 af.setBounds(x, y, w, h);
5139 // startSeq set in af.alignPanel.updateLayout below
5140 af.alignPanel.updateLayout();
5141 ColourSchemeI cs = null;
5142 // apply colourschemes
5143 if (view.getBgColour() != null)
5145 if (view.getBgColour().startsWith("ucs"))
5147 cs = getUserColourScheme(jm, view.getBgColour());
5149 else if (view.getBgColour().startsWith("Annotation"))
5151 AnnotationColourScheme viewAnnColour = view.getAnnotationColours();
5152 cs = constructAnnotationColour(viewAnnColour, af, al, jm, true);
5159 cs = ColourSchemeProperty.getColourScheme(af.getViewport(), al,
5160 view.getBgColour());
5165 * turn off 'alignment colour applies to all groups'
5166 * while restoring global colour scheme
5168 viewport.setColourAppliesToAllGroups(false);
5169 viewport.setGlobalColourScheme(cs);
5170 viewport.getResidueShading().setThreshold(pidThreshold,
5171 view.isIgnoreGapsinConsensus());
5172 viewport.getResidueShading()
5173 .setConsensus(viewport.getSequenceConsensusHash());
5174 if (safeBoolean(view.isConservationSelected()) && cs != null)
5176 viewport.getResidueShading()
5177 .setConservationInc(safeInt(view.getConsThreshold()));
5179 af.changeColour(cs);
5180 viewport.setColourAppliesToAllGroups(true);
5183 .setShowSequenceFeatures(
5184 safeBoolean(view.isShowSequenceFeatures()));
5186 viewport.setCentreColumnLabels(view.isCentreColumnLabels());
5187 viewport.setIgnoreGapsConsensus(view.isIgnoreGapsinConsensus(), null);
5188 viewport.setFollowHighlight(view.isFollowHighlight());
5189 viewport.followSelection = view.isFollowSelection();
5190 viewport.setShowConsensusHistogram(view.isShowConsensusHistogram());
5191 viewport.setShowSequenceLogo(view.isShowSequenceLogo());
5192 viewport.setNormaliseSequenceLogo(view.isNormaliseSequenceLogo());
5193 viewport.setShowDBRefs(safeBoolean(view.isShowDbRefTooltip()));
5194 viewport.setShowNPFeats(safeBoolean(view.isShowNPfeatureTooltip()));
5195 viewport.setShowGroupConsensus(view.isShowGroupConsensus());
5196 viewport.setShowGroupConservation(view.isShowGroupConservation());
5198 // recover feature settings
5199 if (jm.getFeatureSettings() != null)
5201 FeatureRenderer fr = af.alignPanel.getSeqPanel().seqCanvas
5202 .getFeatureRenderer();
5203 FeaturesDisplayed fdi;
5204 viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
5205 String[] renderOrder = new String[jm.getFeatureSettings()
5206 .getSetting().size()];
5207 Map<String, FeatureColourI> featureColours = new Hashtable<>();
5208 Map<String, Float> featureOrder = new Hashtable<>();
5210 for (int fs = 0; fs < jm.getFeatureSettings()
5211 .getSetting().size(); fs++)
5213 Setting setting = jm.getFeatureSettings().getSetting().get(fs);
5214 String featureType = setting.getType();
5217 * restore feature filters (if any)
5219 jalview.xml.binding.jalview.FeatureMatcherSet filters = setting
5221 if (filters != null)
5223 FeatureMatcherSetI filter = Jalview2XML
5224 .parseFilter(featureType, filters);
5225 if (!filter.isEmpty())
5227 fr.setFeatureFilter(featureType, filter);
5232 * restore feature colour scheme
5234 Color maxColour = new Color(setting.getColour());
5235 if (setting.getMincolour() != null)
5238 * minColour is always set unless a simple colour
5239 * (including for colour by label though it doesn't use it)
5241 Color minColour = new Color(setting.getMincolour().intValue());
5242 Color noValueColour = minColour;
5243 NoValueColour noColour = setting.getNoValueColour();
5244 if (noColour == NoValueColour.NONE)
5246 noValueColour = null;
5248 else if (noColour == NoValueColour.MAX)
5250 noValueColour = maxColour;
5252 float min = safeFloat(safeFloat(setting.getMin()));
5253 float max = setting.getMax() == null ? 1f
5254 : setting.getMax().floatValue();
5255 FeatureColourI gc = new FeatureColour(maxColour, minColour,
5257 noValueColour, min, max);
5258 if (setting.getAttributeName().size() > 0)
5260 gc.setAttributeName(setting.getAttributeName().toArray(
5261 new String[setting.getAttributeName().size()]));
5263 if (setting.getThreshold() != null)
5265 gc.setThreshold(setting.getThreshold().floatValue());
5266 int threshstate = safeInt(setting.getThreshstate());
5267 // -1 = None, 0 = Below, 1 = Above threshold
5268 if (threshstate == 0)
5270 gc.setBelowThreshold(true);
5272 else if (threshstate == 1)
5274 gc.setAboveThreshold(true);
5277 gc.setAutoScaled(true); // default
5278 if (setting.isAutoScale() != null)
5280 gc.setAutoScaled(setting.isAutoScale());
5282 if (setting.isColourByLabel() != null)
5284 gc.setColourByLabel(setting.isColourByLabel());
5286 // and put in the feature colour table.
5287 featureColours.put(featureType, gc);
5291 featureColours.put(featureType,
5292 new FeatureColour(maxColour));
5294 renderOrder[fs] = featureType;
5295 if (setting.getOrder() != null)
5297 featureOrder.put(featureType, setting.getOrder().floatValue());
5301 featureOrder.put(featureType, new Float(
5302 fs / jm.getFeatureSettings().getSetting().size()));
5304 if (safeBoolean(setting.isDisplay()))
5306 fdi.setVisible(featureType);
5309 Map<String, Boolean> fgtable = new Hashtable<>();
5310 for (int gs = 0; gs < jm.getFeatureSettings().getGroup().size(); gs++)
5312 Group grp = jm.getFeatureSettings().getGroup().get(gs);
5313 fgtable.put(grp.getName(), new Boolean(grp.isDisplay()));
5315 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
5316 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
5317 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
5318 FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
5319 fgtable, featureColours, 1.0f, featureOrder);
5320 fr.transferSettings(frs);
5323 if (view.getHiddenColumns().size() > 0)
5325 for (int c = 0; c < view.getHiddenColumns().size(); c++)
5327 final HiddenColumns hc = view.getHiddenColumns().get(c);
5328 viewport.hideColumns(safeInt(hc.getStart()),
5329 safeInt(hc.getEnd()) /* +1 */);
5332 if (view.getCalcIdParam() != null)
5334 for (CalcIdParam calcIdParam : view.getCalcIdParam())
5336 if (calcIdParam != null)
5338 if (recoverCalcIdParam(calcIdParam, viewport))
5343 warn("Couldn't recover parameters for "
5344 + calcIdParam.getCalcId());
5349 af.setMenusFromViewport(viewport);
5350 af.setTitle(view.getTitle());
5351 // TODO: we don't need to do this if the viewport is aready visible.
5353 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
5354 * has a 'cdna/protein complement' view, in which case save it in order to
5355 * populate a SplitFrame once all views have been read in.
5357 String complementaryViewId = view.getComplementId();
5358 if (complementaryViewId == null)
5360 Desktop.addInternalFrame(af, view.getTitle(),
5361 safeInt(view.getWidth()), safeInt(view.getHeight()));
5362 // recompute any autoannotation
5363 af.alignPanel.updateAnnotation(false, true);
5364 reorderAutoannotation(af, al, autoAlan);
5365 af.alignPanel.alignmentChanged();
5369 splitFrameCandidates.put(view, af);
5375 * Reads saved data to restore Colour by Annotation settings
5377 * @param viewAnnColour
5381 * @param checkGroupAnnColour
5384 private ColourSchemeI constructAnnotationColour(
5385 AnnotationColourScheme viewAnnColour, AlignFrame af,
5386 AlignmentI al, JalviewModel model, boolean checkGroupAnnColour)
5388 boolean propagateAnnColour = false;
5389 AlignmentI annAlignment = af != null ? af.getViewport().getAlignment()
5391 if (checkGroupAnnColour && al.getGroups() != null
5392 && al.getGroups().size() > 0)
5394 // pre 2.8.1 behaviour
5395 // check to see if we should transfer annotation colours
5396 propagateAnnColour = true;
5397 for (SequenceGroup sg : al.getGroups())
5399 if (sg.getColourScheme() instanceof AnnotationColourGradient)
5401 propagateAnnColour = false;
5407 * 2.10.2- : saved annotationId is AlignmentAnnotation.annotationId
5409 String annotationId = viewAnnColour.getAnnotation();
5410 AlignmentAnnotation matchedAnnotation = annotationIds.get(annotationId);
5413 * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
5415 if (matchedAnnotation == null
5416 && annAlignment.getAlignmentAnnotation() != null)
5418 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
5421 .equals(annAlignment.getAlignmentAnnotation()[i].label))
5423 matchedAnnotation = annAlignment.getAlignmentAnnotation()[i];
5428 if (matchedAnnotation == null)
5430 System.err.println("Failed to match annotation colour scheme for "
5434 if (matchedAnnotation.getThreshold() == null)
5436 matchedAnnotation.setThreshold(
5437 new GraphLine(safeFloat(viewAnnColour.getThreshold()),
5438 "Threshold", Color.black));
5441 AnnotationColourGradient cs = null;
5442 if (viewAnnColour.getColourScheme().equals("None"))
5444 cs = new AnnotationColourGradient(matchedAnnotation,
5445 new Color(safeInt(viewAnnColour.getMinColour())),
5446 new Color(safeInt(viewAnnColour.getMaxColour())),
5447 safeInt(viewAnnColour.getAboveThreshold()));
5449 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
5451 cs = new AnnotationColourGradient(matchedAnnotation,
5452 getUserColourScheme(model, viewAnnColour.getColourScheme()),
5453 safeInt(viewAnnColour.getAboveThreshold()));
5457 cs = new AnnotationColourGradient(matchedAnnotation,
5458 ColourSchemeProperty.getColourScheme(af.getViewport(), al,
5459 viewAnnColour.getColourScheme()),
5460 safeInt(viewAnnColour.getAboveThreshold()));
5463 boolean perSequenceOnly = safeBoolean(viewAnnColour.isPerSequence());
5464 boolean useOriginalColours = safeBoolean(
5465 viewAnnColour.isPredefinedColours());
5466 cs.setSeqAssociated(perSequenceOnly);
5467 cs.setPredefinedColours(useOriginalColours);
5469 if (propagateAnnColour && al.getGroups() != null)
5471 // Also use these settings for all the groups
5472 for (int g = 0; g < al.getGroups().size(); g++)
5474 SequenceGroup sg = al.getGroups().get(g);
5475 if (sg.getGroupColourScheme() == null)
5480 AnnotationColourGradient groupScheme = new AnnotationColourGradient(
5481 matchedAnnotation, sg.getColourScheme(),
5482 safeInt(viewAnnColour.getAboveThreshold()));
5483 sg.setColourScheme(groupScheme);
5484 groupScheme.setSeqAssociated(perSequenceOnly);
5485 groupScheme.setPredefinedColours(useOriginalColours);
5491 private void reorderAutoannotation(AlignFrame af, AlignmentI al,
5492 List<JvAnnotRow> autoAlan)
5494 // copy over visualization settings for autocalculated annotation in the
5496 if (al.getAlignmentAnnotation() != null)
5499 * Kludge for magic autoannotation names (see JAL-811)
5501 String[] magicNames = new String[] { "Consensus", "Quality",
5503 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
5504 Hashtable<String, JvAnnotRow> visan = new Hashtable<>();
5505 for (String nm : magicNames)
5507 visan.put(nm, nullAnnot);
5509 for (JvAnnotRow auan : autoAlan)
5511 visan.put(auan.template.label
5512 + (auan.template.getCalcId() == null ? ""
5513 : "\t" + auan.template.getCalcId()),
5516 int hSize = al.getAlignmentAnnotation().length;
5517 List<JvAnnotRow> reorder = new ArrayList<>();
5518 // work through any autoCalculated annotation already on the view
5519 // removing it if it should be placed in a different location on the
5520 // annotation panel.
5521 List<String> remains = new ArrayList<>(visan.keySet());
5522 for (int h = 0; h < hSize; h++)
5524 jalview.datamodel.AlignmentAnnotation jalan = al
5525 .getAlignmentAnnotation()[h];
5526 if (jalan.autoCalculated)
5529 JvAnnotRow valan = visan.get(k = jalan.label);
5530 if (jalan.getCalcId() != null)
5532 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
5537 // delete the auto calculated row from the alignment
5538 al.deleteAnnotation(jalan, false);
5542 if (valan != nullAnnot)
5544 if (jalan != valan.template)
5546 // newly created autoannotation row instance
5547 // so keep a reference to the visible annotation row
5548 // and copy over all relevant attributes
5549 if (valan.template.graphHeight >= 0)
5552 jalan.graphHeight = valan.template.graphHeight;
5554 jalan.visible = valan.template.visible;
5556 reorder.add(new JvAnnotRow(valan.order, jalan));
5561 // Add any (possibly stale) autocalculated rows that were not appended to
5562 // the view during construction
5563 for (String other : remains)
5565 JvAnnotRow othera = visan.get(other);
5566 if (othera != nullAnnot && othera.template.getCalcId() != null
5567 && othera.template.getCalcId().length() > 0)
5569 reorder.add(othera);
5572 // now put the automatic annotation in its correct place
5573 int s = 0, srt[] = new int[reorder.size()];
5574 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
5575 for (JvAnnotRow jvar : reorder)
5578 srt[s++] = jvar.order;
5581 jalview.util.QuickSort.sort(srt, rws);
5582 // and re-insert the annotation at its correct position
5583 for (JvAnnotRow jvar : rws)
5585 al.addAnnotation(jvar.template, jvar.order);
5587 af.alignPanel.adjustAnnotationHeight();
5591 Hashtable skipList = null;
5594 * TODO remove this method
5597 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
5598 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
5599 * throw new Error("Implementation Error. No skipList defined for this
5600 * Jalview2XML instance."); } return (AlignFrame)
5601 * skipList.get(view.getSequenceSetId()); }
5605 * Check if the Jalview view contained in object should be skipped or not.
5608 * @return true if view's sequenceSetId is a key in skipList
5610 private boolean skipViewport(JalviewModel object)
5612 if (skipList == null)
5616 String id = object.getViewport().get(0).getSequenceSetId();
5617 if (skipList.containsKey(id))
5619 if (Cache.log != null && Cache.log.isDebugEnabled())
5621 Cache.log.debug("Skipping seuqence set id " + id);
5628 public void addToSkipList(AlignFrame af)
5630 if (skipList == null)
5632 skipList = new Hashtable();
5634 skipList.put(af.getViewport().getSequenceSetId(), af);
5637 public void clearSkipList()
5639 if (skipList != null)
5646 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
5647 boolean ignoreUnrefed, String uniqueSeqSetId)
5649 jalview.datamodel.AlignmentI ds = getDatasetFor(
5650 vamsasSet.getDatasetId());
5651 AlignmentI xtant_ds = ds;
5652 if (xtant_ds == null)
5654 // good chance we are about to create a new dataset, but check if we've
5655 // seen some of the dataset sequence IDs before.
5656 // TODO: skip this check if we are working with project generated by
5657 // version 2.11 or later
5658 xtant_ds = checkIfHasDataset(vamsasSet.getSequence());
5659 if (xtant_ds != null)
5662 addDatasetRef(vamsasSet.getDatasetId(), ds);
5665 Vector dseqs = null;
5668 // recovering an alignment View
5669 AlignmentI seqSetDS = getDatasetFor(UNIQSEQSETID + uniqueSeqSetId);
5670 if (seqSetDS != null)
5672 if (ds != null && ds != seqSetDS)
5674 warn("JAL-3171 regression: Overwriting a dataset reference for an alignment"
5675 + " - CDS/Protein crossreference data may be lost");
5676 if (xtant_ds != null)
5678 // This can only happen if the unique sequence set ID was bound to a
5679 // dataset that did not contain any of the sequences in the view
5680 // currently being restored.
5681 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.");
5685 addDatasetRef(vamsasSet.getDatasetId(), ds);
5690 // try even harder to restore dataset
5691 AlignmentI xtantDS = checkIfHasDataset(vamsasSet.getSequence());
5692 // create a list of new dataset sequences
5693 dseqs = new Vector();
5695 for (int i = 0, iSize = vamsasSet.getSequence().size(); i < iSize; i++)
5697 Sequence vamsasSeq = vamsasSet.getSequence().get(i);
5698 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
5700 // create a new dataset
5703 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
5704 dseqs.copyInto(dsseqs);
5705 ds = new jalview.datamodel.Alignment(dsseqs);
5706 // debug("Jalview2XML Created new dataset " + vamsasSet.getDatasetId()
5707 // + " for alignment " + System.identityHashCode(al));
5708 addDatasetRef(vamsasSet.getDatasetId(), ds);
5710 // set the dataset for the newly imported alignment.
5711 if (al.getDataset() == null && !ignoreUnrefed)
5714 // register dataset for the alignment's uniqueSeqSetId for legacy projects
5715 addDatasetRef(UNIQSEQSETID + uniqueSeqSetId, ds);
5717 updateSeqDatasetBinding(vamsasSet.getSequence(), ds);
5721 * XML dataset sequence ID to materialised dataset reference
5723 HashMap<String, AlignmentI> seqToDataset = new HashMap<>();
5726 * @return the first materialised dataset reference containing a dataset
5727 * sequence referenced in the given view
5729 * - sequences from the view
5731 AlignmentI checkIfHasDataset(List<Sequence> list)
5733 for (Sequence restoredSeq : list)
5735 AlignmentI datasetFor = seqToDataset.get(restoredSeq.getDsseqid());
5736 if (datasetFor != null)
5745 * Register ds as the containing dataset for the dataset sequences referenced
5746 * by sequences in list
5749 * - sequences in a view
5752 void updateSeqDatasetBinding(List<Sequence> list, AlignmentI ds)
5754 for (Sequence restoredSeq : list)
5756 AlignmentI prevDS = seqToDataset.put(restoredSeq.getDsseqid(), ds);
5757 if (prevDS != null && prevDS != ds)
5759 warn("Dataset sequence appears in many datasets: "
5760 + restoredSeq.getDsseqid());
5761 // TODO: try to merge!
5768 * sequence definition to create/merge dataset sequence for
5772 * vector to add new dataset sequence to
5773 * @param ignoreUnrefed
5774 * - when true, don't create new sequences from vamsasSeq if it's id
5775 * doesn't already have an asssociated Jalview sequence.
5777 * - used to reorder the sequence in the alignment according to the
5778 * vamsasSeq array ordering, to preserve ordering of dataset
5780 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
5781 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed, int vseqpos)
5783 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
5785 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
5786 boolean reorder = false;
5787 SequenceI dsq = null;
5788 if (sq != null && sq.getDatasetSequence() != null)
5790 dsq = sq.getDatasetSequence();
5796 if (sq == null && ignoreUnrefed)
5800 String sqid = vamsasSeq.getDsseqid();
5803 // need to create or add a new dataset sequence reference to this sequence
5806 dsq = seqRefIds.get(sqid);
5811 // make a new dataset sequence
5812 dsq = sq.createDatasetSequence();
5815 // make up a new dataset reference for this sequence
5816 sqid = seqHash(dsq);
5818 dsq.setVamsasId(uniqueSetSuffix + sqid);
5819 seqRefIds.put(sqid, dsq);
5824 dseqs.addElement(dsq);
5829 ds.addSequence(dsq);
5835 { // make this dataset sequence sq's dataset sequence
5836 sq.setDatasetSequence(dsq);
5837 // and update the current dataset alignment
5842 if (!dseqs.contains(dsq))
5849 if (ds.findIndex(dsq) < 0)
5851 ds.addSequence(dsq);
5858 // TODO: refactor this as a merge dataset sequence function
5859 // now check that sq (the dataset sequence) sequence really is the union of
5860 // all references to it
5861 // boolean pre = sq.getStart() < dsq.getStart();
5862 // boolean post = sq.getEnd() > dsq.getEnd();
5866 // StringBuffer sb = new StringBuffer();
5867 String newres = jalview.analysis.AlignSeq.extractGaps(
5868 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
5869 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
5870 && newres.length() > dsq.getLength())
5872 // Update with the longer sequence.
5876 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
5877 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
5878 * sb.append(newres.substring(newres.length() - sq.getEnd() -
5879 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
5881 dsq.setSequence(newres);
5883 // TODO: merges will never happen if we 'know' we have the real dataset
5884 // sequence - this should be detected when id==dssid
5886 "DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
5887 // + (pre ? "prepended" : "") + " "
5888 // + (post ? "appended" : ""));
5893 // sequence refs are identical. We may need to update the existing dataset
5894 // alignment with this one, though.
5895 if (ds != null && dseqs == null)
5897 int opos = ds.findIndex(dsq);
5898 SequenceI tseq = null;
5899 if (opos != -1 && vseqpos != opos)
5901 // remove from old position
5902 ds.deleteSequence(dsq);
5904 if (vseqpos < ds.getHeight())
5906 if (vseqpos != opos)
5908 // save sequence at destination position
5909 tseq = ds.getSequenceAt(vseqpos);
5910 ds.replaceSequenceAt(vseqpos, dsq);
5911 ds.addSequence(tseq);
5916 ds.addSequence(dsq);
5923 * TODO use AlignmentI here and in related methods - needs
5924 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
5926 Hashtable<String, AlignmentI> datasetIds = null;
5928 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
5930 private AlignmentI getDatasetFor(String datasetId)
5932 if (datasetIds == null)
5934 datasetIds = new Hashtable<>();
5937 if (datasetIds.containsKey(datasetId))
5939 return datasetIds.get(datasetId);
5944 private void addDatasetRef(String datasetId, AlignmentI dataset)
5946 if (datasetIds == null)
5948 datasetIds = new Hashtable<>();
5950 datasetIds.put(datasetId, dataset);
5954 * make a new dataset ID for this jalview dataset alignment
5959 private String getDatasetIdRef(AlignmentI dataset)
5961 if (dataset.getDataset() != null)
5963 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
5965 String datasetId = makeHashCode(dataset, null);
5966 if (datasetId == null)
5968 // make a new datasetId and record it
5969 if (dataset2Ids == null)
5971 dataset2Ids = new IdentityHashMap<>();
5975 datasetId = dataset2Ids.get(dataset);
5977 if (datasetId == null)
5979 datasetId = "ds" + dataset2Ids.size() + 1;
5980 dataset2Ids.put(dataset, datasetId);
5986 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5988 for (int d = 0; d < sequence.getDBRef().size(); d++)
5990 DBRef dr = sequence.getDBRef().get(d);
5991 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
5992 dr.getSource(), dr.getVersion(), dr.getAccessionId());
5993 if (dr.getMapping() != null)
5995 entry.setMap(addMapping(dr.getMapping()));
5997 datasetSequence.addDBRef(entry);
6001 private jalview.datamodel.Mapping addMapping(Mapping m)
6003 SequenceI dsto = null;
6004 // Mapping m = dr.getMapping();
6005 int fr[] = new int[m.getMapListFrom().size() * 2];
6006 Iterator<MapListFrom> from = m.getMapListFrom().iterator();// enumerateMapListFrom();
6007 for (int _i = 0; from.hasNext(); _i += 2)
6009 MapListFrom mf = from.next();
6010 fr[_i] = mf.getStart();
6011 fr[_i + 1] = mf.getEnd();
6013 int fto[] = new int[m.getMapListTo().size() * 2];
6014 Iterator<MapListTo> to = m.getMapListTo().iterator();// enumerateMapListTo();
6015 for (int _i = 0; to.hasNext(); _i += 2)
6017 MapListTo mf = to.next();
6018 fto[_i] = mf.getStart();
6019 fto[_i + 1] = mf.getEnd();
6021 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto, fr,
6022 fto, m.getMapFromUnit().intValue(),
6023 m.getMapToUnit().intValue());
6026 * (optional) choice of dseqFor or Sequence
6028 if (m.getDseqFor() != null)
6030 String dsfor = m.getDseqFor();
6031 if (seqRefIds.containsKey(dsfor))
6036 jmap.setTo(seqRefIds.get(dsfor));
6040 frefedSequence.add(newMappingRef(dsfor, jmap));
6043 else if (m.getSequence() != null)
6046 * local sequence definition
6048 Sequence ms = m.getSequence();
6049 SequenceI djs = null;
6050 String sqid = ms.getDsseqid();
6051 if (sqid != null && sqid.length() > 0)
6054 * recover dataset sequence
6056 djs = seqRefIds.get(sqid);
6061 "Warning - making up dataset sequence id for DbRef sequence map reference");
6062 sqid = ((Object) ms).toString(); // make up a new hascode for
6063 // undefined dataset sequence hash
6064 // (unlikely to happen)
6070 * make a new dataset sequence and add it to refIds hash
6072 djs = new jalview.datamodel.Sequence(ms.getName(),
6074 djs.setStart(jmap.getMap().getToLowest());
6075 djs.setEnd(jmap.getMap().getToHighest());
6076 djs.setVamsasId(uniqueSetSuffix + sqid);
6078 incompleteSeqs.put(sqid, djs);
6079 seqRefIds.put(sqid, djs);
6082 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
6091 * Provides a 'copy' of an alignment view (on action New View) by 'saving' the
6092 * view as XML (but not to file), and then reloading it
6097 public AlignmentPanel copyAlignPanel(AlignmentPanel ap)
6100 JalviewModel jm = saveState(ap, null, null, null);
6103 jm.getVamsasModel().getSequenceSet().get(0).getDatasetId(),
6104 ap.getAlignment().getDataset());
6106 uniqueSetSuffix = "";
6107 // jm.getJalviewModelSequence().getViewport(0).setId(null);
6108 jm.getViewport().get(0).setId(null);
6109 // we don't overwrite the view we just copied
6111 if (this.frefedSequence == null)
6113 frefedSequence = new Vector<>();
6116 viewportsAdded.clear();
6118 AlignFrame af = loadFromObject(jm, null, false, null);
6119 af.getAlignPanels().clear();
6120 af.closeMenuItem_actionPerformed(true);
6123 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
6124 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
6125 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
6126 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
6127 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
6130 return af.alignPanel;
6133 private Hashtable jvids2vobj;
6135 private void warn(String msg)
6140 private void warn(String msg, Exception e)
6142 if (Cache.log != null)
6146 Cache.log.warn(msg, e);
6150 Cache.log.warn(msg);
6155 System.err.println("Warning: " + msg);
6158 e.printStackTrace();
6163 private void debug(String string)
6165 debug(string, null);
6168 private void debug(String msg, Exception e)
6170 if (Cache.log != null)
6174 Cache.log.debug(msg, e);
6178 Cache.log.debug(msg);
6183 System.err.println("Warning: " + msg);
6186 e.printStackTrace();
6192 * set the object to ID mapping tables used to write/recover objects and XML
6193 * ID strings for the jalview project. If external tables are provided then
6194 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
6195 * object goes out of scope. - also populates the datasetIds hashtable with
6196 * alignment objects containing dataset sequences
6199 * Map from ID strings to jalview datamodel
6201 * Map from jalview datamodel to ID strings
6205 public void setObjectMappingTables(Hashtable vobj2jv,
6206 IdentityHashMap jv2vobj)
6208 this.jv2vobj = jv2vobj;
6209 this.vobj2jv = vobj2jv;
6210 Iterator ds = jv2vobj.keySet().iterator();
6212 while (ds.hasNext())
6214 Object jvobj = ds.next();
6215 id = jv2vobj.get(jvobj).toString();
6216 if (jvobj instanceof jalview.datamodel.Alignment)
6218 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
6220 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
6223 else if (jvobj instanceof jalview.datamodel.Sequence)
6225 // register sequence object so the XML parser can recover it.
6226 if (seqRefIds == null)
6228 seqRefIds = new HashMap<>();
6230 if (seqsToIds == null)
6232 seqsToIds = new IdentityHashMap<>();
6234 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
6235 seqsToIds.put((SequenceI) jvobj, id);
6237 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
6240 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
6241 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
6242 if (jvann.annotationId == null)
6244 jvann.annotationId = anid;
6246 if (!jvann.annotationId.equals(anid))
6248 // TODO verify that this is the correct behaviour
6249 this.warn("Overriding Annotation ID for " + anid
6250 + " from different id : " + jvann.annotationId);
6251 jvann.annotationId = anid;
6254 else if (jvobj instanceof String)
6256 if (jvids2vobj == null)
6258 jvids2vobj = new Hashtable();
6259 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
6264 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
6270 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
6271 * objects created from the project archive. If string is null (default for
6272 * construction) then suffix will be set automatically.
6276 public void setUniqueSetSuffix(String string)
6278 uniqueSetSuffix = string;
6283 * uses skipList2 as the skipList for skipping views on sequence sets
6284 * associated with keys in the skipList
6288 public void setSkipList(Hashtable skipList2)
6290 skipList = skipList2;
6294 * Reads the jar entry of given name and returns its contents, or null if the
6295 * entry is not found.
6298 * @param jarEntryName
6301 protected String readJarEntry(jarInputStreamProvider jprovider,
6302 String jarEntryName)
6304 String result = null;
6305 BufferedReader in = null;
6310 * Reopen the jar input stream and traverse its entries to find a matching
6313 JarInputStream jin = jprovider.getJarInputStream();
6314 JarEntry entry = null;
6317 entry = jin.getNextJarEntry();
6318 } while (entry != null && !entry.getName().equals(jarEntryName));
6322 StringBuilder out = new StringBuilder(256);
6323 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
6326 while ((data = in.readLine()) != null)
6330 result = out.toString();
6334 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
6336 } catch (Exception ex)
6338 ex.printStackTrace();
6346 } catch (IOException e)
6357 * Returns an incrementing counter (0, 1, 2...)
6361 private synchronized int nextCounter()
6367 * Loads any saved PCA viewers
6372 protected void loadPCAViewers(JalviewModel model, AlignmentPanel ap)
6376 List<PcaViewer> pcaviewers = model.getPcaViewer();
6377 for (PcaViewer viewer : pcaviewers)
6379 String modelName = viewer.getScoreModelName();
6380 SimilarityParamsI params = new SimilarityParams(
6381 viewer.isIncludeGappedColumns(), viewer.isMatchGaps(),
6382 viewer.isIncludeGaps(),
6383 viewer.isDenominateByShortestLength());
6386 * create the panel (without computing the PCA)
6388 PCAPanel panel = new PCAPanel(ap, modelName, params);
6390 panel.setTitle(viewer.getTitle());
6391 panel.setBounds(new Rectangle(viewer.getXpos(), viewer.getYpos(),
6392 viewer.getWidth(), viewer.getHeight()));
6394 boolean showLabels = viewer.isShowLabels();
6395 panel.setShowLabels(showLabels);
6396 panel.getRotatableCanvas().setShowLabels(showLabels);
6397 panel.getRotatableCanvas()
6398 .setBgColour(new Color(viewer.getBgColour()));
6399 panel.getRotatableCanvas()
6400 .setApplyToAllViews(viewer.isLinkToAllViews());
6403 * load PCA output data
6405 ScoreModelI scoreModel = ScoreModels.getInstance()
6406 .getScoreModel(modelName, ap);
6407 PCA pca = new PCA(null, scoreModel, params);
6408 PcaDataType pcaData = viewer.getPcaData();
6410 MatrixI pairwise = loadDoubleMatrix(pcaData.getPairwiseMatrix());
6411 pca.setPairwiseScores(pairwise);
6413 MatrixI triDiag = loadDoubleMatrix(pcaData.getTridiagonalMatrix());
6414 pca.setTridiagonal(triDiag);
6416 MatrixI result = loadDoubleMatrix(pcaData.getEigenMatrix());
6417 pca.setEigenmatrix(result);
6419 panel.getPcaModel().setPCA(pca);
6422 * we haven't saved the input data! (JAL-2647 to do)
6424 panel.setInputData(null);
6427 * add the sequence points for the PCA display
6429 List<jalview.datamodel.SequencePoint> seqPoints = new ArrayList<>();
6430 for (SequencePoint sp : viewer.getSequencePoint())
6432 String seqId = sp.getSequenceRef();
6433 SequenceI seq = seqRefIds.get(seqId);
6436 throw new IllegalStateException(
6437 "Unmatched seqref for PCA: " + seqId);
6439 Point pt = new Point(sp.getXPos(), sp.getYPos(), sp.getZPos());
6440 jalview.datamodel.SequencePoint seqPoint = new jalview.datamodel.SequencePoint(
6442 seqPoints.add(seqPoint);
6444 panel.getRotatableCanvas().setPoints(seqPoints, seqPoints.size());
6447 * set min-max ranges and scale after setPoints (which recomputes them)
6449 panel.getRotatableCanvas().setScaleFactor(viewer.getScaleFactor());
6450 SeqPointMin spMin = viewer.getSeqPointMin();
6451 float[] min = new float[] { spMin.getXPos(), spMin.getYPos(),
6453 SeqPointMax spMax = viewer.getSeqPointMax();
6454 float[] max = new float[] { spMax.getXPos(), spMax.getYPos(),
6456 panel.getRotatableCanvas().setSeqMinMax(min, max);
6458 // todo: hold points list in PCAModel only
6459 panel.getPcaModel().setSequencePoints(seqPoints);
6461 panel.setSelectedDimensionIndex(viewer.getXDim(), X);
6462 panel.setSelectedDimensionIndex(viewer.getYDim(), Y);
6463 panel.setSelectedDimensionIndex(viewer.getZDim(), Z);
6465 // is this duplication needed?
6466 panel.setTop(seqPoints.size() - 1);
6467 panel.getPcaModel().setTop(seqPoints.size() - 1);
6470 * add the axes' end points for the display
6472 for (int i = 0; i < 3; i++)
6474 Axis axis = viewer.getAxis().get(i);
6475 panel.getRotatableCanvas().getAxisEndPoints()[i] = new Point(
6476 axis.getXPos(), axis.getYPos(), axis.getZPos());
6479 Desktop.addInternalFrame(panel, MessageManager.formatMessage(
6480 "label.calc_title", "PCA", modelName), 475, 450);
6482 } catch (Exception ex)
6484 Cache.log.error("Error loading PCA: " + ex.toString());
6489 * Populates an XML model of the feature colour scheme for one feature type
6491 * @param featureType
6495 public static Colour marshalColour(
6496 String featureType, FeatureColourI fcol)
6498 Colour col = new Colour();
6499 if (fcol.isSimpleColour())
6501 col.setRGB(Format.getHexString(fcol.getColour()));
6505 col.setRGB(Format.getHexString(fcol.getMaxColour()));
6506 col.setMin(fcol.getMin());
6507 col.setMax(fcol.getMax());
6508 col.setMinRGB(jalview.util.Format.getHexString(fcol.getMinColour()));
6509 col.setAutoScale(fcol.isAutoScaled());
6510 col.setThreshold(fcol.getThreshold());
6511 col.setColourByLabel(fcol.isColourByLabel());
6512 col.setThreshType(fcol.isAboveThreshold() ? ThresholdType.ABOVE
6513 : (fcol.isBelowThreshold() ? ThresholdType.BELOW
6514 : ThresholdType.NONE));
6515 if (fcol.isColourByAttribute())
6517 final String[] attName = fcol.getAttributeName();
6518 col.getAttributeName().add(attName[0]);
6519 if (attName.length > 1)
6521 col.getAttributeName().add(attName[1]);
6524 Color noColour = fcol.getNoColour();
6525 if (noColour == null)
6527 col.setNoValueColour(NoValueColour.NONE);
6529 else if (noColour == fcol.getMaxColour())
6531 col.setNoValueColour(NoValueColour.MAX);
6535 col.setNoValueColour(NoValueColour.MIN);
6538 col.setName(featureType);
6543 * Populates an XML model of the feature filter(s) for one feature type
6545 * @param firstMatcher
6546 * the first (or only) match condition)
6548 * remaining match conditions (if any)
6550 * if true, conditions are and-ed, else or-ed
6552 public static jalview.xml.binding.jalview.FeatureMatcherSet marshalFilter(
6553 FeatureMatcherI firstMatcher, Iterator<FeatureMatcherI> filters,
6556 jalview.xml.binding.jalview.FeatureMatcherSet result = new jalview.xml.binding.jalview.FeatureMatcherSet();
6558 if (filters.hasNext())
6563 CompoundMatcher compound = new CompoundMatcher();
6564 compound.setAnd(and);
6565 jalview.xml.binding.jalview.FeatureMatcherSet matcher1 = marshalFilter(
6566 firstMatcher, Collections.emptyIterator(), and);
6567 // compound.addMatcherSet(matcher1);
6568 compound.getMatcherSet().add(matcher1);
6569 FeatureMatcherI nextMatcher = filters.next();
6570 jalview.xml.binding.jalview.FeatureMatcherSet matcher2 = marshalFilter(
6571 nextMatcher, filters, and);
6572 // compound.addMatcherSet(matcher2);
6573 compound.getMatcherSet().add(matcher2);
6574 result.setCompoundMatcher(compound);
6579 * single condition matcher
6581 // MatchCondition matcherModel = new MatchCondition();
6582 jalview.xml.binding.jalview.FeatureMatcher matcherModel = new jalview.xml.binding.jalview.FeatureMatcher();
6583 matcherModel.setCondition(
6584 firstMatcher.getMatcher().getCondition().getStableName());
6585 matcherModel.setValue(firstMatcher.getMatcher().getPattern());
6586 if (firstMatcher.isByAttribute())
6588 matcherModel.setBy(FilterBy.BY_ATTRIBUTE);
6589 // matcherModel.setAttributeName(firstMatcher.getAttribute());
6590 String[] attName = firstMatcher.getAttribute();
6591 matcherModel.getAttributeName().add(attName[0]); // attribute
6592 if (attName.length > 1)
6594 matcherModel.getAttributeName().add(attName[1]); // sub-attribute
6597 else if (firstMatcher.isByLabel())
6599 matcherModel.setBy(FilterBy.BY_LABEL);
6601 else if (firstMatcher.isByScore())
6603 matcherModel.setBy(FilterBy.BY_SCORE);
6605 result.setMatchCondition(matcherModel);
6612 * Loads one XML model of a feature filter to a Jalview object
6614 * @param featureType
6615 * @param matcherSetModel
6618 public static FeatureMatcherSetI parseFilter(
6620 jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel)
6622 FeatureMatcherSetI result = new FeatureMatcherSet();
6625 parseFilterConditions(result, matcherSetModel, true);
6626 } catch (IllegalStateException e)
6628 // mixing AND and OR conditions perhaps
6630 String.format("Error reading filter conditions for '%s': %s",
6631 featureType, e.getMessage()));
6632 // return as much as was parsed up to the error
6639 * Adds feature match conditions to matcherSet as unmarshalled from XML
6640 * (possibly recursively for compound conditions)
6643 * @param matcherSetModel
6645 * if true, multiple conditions are AND-ed, else they are OR-ed
6646 * @throws IllegalStateException
6647 * if AND and OR conditions are mixed
6649 protected static void parseFilterConditions(
6650 FeatureMatcherSetI matcherSet,
6651 jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel,
6654 jalview.xml.binding.jalview.FeatureMatcher mc = matcherSetModel
6655 .getMatchCondition();
6661 FilterBy filterBy = mc.getBy();
6662 Condition cond = Condition.fromString(mc.getCondition());
6663 String pattern = mc.getValue();
6664 FeatureMatcherI matchCondition = null;
6665 if (filterBy == FilterBy.BY_LABEL)
6667 matchCondition = FeatureMatcher.byLabel(cond, pattern);
6669 else if (filterBy == FilterBy.BY_SCORE)
6671 matchCondition = FeatureMatcher.byScore(cond, pattern);
6674 else if (filterBy == FilterBy.BY_ATTRIBUTE)
6676 final List<String> attributeName = mc.getAttributeName();
6677 String[] attNames = attributeName
6678 .toArray(new String[attributeName.size()]);
6679 matchCondition = FeatureMatcher.byAttribute(cond, pattern,
6684 * note this throws IllegalStateException if AND-ing to a
6685 * previously OR-ed compound condition, or vice versa
6689 matcherSet.and(matchCondition);
6693 matcherSet.or(matchCondition);
6699 * compound condition
6701 List<jalview.xml.binding.jalview.FeatureMatcherSet> matchers = matcherSetModel
6702 .getCompoundMatcher().getMatcherSet();
6703 boolean anded = matcherSetModel.getCompoundMatcher().isAnd();
6704 if (matchers.size() == 2)
6706 parseFilterConditions(matcherSet, matchers.get(0), anded);
6707 parseFilterConditions(matcherSet, matchers.get(1), anded);
6711 System.err.println("Malformed compound filter condition");
6717 * Loads one XML model of a feature colour to a Jalview object
6719 * @param colourModel
6722 public static FeatureColourI parseColour(Colour colourModel)
6724 FeatureColourI colour = null;
6726 if (colourModel.getMax() != null)
6728 Color mincol = null;
6729 Color maxcol = null;
6730 Color noValueColour = null;
6734 mincol = new Color(Integer.parseInt(colourModel.getMinRGB(), 16));
6735 maxcol = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6736 } catch (Exception e)
6738 Cache.log.warn("Couldn't parse out graduated feature color.", e);
6741 NoValueColour noCol = colourModel.getNoValueColour();
6742 if (noCol == NoValueColour.MIN)
6744 noValueColour = mincol;
6746 else if (noCol == NoValueColour.MAX)
6748 noValueColour = maxcol;
6751 colour = new FeatureColour(maxcol, mincol, maxcol, noValueColour,
6752 safeFloat(colourModel.getMin()),
6753 safeFloat(colourModel.getMax()));
6754 final List<String> attributeName = colourModel.getAttributeName();
6755 String[] attributes = attributeName
6756 .toArray(new String[attributeName.size()]);
6757 if (attributes != null && attributes.length > 0)
6759 colour.setAttributeName(attributes);
6761 if (colourModel.isAutoScale() != null)
6763 colour.setAutoScaled(colourModel.isAutoScale().booleanValue());
6765 if (colourModel.isColourByLabel() != null)
6767 colour.setColourByLabel(
6768 colourModel.isColourByLabel().booleanValue());
6770 if (colourModel.getThreshold() != null)
6772 colour.setThreshold(colourModel.getThreshold().floatValue());
6774 ThresholdType ttyp = colourModel.getThreshType();
6775 if (ttyp == ThresholdType.ABOVE)
6777 colour.setAboveThreshold(true);
6779 else if (ttyp == ThresholdType.BELOW)
6781 colour.setBelowThreshold(true);
6786 Color color = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6787 colour = new FeatureColour(color);