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.FeatureColourI;
32 import jalview.api.ViewStyleI;
33 import jalview.api.analysis.ScoreModelI;
34 import jalview.api.analysis.SimilarityParamsI;
35 import jalview.api.structures.JalviewStructureDisplayI;
36 import jalview.bin.Cache;
37 import jalview.datamodel.AlignedCodonFrame;
38 import jalview.datamodel.Alignment;
39 import jalview.datamodel.AlignmentAnnotation;
40 import jalview.datamodel.AlignmentI;
41 import jalview.datamodel.GraphLine;
42 import jalview.datamodel.PDBEntry;
43 import jalview.datamodel.Point;
44 import jalview.datamodel.RnaViewerModel;
45 import jalview.datamodel.SequenceFeature;
46 import jalview.datamodel.SequenceGroup;
47 import jalview.datamodel.SequenceI;
48 import jalview.datamodel.StructureViewerModel;
49 import jalview.datamodel.StructureViewerModel.StructureData;
50 import jalview.datamodel.features.FeatureMatcher;
51 import jalview.datamodel.features.FeatureMatcherI;
52 import jalview.datamodel.features.FeatureMatcherSet;
53 import jalview.datamodel.features.FeatureMatcherSetI;
54 import jalview.ext.varna.RnaModel;
55 import jalview.gui.AlignFrame;
56 import jalview.gui.AlignViewport;
57 import jalview.gui.AlignmentPanel;
58 import jalview.gui.AppVarna;
59 import jalview.gui.ChimeraViewFrame;
60 import jalview.gui.Desktop;
61 import jalview.gui.FeatureRenderer;
62 import jalview.gui.JvOptionPane;
63 import jalview.gui.OOMWarning;
64 import jalview.gui.PCAPanel;
65 import jalview.gui.PaintRefresher;
66 import jalview.gui.SplitFrame;
67 import jalview.gui.StructureViewer;
68 import jalview.gui.StructureViewer.ViewerType;
69 import jalview.gui.StructureViewerBase;
70 import jalview.gui.TreePanel;
71 import jalview.io.DataSourceType;
72 import jalview.io.FileFormat;
73 import jalview.io.NewickFile;
74 import jalview.math.Matrix;
75 import jalview.math.MatrixI;
76 import jalview.renderer.ResidueShaderI;
77 import jalview.schemes.AnnotationColourGradient;
78 import jalview.schemes.ColourSchemeI;
79 import jalview.schemes.ColourSchemeProperty;
80 import jalview.schemes.FeatureColour;
81 import jalview.schemes.ResidueProperties;
82 import jalview.schemes.UserColourScheme;
83 import jalview.structure.StructureSelectionManager;
84 import jalview.structures.models.AAStructureBindingModel;
85 import jalview.util.Format;
86 import jalview.util.MessageManager;
87 import jalview.util.Platform;
88 import jalview.util.StringUtils;
89 import jalview.util.jarInputStreamProvider;
90 import jalview.util.matcher.Condition;
91 import jalview.viewmodel.AlignmentViewport;
92 import jalview.viewmodel.PCAModel;
93 import jalview.viewmodel.ViewportRanges;
94 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
95 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
96 import jalview.ws.jws2.Jws2Discoverer;
97 import jalview.ws.jws2.dm.AAConSettings;
98 import jalview.ws.jws2.jabaws2.Jws2Instance;
99 import jalview.ws.params.ArgumentI;
100 import jalview.ws.params.AutoCalcSetting;
101 import jalview.ws.params.WsParamSetI;
102 import jalview.xml.binding.jalview.AlcodonFrame;
103 import jalview.xml.binding.jalview.AlcodonFrame.AlcodMap;
104 import jalview.xml.binding.jalview.Annotation;
105 import jalview.xml.binding.jalview.Annotation.ThresholdLine;
106 import jalview.xml.binding.jalview.AnnotationColourScheme;
107 import jalview.xml.binding.jalview.AnnotationElement;
108 import jalview.xml.binding.jalview.DoubleMatrix;
109 import jalview.xml.binding.jalview.DoubleVector;
110 import jalview.xml.binding.jalview.Feature;
111 import jalview.xml.binding.jalview.Feature.OtherData;
112 import jalview.xml.binding.jalview.FeatureMatcherSet.CompoundMatcher;
113 import jalview.xml.binding.jalview.FilterBy;
114 import jalview.xml.binding.jalview.JalviewModel;
115 import jalview.xml.binding.jalview.JalviewModel.FeatureSettings;
116 import jalview.xml.binding.jalview.JalviewModel.FeatureSettings.Group;
117 import jalview.xml.binding.jalview.JalviewModel.FeatureSettings.Setting;
118 import jalview.xml.binding.jalview.JalviewModel.JGroup;
119 import jalview.xml.binding.jalview.JalviewModel.JSeq;
120 import jalview.xml.binding.jalview.JalviewModel.JSeq.Pdbids;
121 import jalview.xml.binding.jalview.JalviewModel.JSeq.Pdbids.StructureState;
122 import jalview.xml.binding.jalview.JalviewModel.JSeq.RnaViewer;
123 import jalview.xml.binding.jalview.JalviewModel.JSeq.RnaViewer.SecondaryStructure;
124 import jalview.xml.binding.jalview.JalviewModel.PcaViewer;
125 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.Axis;
126 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.SeqPointMax;
127 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.SeqPointMin;
128 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.SequencePoint;
129 import jalview.xml.binding.jalview.JalviewModel.Tree;
130 import jalview.xml.binding.jalview.JalviewModel.UserColours;
131 import jalview.xml.binding.jalview.JalviewModel.Viewport;
132 import jalview.xml.binding.jalview.JalviewModel.Viewport.CalcIdParam;
133 import jalview.xml.binding.jalview.JalviewModel.Viewport.HiddenColumns;
134 import jalview.xml.binding.jalview.JalviewUserColours;
135 import jalview.xml.binding.jalview.JalviewUserColours.Colour;
136 import jalview.xml.binding.jalview.MapListType.MapListFrom;
137 import jalview.xml.binding.jalview.MapListType.MapListTo;
138 import jalview.xml.binding.jalview.Mapping;
139 import jalview.xml.binding.jalview.NoValueColour;
140 import jalview.xml.binding.jalview.ObjectFactory;
141 import jalview.xml.binding.jalview.PcaDataType;
142 import jalview.xml.binding.jalview.Pdbentry.Property;
143 import jalview.xml.binding.jalview.Sequence;
144 import jalview.xml.binding.jalview.Sequence.DBRef;
145 import jalview.xml.binding.jalview.SequenceSet;
146 import jalview.xml.binding.jalview.SequenceSet.SequenceSetProperties;
147 import jalview.xml.binding.jalview.ThresholdType;
148 import jalview.xml.binding.jalview.VAMSAS;
150 import java.awt.Color;
151 import java.awt.Font;
152 import java.awt.Rectangle;
153 import java.io.BufferedReader;
154 import java.io.DataInputStream;
155 import java.io.DataOutputStream;
157 import java.io.FileInputStream;
158 import java.io.FileOutputStream;
159 import java.io.IOException;
160 import java.io.InputStreamReader;
161 import java.io.OutputStreamWriter;
162 import java.io.PrintWriter;
163 import java.lang.reflect.InvocationTargetException;
164 import java.math.BigInteger;
165 import java.net.MalformedURLException;
167 import java.util.ArrayList;
168 import java.util.Arrays;
169 import java.util.Collections;
170 import java.util.Enumeration;
171 import java.util.GregorianCalendar;
172 import java.util.HashMap;
173 import java.util.HashSet;
174 import java.util.Hashtable;
175 import java.util.IdentityHashMap;
176 import java.util.Iterator;
177 import java.util.LinkedHashMap;
178 import java.util.List;
179 import java.util.Map;
180 import java.util.Map.Entry;
181 import java.util.Set;
182 import java.util.Vector;
183 import java.util.jar.JarEntry;
184 import java.util.jar.JarInputStream;
185 import java.util.jar.JarOutputStream;
187 import javax.swing.JInternalFrame;
188 import javax.swing.SwingUtilities;
189 import javax.xml.bind.JAXBContext;
190 import javax.xml.bind.JAXBElement;
191 import javax.xml.bind.Marshaller;
192 import javax.xml.datatype.DatatypeConfigurationException;
193 import javax.xml.datatype.DatatypeFactory;
194 import javax.xml.datatype.XMLGregorianCalendar;
195 import javax.xml.stream.XMLInputFactory;
196 import javax.xml.stream.XMLStreamReader;
199 * Write out the current jalview desktop state as a Jalview XML stream.
201 * Note: the vamsas objects referred to here are primitive versions of the
202 * VAMSAS project schema elements - they are not the same and most likely never
206 * @version $Revision: 1.134 $
208 public class Jalview2XML
210 private static final String VIEWER_PREFIX = "viewer_";
212 private static final String RNA_PREFIX = "rna_";
214 private static final String UTF_8 = "UTF-8";
217 * prefix for recovering datasets for alignments with multiple views where
218 * non-existent dataset IDs were written for some views
220 private static final String UNIQSEQSETID = "uniqueSeqSetId.";
222 // use this with nextCounter() to make unique names for entities
223 private int counter = 0;
226 * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
227 * of sequence objects are created.
229 IdentityHashMap<SequenceI, String> seqsToIds = null;
232 * jalview XML Sequence ID to jalview sequence object reference (both dataset
233 * and alignment sequences. Populated as XML reps of sequence objects are
236 Map<String, SequenceI> seqRefIds = null;
238 Map<String, SequenceI> incompleteSeqs = null;
240 List<SeqFref> frefedSequence = null;
242 boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
245 * Map of reconstructed AlignFrame objects that appear to have come from
246 * SplitFrame objects (have a dna/protein complement view).
248 private Map<Viewport, AlignFrame> splitFrameCandidates = new HashMap<>();
251 * Map from displayed rna structure models to their saved session state jar
254 private Map<RnaModel, String> rnaSessions = new HashMap<>();
257 * A helper method for safely using the value of an optional attribute that
258 * may be null if not present in the XML. Answers the boolean value, or false
264 public static boolean safeBoolean(Boolean b)
266 return b == null ? false : b.booleanValue();
270 * A helper method for safely using the value of an optional attribute that
271 * may be null if not present in the XML. Answers the integer value, or zero
277 public static int safeInt(Integer i)
279 return i == null ? 0 : i.intValue();
283 * A helper method for safely using the value of an optional attribute that
284 * may be null if not present in the XML. Answers the float value, or zero if
290 public static float safeFloat(Float f)
292 return f == null ? 0f : f.floatValue();
296 * create/return unique hash string for sq
299 * @return new or existing unique string for sq
301 String seqHash(SequenceI sq)
303 if (seqsToIds == null)
307 if (seqsToIds.containsKey(sq))
309 return seqsToIds.get(sq);
313 // create sequential key
314 String key = "sq" + (seqsToIds.size() + 1);
315 key = makeHashCode(sq, key); // check we don't have an external reference
317 seqsToIds.put(sq, key);
324 if (seqsToIds == null)
326 seqsToIds = new IdentityHashMap<>();
328 if (seqRefIds == null)
330 seqRefIds = new HashMap<>();
332 if (incompleteSeqs == null)
334 incompleteSeqs = new HashMap<>();
336 if (frefedSequence == null)
338 frefedSequence = new ArrayList<>();
346 public Jalview2XML(boolean raiseGUI)
348 this.raiseGUI = raiseGUI;
352 * base class for resolving forward references to sequences by their ID
357 abstract class SeqFref
363 public SeqFref(String _sref, String type)
369 public String getSref()
374 public SequenceI getSrefSeq()
376 return seqRefIds.get(sref);
379 public boolean isResolvable()
381 return seqRefIds.get(sref) != null;
384 public SequenceI getSrefDatasetSeq()
386 SequenceI sq = seqRefIds.get(sref);
389 while (sq.getDatasetSequence() != null)
391 sq = sq.getDatasetSequence();
398 * @return true if the forward reference was fully resolved
400 abstract boolean resolve();
403 public String toString()
405 return type + " reference to " + sref;
410 * create forward reference for a mapping
416 public SeqFref newMappingRef(final String sref,
417 final jalview.datamodel.Mapping _jmap)
419 SeqFref fref = new SeqFref(sref, "Mapping")
421 public jalview.datamodel.Mapping jmap = _jmap;
426 SequenceI seq = getSrefDatasetSeq();
438 public SeqFref newAlcodMapRef(final String sref,
439 final AlignedCodonFrame _cf,
440 final jalview.datamodel.Mapping _jmap)
443 SeqFref fref = new SeqFref(sref, "Codon Frame")
445 AlignedCodonFrame cf = _cf;
447 public jalview.datamodel.Mapping mp = _jmap;
450 public boolean isResolvable()
452 return super.isResolvable() && mp.getTo() != null;
458 SequenceI seq = getSrefDatasetSeq();
463 cf.addMap(seq, mp.getTo(), mp.getMap());
470 public void resolveFrefedSequences()
472 Iterator<SeqFref> nextFref = frefedSequence.iterator();
473 int toresolve = frefedSequence.size();
474 int unresolved = 0, failedtoresolve = 0;
475 while (nextFref.hasNext())
477 SeqFref ref = nextFref.next();
478 if (ref.isResolvable())
490 } catch (Exception x)
493 "IMPLEMENTATION ERROR: Failed to resolve forward reference for sequence "
506 System.err.println("Jalview Project Import: There were " + unresolved
507 + " forward references left unresolved on the stack.");
509 if (failedtoresolve > 0)
511 System.err.println("SERIOUS! " + failedtoresolve
512 + " resolvable forward references failed to resolve.");
514 if (incompleteSeqs != null && incompleteSeqs.size() > 0)
517 "Jalview Project Import: There are " + incompleteSeqs.size()
518 + " sequences which may have incomplete metadata.");
519 if (incompleteSeqs.size() < 10)
521 for (SequenceI s : incompleteSeqs.values())
523 System.err.println(s.toString());
529 "Too many to report. Skipping output of incomplete sequences.");
535 * This maintains a map of viewports, the key being the seqSetId. Important to
536 * set historyItem and redoList for multiple views
538 Map<String, AlignViewport> viewportsAdded = new HashMap<>();
540 Map<String, AlignmentAnnotation> annotationIds = new HashMap<>();
542 String uniqueSetSuffix = "";
545 * List of pdbfiles added to Jar
547 List<String> pdbfiles = null;
549 // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
550 public void saveState(File statefile)
552 FileOutputStream fos = null;
555 fos = new FileOutputStream(statefile);
556 JarOutputStream jout = new JarOutputStream(fos);
559 } catch (Exception e)
561 // TODO: inform user of the problem - they need to know if their data was
563 if (errorMessage == null)
565 errorMessage = "Couldn't write Jalview Archive to output file '"
566 + statefile + "' - See console error log for details";
570 errorMessage += "(output file was '" + statefile + "')";
580 } catch (IOException e)
590 * Writes a jalview project archive to the given Jar output stream.
594 public void saveState(JarOutputStream jout)
596 AlignFrame[] frames = Desktop.getAlignFrames();
602 saveAllFrames(Arrays.asList(frames), jout);
606 * core method for storing state for a set of AlignFrames.
609 * - frames involving all data to be exported (including containing
612 * - project output stream
614 private void saveAllFrames(List<AlignFrame> frames, JarOutputStream jout)
616 Hashtable<String, AlignFrame> dsses = new Hashtable<>();
619 * ensure cached data is clear before starting
621 // todo tidy up seqRefIds, seqsToIds initialisation / reset
623 splitFrameCandidates.clear();
628 // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
629 // //////////////////////////////////////////////////
631 List<String> shortNames = new ArrayList<>();
632 List<String> viewIds = new ArrayList<>();
635 for (int i = frames.size() - 1; i > -1; i--)
637 AlignFrame af = frames.get(i);
639 if (skipList != null && skipList
640 .containsKey(af.getViewport().getSequenceSetId()))
645 String shortName = makeFilename(af, shortNames);
647 int apSize = af.getAlignPanels().size();
649 for (int ap = 0; ap < apSize; ap++)
651 AlignmentPanel apanel = (AlignmentPanel) af.getAlignPanels()
653 String fileName = apSize == 1 ? shortName : ap + shortName;
654 if (!fileName.endsWith(".xml"))
656 fileName = fileName + ".xml";
659 saveState(apanel, fileName, jout, viewIds);
661 String dssid = getDatasetIdRef(
662 af.getViewport().getAlignment().getDataset());
663 if (!dsses.containsKey(dssid))
665 dsses.put(dssid, af);
670 writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix,
676 } catch (Exception foo)
681 } catch (Exception ex)
683 // TODO: inform user of the problem - they need to know if their data was
685 if (errorMessage == null)
687 errorMessage = "Couldn't write Jalview Archive - see error output for details";
689 ex.printStackTrace();
694 * Generates a distinct file name, based on the title of the AlignFrame, by
695 * appending _n for increasing n until an unused name is generated. The new
696 * name (without its extension) is added to the list.
700 * @return the generated name, with .xml extension
702 protected String makeFilename(AlignFrame af, List<String> namesUsed)
704 String shortName = af.getTitle();
706 if (shortName.indexOf(File.separatorChar) > -1)
708 shortName = shortName
709 .substring(shortName.lastIndexOf(File.separatorChar) + 1);
714 while (namesUsed.contains(shortName))
716 if (shortName.endsWith("_" + (count - 1)))
718 shortName = shortName.substring(0, shortName.lastIndexOf("_"));
721 shortName = shortName.concat("_" + count);
725 namesUsed.add(shortName);
727 if (!shortName.endsWith(".xml"))
729 shortName = shortName + ".xml";
734 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
735 public boolean saveAlignment(AlignFrame af, String jarFile,
740 FileOutputStream fos = new FileOutputStream(jarFile);
741 JarOutputStream jout = new JarOutputStream(fos);
742 List<AlignFrame> frames = new ArrayList<>();
744 // resolve splitframes
745 if (af.getViewport().getCodingComplement() != null)
747 frames = ((SplitFrame) af.getSplitViewContainer()).getAlignFrames();
753 saveAllFrames(frames, jout);
757 } catch (Exception foo)
763 } catch (Exception ex)
765 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
766 ex.printStackTrace();
771 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
772 String fileName, JarOutputStream jout)
775 for (String dssids : dsses.keySet())
777 AlignFrame _af = dsses.get(dssids);
778 String jfileName = fileName + " Dataset for " + _af.getTitle();
779 if (!jfileName.endsWith(".xml"))
781 jfileName = jfileName + ".xml";
783 saveState(_af.alignPanel, jfileName, true, jout, null);
788 * create a JalviewModel from an alignment view and marshall it to a
792 * panel to create jalview model for
794 * name of alignment panel written to output stream
801 public JalviewModel saveState(AlignmentPanel ap, String fileName,
802 JarOutputStream jout, List<String> viewIds)
804 return saveState(ap, fileName, false, jout, viewIds);
808 * create a JalviewModel from an alignment view and marshall it to a
812 * panel to create jalview model for
814 * name of alignment panel written to output stream
816 * when true, only write the dataset for the alignment, not the data
817 * associated with the view.
823 public JalviewModel saveState(AlignmentPanel ap, String fileName,
824 boolean storeDS, JarOutputStream jout, List<String> viewIds)
828 viewIds = new ArrayList<>();
833 List<UserColourScheme> userColours = new ArrayList<>();
835 AlignViewport av = ap.av;
836 ViewportRanges vpRanges = av.getRanges();
838 final ObjectFactory objectFactory = new ObjectFactory();
839 JalviewModel object = objectFactory.createJalviewModel();
840 object.setVamsasModel(new VAMSAS());
842 // object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
845 GregorianCalendar c = new GregorianCalendar();
846 DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
847 XMLGregorianCalendar now = datatypeFactory.newXMLGregorianCalendar(c);// gregorianCalendar);
848 object.setCreationDate(now);
849 } catch (DatatypeConfigurationException e)
851 System.err.println("error writing date: " + e.toString());
854 jalview.bin.Cache.getDefault("VERSION", "Development Build"));
857 * rjal is full height alignment, jal is actual alignment with full metadata
858 * but excludes hidden sequences.
860 jalview.datamodel.AlignmentI rjal = av.getAlignment(), jal = rjal;
862 if (av.hasHiddenRows())
864 rjal = jal.getHiddenSequences().getFullAlignment();
867 SequenceSet vamsasSet = new SequenceSet();
869 // JalviewModelSequence jms = new JalviewModelSequence();
871 vamsasSet.setGapChar(jal.getGapCharacter() + "");
873 if (jal.getDataset() != null)
875 // dataset id is the dataset's hashcode
876 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
879 // switch jal and the dataset
880 jal = jal.getDataset();
884 if (jal.getProperties() != null)
886 Enumeration en = jal.getProperties().keys();
887 while (en.hasMoreElements())
889 String key = en.nextElement().toString();
890 SequenceSetProperties ssp = new SequenceSetProperties();
892 ssp.setValue(jal.getProperties().get(key).toString());
893 // vamsasSet.addSequenceSetProperties(ssp);
894 vamsasSet.getSequenceSetProperties().add(ssp);
899 Set<String> calcIdSet = new HashSet<>();
900 // record the set of vamsas sequence XML POJO we create.
901 HashMap<String, Sequence> vamsasSetIds = new HashMap<>();
903 for (final SequenceI jds : rjal.getSequences())
905 final SequenceI jdatasq = jds.getDatasetSequence() == null ? jds
906 : jds.getDatasetSequence();
907 String id = seqHash(jds);
908 if (vamsasSetIds.get(id) == null)
910 if (seqRefIds.get(id) != null && !storeDS)
912 // This happens for two reasons: 1. multiple views are being
914 // 2. the hashCode has collided with another sequence's code. This
916 // HAPPEN! (PF00072.15.stk does this)
917 // JBPNote: Uncomment to debug writing out of files that do not read
918 // back in due to ArrayOutOfBoundExceptions.
919 // System.err.println("vamsasSeq backref: "+id+"");
920 // System.err.println(jds.getName()+"
921 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
922 // System.err.println("Hashcode: "+seqHash(jds));
923 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
924 // System.err.println(rsq.getName()+"
925 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
926 // System.err.println("Hashcode: "+seqHash(rsq));
930 vamsasSeq = createVamsasSequence(id, jds);
931 // vamsasSet.addSequence(vamsasSeq);
932 vamsasSet.getSequence().add(vamsasSeq);
933 vamsasSetIds.put(id, vamsasSeq);
934 seqRefIds.put(id, jds);
938 jseq.setStart(jds.getStart());
939 jseq.setEnd(jds.getEnd());
940 jseq.setColour(av.getSequenceColour(jds).getRGB());
942 jseq.setId(id); // jseq id should be a string not a number
945 // Store any sequences this sequence represents
946 if (av.hasHiddenRows())
948 // use rjal, contains the full height alignment
950 av.getAlignment().getHiddenSequences().isHidden(jds));
952 if (av.isHiddenRepSequence(jds))
954 jalview.datamodel.SequenceI[] reps = av
955 .getRepresentedSequences(jds).getSequencesInOrder(rjal);
957 for (int h = 0; h < reps.length; h++)
961 // jseq.addHiddenSequences(rjal.findIndex(reps[h]));
962 jseq.getHiddenSequences().add(rjal.findIndex(reps[h]));
967 // mark sequence as reference - if it is the reference for this view
970 jseq.setViewreference(jds == jal.getSeqrep());
974 // TODO: omit sequence features from each alignment view's XML dump if we
975 // are storing dataset
976 List<SequenceFeature> sfs = jds.getSequenceFeatures();
977 for (SequenceFeature sf : sfs)
979 // Features features = new Features();
980 Feature features = new Feature();
982 features.setBegin(sf.getBegin());
983 features.setEnd(sf.getEnd());
984 features.setDescription(sf.getDescription());
985 features.setType(sf.getType());
986 features.setFeatureGroup(sf.getFeatureGroup());
987 features.setScore(sf.getScore());
988 if (sf.links != null)
990 for (int l = 0; l < sf.links.size(); l++)
992 OtherData keyValue = new OtherData();
993 keyValue.setKey("LINK_" + l);
994 keyValue.setValue(sf.links.elementAt(l).toString());
995 // features.addOtherData(keyValue);
996 features.getOtherData().add(keyValue);
999 if (sf.otherDetails != null)
1002 * save feature attributes, which may be simple strings or
1003 * map valued (have sub-attributes)
1005 for (Entry<String, Object> entry : sf.otherDetails.entrySet())
1007 String key = entry.getKey();
1008 Object value = entry.getValue();
1009 if (value instanceof Map<?, ?>)
1011 for (Entry<String, Object> subAttribute : ((Map<String, Object>) value)
1014 OtherData otherData = new OtherData();
1015 otherData.setKey(key);
1016 otherData.setKey2(subAttribute.getKey());
1017 otherData.setValue(subAttribute.getValue().toString());
1018 // features.addOtherData(otherData);
1019 features.getOtherData().add(otherData);
1024 OtherData otherData = new OtherData();
1025 otherData.setKey(key);
1026 otherData.setValue(value.toString());
1027 // features.addOtherData(otherData);
1028 features.getOtherData().add(otherData);
1033 // jseq.addFeatures(features);
1034 jseq.getFeatures().add(features);
1037 if (jdatasq.getAllPDBEntries() != null)
1039 Enumeration<PDBEntry> en = jdatasq.getAllPDBEntries().elements();
1040 while (en.hasMoreElements())
1042 Pdbids pdb = new Pdbids();
1043 jalview.datamodel.PDBEntry entry = en.nextElement();
1045 String pdbId = entry.getId();
1047 pdb.setType(entry.getType());
1050 * Store any structure views associated with this sequence. This
1051 * section copes with duplicate entries in the project, so a dataset
1052 * only view *should* be coped with sensibly.
1054 // This must have been loaded, is it still visible?
1055 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1056 String matchedFile = null;
1057 for (int f = frames.length - 1; f > -1; f--)
1059 if (frames[f] instanceof StructureViewerBase)
1061 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
1062 matchedFile = saveStructureState(ap, jds, pdb, entry, viewIds,
1063 matchedFile, viewFrame);
1065 * Only store each structure viewer's state once in the project
1066 * jar. First time through only (storeDS==false)
1068 String viewId = viewFrame.getViewId();
1069 if (!storeDS && !viewIds.contains(viewId))
1071 viewIds.add(viewId);
1074 String viewerState = viewFrame.getStateInfo();
1075 writeJarEntry(jout, getViewerJarEntryName(viewId),
1076 viewerState.getBytes());
1077 } catch (IOException e)
1080 "Error saving viewer state: " + e.getMessage());
1086 if (matchedFile != null || entry.getFile() != null)
1088 if (entry.getFile() != null)
1091 matchedFile = entry.getFile();
1093 pdb.setFile(matchedFile); // entry.getFile());
1094 if (pdbfiles == null)
1096 pdbfiles = new ArrayList<>();
1099 if (!pdbfiles.contains(pdbId))
1101 pdbfiles.add(pdbId);
1102 copyFileToJar(jout, matchedFile, pdbId);
1106 Enumeration<String> props = entry.getProperties();
1107 if (props.hasMoreElements())
1109 // PdbentryItem item = new PdbentryItem();
1110 while (props.hasMoreElements())
1112 Property prop = new Property();
1113 String key = props.nextElement();
1115 prop.setValue(entry.getProperty(key).toString());
1116 // item.addProperty(prop);
1117 pdb.getProperty().add(prop);
1119 // pdb.addPdbentryItem(item);
1122 // jseq.addPdbids(pdb);
1123 jseq.getPdbids().add(pdb);
1127 saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
1129 // jms.addJSeq(jseq);
1130 object.getJSeq().add(jseq);
1133 if (!storeDS && av.hasHiddenRows())
1135 jal = av.getAlignment();
1139 if (storeDS && jal.getCodonFrames() != null)
1141 List<AlignedCodonFrame> jac = jal.getCodonFrames();
1142 for (AlignedCodonFrame acf : jac)
1144 AlcodonFrame alc = new AlcodonFrame();
1145 if (acf.getProtMappings() != null
1146 && acf.getProtMappings().length > 0)
1148 boolean hasMap = false;
1149 SequenceI[] dnas = acf.getdnaSeqs();
1150 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1151 for (int m = 0; m < pmaps.length; m++)
1153 AlcodMap alcmap = new AlcodMap();
1154 alcmap.setDnasq(seqHash(dnas[m]));
1156 createVamsasMapping(pmaps[m], dnas[m], null, false));
1157 // alc.addAlcodMap(alcmap);
1158 alc.getAlcodMap().add(alcmap);
1163 // vamsasSet.addAlcodonFrame(alc);
1164 vamsasSet.getAlcodonFrame().add(alc);
1167 // TODO: delete this ? dead code from 2.8.3->2.9 ?
1169 // AlcodonFrame alc = new AlcodonFrame();
1170 // vamsasSet.addAlcodonFrame(alc);
1171 // for (int p = 0; p < acf.aaWidth; p++)
1173 // Alcodon cmap = new Alcodon();
1174 // if (acf.codons[p] != null)
1176 // // Null codons indicate a gapped column in the translated peptide
1178 // cmap.setPos1(acf.codons[p][0]);
1179 // cmap.setPos2(acf.codons[p][1]);
1180 // cmap.setPos3(acf.codons[p][2]);
1182 // alc.addAlcodon(cmap);
1184 // if (acf.getProtMappings() != null
1185 // && acf.getProtMappings().length > 0)
1187 // SequenceI[] dnas = acf.getdnaSeqs();
1188 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1189 // for (int m = 0; m < pmaps.length; m++)
1191 // AlcodMap alcmap = new AlcodMap();
1192 // alcmap.setDnasq(seqHash(dnas[m]));
1193 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
1195 // alc.addAlcodMap(alcmap);
1202 // /////////////////////////////////
1203 if (!storeDS && av.getCurrentTree() != null)
1205 // FIND ANY ASSOCIATED TREES
1206 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
1207 if (Desktop.desktop != null)
1209 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1211 for (int t = 0; t < frames.length; t++)
1213 if (frames[t] instanceof TreePanel)
1215 TreePanel tp = (TreePanel) frames[t];
1217 if (tp.getTreeCanvas().getViewport().getAlignment() == jal)
1219 JalviewModel.Tree tree = new JalviewModel.Tree();
1220 tree.setTitle(tp.getTitle());
1221 tree.setCurrentTree((av.getCurrentTree() == tp.getTree()));
1222 tree.setNewick(tp.getTree().print());
1223 tree.setThreshold(tp.getTreeCanvas().getThreshold());
1225 tree.setFitToWindow(tp.fitToWindow.getState());
1226 tree.setFontName(tp.getTreeFont().getName());
1227 tree.setFontSize(tp.getTreeFont().getSize());
1228 tree.setFontStyle(tp.getTreeFont().getStyle());
1229 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
1231 tree.setShowBootstrap(tp.bootstrapMenu.getState());
1232 tree.setShowDistances(tp.distanceMenu.getState());
1234 tree.setHeight(tp.getHeight());
1235 tree.setWidth(tp.getWidth());
1236 tree.setXpos(tp.getX());
1237 tree.setYpos(tp.getY());
1238 tree.setId(makeHashCode(tp, null));
1239 tree.setLinkToAllViews(
1240 tp.getTreeCanvas().isApplyToAllViews());
1242 // jms.addTree(tree);
1243 object.getTree().add(tree);
1253 if (!storeDS && Desktop.desktop != null)
1255 for (JInternalFrame frame : Desktop.desktop.getAllFrames())
1257 if (frame instanceof PCAPanel)
1259 PCAPanel panel = (PCAPanel) frame;
1260 if (panel.getAlignViewport().getAlignment() == jal)
1262 savePCA(panel, object);
1270 * store forward refs from an annotationRow to any groups
1272 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<>();
1275 for (SequenceI sq : jal.getSequences())
1277 // Store annotation on dataset sequences only
1278 AlignmentAnnotation[] aa = sq.getAnnotation();
1279 if (aa != null && aa.length > 0)
1281 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1288 if (jal.getAlignmentAnnotation() != null)
1290 // Store the annotation shown on the alignment.
1291 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1292 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1297 if (jal.getGroups() != null)
1299 JGroup[] groups = new JGroup[jal.getGroups().size()];
1301 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1303 JGroup jGroup = new JGroup();
1304 groups[++i] = jGroup;
1306 jGroup.setStart(sg.getStartRes());
1307 jGroup.setEnd(sg.getEndRes());
1308 jGroup.setName(sg.getName());
1309 if (groupRefs.containsKey(sg))
1311 // group has references so set its ID field
1312 jGroup.setId(groupRefs.get(sg));
1314 ColourSchemeI colourScheme = sg.getColourScheme();
1315 if (colourScheme != null)
1317 ResidueShaderI groupColourScheme = sg.getGroupColourScheme();
1318 if (groupColourScheme.conservationApplied())
1320 jGroup.setConsThreshold(groupColourScheme.getConservationInc());
1322 if (colourScheme instanceof jalview.schemes.UserColourScheme)
1325 setUserColourScheme(colourScheme, userColours,
1330 jGroup.setColour(colourScheme.getSchemeName());
1333 else if (colourScheme instanceof jalview.schemes.AnnotationColourGradient)
1335 jGroup.setColour("AnnotationColourGradient");
1336 jGroup.setAnnotationColours(constructAnnotationColours(
1337 (jalview.schemes.AnnotationColourGradient) colourScheme,
1338 userColours, object));
1340 else if (colourScheme instanceof jalview.schemes.UserColourScheme)
1343 setUserColourScheme(colourScheme, userColours, object));
1347 jGroup.setColour(colourScheme.getSchemeName());
1350 jGroup.setPidThreshold(groupColourScheme.getThreshold());
1353 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1354 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1355 jGroup.setDisplayText(sg.getDisplayText());
1356 jGroup.setColourText(sg.getColourText());
1357 jGroup.setTextCol1(sg.textColour.getRGB());
1358 jGroup.setTextCol2(sg.textColour2.getRGB());
1359 jGroup.setTextColThreshold(sg.thresholdTextColour);
1360 jGroup.setShowUnconserved(sg.getShowNonconserved());
1361 jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1362 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1363 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1364 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1365 for (SequenceI seq : sg.getSequences())
1367 // jGroup.addSeq(seqHash(seq));
1368 jGroup.getSeq().add(seqHash(seq));
1372 //jms.setJGroup(groups);
1374 for (JGroup grp : groups)
1376 object.getJGroup().add(grp);
1381 // /////////SAVE VIEWPORT
1382 Viewport view = new Viewport();
1383 view.setTitle(ap.alignFrame.getTitle());
1384 view.setSequenceSetId(
1385 makeHashCode(av.getSequenceSetId(), av.getSequenceSetId()));
1386 view.setId(av.getViewId());
1387 if (av.getCodingComplement() != null)
1389 view.setComplementId(av.getCodingComplement().getViewId());
1391 view.setViewName(av.getViewName());
1392 view.setGatheredViews(av.isGatherViewsHere());
1394 Rectangle size = ap.av.getExplodedGeometry();
1395 Rectangle position = size;
1398 size = ap.alignFrame.getBounds();
1399 if (av.getCodingComplement() != null)
1401 position = ((SplitFrame) ap.alignFrame.getSplitViewContainer())
1409 view.setXpos(position.x);
1410 view.setYpos(position.y);
1412 view.setWidth(size.width);
1413 view.setHeight(size.height);
1415 view.setStartRes(vpRanges.getStartRes());
1416 view.setStartSeq(vpRanges.getStartSeq());
1418 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1420 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1421 userColours, object));
1424 .getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1426 AnnotationColourScheme ac = constructAnnotationColours(
1427 (jalview.schemes.AnnotationColourGradient) av
1428 .getGlobalColourScheme(),
1429 userColours, object);
1431 view.setAnnotationColours(ac);
1432 view.setBgColour("AnnotationColourGradient");
1436 view.setBgColour(ColourSchemeProperty
1437 .getColourName(av.getGlobalColourScheme()));
1440 ResidueShaderI vcs = av.getResidueShading();
1441 ColourSchemeI cs = av.getGlobalColourScheme();
1445 if (vcs.conservationApplied())
1447 view.setConsThreshold(vcs.getConservationInc());
1448 if (cs instanceof jalview.schemes.UserColourScheme)
1450 view.setBgColour(setUserColourScheme(cs, userColours, object));
1453 view.setPidThreshold(vcs.getThreshold());
1456 view.setConservationSelected(av.getConservationSelected());
1457 view.setPidSelected(av.getAbovePIDThreshold());
1458 final Font font = av.getFont();
1459 view.setFontName(font.getName());
1460 view.setFontSize(font.getSize());
1461 view.setFontStyle(font.getStyle());
1462 view.setScaleProteinAsCdna(av.getViewStyle().isScaleProteinAsCdna());
1463 view.setRenderGaps(av.isRenderGaps());
1464 view.setShowAnnotation(av.isShowAnnotation());
1465 view.setShowBoxes(av.getShowBoxes());
1466 view.setShowColourText(av.getColourText());
1467 view.setShowFullId(av.getShowJVSuffix());
1468 view.setRightAlignIds(av.isRightAlignIds());
1469 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1470 view.setShowText(av.getShowText());
1471 view.setShowUnconserved(av.getShowUnconserved());
1472 view.setWrapAlignment(av.getWrapAlignment());
1473 view.setTextCol1(av.getTextColour().getRGB());
1474 view.setTextCol2(av.getTextColour2().getRGB());
1475 view.setTextColThreshold(av.getThresholdTextColour());
1476 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1477 view.setShowSequenceLogo(av.isShowSequenceLogo());
1478 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1479 view.setShowGroupConsensus(av.isShowGroupConsensus());
1480 view.setShowGroupConservation(av.isShowGroupConservation());
1481 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1482 view.setShowDbRefTooltip(av.isShowDBRefs());
1483 view.setFollowHighlight(av.isFollowHighlight());
1484 view.setFollowSelection(av.followSelection);
1485 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1486 if (av.getFeaturesDisplayed() != null)
1488 FeatureSettings fs = new FeatureSettings();
1490 FeatureRenderer fr = ap.getSeqPanel().seqCanvas
1491 .getFeatureRenderer();
1492 String[] renderOrder = fr.getRenderOrder().toArray(new String[0]);
1494 Vector<String> settingsAdded = new Vector<>();
1495 if (renderOrder != null)
1497 for (String featureType : renderOrder)
1499 FeatureSettings.Setting setting = new FeatureSettings.Setting();
1500 setting.setType(featureType);
1503 * save any filter for the feature type
1505 FeatureMatcherSetI filter = fr.getFeatureFilter(featureType);
1506 if (filter != null) {
1507 Iterator<FeatureMatcherI> filters = filter.getMatchers().iterator();
1508 FeatureMatcherI firstFilter = filters.next();
1509 setting.setMatcherSet(Jalview2XML.marshalFilter(
1510 firstFilter, filters, filter.isAnded()));
1514 * save colour scheme for the feature type
1516 FeatureColourI fcol = fr.getFeatureStyle(featureType);
1517 if (!fcol.isSimpleColour())
1519 setting.setColour(fcol.getMaxColour().getRGB());
1520 setting.setMincolour(fcol.getMinColour().getRGB());
1521 setting.setMin(fcol.getMin());
1522 setting.setMax(fcol.getMax());
1523 setting.setColourByLabel(fcol.isColourByLabel());
1524 if (fcol.isColourByAttribute())
1526 String[] attName = fcol.getAttributeName();
1527 setting.getAttributeName().add(attName[0]);
1528 if (attName.length > 1)
1530 setting.getAttributeName().add(attName[1]);
1533 setting.setAutoScale(fcol.isAutoScaled());
1534 setting.setThreshold(fcol.getThreshold());
1535 Color noColour = fcol.getNoColour();
1536 if (noColour == null)
1538 setting.setNoValueColour(NoValueColour.NONE);
1540 else if (noColour.equals(fcol.getMaxColour()))
1542 setting.setNoValueColour(NoValueColour.MAX);
1546 setting.setNoValueColour(NoValueColour.MIN);
1548 // -1 = No threshold, 0 = Below, 1 = Above
1549 setting.setThreshstate(fcol.isAboveThreshold() ? 1
1550 : (fcol.isBelowThreshold() ? 0 : -1));
1554 setting.setColour(fcol.getColour().getRGB());
1558 av.getFeaturesDisplayed().isVisible(featureType));
1560 .getOrder(featureType);
1563 setting.setOrder(rorder);
1565 /// fs.addSetting(setting);
1566 fs.getSetting().add(setting);
1567 settingsAdded.addElement(featureType);
1571 // is groups actually supposed to be a map here ?
1572 Iterator<String> en = fr.getFeatureGroups().iterator();
1573 Vector<String> groupsAdded = new Vector<>();
1574 while (en.hasNext())
1576 String grp = en.next();
1577 if (groupsAdded.contains(grp))
1581 Group g = new Group();
1583 g.setDisplay(((Boolean) fr.checkGroupVisibility(grp, false))
1586 fs.getGroup().add(g);
1587 groupsAdded.addElement(grp);
1589 // jms.setFeatureSettings(fs);
1590 object.setFeatureSettings(fs);
1593 if (av.hasHiddenColumns())
1595 jalview.datamodel.HiddenColumns hidden = av.getAlignment()
1596 .getHiddenColumns();
1599 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1603 Iterator<int[]> hiddenRegions = hidden.iterator();
1604 while (hiddenRegions.hasNext())
1606 int[] region = hiddenRegions.next();
1607 HiddenColumns hc = new HiddenColumns();
1608 hc.setStart(region[0]);
1609 hc.setEnd(region[1]);
1610 // view.addHiddenColumns(hc);
1611 view.getHiddenColumns().add(hc);
1615 if (calcIdSet.size() > 0)
1617 for (String calcId : calcIdSet)
1619 if (calcId.trim().length() > 0)
1621 CalcIdParam cidp = createCalcIdParam(calcId, av);
1622 // Some calcIds have no parameters.
1625 // view.addCalcIdParam(cidp);
1626 view.getCalcIdParam().add(cidp);
1632 // jms.addViewport(view);
1633 object.getViewport().add(view);
1635 // object.setJalviewModelSequence(jms);
1636 // object.getVamsasModel().addSequenceSet(vamsasSet);
1637 object.getVamsasModel().getSequenceSet().add(vamsasSet);
1639 if (jout != null && fileName != null)
1641 // We may not want to write the object to disk,
1642 // eg we can copy the alignViewport to a new view object
1643 // using save and then load
1646 System.out.println("Writing jar entry " + fileName);
1647 JarEntry entry = new JarEntry(fileName);
1648 jout.putNextEntry(entry);
1649 PrintWriter pout = new PrintWriter(
1650 new OutputStreamWriter(jout, UTF_8));
1651 JAXBContext jaxbContext = JAXBContext
1652 .newInstance(JalviewModel.class);
1653 Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
1655 // output pretty printed
1656 // jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
1657 jaxbMarshaller.marshal(
1658 new ObjectFactory().createJalviewModel(object), pout);
1660 // jaxbMarshaller.marshal(object, pout);
1661 // marshaller.marshal(object);
1664 } catch (Exception ex)
1666 // TODO: raise error in GUI if marshalling failed.
1667 System.err.println("Error writing Jalview project");
1668 ex.printStackTrace();
1675 * Writes PCA viewer attributes and computed values to an XML model object and
1676 * adds it to the JalviewModel. Any exceptions are reported by logging.
1678 protected void savePCA(PCAPanel panel, JalviewModel object)
1682 PcaViewer viewer = new PcaViewer();
1683 viewer.setHeight(panel.getHeight());
1684 viewer.setWidth(panel.getWidth());
1685 viewer.setXpos(panel.getX());
1686 viewer.setYpos(panel.getY());
1687 viewer.setTitle(panel.getTitle());
1688 PCAModel pcaModel = panel.getPcaModel();
1689 viewer.setScoreModelName(pcaModel.getScoreModelName());
1690 viewer.setXDim(panel.getSelectedDimensionIndex(X));
1691 viewer.setYDim(panel.getSelectedDimensionIndex(Y));
1692 viewer.setZDim(panel.getSelectedDimensionIndex(Z));
1694 panel.getRotatableCanvas().getBackgroundColour().getRGB());
1695 viewer.setScaleFactor(panel.getRotatableCanvas().getScaleFactor());
1696 float[] spMin = panel.getRotatableCanvas().getSeqMin();
1697 SeqPointMin spmin = new SeqPointMin();
1698 spmin.setXPos(spMin[0]);
1699 spmin.setYPos(spMin[1]);
1700 spmin.setZPos(spMin[2]);
1701 viewer.setSeqPointMin(spmin);
1702 float[] spMax = panel.getRotatableCanvas().getSeqMax();
1703 SeqPointMax spmax = new SeqPointMax();
1704 spmax.setXPos(spMax[0]);
1705 spmax.setYPos(spMax[1]);
1706 spmax.setZPos(spMax[2]);
1707 viewer.setSeqPointMax(spmax);
1708 viewer.setShowLabels(panel.getRotatableCanvas().isShowLabels());
1709 viewer.setLinkToAllViews(
1710 panel.getRotatableCanvas().isApplyToAllViews());
1711 SimilarityParamsI sp = pcaModel.getSimilarityParameters();
1712 viewer.setIncludeGaps(sp.includeGaps());
1713 viewer.setMatchGaps(sp.matchGaps());
1714 viewer.setIncludeGappedColumns(sp.includeGappedColumns());
1715 viewer.setDenominateByShortestLength(sp.denominateByShortestLength());
1718 * sequence points on display
1720 for (jalview.datamodel.SequencePoint spt : pcaModel
1721 .getSequencePoints())
1723 SequencePoint point = new SequencePoint();
1724 point.setSequenceRef(seqHash(spt.getSequence()));
1725 point.setXPos(spt.coord.x);
1726 point.setYPos(spt.coord.y);
1727 point.setZPos(spt.coord.z);
1728 viewer.getSequencePoint().add(point);
1732 * (end points of) axes on display
1734 for (Point p : panel.getRotatableCanvas().getAxisEndPoints())
1737 Axis axis = new Axis();
1741 viewer.getAxis().add(axis);
1745 * raw PCA data (note we are not restoring PCA inputs here -
1746 * alignment view, score model, similarity parameters)
1748 PcaDataType data = new PcaDataType();
1749 viewer.setPcaData(data);
1750 PCA pca = pcaModel.getPcaData();
1752 DoubleMatrix pm = new DoubleMatrix();
1753 saveDoubleMatrix(pca.getPairwiseScores(), pm);
1754 data.setPairwiseMatrix(pm);
1756 DoubleMatrix tm = new DoubleMatrix();
1757 saveDoubleMatrix(pca.getTridiagonal(), tm);
1758 data.setTridiagonalMatrix(tm);
1760 DoubleMatrix eigenMatrix = new DoubleMatrix();
1761 data.setEigenMatrix(eigenMatrix);
1762 saveDoubleMatrix(pca.getEigenmatrix(), eigenMatrix);
1764 object.getPcaViewer().add(viewer);
1765 } catch (Throwable t)
1767 Cache.log.error("Error saving PCA: " + t.getMessage());
1772 * Stores values from a matrix into an XML element, including (if present) the
1777 * @see #loadDoubleMatrix(DoubleMatrix)
1779 protected void saveDoubleMatrix(MatrixI m, DoubleMatrix xmlMatrix)
1781 xmlMatrix.setRows(m.height());
1782 xmlMatrix.setColumns(m.width());
1783 for (int i = 0; i < m.height(); i++)
1785 DoubleVector row = new DoubleVector();
1786 for (int j = 0; j < m.width(); j++)
1788 row.getV().add(m.getValue(i, j));
1790 xmlMatrix.getRow().add(row);
1792 if (m.getD() != null)
1794 DoubleVector dVector = new DoubleVector();
1795 for (double d : m.getD())
1797 dVector.getV().add(d);
1799 xmlMatrix.setD(dVector);
1801 if (m.getE() != null)
1803 DoubleVector eVector = new DoubleVector();
1804 for (double e : m.getE())
1806 eVector.getV().add(e);
1808 xmlMatrix.setE(eVector);
1813 * Loads XML matrix data into a new Matrix object, including the D and/or E
1814 * vectors (if present)
1818 * @see Jalview2XML#saveDoubleMatrix(MatrixI, DoubleMatrix)
1820 protected MatrixI loadDoubleMatrix(DoubleMatrix mData)
1822 int rows = mData.getRows();
1823 double[][] vals = new double[rows][];
1825 for (int i = 0; i < rows; i++)
1827 List<Double> dVector = mData.getRow().get(i).getV();
1828 vals[i] = new double[dVector.size()];
1830 for (Double d : dVector)
1836 MatrixI m = new Matrix(vals);
1838 if (mData.getD() != null)
1840 List<Double> dVector = mData.getD().getV();
1841 double[] vec = new double[dVector.size()];
1843 for (Double d : dVector)
1849 if (mData.getE() != null)
1851 List<Double> dVector = mData.getE().getV();
1852 double[] vec = new double[dVector.size()];
1854 for (Double d : dVector)
1865 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1866 * for each viewer, with
1868 * <li>viewer geometry (position, size, split pane divider location)</li>
1869 * <li>index of the selected structure in the viewer (currently shows gapped
1871 * <li>the id of the annotation holding RNA secondary structure</li>
1872 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1874 * Varna viewer state is also written out (in native Varna XML) to separate
1875 * project jar entries. A separate entry is written for each RNA structure
1876 * displayed, with the naming convention
1878 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
1886 * @param storeDataset
1888 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
1889 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
1890 boolean storeDataset)
1892 if (Desktop.desktop == null)
1896 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1897 for (int f = frames.length - 1; f > -1; f--)
1899 if (frames[f] instanceof AppVarna)
1901 AppVarna varna = (AppVarna) frames[f];
1903 * link the sequence to every viewer that is showing it and is linked to
1904 * its alignment panel
1906 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1908 String viewId = varna.getViewId();
1909 RnaViewer rna = new RnaViewer();
1910 rna.setViewId(viewId);
1911 rna.setTitle(varna.getTitle());
1912 rna.setXpos(varna.getX());
1913 rna.setYpos(varna.getY());
1914 rna.setWidth(varna.getWidth());
1915 rna.setHeight(varna.getHeight());
1916 rna.setDividerLocation(varna.getDividerLocation());
1917 rna.setSelectedRna(varna.getSelectedIndex());
1918 // jseq.addRnaViewer(rna);
1919 jseq.getRnaViewer().add(rna);
1922 * Store each Varna panel's state once in the project per sequence.
1923 * First time through only (storeDataset==false)
1925 // boolean storeSessions = false;
1926 // String sequenceViewId = viewId + seqsToIds.get(jds);
1927 // if (!storeDataset && !viewIds.contains(sequenceViewId))
1929 // viewIds.add(sequenceViewId);
1930 // storeSessions = true;
1932 for (RnaModel model : varna.getModels())
1934 if (model.seq == jds)
1937 * VARNA saves each view (sequence or alignment secondary
1938 * structure, gapped or trimmed) as a separate XML file
1940 String jarEntryName = rnaSessions.get(model);
1941 if (jarEntryName == null)
1944 String varnaStateFile = varna.getStateInfo(model.rna);
1945 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
1946 copyFileToJar(jout, varnaStateFile, jarEntryName);
1947 rnaSessions.put(model, jarEntryName);
1949 SecondaryStructure ss = new SecondaryStructure();
1950 String annotationId = varna.getAnnotation(jds).annotationId;
1951 ss.setAnnotationId(annotationId);
1952 ss.setViewerState(jarEntryName);
1953 ss.setGapped(model.gapped);
1954 ss.setTitle(model.title);
1955 // rna.addSecondaryStructure(ss);
1956 rna.getSecondaryStructure().add(ss);
1965 * Copy the contents of a file to a new entry added to the output jar
1969 * @param jarEntryName
1971 protected void copyFileToJar(JarOutputStream jout, String infilePath,
1972 String jarEntryName)
1974 DataInputStream dis = null;
1977 File file = new File(infilePath);
1978 if (file.exists() && jout != null)
1980 dis = new DataInputStream(new FileInputStream(file));
1981 byte[] data = new byte[(int) file.length()];
1982 dis.readFully(data);
1983 writeJarEntry(jout, jarEntryName, data);
1985 } catch (Exception ex)
1987 ex.printStackTrace();
1995 } catch (IOException e)
2004 * Write the data to a new entry of given name in the output jar file
2007 * @param jarEntryName
2009 * @throws IOException
2011 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
2012 byte[] data) throws IOException
2016 System.out.println("Writing jar entry " + jarEntryName);
2017 jout.putNextEntry(new JarEntry(jarEntryName));
2018 DataOutputStream dout = new DataOutputStream(jout);
2019 dout.write(data, 0, data.length);
2026 * Save the state of a structure viewer
2031 * the archive XML element under which to save the state
2034 * @param matchedFile
2038 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
2039 Pdbids pdb, PDBEntry entry, List<String> viewIds,
2040 String matchedFile, StructureViewerBase viewFrame)
2042 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
2045 * Look for any bindings for this viewer to the PDB file of interest
2046 * (including part matches excluding chain id)
2048 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
2050 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
2051 final String pdbId = pdbentry.getId();
2052 if (!pdbId.equals(entry.getId())
2053 && !(entry.getId().length() > 4 && entry.getId().toLowerCase()
2054 .startsWith(pdbId.toLowerCase())))
2057 * not interested in a binding to a different PDB entry here
2061 if (matchedFile == null)
2063 matchedFile = pdbentry.getFile();
2065 else if (!matchedFile.equals(pdbentry.getFile()))
2068 "Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
2069 + pdbentry.getFile());
2073 // can get at it if the ID
2074 // match is ambiguous (e.g.
2077 for (int smap = 0; smap < viewFrame.getBinding()
2078 .getSequence()[peid].length; smap++)
2080 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
2081 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
2083 StructureState state = new StructureState();
2084 state.setVisible(true);
2085 state.setXpos(viewFrame.getX());
2086 state.setYpos(viewFrame.getY());
2087 state.setWidth(viewFrame.getWidth());
2088 state.setHeight(viewFrame.getHeight());
2089 final String viewId = viewFrame.getViewId();
2090 state.setViewId(viewId);
2091 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
2092 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
2093 state.setColourByJmol(viewFrame.isColouredByViewer());
2094 state.setType(viewFrame.getViewerType().toString());
2095 // pdb.addStructureState(state);
2096 pdb.getStructureState().add(state);
2104 * Populates the AnnotationColourScheme xml for save. This captures the
2105 * settings of the options in the 'Colour by Annotation' dialog.
2108 * @param userColours
2112 private AnnotationColourScheme constructAnnotationColours(
2113 AnnotationColourGradient acg, List<UserColourScheme> userColours,
2116 AnnotationColourScheme ac = new AnnotationColourScheme();
2117 ac.setAboveThreshold(acg.getAboveThreshold());
2118 ac.setThreshold(acg.getAnnotationThreshold());
2119 // 2.10.2 save annotationId (unique) not annotation label
2120 ac.setAnnotation(acg.getAnnotation().annotationId);
2121 if (acg.getBaseColour() instanceof UserColourScheme)
2124 setUserColourScheme(acg.getBaseColour(), userColours, jm));
2129 ColourSchemeProperty.getColourName(acg.getBaseColour()));
2132 ac.setMaxColour(acg.getMaxColour().getRGB());
2133 ac.setMinColour(acg.getMinColour().getRGB());
2134 ac.setPerSequence(acg.isSeqAssociated());
2135 ac.setPredefinedColours(acg.isPredefinedColours());
2139 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
2140 IdentityHashMap<SequenceGroup, String> groupRefs,
2141 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
2142 SequenceSet vamsasSet)
2145 for (int i = 0; i < aa.length; i++)
2147 Annotation an = new Annotation();
2149 AlignmentAnnotation annotation = aa[i];
2150 if (annotation.annotationId != null)
2152 annotationIds.put(annotation.annotationId, annotation);
2155 an.setId(annotation.annotationId);
2157 an.setVisible(annotation.visible);
2159 an.setDescription(annotation.description);
2161 if (annotation.sequenceRef != null)
2163 // 2.9 JAL-1781 xref on sequence id rather than name
2164 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
2166 if (annotation.groupRef != null)
2168 String groupIdr = groupRefs.get(annotation.groupRef);
2169 if (groupIdr == null)
2171 // make a locally unique String
2172 groupRefs.put(annotation.groupRef,
2173 groupIdr = ("" + System.currentTimeMillis()
2174 + annotation.groupRef.getName()
2175 + groupRefs.size()));
2177 an.setGroupRef(groupIdr.toString());
2180 // store all visualization attributes for annotation
2181 an.setGraphHeight(annotation.graphHeight);
2182 an.setCentreColLabels(annotation.centreColLabels);
2183 an.setScaleColLabels(annotation.scaleColLabel);
2184 an.setShowAllColLabels(annotation.showAllColLabels);
2185 an.setBelowAlignment(annotation.belowAlignment);
2187 if (annotation.graph > 0)
2190 an.setGraphType(annotation.graph);
2191 an.setGraphGroup(annotation.graphGroup);
2192 if (annotation.getThreshold() != null)
2194 ThresholdLine line = new ThresholdLine();
2195 line.setLabel(annotation.getThreshold().label);
2196 line.setValue(annotation.getThreshold().value);
2197 line.setColour(annotation.getThreshold().colour.getRGB());
2198 an.setThresholdLine(line);
2206 an.setLabel(annotation.label);
2208 if (annotation == av.getAlignmentQualityAnnot()
2209 || annotation == av.getAlignmentConservationAnnotation()
2210 || annotation == av.getAlignmentConsensusAnnotation()
2211 || annotation.autoCalculated)
2213 // new way of indicating autocalculated annotation -
2214 an.setAutoCalculated(annotation.autoCalculated);
2216 if (annotation.hasScore())
2218 an.setScore(annotation.getScore());
2221 if (annotation.getCalcId() != null)
2223 calcIdSet.add(annotation.getCalcId());
2224 an.setCalcId(annotation.getCalcId());
2226 if (annotation.hasProperties())
2228 for (String pr : annotation.getProperties())
2230 jalview.xml.binding.jalview.Annotation.Property prop = new jalview.xml.binding.jalview.Annotation.Property();
2232 prop.setValue(annotation.getProperty(pr));
2233 // an.addProperty(prop);
2234 an.getProperty().add(prop);
2238 AnnotationElement ae;
2239 if (annotation.annotations != null)
2241 an.setScoreOnly(false);
2242 for (int a = 0; a < annotation.annotations.length; a++)
2244 if ((annotation == null) || (annotation.annotations[a] == null))
2249 ae = new AnnotationElement();
2250 if (annotation.annotations[a].description != null)
2252 ae.setDescription(annotation.annotations[a].description);
2254 if (annotation.annotations[a].displayCharacter != null)
2256 ae.setDisplayCharacter(
2257 annotation.annotations[a].displayCharacter);
2260 if (!Float.isNaN(annotation.annotations[a].value))
2262 ae.setValue(annotation.annotations[a].value);
2266 if (annotation.annotations[a].secondaryStructure > ' ')
2268 ae.setSecondaryStructure(
2269 annotation.annotations[a].secondaryStructure + "");
2272 if (annotation.annotations[a].colour != null
2273 && annotation.annotations[a].colour != java.awt.Color.black)
2275 ae.setColour(annotation.annotations[a].colour.getRGB());
2278 // an.addAnnotationElement(ae);
2279 an.getAnnotationElement().add(ae);
2280 if (annotation.autoCalculated)
2282 // only write one non-null entry into the annotation row -
2283 // sufficient to get the visualization attributes necessary to
2291 an.setScoreOnly(true);
2293 if (!storeDS || (storeDS && !annotation.autoCalculated))
2295 // skip autocalculated annotation - these are only provided for
2297 // vamsasSet.addAnnotation(an);
2298 vamsasSet.getAnnotation().add(an);
2304 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
2306 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
2307 if (settings != null)
2309 CalcIdParam vCalcIdParam = new CalcIdParam();
2310 vCalcIdParam.setCalcId(calcId);
2311 // vCalcIdParam.addServiceURL(settings.getServiceURI());
2312 vCalcIdParam.getServiceURL().add(settings.getServiceURI());
2313 // generic URI allowing a third party to resolve another instance of the
2314 // service used for this calculation
2315 for (String url : settings.getServiceURLs())
2317 // vCalcIdParam.addServiceURL(urls);
2318 vCalcIdParam.getServiceURL().add(url);
2320 vCalcIdParam.setVersion("1.0");
2321 if (settings.getPreset() != null)
2323 WsParamSetI setting = settings.getPreset();
2324 vCalcIdParam.setName(setting.getName());
2325 vCalcIdParam.setDescription(setting.getDescription());
2329 vCalcIdParam.setName("");
2330 vCalcIdParam.setDescription("Last used parameters");
2332 // need to be able to recover 1) settings 2) user-defined presets or
2333 // recreate settings from preset 3) predefined settings provided by
2334 // service - or settings that can be transferred (or discarded)
2335 vCalcIdParam.setParameters(
2336 settings.getWsParamFile().replace("\n", "|\\n|"));
2337 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
2338 // todo - decide if updateImmediately is needed for any projects.
2340 return vCalcIdParam;
2345 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
2348 if (calcIdParam.getVersion().equals("1.0"))
2350 final String[] calcIds = calcIdParam.getServiceURL().toArray(new String[0]);
2351 Jws2Instance service = Jws2Discoverer.getDiscoverer()
2352 .getPreferredServiceFor(calcIds);
2353 if (service != null)
2355 WsParamSetI parmSet = null;
2358 parmSet = service.getParamStore().parseServiceParameterFile(
2359 calcIdParam.getName(), calcIdParam.getDescription(),
2361 calcIdParam.getParameters().replace("|\\n|", "\n"));
2362 } catch (IOException x)
2364 warn("Couldn't parse parameter data for "
2365 + calcIdParam.getCalcId(), x);
2368 List<ArgumentI> argList = null;
2369 if (calcIdParam.getName().length() > 0)
2371 parmSet = service.getParamStore()
2372 .getPreset(calcIdParam.getName());
2373 if (parmSet != null)
2375 // TODO : check we have a good match with settings in AACon -
2376 // otherwise we'll need to create a new preset
2381 argList = parmSet.getArguments();
2384 AAConSettings settings = new AAConSettings(
2385 calcIdParam.isAutoUpdate(), service, parmSet, argList);
2386 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
2387 calcIdParam.isNeedsUpdate());
2392 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
2396 throw new Error(MessageManager.formatMessage(
2397 "error.unsupported_version_calcIdparam", new Object[]
2398 { calcIdParam.toString() }));
2402 * External mapping between jalview objects and objects yielding a valid and
2403 * unique object ID string. This is null for normal Jalview project IO, but
2404 * non-null when a jalview project is being read or written as part of a
2407 IdentityHashMap jv2vobj = null;
2410 * Construct a unique ID for jvobj using either existing bindings or if none
2411 * exist, the result of the hashcode call for the object.
2414 * jalview data object
2415 * @return unique ID for referring to jvobj
2417 private String makeHashCode(Object jvobj, String altCode)
2419 if (jv2vobj != null)
2421 Object id = jv2vobj.get(jvobj);
2424 return id.toString();
2426 // check string ID mappings
2427 if (jvids2vobj != null && jvobj instanceof String)
2429 id = jvids2vobj.get(jvobj);
2433 return id.toString();
2435 // give up and warn that something has gone wrong
2436 warn("Cannot find ID for object in external mapping : " + jvobj);
2442 * return local jalview object mapped to ID, if it exists
2446 * @return null or object bound to idcode
2448 private Object retrieveExistingObj(String idcode)
2450 if (idcode != null && vobj2jv != null)
2452 return vobj2jv.get(idcode);
2458 * binding from ID strings from external mapping table to jalview data model
2461 private Hashtable vobj2jv;
2463 private Sequence createVamsasSequence(String id, SequenceI jds)
2465 return createVamsasSequence(true, id, jds, null);
2468 private Sequence createVamsasSequence(boolean recurse, String id,
2469 SequenceI jds, SequenceI parentseq)
2471 Sequence vamsasSeq = new Sequence();
2472 vamsasSeq.setId(id);
2473 vamsasSeq.setName(jds.getName());
2474 vamsasSeq.setSequence(jds.getSequenceAsString());
2475 vamsasSeq.setDescription(jds.getDescription());
2476 jalview.datamodel.DBRefEntry[] dbrefs = null;
2477 if (jds.getDatasetSequence() != null)
2479 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
2483 // seqId==dsseqid so we can tell which sequences really are
2484 // dataset sequences only
2485 vamsasSeq.setDsseqid(id);
2486 dbrefs = jds.getDBRefs();
2487 if (parentseq == null)
2494 for (int d = 0; d < dbrefs.length; d++)
2496 DBRef dbref = new DBRef();
2497 dbref.setSource(dbrefs[d].getSource());
2498 dbref.setVersion(dbrefs[d].getVersion());
2499 dbref.setAccessionId(dbrefs[d].getAccessionId());
2500 if (dbrefs[d].hasMap())
2502 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
2504 dbref.setMapping(mp);
2506 // vamsasSeq.addDBRef(dbref);
2507 vamsasSeq.getDBRef().add(dbref);
2513 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
2514 SequenceI parentseq, SequenceI jds, boolean recurse)
2517 if (jmp.getMap() != null)
2521 jalview.util.MapList mlst = jmp.getMap();
2522 List<int[]> r = mlst.getFromRanges();
2523 for (int[] range : r)
2525 MapListFrom mfrom = new MapListFrom();
2526 mfrom.setStart(range[0]);
2527 mfrom.setEnd(range[1]);
2528 // mp.addMapListFrom(mfrom);
2529 mp.getMapListFrom().add(mfrom);
2531 r = mlst.getToRanges();
2532 for (int[] range : r)
2534 MapListTo mto = new MapListTo();
2535 mto.setStart(range[0]);
2536 mto.setEnd(range[1]);
2537 // mp.addMapListTo(mto);
2538 mp.getMapListTo().add(mto);
2540 mp.setMapFromUnit(BigInteger.valueOf(mlst.getFromRatio()));
2541 mp.setMapToUnit(BigInteger.valueOf(mlst.getToRatio()));
2542 if (jmp.getTo() != null)
2544 // MappingChoice mpc = new MappingChoice();
2546 // check/create ID for the sequence referenced by getTo()
2549 SequenceI ps = null;
2550 if (parentseq != jmp.getTo()
2551 && parentseq.getDatasetSequence() != jmp.getTo())
2553 // chaining dbref rather than a handshaking one
2554 jmpid = seqHash(ps = jmp.getTo());
2558 jmpid = seqHash(ps = parentseq);
2560 // mpc.setDseqFor(jmpid);
2561 mp.setDseqFor(jmpid);
2562 if (!seqRefIds.containsKey(jmpid))
2564 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2565 seqRefIds.put(jmpid, ps);
2569 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2572 // mp.setMappingChoice(mpc);
2578 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2579 List<UserColourScheme> userColours, JalviewModel jm)
2582 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2583 boolean newucs = false;
2584 if (!userColours.contains(ucs))
2586 userColours.add(ucs);
2589 id = "ucs" + userColours.indexOf(ucs);
2592 // actually create the scheme's entry in the XML model
2593 java.awt.Color[] colours = ucs.getColours();
2594 UserColours uc = new UserColours();
2595 // UserColourScheme jbucs = new UserColourScheme();
2596 JalviewUserColours jbucs = new JalviewUserColours();
2598 for (int i = 0; i < colours.length; i++)
2600 Colour col = new Colour();
2601 col.setName(ResidueProperties.aa[i]);
2602 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2603 // jbucs.addColour(col);
2604 jbucs.getColour().add(col);
2606 if (ucs.getLowerCaseColours() != null)
2608 colours = ucs.getLowerCaseColours();
2609 for (int i = 0; i < colours.length; i++)
2611 Colour col = new Colour();
2612 col.setName(ResidueProperties.aa[i].toLowerCase());
2613 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2614 // jbucs.addColour(col);
2615 jbucs.getColour().add(col);
2620 uc.setUserColourScheme(jbucs);
2621 // jm.addUserColours(uc);
2622 jm.getUserColours().add(uc);
2628 jalview.schemes.UserColourScheme getUserColourScheme(
2629 JalviewModel jm, String id)
2631 List<UserColours> uc = jm.getUserColours();
2632 UserColours colours = null;
2634 for (int i = 0; i < uc.length; i++)
2636 if (uc[i].getId().equals(id))
2643 for (UserColours c : uc)
2645 if (c.getId().equals(id))
2652 java.awt.Color[] newColours = new java.awt.Color[24];
2654 for (int i = 0; i < 24; i++)
2656 newColours[i] = new java.awt.Color(Integer.parseInt(
2657 // colours.getUserColourScheme().getColour(i).getRGB(), 16));
2658 colours.getUserColourScheme().getColour().get(i).getRGB(),
2662 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2665 if (colours.getUserColourScheme().getColour().size()/*Count()*/ > 24)
2667 newColours = new java.awt.Color[23];
2668 for (int i = 0; i < 23; i++)
2670 newColours[i] = new java.awt.Color(Integer.parseInt(
2671 colours.getUserColourScheme().getColour().get(i + 24)
2675 ucs.setLowerCaseColours(newColours);
2682 * contains last error message (if any) encountered by XML loader.
2684 String errorMessage = null;
2687 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2688 * exceptions are raised during project XML parsing
2690 public boolean attemptversion1parse = false;
2693 * Load a jalview project archive from a jar file
2696 * - HTTP URL or filename
2698 public AlignFrame loadJalviewAlign(final String file)
2701 jalview.gui.AlignFrame af = null;
2705 // create list to store references for any new Jmol viewers created
2706 newStructureViewers = new Vector<>();
2707 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2708 // Workaround is to make sure caller implements the JarInputStreamProvider
2710 // so we can re-open the jar input stream for each entry.
2712 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2713 af = loadJalviewAlign(jprovider);
2716 af.setMenusForViewport();
2718 } catch (MalformedURLException e)
2720 errorMessage = "Invalid URL format for '" + file + "'";
2726 SwingUtilities.invokeAndWait(new Runnable()
2731 setLoadingFinishedForNewStructureViewers();
2734 } catch (Exception x)
2736 System.err.println("Error loading alignment: " + x.getMessage());
2742 private jarInputStreamProvider createjarInputStreamProvider(
2743 final String file) throws MalformedURLException
2746 errorMessage = null;
2747 uniqueSetSuffix = null;
2749 viewportsAdded.clear();
2750 frefedSequence = null;
2752 if (file.startsWith("http://"))
2754 url = new URL(file);
2756 final URL _url = url;
2757 return new jarInputStreamProvider()
2761 public JarInputStream getJarInputStream() throws IOException
2765 return new JarInputStream(_url.openStream());
2769 return new JarInputStream(new FileInputStream(file));
2774 public String getFilename()
2782 * Recover jalview session from a jalview project archive. Caller may
2783 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2784 * themselves. Any null fields will be initialised with default values,
2785 * non-null fields are left alone.
2790 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2792 errorMessage = null;
2793 if (uniqueSetSuffix == null)
2795 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2797 if (seqRefIds == null)
2801 AlignFrame af = null, _af = null;
2802 IdentityHashMap<AlignmentI, AlignmentI> importedDatasets = new IdentityHashMap<>();
2803 Map<String, AlignFrame> gatherToThisFrame = new HashMap<>();
2804 final String file = jprovider.getFilename();
2807 JarInputStream jin = null;
2808 JarEntry jarentry = null;
2813 jin = jprovider.getJarInputStream();
2814 for (int i = 0; i < entryCount; i++)
2816 jarentry = jin.getNextJarEntry();
2819 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2821 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2822 // JalviewModel object = new JalviewModel();
2824 JAXBContext jc = JAXBContext
2825 .newInstance("jalview.xml.binding.jalview");
2826 XMLStreamReader streamReader = XMLInputFactory.newInstance()
2827 .createXMLStreamReader(jin);
2828 javax.xml.bind.Unmarshaller um = jc.createUnmarshaller();
2829 JAXBElement<JalviewModel> jbe = um
2830 .unmarshal(streamReader, JalviewModel.class);
2831 JalviewModel object = jbe.getValue();
2834 Unmarshaller unmar = new Unmarshaller(object);
2835 unmar.setValidation(false);
2836 object = (JalviewModel) unmar.unmarshal(in);
2838 if (true) // !skipViewport(object))
2840 _af = loadFromObject(object, file, true, jprovider);
2841 if (_af != null && object.getViewport().size() > 0)
2842 // getJalviewModelSequence().getViewportCount() > 0)
2846 // store a reference to the first view
2849 if (_af.getViewport().isGatherViewsHere())
2851 // if this is a gathered view, keep its reference since
2852 // after gathering views, only this frame will remain
2854 gatherToThisFrame.put(_af.getViewport().getSequenceSetId(),
2857 // Save dataset to register mappings once all resolved
2858 importedDatasets.put(
2859 af.getViewport().getAlignment().getDataset(),
2860 af.getViewport().getAlignment().getDataset());
2865 else if (jarentry != null)
2867 // Some other file here.
2870 } while (jarentry != null);
2871 resolveFrefedSequences();
2872 } catch (IOException ex)
2874 ex.printStackTrace();
2875 errorMessage = "Couldn't locate Jalview XML file : " + file;
2877 "Exception whilst loading jalview XML file : " + ex + "\n");
2878 } catch (Exception ex)
2880 System.err.println("Parsing as Jalview Version 2 file failed.");
2881 ex.printStackTrace(System.err);
2882 if (attemptversion1parse)
2884 // used to attempt to parse as V1 castor-generated xml
2886 if (Desktop.instance != null)
2888 Desktop.instance.stopLoading();
2892 System.out.println("Successfully loaded archive file");
2895 ex.printStackTrace();
2898 "Exception whilst loading jalview XML file : " + ex + "\n");
2899 } catch (OutOfMemoryError e)
2901 // Don't use the OOM Window here
2902 errorMessage = "Out of memory loading jalview XML file";
2903 System.err.println("Out of memory whilst loading jalview XML file");
2904 e.printStackTrace();
2908 * Regather multiple views (with the same sequence set id) to the frame (if
2909 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2910 * views instead of separate frames. Note this doesn't restore a state where
2911 * some expanded views in turn have tabbed views - the last "first tab" read
2912 * in will play the role of gatherer for all.
2914 for (AlignFrame fr : gatherToThisFrame.values())
2916 Desktop.instance.gatherViews(fr);
2919 restoreSplitFrames();
2920 for (AlignmentI ds : importedDatasets.keySet())
2922 if (ds.getCodonFrames() != null)
2924 StructureSelectionManager
2925 .getStructureSelectionManager(Desktop.instance)
2926 .registerMappings(ds.getCodonFrames());
2929 if (errorMessage != null)
2934 if (Desktop.instance != null)
2936 Desktop.instance.stopLoading();
2943 * Try to reconstruct and display SplitFrame windows, where each contains
2944 * complementary dna and protein alignments. Done by pairing up AlignFrame
2945 * objects (created earlier) which have complementary viewport ids associated.
2947 protected void restoreSplitFrames()
2949 List<SplitFrame> gatherTo = new ArrayList<>();
2950 List<AlignFrame> addedToSplitFrames = new ArrayList<>();
2951 Map<String, AlignFrame> dna = new HashMap<>();
2954 * Identify the DNA alignments
2956 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2959 AlignFrame af = candidate.getValue();
2960 if (af.getViewport().getAlignment().isNucleotide())
2962 dna.put(candidate.getKey().getId(), af);
2967 * Try to match up the protein complements
2969 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2972 AlignFrame af = candidate.getValue();
2973 if (!af.getViewport().getAlignment().isNucleotide())
2975 String complementId = candidate.getKey().getComplementId();
2976 // only non-null complements should be in the Map
2977 if (complementId != null && dna.containsKey(complementId))
2979 final AlignFrame dnaFrame = dna.get(complementId);
2980 SplitFrame sf = createSplitFrame(dnaFrame, af);
2981 addedToSplitFrames.add(dnaFrame);
2982 addedToSplitFrames.add(af);
2983 dnaFrame.setMenusForViewport();
2984 af.setMenusForViewport();
2985 if (af.getViewport().isGatherViewsHere())
2994 * Open any that we failed to pair up (which shouldn't happen!) as
2995 * standalone AlignFrame's.
2997 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
3000 AlignFrame af = candidate.getValue();
3001 if (!addedToSplitFrames.contains(af))
3003 Viewport view = candidate.getKey();
3004 Desktop.addInternalFrame(af, view.getTitle(),
3005 safeInt(view.getWidth()), safeInt(view.getHeight()));
3006 af.setMenusForViewport();
3007 System.err.println("Failed to restore view " + view.getTitle()
3008 + " to split frame");
3013 * Gather back into tabbed views as flagged.
3015 for (SplitFrame sf : gatherTo)
3017 Desktop.instance.gatherViews(sf);
3020 splitFrameCandidates.clear();
3024 * Construct and display one SplitFrame holding DNA and protein alignments.
3027 * @param proteinFrame
3030 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
3031 AlignFrame proteinFrame)
3033 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
3034 String title = MessageManager.getString("label.linked_view_title");
3035 int width = (int) dnaFrame.getBounds().getWidth();
3036 int height = (int) (dnaFrame.getBounds().getHeight()
3037 + proteinFrame.getBounds().getHeight() + 50);
3040 * SplitFrame location is saved to both enclosed frames
3042 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
3043 Desktop.addInternalFrame(splitFrame, title, width, height);
3046 * And compute cDNA consensus (couldn't do earlier with consensus as
3047 * mappings were not yet present)
3049 proteinFrame.getViewport().alignmentChanged(proteinFrame.alignPanel);
3055 * check errorMessage for a valid error message and raise an error box in the
3056 * GUI or write the current errorMessage to stderr and then clear the error
3059 protected void reportErrors()
3061 reportErrors(false);
3064 protected void reportErrors(final boolean saving)
3066 if (errorMessage != null)
3068 final String finalErrorMessage = errorMessage;
3071 javax.swing.SwingUtilities.invokeLater(new Runnable()
3076 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
3078 "Error " + (saving ? "saving" : "loading")
3080 JvOptionPane.WARNING_MESSAGE);
3086 System.err.println("Problem loading Jalview file: " + errorMessage);
3089 errorMessage = null;
3092 Map<String, String> alreadyLoadedPDB = new HashMap<>();
3095 * when set, local views will be updated from view stored in JalviewXML
3096 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
3097 * sync if this is set to true.
3099 private final boolean updateLocalViews = false;
3102 * Returns the path to a temporary file holding the PDB file for the given PDB
3103 * id. The first time of asking, searches for a file of that name in the
3104 * Jalview project jar, and copies it to a new temporary file. Any repeat
3105 * requests just return the path to the file previously created.
3111 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId,
3114 if (alreadyLoadedPDB.containsKey(pdbId))
3116 return alreadyLoadedPDB.get(pdbId).toString();
3119 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb",
3121 if (tempFile != null)
3123 alreadyLoadedPDB.put(pdbId, tempFile);
3129 * Copies the jar entry of given name to a new temporary file and returns the
3130 * path to the file, or null if the entry is not found.
3133 * @param jarEntryName
3135 * a prefix for the temporary file name, must be at least three
3138 * null or original file - so new file can be given the same suffix
3142 protected String copyJarEntry(jarInputStreamProvider jprovider,
3143 String jarEntryName, String prefix, String origFile)
3145 BufferedReader in = null;
3146 PrintWriter out = null;
3147 String suffix = ".tmp";
3148 if (origFile == null)
3150 origFile = jarEntryName;
3152 int sfpos = origFile.lastIndexOf(".");
3153 if (sfpos > -1 && sfpos < (origFile.length() - 3))
3155 suffix = "." + origFile.substring(sfpos + 1);
3159 JarInputStream jin = jprovider.getJarInputStream();
3161 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
3162 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
3163 * FileInputStream(jprovider)); }
3166 JarEntry entry = null;
3169 entry = jin.getNextJarEntry();
3170 } while (entry != null && !entry.getName().equals(jarEntryName));
3173 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
3174 File outFile = File.createTempFile(prefix, suffix);
3175 outFile.deleteOnExit();
3176 out = new PrintWriter(new FileOutputStream(outFile));
3179 while ((data = in.readLine()) != null)
3184 String t = outFile.getAbsolutePath();
3189 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
3191 } catch (Exception ex)
3193 ex.printStackTrace();
3201 } catch (IOException e)
3215 private class JvAnnotRow
3217 public JvAnnotRow(int i, AlignmentAnnotation jaa)
3224 * persisted version of annotation row from which to take vis properties
3226 public jalview.datamodel.AlignmentAnnotation template;
3229 * original position of the annotation row in the alignment
3235 * Load alignment frame from jalview XML DOM object
3237 * @param jalviewModel
3240 * filename source string
3241 * @param loadTreesAndStructures
3242 * when false only create Viewport
3244 * data source provider
3245 * @return alignment frame created from view stored in DOM
3247 AlignFrame loadFromObject(JalviewModel jalviewModel, String file,
3248 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
3250 SequenceSet vamsasSet = jalviewModel.getVamsasModel().getSequenceSet().get(0);
3251 List<Sequence> vamsasSeqs = vamsasSet.getSequence();
3253 // JalviewModelSequence jms = object.getJalviewModelSequence();
3255 // Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
3257 Viewport view = (jalviewModel.getViewport().size() > 0)
3258 ? jalviewModel.getViewport().get(0)
3261 // ////////////////////////////////
3262 // INITIALISE ALIGNMENT SEQUENCESETID AND VIEWID
3265 // If we just load in the same jar file again, the sequenceSetId
3266 // will be the same, and we end up with multiple references
3267 // to the same sequenceSet. We must modify this id on load
3268 // so that each load of the file gives a unique id
3271 * used to resolve correct alignment dataset for alignments with multiple
3274 String uniqueSeqSetId = null;
3275 String viewId = null;
3278 uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3279 viewId = (view.getId() == null ? null
3280 : view.getId() + uniqueSetSuffix);
3283 // ////////////////////////////////
3286 List<SequenceI> hiddenSeqs = null;
3288 List<SequenceI> tmpseqs = new ArrayList<>();
3290 boolean multipleView = false;
3291 SequenceI referenceseqForView = null;
3292 // JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
3293 List<JSeq> jseqs = jalviewModel.getJSeq();
3294 int vi = 0; // counter in vamsasSeq array
3295 for (int i = 0; i < jseqs.size(); i++)
3297 JSeq jseq = jseqs.get(i);
3298 String seqId = jseq.getId();
3300 SequenceI tmpSeq = seqRefIds.get(seqId);
3303 if (!incompleteSeqs.containsKey(seqId))
3305 // may not need this check, but keep it for at least 2.9,1 release
3306 if (tmpSeq.getStart() != jseq.getStart()
3307 || tmpSeq.getEnd() != jseq.getEnd())
3310 "Warning JAL-2154 regression: updating start/end for sequence "
3311 + tmpSeq.toString() + " to " + jseq);
3316 incompleteSeqs.remove(seqId);
3318 if (vamsasSeqs.size() > vi
3319 && vamsasSeqs.get(vi).getId().equals(seqId))
3321 // most likely we are reading a dataset XML document so
3322 // update from vamsasSeq section of XML for this sequence
3323 tmpSeq.setName(vamsasSeqs.get(vi).getName());
3324 tmpSeq.setDescription(vamsasSeqs.get(vi).getDescription());
3325 tmpSeq.setSequence(vamsasSeqs.get(vi).getSequence());
3330 // reading multiple views, so vamsasSeq set is a subset of JSeq
3331 multipleView = true;
3333 tmpSeq.setStart(jseq.getStart());
3334 tmpSeq.setEnd(jseq.getEnd());
3335 tmpseqs.add(tmpSeq);
3339 Sequence vamsasSeq = vamsasSeqs.get(vi);
3340 tmpSeq = new jalview.datamodel.Sequence(vamsasSeq.getName(),
3341 vamsasSeq.getSequence());
3342 tmpSeq.setDescription(vamsasSeq.getDescription());
3343 tmpSeq.setStart(jseq.getStart());
3344 tmpSeq.setEnd(jseq.getEnd());
3345 tmpSeq.setVamsasId(uniqueSetSuffix + seqId);
3346 seqRefIds.put(vamsasSeq.getId(), tmpSeq);
3347 tmpseqs.add(tmpSeq);
3351 if (safeBoolean(jseq.isViewreference()))
3353 referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
3356 if (jseq.isHidden() != null && jseq.isHidden().booleanValue())
3358 if (hiddenSeqs == null)
3360 hiddenSeqs = new ArrayList<>();
3363 hiddenSeqs.add(tmpSeq);
3368 // Create the alignment object from the sequence set
3369 // ///////////////////////////////
3370 SequenceI[] orderedSeqs = tmpseqs
3371 .toArray(new SequenceI[tmpseqs.size()]);
3373 AlignmentI al = null;
3374 // so we must create or recover the dataset alignment before going further
3375 // ///////////////////////////////
3376 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
3378 // older jalview projects do not have a dataset - so creat alignment and
3380 al = new Alignment(orderedSeqs);
3381 al.setDataset(null);
3385 boolean isdsal = jalviewModel.getViewport().isEmpty();
3388 // we are importing a dataset record, so
3389 // recover reference to an alignment already materialsed as dataset
3390 al = getDatasetFor(vamsasSet.getDatasetId());
3394 // materialse the alignment
3395 al = new Alignment(orderedSeqs);
3399 addDatasetRef(vamsasSet.getDatasetId(), al);
3402 // finally, verify all data in vamsasSet is actually present in al
3403 // passing on flag indicating if it is actually a stored dataset
3404 recoverDatasetFor(vamsasSet, al, isdsal, uniqueSeqSetId);
3407 if (referenceseqForView != null)
3409 al.setSeqrep(referenceseqForView);
3411 // / Add the alignment properties
3412 for (int i = 0; i < vamsasSet.getSequenceSetProperties().size(); i++)
3414 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties()
3416 al.setProperty(ssp.getKey(), ssp.getValue());
3419 // ///////////////////////////////
3421 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
3424 // load sequence features, database references and any associated PDB
3425 // structures for the alignment
3427 // prior to 2.10, this part would only be executed the first time a
3428 // sequence was encountered, but not afterwards.
3429 // now, for 2.10 projects, this is also done if the xml doc includes
3430 // dataset sequences not actually present in any particular view.
3432 for (int i = 0; i < vamsasSeqs.size(); i++)
3434 JSeq jseq = jseqs.get(i);
3435 if (jseq.getFeatures().size() > 0)
3437 List<Feature> features = jseq.getFeatures();
3438 for (int f = 0; f < features.size(); f++)
3440 Feature feat = features.get(f);
3441 SequenceFeature sf = new SequenceFeature(feat.getType(),
3442 feat.getDescription(), feat.getBegin(), feat.getEnd(),
3443 safeFloat(feat.getScore()), feat.getFeatureGroup());
3444 sf.setStatus(feat.getStatus());
3447 * load any feature attributes - include map-valued attributes
3449 Map<String, Map<String, String>> mapAttributes = new HashMap<>();
3450 for (int od = 0; od < feat.getOtherData().size(); od++)
3452 OtherData keyValue = feat.getOtherData().get(od);
3453 String attributeName = keyValue.getKey();
3454 String attributeValue = keyValue.getValue();
3455 if (attributeName.startsWith("LINK"))
3457 sf.addLink(attributeValue);
3461 String subAttribute = keyValue.getKey2();
3462 if (subAttribute == null)
3464 // simple string-valued attribute
3465 sf.setValue(attributeName, attributeValue);
3469 // attribute 'key' has sub-attribute 'key2'
3470 if (!mapAttributes.containsKey(attributeName))
3472 mapAttributes.put(attributeName, new HashMap<>());
3474 mapAttributes.get(attributeName).put(subAttribute,
3479 for (Entry<String, Map<String, String>> mapAttribute : mapAttributes
3482 sf.setValue(mapAttribute.getKey(), mapAttribute.getValue());
3485 // adds feature to datasequence's feature set (since Jalview 2.10)
3486 al.getSequenceAt(i).addSequenceFeature(sf);
3489 if (vamsasSeqs.get(i).getDBRef().size() > 0)
3491 // adds dbrefs to datasequence's set (since Jalview 2.10)
3493 al.getSequenceAt(i).getDatasetSequence() == null
3494 ? al.getSequenceAt(i)
3495 : al.getSequenceAt(i).getDatasetSequence(),
3498 if (jseq.getPdbids().size() > 0)
3500 List<Pdbids> ids = jseq.getPdbids();
3501 for (int p = 0; p < ids.size(); p++)
3503 Pdbids pdbid = ids.get(p);
3504 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
3505 entry.setId(pdbid.getId());
3506 if (pdbid.getType() != null)
3508 if (PDBEntry.Type.getType(pdbid.getType()) != null)
3510 entry.setType(PDBEntry.Type.getType(pdbid.getType()));
3514 entry.setType(PDBEntry.Type.FILE);
3517 // jprovider is null when executing 'New View'
3518 if (pdbid.getFile() != null && jprovider != null)
3520 if (!pdbloaded.containsKey(pdbid.getFile()))
3522 entry.setFile(loadPDBFile(jprovider, pdbid.getId(),
3527 entry.setFile(pdbloaded.get(pdbid.getId()).toString());
3531 if (pdbid.getPdbentryItem() != null)
3533 for (PdbentryItem item : pdbid.getPdbentryItem())
3535 for (Property pr : item.getProperty())
3537 entry.setProperty(pr.getName(), pr.getValue());
3542 for (Property prop : pdbid.getProperty())
3544 entry.setProperty(prop.getName(), prop.getValue());
3546 StructureSelectionManager
3547 .getStructureSelectionManager(Desktop.instance)
3548 .registerPDBEntry(entry);
3549 // adds PDBEntry to datasequence's set (since Jalview 2.10)
3550 if (al.getSequenceAt(i).getDatasetSequence() != null)
3552 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
3556 al.getSequenceAt(i).addPDBId(entry);
3561 } // end !multipleview
3563 // ///////////////////////////////
3564 // LOAD SEQUENCE MAPPINGS
3566 if (vamsasSet.getAlcodonFrame().size() > 0)
3568 // TODO Potentially this should only be done once for all views of an
3570 List<AlcodonFrame> alc = vamsasSet.getAlcodonFrame();
3571 for (int i = 0; i < alc.size(); i++)
3573 AlignedCodonFrame cf = new AlignedCodonFrame();
3574 if (alc.get(i).getAlcodMap().size() > 0)
3576 List<AlcodMap> maps = alc.get(i).getAlcodMap();
3577 for (int m = 0; m < maps.size(); m++)
3579 AlcodMap map = maps.get(m);
3580 SequenceI dnaseq = seqRefIds.get(map.getDnasq());
3582 jalview.datamodel.Mapping mapping = null;
3583 // attach to dna sequence reference.
3584 if (map.getMapping() != null)
3586 mapping = addMapping(map.getMapping());
3587 if (dnaseq != null && mapping.getTo() != null)
3589 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
3595 newAlcodMapRef(map.getDnasq(), cf, mapping));
3599 al.addCodonFrame(cf);
3604 // ////////////////////////////////
3606 List<JvAnnotRow> autoAlan = new ArrayList<>();
3609 * store any annotations which forward reference a group's ID
3611 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<>();
3613 if (vamsasSet.getAnnotation().size()/*Count()*/ > 0)
3615 List<Annotation> an = vamsasSet.getAnnotation();
3617 for (int i = 0; i < an.size(); i++)
3619 Annotation annotation = an.get(i);
3622 * test if annotation is automatically calculated for this view only
3624 boolean autoForView = false;
3625 if (annotation.getLabel().equals("Quality")
3626 || annotation.getLabel().equals("Conservation")
3627 || annotation.getLabel().equals("Consensus"))
3629 // Kludge for pre 2.5 projects which lacked the autocalculated flag
3631 // JAXB has no has() test; schema defaults value to false
3632 // if (!annotation.hasAutoCalculated())
3634 // annotation.setAutoCalculated(true);
3637 if (autoForView || annotation.isAutoCalculated())
3639 // remove ID - we don't recover annotation from other views for
3640 // view-specific annotation
3641 annotation.setId(null);
3644 // set visibility for other annotation in this view
3645 String annotationId = annotation.getId();
3646 if (annotationId != null && annotationIds.containsKey(annotationId))
3648 AlignmentAnnotation jda = annotationIds.get(annotationId);
3649 // in principle Visible should always be true for annotation displayed
3650 // in multiple views
3651 if (annotation.isVisible() != null)
3653 jda.visible = annotation.isVisible();
3656 al.addAnnotation(jda);
3660 // Construct new annotation from model.
3661 List<AnnotationElement> ae = annotation.getAnnotationElement();
3662 jalview.datamodel.Annotation[] anot = null;
3663 java.awt.Color firstColour = null;
3665 if (!annotation.isScoreOnly())
3667 anot = new jalview.datamodel.Annotation[al.getWidth()];
3668 for (int aa = 0; aa < ae.size() && aa < anot.length; aa++)
3670 AnnotationElement annElement = ae.get(aa);
3671 anpos = annElement.getPosition();
3673 if (anpos >= anot.length)
3678 float value = safeFloat(annElement.getValue());
3679 anot[anpos] = new jalview.datamodel.Annotation(
3680 annElement.getDisplayCharacter(),
3681 annElement.getDescription(),
3682 (annElement.getSecondaryStructure() == null
3683 || annElement.getSecondaryStructure()
3687 .getSecondaryStructure()
3690 anot[anpos].colour = new Color(safeInt(annElement.getColour()));
3691 if (firstColour == null)
3693 firstColour = anot[anpos].colour;
3697 jalview.datamodel.AlignmentAnnotation jaa = null;
3699 if (annotation.isGraph())
3701 float llim = 0, hlim = 0;
3702 // if (autoForView || an[i].isAutoCalculated()) {
3705 jaa = new jalview.datamodel.AlignmentAnnotation(
3706 annotation.getLabel(), annotation.getDescription(), anot,
3707 llim, hlim, safeInt(annotation.getGraphType()));
3709 jaa.graphGroup = safeInt(annotation.getGraphGroup());
3710 jaa._linecolour = firstColour;
3711 if (annotation.getThresholdLine() != null)
3713 jaa.setThreshold(new jalview.datamodel.GraphLine(
3714 safeFloat(annotation.getThresholdLine().getValue()),
3715 annotation.getThresholdLine().getLabel(),
3716 new java.awt.Color(safeInt(
3717 annotation.getThresholdLine().getColour()))));
3719 if (autoForView || annotation.isAutoCalculated())
3721 // Hardwire the symbol display line to ensure that labels for
3722 // histograms are displayed
3728 jaa = new jalview.datamodel.AlignmentAnnotation(
3729 annotation.getLabel(), annotation.getDescription(), anot);
3730 jaa._linecolour = firstColour;
3732 // register new annotation
3733 if (annotation.getId() != null)
3735 annotationIds.put(annotation.getId(), jaa);
3736 jaa.annotationId = annotation.getId();
3738 // recover sequence association
3739 String sequenceRef = annotation.getSequenceRef();
3740 if (sequenceRef != null)
3742 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3743 SequenceI sequence = seqRefIds.get(sequenceRef);
3744 if (sequence == null)
3746 // in pre-2.9 projects sequence ref is to sequence name
3747 sequence = al.findName(sequenceRef);
3749 if (sequence != null)
3751 jaa.createSequenceMapping(sequence, 1, true);
3752 sequence.addAlignmentAnnotation(jaa);
3755 // and make a note of any group association
3756 if (annotation.getGroupRef() != null
3757 && annotation.getGroupRef().length() > 0)
3759 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3760 .get(annotation.getGroupRef());
3763 aal = new ArrayList<>();
3764 groupAnnotRefs.put(annotation.getGroupRef(), aal);
3769 if (annotation.getScore() != null)
3771 jaa.setScore(annotation.getScore().doubleValue());
3773 if (annotation.isVisible() != null)
3775 jaa.visible = annotation.isVisible().booleanValue();
3778 if (annotation.isCentreColLabels() != null)
3780 jaa.centreColLabels = annotation.isCentreColLabels()
3784 if (annotation.isScaleColLabels() != null)
3786 jaa.scaleColLabel = annotation.isScaleColLabels().booleanValue();
3788 if (annotation.isAutoCalculated())
3790 // newer files have an 'autoCalculated' flag and store calculation
3791 // state in viewport properties
3792 jaa.autoCalculated = true; // means annotation will be marked for
3793 // update at end of load.
3795 if (annotation.getGraphHeight() != null)
3797 jaa.graphHeight = annotation.getGraphHeight().intValue();
3799 jaa.belowAlignment = annotation.isBelowAlignment();
3800 jaa.setCalcId(annotation.getCalcId());
3801 if (annotation.getProperty().size() > 0)
3803 for (Annotation.Property prop : annotation
3806 jaa.setProperty(prop.getName(), prop.getValue());
3809 if (jaa.autoCalculated)
3811 autoAlan.add(new JvAnnotRow(i, jaa));
3814 // if (!autoForView)
3816 // add autocalculated group annotation and any user created annotation
3818 al.addAnnotation(jaa);
3822 // ///////////////////////
3824 // Create alignment markup and styles for this view
3825 if (jalviewModel.getJGroup().size() > 0)
3827 List<JGroup> groups = jalviewModel.getJGroup();
3828 boolean addAnnotSchemeGroup = false;
3829 for (int i = 0; i < groups.size(); i++)
3831 JGroup jGroup = groups.get(i);
3832 ColourSchemeI cs = null;
3833 if (jGroup.getColour() != null)
3835 if (jGroup.getColour().startsWith("ucs"))
3837 cs = getUserColourScheme(jalviewModel, jGroup.getColour());
3839 else if (jGroup.getColour().equals("AnnotationColourGradient")
3840 && jGroup.getAnnotationColours() != null)
3842 addAnnotSchemeGroup = true;
3846 cs = ColourSchemeProperty.getColourScheme(al,
3847 jGroup.getColour());
3850 int pidThreshold = safeInt(jGroup.getPidThreshold());
3852 Vector<SequenceI> seqs = new Vector<>();
3854 for (int s = 0; s < jGroup.getSeq().size(); s++)
3856 String seqId = jGroup.getSeq().get(s);
3857 SequenceI ts = seqRefIds.get(seqId);
3861 seqs.addElement(ts);
3865 if (seqs.size() < 1)
3870 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3871 safeBoolean(jGroup.isDisplayBoxes()),
3872 safeBoolean(jGroup.isDisplayText()),
3873 safeBoolean(jGroup.isColourText()),
3874 safeInt(jGroup.getStart()), safeInt(jGroup.getEnd()));
3875 sg.getGroupColourScheme().setThreshold(pidThreshold, true);
3876 sg.getGroupColourScheme()
3877 .setConservationInc(safeInt(jGroup.getConsThreshold()));
3878 sg.setOutlineColour(new Color(safeInt(jGroup.getOutlineColour())));
3880 sg.textColour = new Color(safeInt(jGroup.getTextCol1()));
3881 sg.textColour2 = new Color(safeInt(jGroup.getTextCol2()));
3882 sg.setShowNonconserved(safeBoolean(jGroup.isShowUnconserved()));
3883 sg.thresholdTextColour = safeInt(jGroup.getTextColThreshold());
3884 // attributes with a default in the schema are never null
3885 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3886 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3887 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3888 sg.setIgnoreGapsConsensus(jGroup.isIgnoreGapsinConsensus());
3889 if (jGroup.getConsThreshold() != null
3890 && jGroup.getConsThreshold().intValue() != 0)
3892 Conservation c = new Conservation("All", sg.getSequences(null), 0,
3895 c.verdict(false, 25);
3896 sg.cs.setConservation(c);
3899 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3901 // re-instate unique group/annotation row reference
3902 List<AlignmentAnnotation> jaal = groupAnnotRefs
3903 .get(jGroup.getId());
3906 for (AlignmentAnnotation jaa : jaal)
3909 if (jaa.autoCalculated)
3911 // match up and try to set group autocalc alignment row for this
3913 if (jaa.label.startsWith("Consensus for "))
3915 sg.setConsensus(jaa);
3917 // match up and try to set group autocalc alignment row for this
3919 if (jaa.label.startsWith("Conservation for "))
3921 sg.setConservationRow(jaa);
3928 if (addAnnotSchemeGroup)
3930 // reconstruct the annotation colourscheme
3931 sg.setColourScheme(constructAnnotationColour(
3932 jGroup.getAnnotationColours(), null, al, jalviewModel, false));
3938 // only dataset in this model, so just return.
3941 // ///////////////////////////////
3944 AlignFrame af = null;
3945 AlignViewport av = null;
3946 // now check to see if we really need to create a new viewport.
3947 if (multipleView && viewportsAdded.size() == 0)
3949 // We recovered an alignment for which a viewport already exists.
3950 // TODO: fix up any settings necessary for overlaying stored state onto
3951 // state recovered from another document. (may not be necessary).
3952 // we may need a binding from a viewport in memory to one recovered from
3954 // and then recover its containing af to allow the settings to be applied.
3955 // TODO: fix for vamsas demo
3957 "About to recover a viewport for existing alignment: Sequence set ID is "
3959 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3960 if (seqsetobj != null)
3962 if (seqsetobj instanceof String)
3964 uniqueSeqSetId = (String) seqsetobj;
3966 "Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
3972 "Warning : Collision between sequence set ID string and existing jalview object mapping.");
3978 * indicate that annotation colours are applied across all groups (pre
3979 * Jalview 2.8.1 behaviour)
3981 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan("2.8.1",
3982 jalviewModel.getVersion());
3984 AlignmentPanel ap = null;
3985 boolean isnewview = true;
3988 // Check to see if this alignment already has a view id == viewId
3989 jalview.gui.AlignmentPanel views[] = Desktop
3990 .getAlignmentPanels(uniqueSeqSetId);
3991 if (views != null && views.length > 0)
3993 for (int v = 0; v < views.length; v++)
3995 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
3997 // recover the existing alignpanel, alignframe, viewport
3998 af = views[v].alignFrame;
4001 // TODO: could even skip resetting view settings if we don't want to
4002 // change the local settings from other jalview processes
4011 af = loadViewport(file, jseqs, hiddenSeqs, al, jalviewModel, view,
4012 uniqueSeqSetId, viewId, autoAlan);
4013 av = af.getViewport();
4018 * Load any trees, PDB structures and viewers
4020 * Not done if flag is false (when this method is used for New View)
4022 if (loadTreesAndStructures)
4024 loadTrees(jalviewModel, view, af, av, ap);
4025 loadPCAViewers(jalviewModel, ap);
4026 loadPDBStructures(jprovider, jseqs, af, ap);
4027 loadRnaViewers(jprovider, jseqs, ap);
4029 // and finally return.
4034 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
4035 * panel is restored from separate jar entries, two (gapped and trimmed) per
4036 * sequence and secondary structure.
4038 * Currently each viewer shows just one sequence and structure (gapped and
4039 * trimmed), however this method is designed to support multiple sequences or
4040 * structures in viewers if wanted in future.
4046 private void loadRnaViewers(jarInputStreamProvider jprovider,
4047 List<JSeq> jseqs, AlignmentPanel ap)
4050 * scan the sequences for references to viewers; create each one the first
4051 * time it is referenced, add Rna models to existing viewers
4053 for (JSeq jseq : jseqs)
4055 for (int i = 0; i < jseq.getRnaViewer().size(); i++)
4057 RnaViewer viewer = jseq.getRnaViewer().get(i);
4058 AppVarna appVarna = findOrCreateVarnaViewer(viewer, uniqueSetSuffix,
4061 for (int j = 0; j < viewer.getSecondaryStructure().size(); j++)
4063 SecondaryStructure ss = viewer.getSecondaryStructure().get(j);
4064 SequenceI seq = seqRefIds.get(jseq.getId());
4065 AlignmentAnnotation ann = this.annotationIds
4066 .get(ss.getAnnotationId());
4069 * add the structure to the Varna display (with session state copied
4070 * from the jar to a temporary file)
4072 boolean gapped = safeBoolean(ss.isGapped());
4073 String rnaTitle = ss.getTitle();
4074 String sessionState = ss.getViewerState();
4075 String tempStateFile = copyJarEntry(jprovider, sessionState,
4077 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
4078 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
4080 appVarna.setInitialSelection(safeInt(viewer.getSelectedRna()));
4086 * Locate and return an already instantiated matching AppVarna, or create one
4090 * @param viewIdSuffix
4094 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
4095 String viewIdSuffix, AlignmentPanel ap)
4098 * on each load a suffix is appended to the saved viewId, to avoid conflicts
4099 * if load is repeated
4101 String postLoadId = viewer.getViewId() + viewIdSuffix;
4102 for (JInternalFrame frame : getAllFrames())
4104 if (frame instanceof AppVarna)
4106 AppVarna varna = (AppVarna) frame;
4107 if (postLoadId.equals(varna.getViewId()))
4109 // this viewer is already instantiated
4110 // could in future here add ap as another 'parent' of the
4111 // AppVarna window; currently just 1-to-many
4118 * viewer not found - make it
4120 RnaViewerModel model = new RnaViewerModel(postLoadId, viewer.getTitle(),
4121 safeInt(viewer.getXpos()), safeInt(viewer.getYpos()),
4122 safeInt(viewer.getWidth()), safeInt(viewer.getHeight()),
4123 safeInt(viewer.getDividerLocation()));
4124 AppVarna varna = new AppVarna(model, ap);
4130 * Load any saved trees
4138 protected void loadTrees(JalviewModel jm, Viewport view,
4139 AlignFrame af, AlignViewport av, AlignmentPanel ap)
4141 // TODO result of automated refactoring - are all these parameters needed?
4144 for (int t = 0; t < jm.getTree().size(); t++)
4147 Tree tree = jm.getTree().get(t);
4149 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
4152 tp = af.showNewickTree(new NewickFile(tree.getNewick()),
4153 tree.getTitle(), safeInt(tree.getWidth()),
4154 safeInt(tree.getHeight()), safeInt(tree.getXpos()),
4155 safeInt(tree.getYpos()));
4156 if (tree.getId() != null)
4158 // perhaps bind the tree id to something ?
4163 // update local tree attributes ?
4164 // TODO: should check if tp has been manipulated by user - if so its
4165 // settings shouldn't be modified
4166 tp.setTitle(tree.getTitle());
4167 tp.setBounds(new Rectangle(safeInt(tree.getXpos()),
4168 safeInt(tree.getYpos()), safeInt(tree.getWidth()),
4169 safeInt(tree.getHeight())));
4170 tp.setViewport(av); // af.viewport;
4171 // TODO: verify 'associate with all views' works still
4172 tp.getTreeCanvas().setViewport(av); // af.viewport;
4173 tp.getTreeCanvas().setAssociatedPanel(ap); // af.alignPanel;
4174 // FIXME: should we use safeBoolean here ?
4175 tp.getTreeCanvas().setApplyToAllViews(tree.isLinkToAllViews());
4180 warn("There was a problem recovering stored Newick tree: \n"
4181 + tree.getNewick());
4185 tp.fitToWindow.setState(safeBoolean(tree.isFitToWindow()));
4186 tp.fitToWindow_actionPerformed(null);
4188 if (tree.getFontName() != null)
4191 new Font(tree.getFontName(), safeInt(tree.getFontStyle()),
4192 safeInt(tree.getFontSize())));
4197 new Font(view.getFontName(), safeInt(view.getFontStyle()),
4198 safeInt(view.getFontSize())));
4201 tp.showPlaceholders(safeBoolean(tree.isMarkUnlinked()));
4202 tp.showBootstrap(safeBoolean(tree.isShowBootstrap()));
4203 tp.showDistances(safeBoolean(tree.isShowDistances()));
4205 tp.getTreeCanvas().setThreshold(safeFloat(tree.getThreshold()));
4207 if (safeBoolean(tree.isCurrentTree()))
4209 af.getViewport().setCurrentTree(tp.getTree());
4213 } catch (Exception ex)
4215 ex.printStackTrace();
4220 * Load and link any saved structure viewers.
4227 protected void loadPDBStructures(jarInputStreamProvider jprovider,
4228 List<JSeq> jseqs, AlignFrame af, AlignmentPanel ap)
4231 * Run through all PDB ids on the alignment, and collect mappings between
4232 * distinct view ids and all sequences referring to that view.
4234 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<>();
4236 for (int i = 0; i < jseqs.size(); i++)
4238 JSeq jseq = jseqs.get(i);
4239 if (jseq.getPdbids().size() > 0)
4241 List<Pdbids> ids = jseq.getPdbids();
4242 for (int p = 0; p < ids.size(); p++)
4244 Pdbids pdbid = ids.get(p);
4245 final int structureStateCount = pdbid.getStructureState().size();
4246 for (int s = 0; s < structureStateCount; s++)
4248 // check to see if we haven't already created this structure view
4249 final StructureState structureState = pdbid
4250 .getStructureState().get(s);
4251 String sviewid = (structureState.getViewId() == null) ? null
4252 : structureState.getViewId() + uniqueSetSuffix;
4253 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
4254 // Originally : pdbid.getFile()
4255 // : TODO: verify external PDB file recovery still works in normal
4256 // jalview project load
4258 loadPDBFile(jprovider, pdbid.getId(), pdbid.getFile()));
4259 jpdb.setId(pdbid.getId());
4261 int x = safeInt(structureState.getXpos());
4262 int y = safeInt(structureState.getYpos());
4263 int width = safeInt(structureState.getWidth());
4264 int height = safeInt(structureState.getHeight());
4266 // Probably don't need to do this anymore...
4267 // Desktop.desktop.getComponentAt(x, y);
4268 // TODO: NOW: check that this recovers the PDB file correctly.
4269 String pdbFile = loadPDBFile(jprovider, pdbid.getId(),
4271 jalview.datamodel.SequenceI seq = seqRefIds
4272 .get(jseq.getId() + "");
4273 if (sviewid == null)
4275 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width + ","
4278 if (!structureViewers.containsKey(sviewid))
4280 structureViewers.put(sviewid,
4281 new StructureViewerModel(x, y, width, height, false,
4282 false, true, structureState.getViewId(),
4283 structureState.getType()));
4284 // Legacy pre-2.7 conversion JAL-823 :
4285 // do not assume any view has to be linked for colour by
4289 // assemble String[] { pdb files }, String[] { id for each
4290 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
4291 // seqs_file 2}, boolean[] {
4292 // linkAlignPanel,superposeWithAlignpanel}} from hash
4293 StructureViewerModel jmoldat = structureViewers.get(sviewid);
4294 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
4295 || structureState.isAlignwithAlignPanel());
4298 * Default colour by linked panel to false if not specified (e.g.
4299 * for pre-2.7 projects)
4301 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
4302 colourWithAlignPanel |= structureState.isColourwithAlignPanel();
4303 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
4306 * Default colour by viewer to true if not specified (e.g. for
4309 boolean colourByViewer = jmoldat.isColourByViewer();
4310 colourByViewer &= structureState.isColourByJmol();
4311 jmoldat.setColourByViewer(colourByViewer);
4313 if (jmoldat.getStateData().length() < structureState
4314 .getValue()/*Content()*/.length())
4316 jmoldat.setStateData(structureState.getValue());// Content());
4318 if (pdbid.getFile() != null)
4320 File mapkey = new File(pdbid.getFile());
4321 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
4322 if (seqstrmaps == null)
4324 jmoldat.getFileData().put(mapkey,
4325 seqstrmaps = jmoldat.new StructureData(pdbFile,
4328 if (!seqstrmaps.getSeqList().contains(seq))
4330 seqstrmaps.getSeqList().add(seq);
4336 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");
4343 // Instantiate the associated structure views
4344 for (Entry<String, StructureViewerModel> entry : structureViewers
4349 createOrLinkStructureViewer(entry, af, ap, jprovider);
4350 } catch (Exception e)
4353 "Error loading structure viewer: " + e.getMessage());
4354 // failed - try the next one
4366 protected void createOrLinkStructureViewer(
4367 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4368 AlignmentPanel ap, jarInputStreamProvider jprovider)
4370 final StructureViewerModel stateData = viewerData.getValue();
4373 * Search for any viewer windows already open from other alignment views
4374 * that exactly match the stored structure state
4376 StructureViewerBase comp = findMatchingViewer(viewerData);
4380 linkStructureViewer(ap, comp, stateData);
4385 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
4386 * "viewer_"+stateData.viewId
4388 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
4390 createChimeraViewer(viewerData, af, jprovider);
4395 * else Jmol (if pre-2.9, stateData contains JMOL state string)
4397 createJmolViewer(viewerData, af, jprovider);
4402 * Create a new Chimera viewer.
4408 protected void createChimeraViewer(
4409 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4410 jarInputStreamProvider jprovider)
4412 StructureViewerModel data = viewerData.getValue();
4413 String chimeraSessionFile = data.getStateData();
4416 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
4418 * NB this is the 'saved' viewId as in the project file XML, _not_ the
4419 * 'uniquified' sviewid used to reconstruct the viewer here
4421 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
4422 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
4425 Set<Entry<File, StructureData>> fileData = data.getFileData()
4427 List<PDBEntry> pdbs = new ArrayList<>();
4428 List<SequenceI[]> allseqs = new ArrayList<>();
4429 for (Entry<File, StructureData> pdb : fileData)
4431 String filePath = pdb.getValue().getFilePath();
4432 String pdbId = pdb.getValue().getPdbId();
4433 // pdbs.add(new PDBEntry(filePath, pdbId));
4434 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
4435 final List<SequenceI> seqList = pdb.getValue().getSeqList();
4436 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
4440 boolean colourByChimera = data.isColourByViewer();
4441 boolean colourBySequence = data.isColourWithAlignPanel();
4443 // TODO use StructureViewer as a factory here, see JAL-1761
4444 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
4445 final SequenceI[][] seqsArray = allseqs
4446 .toArray(new SequenceI[allseqs.size()][]);
4447 String newViewId = viewerData.getKey();
4449 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
4450 af.alignPanel, pdbArray, seqsArray, colourByChimera,
4451 colourBySequence, newViewId);
4452 cvf.setSize(data.getWidth(), data.getHeight());
4453 cvf.setLocation(data.getX(), data.getY());
4457 * Create a new Jmol window. First parse the Jmol state to translate filenames
4458 * loaded into the view, and record the order in which files are shown in the
4459 * Jmol view, so we can add the sequence mappings in same order.
4465 protected void createJmolViewer(
4466 final Entry<String, StructureViewerModel> viewerData,
4467 AlignFrame af, jarInputStreamProvider jprovider)
4469 final StructureViewerModel svattrib = viewerData.getValue();
4470 String state = svattrib.getStateData();
4473 * Pre-2.9: state element value is the Jmol state string
4475 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
4478 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
4480 state = readJarEntry(jprovider,
4481 getViewerJarEntryName(svattrib.getViewId()));
4484 List<String> pdbfilenames = new ArrayList<>();
4485 List<SequenceI[]> seqmaps = new ArrayList<>();
4486 List<String> pdbids = new ArrayList<>();
4487 StringBuilder newFileLoc = new StringBuilder(64);
4488 int cp = 0, ncp, ecp;
4489 Map<File, StructureData> oldFiles = svattrib.getFileData();
4490 while ((ncp = state.indexOf("load ", cp)) > -1)
4494 // look for next filename in load statement
4495 newFileLoc.append(state.substring(cp,
4496 ncp = (state.indexOf("\"", ncp + 1) + 1)));
4497 String oldfilenam = state.substring(ncp,
4498 ecp = state.indexOf("\"", ncp));
4499 // recover the new mapping data for this old filename
4500 // have to normalize filename - since Jmol and jalview do
4502 // translation differently.
4503 StructureData filedat = oldFiles.get(new File(oldfilenam));
4504 if (filedat == null)
4506 String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\");
4507 filedat = oldFiles.get(new File(reformatedOldFilename));
4509 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
4510 pdbfilenames.add(filedat.getFilePath());
4511 pdbids.add(filedat.getPdbId());
4512 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4513 newFileLoc.append("\"");
4514 cp = ecp + 1; // advance beyond last \" and set cursor so we can
4515 // look for next file statement.
4516 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
4520 // just append rest of state
4521 newFileLoc.append(state.substring(cp));
4525 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
4526 newFileLoc = new StringBuilder(state);
4527 newFileLoc.append("; load append ");
4528 for (File id : oldFiles.keySet())
4530 // add this and any other pdb files that should be present in
4532 StructureData filedat = oldFiles.get(id);
4533 newFileLoc.append(filedat.getFilePath());
4534 pdbfilenames.add(filedat.getFilePath());
4535 pdbids.add(filedat.getPdbId());
4536 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4537 newFileLoc.append(" \"");
4538 newFileLoc.append(filedat.getFilePath());
4539 newFileLoc.append("\"");
4542 newFileLoc.append(";");
4545 if (newFileLoc.length() == 0)
4549 int histbug = newFileLoc.indexOf("history = ");
4553 * change "history = [true|false];" to "history = [1|0];"
4556 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
4557 String val = (diff == -1) ? null
4558 : newFileLoc.substring(histbug, diff);
4559 if (val != null && val.length() >= 4)
4561 if (val.contains("e")) // eh? what can it be?
4563 if (val.trim().equals("true"))
4571 newFileLoc.replace(histbug, diff, val);
4576 final String[] pdbf = pdbfilenames
4577 .toArray(new String[pdbfilenames.size()]);
4578 final String[] id = pdbids.toArray(new String[pdbids.size()]);
4579 final SequenceI[][] sq = seqmaps
4580 .toArray(new SequenceI[seqmaps.size()][]);
4581 final String fileloc = newFileLoc.toString();
4582 final String sviewid = viewerData.getKey();
4583 final AlignFrame alf = af;
4584 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
4585 svattrib.getWidth(), svattrib.getHeight());
4588 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
4593 JalviewStructureDisplayI sview = null;
4596 sview = new StructureViewer(
4597 alf.alignPanel.getStructureSelectionManager())
4598 .createView(StructureViewer.ViewerType.JMOL,
4599 pdbf, id, sq, alf.alignPanel, svattrib,
4600 fileloc, rect, sviewid);
4601 addNewStructureViewer(sview);
4602 } catch (OutOfMemoryError ex)
4604 new OOMWarning("restoring structure view for PDB id " + id,
4605 (OutOfMemoryError) ex.getCause());
4606 if (sview != null && sview.isVisible())
4608 sview.closeViewer(false);
4609 sview.setVisible(false);
4615 } catch (InvocationTargetException ex)
4617 warn("Unexpected error when opening Jmol view.", ex);
4619 } catch (InterruptedException e)
4621 // e.printStackTrace();
4627 * Generates a name for the entry in the project jar file to hold state
4628 * information for a structure viewer
4633 protected String getViewerJarEntryName(String viewId)
4635 return VIEWER_PREFIX + viewId;
4639 * Returns any open frame that matches given structure viewer data. The match
4640 * is based on the unique viewId, or (for older project versions) the frame's
4646 protected StructureViewerBase findMatchingViewer(
4647 Entry<String, StructureViewerModel> viewerData)
4649 final String sviewid = viewerData.getKey();
4650 final StructureViewerModel svattrib = viewerData.getValue();
4651 StructureViewerBase comp = null;
4652 JInternalFrame[] frames = getAllFrames();
4653 for (JInternalFrame frame : frames)
4655 if (frame instanceof StructureViewerBase)
4658 * Post jalview 2.4 schema includes structure view id
4660 if (sviewid != null && ((StructureViewerBase) frame).getViewId()
4663 comp = (StructureViewerBase) frame;
4664 break; // break added in 2.9
4667 * Otherwise test for matching position and size of viewer frame
4669 else if (frame.getX() == svattrib.getX()
4670 && frame.getY() == svattrib.getY()
4671 && frame.getHeight() == svattrib.getHeight()
4672 && frame.getWidth() == svattrib.getWidth())
4674 comp = (StructureViewerBase) frame;
4675 // no break in faint hope of an exact match on viewId
4683 * Link an AlignmentPanel to an existing structure viewer.
4688 * @param useinViewerSuperpos
4689 * @param usetoColourbyseq
4690 * @param viewerColouring
4692 protected void linkStructureViewer(AlignmentPanel ap,
4693 StructureViewerBase viewer, StructureViewerModel stateData)
4695 // NOTE: if the jalview project is part of a shared session then
4696 // view synchronization should/could be done here.
4698 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4699 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4700 final boolean viewerColouring = stateData.isColourByViewer();
4701 Map<File, StructureData> oldFiles = stateData.getFileData();
4704 * Add mapping for sequences in this view to an already open viewer
4706 final AAStructureBindingModel binding = viewer.getBinding();
4707 for (File id : oldFiles.keySet())
4709 // add this and any other pdb files that should be present in the
4711 StructureData filedat = oldFiles.get(id);
4712 String pdbFile = filedat.getFilePath();
4713 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4714 binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE,
4716 binding.addSequenceForStructFile(pdbFile, seq);
4718 // and add the AlignmentPanel's reference to the view panel
4719 viewer.addAlignmentPanel(ap);
4720 if (useinViewerSuperpos)
4722 viewer.useAlignmentPanelForSuperposition(ap);
4726 viewer.excludeAlignmentPanelForSuperposition(ap);
4728 if (usetoColourbyseq)
4730 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4734 viewer.excludeAlignmentPanelForColourbyseq(ap);
4739 * Get all frames within the Desktop.
4743 protected JInternalFrame[] getAllFrames()
4745 JInternalFrame[] frames = null;
4746 // TODO is this necessary - is it safe - risk of hanging?
4751 frames = Desktop.desktop.getAllFrames();
4752 } catch (ArrayIndexOutOfBoundsException e)
4754 // occasional No such child exceptions are thrown here...
4758 } catch (InterruptedException f)
4762 } while (frames == null);
4767 * Answers true if 'version' is equal to or later than 'supported', where each
4768 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4769 * changes. Development and test values for 'version' are leniently treated
4773 * - minimum version we are comparing against
4775 * - version of data being processsed
4778 public static boolean isVersionStringLaterThan(String supported,
4781 if (supported == null || version == null
4782 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4783 || version.equalsIgnoreCase("Test")
4784 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4786 System.err.println("Assuming project file with "
4787 + (version == null ? "null" : version)
4788 + " is compatible with Jalview version " + supported);
4793 return StringUtils.compareVersions(version, supported, "b") >= 0;
4797 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4799 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4801 if (newStructureViewers != null)
4803 sview.getBinding().setFinishedLoadingFromArchive(false);
4804 newStructureViewers.add(sview);
4808 protected void setLoadingFinishedForNewStructureViewers()
4810 if (newStructureViewers != null)
4812 for (JalviewStructureDisplayI sview : newStructureViewers)
4814 sview.getBinding().setFinishedLoadingFromArchive(true);
4816 newStructureViewers.clear();
4817 newStructureViewers = null;
4821 AlignFrame loadViewport(String file, List<JSeq> JSEQ,
4822 List<SequenceI> hiddenSeqs, AlignmentI al,
4823 JalviewModel jm, Viewport view, String uniqueSeqSetId,
4824 String viewId, List<JvAnnotRow> autoAlan)
4826 AlignFrame af = null;
4827 af = new AlignFrame(al, safeInt(view.getWidth()),
4828 safeInt(view.getHeight()), uniqueSeqSetId, viewId);
4830 af.setFileName(file, FileFormat.Jalview);
4832 final AlignViewport viewport = af.getViewport();
4833 for (int i = 0; i < JSEQ.size(); i++)
4835 int colour = safeInt(JSEQ.get(i).getColour());
4836 viewport.setSequenceColour(viewport.getAlignment().getSequenceAt(i),
4842 viewport.setColourByReferenceSeq(true);
4843 viewport.setDisplayReferenceSeq(true);
4846 viewport.setGatherViewsHere(safeBoolean(view.isGatheredViews()));
4848 if (view.getSequenceSetId() != null)
4850 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4852 viewport.setSequenceSetId(uniqueSeqSetId);
4855 // propagate shared settings to this new view
4856 viewport.setHistoryList(av.getHistoryList());
4857 viewport.setRedoList(av.getRedoList());
4861 viewportsAdded.put(uniqueSeqSetId, viewport);
4863 // TODO: check if this method can be called repeatedly without
4864 // side-effects if alignpanel already registered.
4865 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4867 // apply Hidden regions to view.
4868 if (hiddenSeqs != null)
4870 for (int s = 0; s < JSEQ.size(); s++)
4872 SequenceGroup hidden = new SequenceGroup();
4873 boolean isRepresentative = false;
4874 for (int r = 0; r < JSEQ.get(s).getHiddenSequences().size(); r++)
4876 isRepresentative = true;
4877 SequenceI sequenceToHide = al
4878 .getSequenceAt(JSEQ.get(s).getHiddenSequences().get(r));
4879 hidden.addSequence(sequenceToHide, false);
4880 // remove from hiddenSeqs list so we don't try to hide it twice
4881 hiddenSeqs.remove(sequenceToHide);
4883 if (isRepresentative)
4885 SequenceI representativeSequence = al.getSequenceAt(s);
4886 hidden.addSequence(representativeSequence, false);
4887 viewport.hideRepSequences(representativeSequence, hidden);
4891 SequenceI[] hseqs = hiddenSeqs
4892 .toArray(new SequenceI[hiddenSeqs.size()]);
4893 viewport.hideSequence(hseqs);
4896 // recover view properties and display parameters
4898 viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
4899 viewport.setAbovePIDThreshold(safeBoolean(view.isPidSelected()));
4900 final int pidThreshold = safeInt(view.getPidThreshold());
4901 viewport.setThreshold(pidThreshold);
4903 viewport.setColourText(safeBoolean(view.isShowColourText()));
4906 .setConservationSelected(
4907 safeBoolean(view.isConservationSelected()));
4908 viewport.setIncrement(safeInt(view.getConsThreshold()));
4909 viewport.setShowJVSuffix(safeBoolean(view.isShowFullId()));
4910 viewport.setRightAlignIds(safeBoolean(view.isRightAlignIds()));
4911 viewport.setFont(new Font(view.getFontName(),
4912 safeInt(view.getFontStyle()), safeInt(view.getFontSize())),
4914 ViewStyleI vs = viewport.getViewStyle();
4915 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
4916 viewport.setViewStyle(vs);
4917 // TODO: allow custom charWidth/Heights to be restored by updating them
4918 // after setting font - which means set above to false
4919 viewport.setRenderGaps(safeBoolean(view.isRenderGaps()));
4920 viewport.setWrapAlignment(safeBoolean(view.isWrapAlignment()));
4921 viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
4923 viewport.setShowBoxes(safeBoolean(view.isShowBoxes()));
4925 viewport.setShowText(safeBoolean(view.isShowText()));
4927 viewport.setTextColour(new Color(safeInt(view.getTextCol1())));
4928 viewport.setTextColour2(new Color(safeInt(view.getTextCol2())));
4929 viewport.setThresholdTextColour(safeInt(view.getTextColThreshold()));
4930 viewport.setShowUnconserved(view.isShowUnconserved());
4931 viewport.getRanges().setStartRes(safeInt(view.getStartRes()));
4933 if (view.getViewName() != null)
4935 viewport.setViewName(view.getViewName());
4936 af.setInitialTabVisible();
4938 af.setBounds(safeInt(view.getXpos()), safeInt(view.getYpos()),
4939 safeInt(view.getWidth()), safeInt(view.getHeight()));
4940 // startSeq set in af.alignPanel.updateLayout below
4941 af.alignPanel.updateLayout();
4942 ColourSchemeI cs = null;
4943 // apply colourschemes
4944 if (view.getBgColour() != null)
4946 if (view.getBgColour().startsWith("ucs"))
4948 cs = getUserColourScheme(jm, view.getBgColour());
4950 else if (view.getBgColour().startsWith("Annotation"))
4952 AnnotationColourScheme viewAnnColour = view.getAnnotationColours();
4953 cs = constructAnnotationColour(viewAnnColour, af, al, jm, true);
4960 cs = ColourSchemeProperty.getColourScheme(al, view.getBgColour());
4964 viewport.setGlobalColourScheme(cs);
4965 viewport.getResidueShading().setThreshold(pidThreshold,
4966 view.isIgnoreGapsinConsensus());
4967 viewport.getResidueShading()
4968 .setConsensus(viewport.getSequenceConsensusHash());
4969 viewport.setColourAppliesToAllGroups(false);
4971 if (safeBoolean(view.isConservationSelected()) && cs != null)
4973 viewport.getResidueShading()
4974 .setConservationInc(safeInt(view.getConsThreshold()));
4977 af.changeColour(cs);
4979 viewport.setColourAppliesToAllGroups(true);
4982 .setShowSequenceFeatures(
4983 safeBoolean(view.isShowSequenceFeatures()));
4985 viewport.setCentreColumnLabels(view.isCentreColumnLabels());
4986 viewport.setIgnoreGapsConsensus(view.isIgnoreGapsinConsensus(), null);
4987 viewport.setFollowHighlight(view.isFollowHighlight());
4988 viewport.followSelection = view.isFollowSelection();
4989 viewport.setShowConsensusHistogram(view.isShowConsensusHistogram());
4990 viewport.setShowSequenceLogo(view.isShowSequenceLogo());
4991 viewport.setNormaliseSequenceLogo(view.isNormaliseSequenceLogo());
4992 viewport.setShowDBRefs(safeBoolean(view.isShowDbRefTooltip()));
4993 viewport.setShowNPFeats(safeBoolean(view.isShowNPfeatureTooltip()));
4994 viewport.setShowGroupConsensus(view.isShowGroupConsensus());
4995 viewport.setShowGroupConservation(view.isShowGroupConservation());
4997 // recover feature settings
4998 if (jm.getFeatureSettings() != null)
5000 FeatureRenderer fr = af.alignPanel.getSeqPanel().seqCanvas
5001 .getFeatureRenderer();
5002 FeaturesDisplayed fdi;
5003 viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
5004 String[] renderOrder = new String[jm.getFeatureSettings()
5005 .getSetting().size()];
5006 Map<String, FeatureColourI> featureColours = new Hashtable<>();
5007 Map<String, Float> featureOrder = new Hashtable<>();
5009 for (int fs = 0; fs < jm.getFeatureSettings()
5010 .getSetting().size(); fs++)
5012 Setting setting = jm.getFeatureSettings().getSetting().get(fs);
5013 String featureType = setting.getType();
5016 * restore feature filters (if any)
5018 jalview.xml.binding.jalview.FeatureMatcherSet filters = setting
5020 if (filters != null)
5022 FeatureMatcherSetI filter = Jalview2XML
5023 .parseFilter(featureType, filters);
5024 if (!filter.isEmpty())
5026 fr.setFeatureFilter(featureType, filter);
5031 * restore feature colour scheme
5033 Color maxColour = new Color(setting.getColour());
5034 if (setting.getMincolour() != null)
5037 * minColour is always set unless a simple colour
5038 * (including for colour by label though it doesn't use it)
5040 Color minColour = new Color(setting.getMincolour().intValue());
5041 Color noValueColour = minColour;
5042 NoValueColour noColour = setting.getNoValueColour();
5043 if (noColour == NoValueColour.NONE)
5045 noValueColour = null;
5047 else if (noColour == NoValueColour.MAX)
5049 noValueColour = maxColour;
5051 float min = safeFloat(safeFloat(setting.getMin()));
5052 float max = setting.getMax() == null ? 1f
5053 : setting.getMax().floatValue();
5054 FeatureColourI gc = new FeatureColour(minColour, maxColour,
5055 noValueColour, min, max);
5056 if (setting.getAttributeName().size() > 0)
5058 gc.setAttributeName(setting.getAttributeName().toArray(
5059 new String[setting.getAttributeName().size()]));
5061 if (setting.getThreshold() != null)
5063 gc.setThreshold(setting.getThreshold().floatValue());
5064 int threshstate = safeInt(setting.getThreshstate());
5065 // -1 = None, 0 = Below, 1 = Above threshold
5066 if (threshstate == 0)
5068 gc.setBelowThreshold(true);
5070 else if (threshstate == 1)
5072 gc.setAboveThreshold(true);
5075 gc.setAutoScaled(true); // default
5076 if (setting.isAutoScale() != null)
5078 gc.setAutoScaled(setting.isAutoScale());
5080 if (setting.isColourByLabel() != null)
5082 gc.setColourByLabel(setting.isColourByLabel());
5084 // and put in the feature colour table.
5085 featureColours.put(featureType, gc);
5089 featureColours.put(featureType,
5090 new FeatureColour(maxColour));
5092 renderOrder[fs] = featureType;
5093 if (setting.getOrder() != null)
5095 featureOrder.put(featureType, setting.getOrder().floatValue());
5099 featureOrder.put(featureType, new Float(
5100 fs / jm.getFeatureSettings().getSetting().size()));
5102 if (safeBoolean(setting.isDisplay()))
5104 fdi.setVisible(featureType);
5107 Map<String, Boolean> fgtable = new Hashtable<>();
5108 for (int gs = 0; gs < jm.getFeatureSettings().getGroup().size(); gs++)
5110 Group grp = jm.getFeatureSettings().getGroup().get(gs);
5111 fgtable.put(grp.getName(), new Boolean(grp.isDisplay()));
5113 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
5114 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
5115 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
5116 FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
5117 fgtable, featureColours, 1.0f, featureOrder);
5118 fr.transferSettings(frs);
5121 if (view.getHiddenColumns().size() > 0)
5123 for (int c = 0; c < view.getHiddenColumns().size(); c++)
5125 final HiddenColumns hc = view.getHiddenColumns().get(c);
5126 viewport.hideColumns(safeInt(hc.getStart()),
5127 safeInt(hc.getEnd()) /* +1 */);
5130 if (view.getCalcIdParam() != null)
5132 for (CalcIdParam calcIdParam : view.getCalcIdParam())
5134 if (calcIdParam != null)
5136 if (recoverCalcIdParam(calcIdParam, viewport))
5141 warn("Couldn't recover parameters for "
5142 + calcIdParam.getCalcId());
5147 af.setMenusFromViewport(viewport);
5148 af.setTitle(view.getTitle());
5149 // TODO: we don't need to do this if the viewport is aready visible.
5151 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
5152 * has a 'cdna/protein complement' view, in which case save it in order to
5153 * populate a SplitFrame once all views have been read in.
5155 String complementaryViewId = view.getComplementId();
5156 if (complementaryViewId == null)
5158 Desktop.addInternalFrame(af, view.getTitle(),
5159 safeInt(view.getWidth()), safeInt(view.getHeight()));
5160 // recompute any autoannotation
5161 af.alignPanel.updateAnnotation(false, true);
5162 reorderAutoannotation(af, al, autoAlan);
5163 af.alignPanel.alignmentChanged();
5167 splitFrameCandidates.put(view, af);
5173 * Reads saved data to restore Colour by Annotation settings
5175 * @param viewAnnColour
5179 * @param checkGroupAnnColour
5182 private ColourSchemeI constructAnnotationColour(
5183 AnnotationColourScheme viewAnnColour, AlignFrame af,
5184 AlignmentI al, JalviewModel model, boolean checkGroupAnnColour)
5186 boolean propagateAnnColour = false;
5187 AlignmentI annAlignment = af != null ? af.getViewport().getAlignment()
5189 if (checkGroupAnnColour && al.getGroups() != null
5190 && al.getGroups().size() > 0)
5192 // pre 2.8.1 behaviour
5193 // check to see if we should transfer annotation colours
5194 propagateAnnColour = true;
5195 for (SequenceGroup sg : al.getGroups())
5197 if (sg.getColourScheme() instanceof AnnotationColourGradient)
5199 propagateAnnColour = false;
5205 * 2.10.2- : saved annotationId is AlignmentAnnotation.annotationId
5207 String annotationId = viewAnnColour.getAnnotation();
5208 AlignmentAnnotation matchedAnnotation = annotationIds.get(annotationId);
5211 * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
5213 if (matchedAnnotation == null
5214 && annAlignment.getAlignmentAnnotation() != null)
5216 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
5219 .equals(annAlignment.getAlignmentAnnotation()[i].label))
5221 matchedAnnotation = annAlignment.getAlignmentAnnotation()[i];
5226 if (matchedAnnotation == null)
5228 System.err.println("Failed to match annotation colour scheme for "
5232 if (matchedAnnotation.getThreshold() == null)
5234 matchedAnnotation.setThreshold(
5235 new GraphLine(safeFloat(viewAnnColour.getThreshold()),
5236 "Threshold", Color.black));
5239 AnnotationColourGradient cs = null;
5240 if (viewAnnColour.getColourScheme().equals("None"))
5242 cs = new AnnotationColourGradient(matchedAnnotation,
5243 new Color(safeInt(viewAnnColour.getMinColour())),
5244 new Color(safeInt(viewAnnColour.getMaxColour())),
5245 safeInt(viewAnnColour.getAboveThreshold()));
5247 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
5249 cs = new AnnotationColourGradient(matchedAnnotation,
5250 getUserColourScheme(model, viewAnnColour.getColourScheme()),
5251 safeInt(viewAnnColour.getAboveThreshold()));
5255 cs = new AnnotationColourGradient(matchedAnnotation,
5256 ColourSchemeProperty.getColourScheme(al,
5257 viewAnnColour.getColourScheme()),
5258 safeInt(viewAnnColour.getAboveThreshold()));
5261 boolean perSequenceOnly = safeBoolean(viewAnnColour.isPerSequence());
5262 boolean useOriginalColours = safeBoolean(
5263 viewAnnColour.isPredefinedColours());
5264 cs.setSeqAssociated(perSequenceOnly);
5265 cs.setPredefinedColours(useOriginalColours);
5267 if (propagateAnnColour && al.getGroups() != null)
5269 // Also use these settings for all the groups
5270 for (int g = 0; g < al.getGroups().size(); g++)
5272 SequenceGroup sg = al.getGroups().get(g);
5273 if (sg.getGroupColourScheme() == null)
5278 AnnotationColourGradient groupScheme = new AnnotationColourGradient(
5279 matchedAnnotation, sg.getColourScheme(),
5280 safeInt(viewAnnColour.getAboveThreshold()));
5281 sg.setColourScheme(groupScheme);
5282 groupScheme.setSeqAssociated(perSequenceOnly);
5283 groupScheme.setPredefinedColours(useOriginalColours);
5289 private void reorderAutoannotation(AlignFrame af, AlignmentI al,
5290 List<JvAnnotRow> autoAlan)
5292 // copy over visualization settings for autocalculated annotation in the
5294 if (al.getAlignmentAnnotation() != null)
5297 * Kludge for magic autoannotation names (see JAL-811)
5299 String[] magicNames = new String[] { "Consensus", "Quality",
5301 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
5302 Hashtable<String, JvAnnotRow> visan = new Hashtable<>();
5303 for (String nm : magicNames)
5305 visan.put(nm, nullAnnot);
5307 for (JvAnnotRow auan : autoAlan)
5309 visan.put(auan.template.label
5310 + (auan.template.getCalcId() == null ? ""
5311 : "\t" + auan.template.getCalcId()),
5314 int hSize = al.getAlignmentAnnotation().length;
5315 List<JvAnnotRow> reorder = new ArrayList<>();
5316 // work through any autoCalculated annotation already on the view
5317 // removing it if it should be placed in a different location on the
5318 // annotation panel.
5319 List<String> remains = new ArrayList<>(visan.keySet());
5320 for (int h = 0; h < hSize; h++)
5322 jalview.datamodel.AlignmentAnnotation jalan = al
5323 .getAlignmentAnnotation()[h];
5324 if (jalan.autoCalculated)
5327 JvAnnotRow valan = visan.get(k = jalan.label);
5328 if (jalan.getCalcId() != null)
5330 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
5335 // delete the auto calculated row from the alignment
5336 al.deleteAnnotation(jalan, false);
5340 if (valan != nullAnnot)
5342 if (jalan != valan.template)
5344 // newly created autoannotation row instance
5345 // so keep a reference to the visible annotation row
5346 // and copy over all relevant attributes
5347 if (valan.template.graphHeight >= 0)
5350 jalan.graphHeight = valan.template.graphHeight;
5352 jalan.visible = valan.template.visible;
5354 reorder.add(new JvAnnotRow(valan.order, jalan));
5359 // Add any (possibly stale) autocalculated rows that were not appended to
5360 // the view during construction
5361 for (String other : remains)
5363 JvAnnotRow othera = visan.get(other);
5364 if (othera != nullAnnot && othera.template.getCalcId() != null
5365 && othera.template.getCalcId().length() > 0)
5367 reorder.add(othera);
5370 // now put the automatic annotation in its correct place
5371 int s = 0, srt[] = new int[reorder.size()];
5372 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
5373 for (JvAnnotRow jvar : reorder)
5376 srt[s++] = jvar.order;
5379 jalview.util.QuickSort.sort(srt, rws);
5380 // and re-insert the annotation at its correct position
5381 for (JvAnnotRow jvar : rws)
5383 al.addAnnotation(jvar.template, jvar.order);
5385 af.alignPanel.adjustAnnotationHeight();
5389 Hashtable skipList = null;
5392 * TODO remove this method
5395 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
5396 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
5397 * throw new Error("Implementation Error. No skipList defined for this
5398 * Jalview2XML instance."); } return (AlignFrame)
5399 * skipList.get(view.getSequenceSetId()); }
5403 * Check if the Jalview view contained in object should be skipped or not.
5406 * @return true if view's sequenceSetId is a key in skipList
5408 private boolean skipViewport(JalviewModel object)
5410 if (skipList == null)
5414 String id = object.getViewport().get(0).getSequenceSetId();
5415 if (skipList.containsKey(id))
5417 if (Cache.log != null && Cache.log.isDebugEnabled())
5419 Cache.log.debug("Skipping seuqence set id " + id);
5426 public void addToSkipList(AlignFrame af)
5428 if (skipList == null)
5430 skipList = new Hashtable();
5432 skipList.put(af.getViewport().getSequenceSetId(), af);
5435 public void clearSkipList()
5437 if (skipList != null)
5444 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
5445 boolean ignoreUnrefed, String uniqueSeqSetId)
5447 jalview.datamodel.AlignmentI ds = getDatasetFor(
5448 vamsasSet.getDatasetId());
5449 AlignmentI xtant_ds = ds;
5450 if (xtant_ds == null)
5452 // good chance we are about to create a new dataset, but check if we've
5453 // seen some of the dataset sequence IDs before.
5454 // TODO: skip this check if we are working with project generated by
5455 // version 2.11 or later
5456 xtant_ds = checkIfHasDataset(vamsasSet.getSequence());
5457 if (xtant_ds != null)
5460 addDatasetRef(vamsasSet.getDatasetId(), ds);
5463 Vector dseqs = null;
5466 // recovering an alignment View
5467 AlignmentI seqSetDS = getDatasetFor(UNIQSEQSETID + uniqueSeqSetId);
5468 if (seqSetDS != null)
5470 if (ds != null && ds != seqSetDS)
5472 warn("JAL-3171 regression: Overwriting a dataset reference for an alignment"
5473 + " - CDS/Protein crossreference data may be lost");
5474 if (xtant_ds != null)
5476 // This can only happen if the unique sequence set ID was bound to a
5477 // dataset that did not contain any of the sequences in the view
5478 // currently being restored.
5479 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.");
5483 addDatasetRef(vamsasSet.getDatasetId(), ds);
5488 // try even harder to restore dataset
5489 AlignmentI xtantDS = checkIfHasDataset(vamsasSet.getSequence());
5490 // create a list of new dataset sequences
5491 dseqs = new Vector();
5493 for (int i = 0, iSize = vamsasSet.getSequence().size(); i < iSize; i++)
5495 Sequence vamsasSeq = vamsasSet.getSequence().get(i);
5496 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
5498 // create a new dataset
5501 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
5502 dseqs.copyInto(dsseqs);
5503 ds = new jalview.datamodel.Alignment(dsseqs);
5504 debug("Created new dataset " + vamsasSet.getDatasetId()
5505 + " for alignment " + System.identityHashCode(al));
5506 addDatasetRef(vamsasSet.getDatasetId(), ds);
5508 // set the dataset for the newly imported alignment.
5509 if (al.getDataset() == null && !ignoreUnrefed)
5512 // register dataset for the alignment's uniqueSeqSetId for legacy projects
5513 addDatasetRef(UNIQSEQSETID + uniqueSeqSetId, ds);
5515 updateSeqDatasetBinding(vamsasSet.getSequence(), ds);
5519 * XML dataset sequence ID to materialised dataset reference
5521 HashMap<String, AlignmentI> seqToDataset = new HashMap<>();
5524 * @return the first materialised dataset reference containing a dataset
5525 * sequence referenced in the given view
5527 * - sequences from the view
5529 AlignmentI checkIfHasDataset(List<Sequence> list)
5531 for (Sequence restoredSeq : list)
5533 AlignmentI datasetFor = seqToDataset.get(restoredSeq.getDsseqid());
5534 if (datasetFor != null)
5543 * Register ds as the containing dataset for the dataset sequences referenced
5544 * by sequences in list
5547 * - sequences in a view
5550 void updateSeqDatasetBinding(List<Sequence> list, AlignmentI ds)
5552 for (Sequence restoredSeq : list)
5554 AlignmentI prevDS = seqToDataset.put(restoredSeq.getDsseqid(), ds);
5555 if (prevDS != null && prevDS != ds)
5557 warn("Dataset sequence appears in many datasets: "
5558 + restoredSeq.getDsseqid());
5559 // TODO: try to merge!
5566 * sequence definition to create/merge dataset sequence for
5570 * vector to add new dataset sequence to
5571 * @param ignoreUnrefed
5572 * - when true, don't create new sequences from vamsasSeq if it's id
5573 * doesn't already have an asssociated Jalview sequence.
5575 * - used to reorder the sequence in the alignment according to the
5576 * vamsasSeq array ordering, to preserve ordering of dataset
5578 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
5579 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed, int vseqpos)
5581 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
5583 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
5584 boolean reorder = false;
5585 SequenceI dsq = null;
5586 if (sq != null && sq.getDatasetSequence() != null)
5588 dsq = sq.getDatasetSequence();
5594 if (sq == null && ignoreUnrefed)
5598 String sqid = vamsasSeq.getDsseqid();
5601 // need to create or add a new dataset sequence reference to this sequence
5604 dsq = seqRefIds.get(sqid);
5609 // make a new dataset sequence
5610 dsq = sq.createDatasetSequence();
5613 // make up a new dataset reference for this sequence
5614 sqid = seqHash(dsq);
5616 dsq.setVamsasId(uniqueSetSuffix + sqid);
5617 seqRefIds.put(sqid, dsq);
5622 dseqs.addElement(dsq);
5627 ds.addSequence(dsq);
5633 { // make this dataset sequence sq's dataset sequence
5634 sq.setDatasetSequence(dsq);
5635 // and update the current dataset alignment
5640 if (!dseqs.contains(dsq))
5647 if (ds.findIndex(dsq) < 0)
5649 ds.addSequence(dsq);
5656 // TODO: refactor this as a merge dataset sequence function
5657 // now check that sq (the dataset sequence) sequence really is the union of
5658 // all references to it
5659 // boolean pre = sq.getStart() < dsq.getStart();
5660 // boolean post = sq.getEnd() > dsq.getEnd();
5664 // StringBuffer sb = new StringBuffer();
5665 String newres = jalview.analysis.AlignSeq.extractGaps(
5666 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
5667 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
5668 && newres.length() > dsq.getLength())
5670 // Update with the longer sequence.
5674 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
5675 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
5676 * sb.append(newres.substring(newres.length() - sq.getEnd() -
5677 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
5679 dsq.setSequence(newres);
5681 // TODO: merges will never happen if we 'know' we have the real dataset
5682 // sequence - this should be detected when id==dssid
5684 "DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
5685 // + (pre ? "prepended" : "") + " "
5686 // + (post ? "appended" : ""));
5691 // sequence refs are identical. We may need to update the existing dataset
5692 // alignment with this one, though.
5693 if (ds != null && dseqs == null)
5695 int opos = ds.findIndex(dsq);
5696 SequenceI tseq = null;
5697 if (opos != -1 && vseqpos != opos)
5699 // remove from old position
5700 ds.deleteSequence(dsq);
5702 if (vseqpos < ds.getHeight())
5704 if (vseqpos != opos)
5706 // save sequence at destination position
5707 tseq = ds.getSequenceAt(vseqpos);
5708 ds.replaceSequenceAt(vseqpos, dsq);
5709 ds.addSequence(tseq);
5714 ds.addSequence(dsq);
5721 * TODO use AlignmentI here and in related methods - needs
5722 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
5724 Hashtable<String, AlignmentI> datasetIds = null;
5726 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
5728 private AlignmentI getDatasetFor(String datasetId)
5730 if (datasetIds == null)
5732 datasetIds = new Hashtable<>();
5735 if (datasetIds.containsKey(datasetId))
5737 return datasetIds.get(datasetId);
5742 private void addDatasetRef(String datasetId, AlignmentI dataset)
5744 if (datasetIds == null)
5746 datasetIds = new Hashtable<>();
5748 datasetIds.put(datasetId, dataset);
5752 * make a new dataset ID for this jalview dataset alignment
5757 private String getDatasetIdRef(AlignmentI dataset)
5759 if (dataset.getDataset() != null)
5761 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
5763 String datasetId = makeHashCode(dataset, null);
5764 if (datasetId == null)
5766 // make a new datasetId and record it
5767 if (dataset2Ids == null)
5769 dataset2Ids = new IdentityHashMap<>();
5773 datasetId = dataset2Ids.get(dataset);
5775 if (datasetId == null)
5777 datasetId = "ds" + dataset2Ids.size() + 1;
5778 dataset2Ids.put(dataset, datasetId);
5784 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5786 for (int d = 0; d < sequence.getDBRef().size(); d++)
5788 DBRef dr = sequence.getDBRef().get(d);
5789 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
5790 dr.getSource(), dr.getVersion(), dr.getAccessionId());
5791 if (dr.getMapping() != null)
5793 entry.setMap(addMapping(dr.getMapping()));
5795 datasetSequence.addDBRef(entry);
5799 private jalview.datamodel.Mapping addMapping(Mapping m)
5801 SequenceI dsto = null;
5802 // Mapping m = dr.getMapping();
5803 int fr[] = new int[m.getMapListFrom().size() * 2];
5804 Iterator<MapListFrom> from = m.getMapListFrom().iterator();// enumerateMapListFrom();
5805 for (int _i = 0; from.hasNext(); _i += 2)
5807 MapListFrom mf = from.next();
5808 fr[_i] = mf.getStart();
5809 fr[_i + 1] = mf.getEnd();
5811 int fto[] = new int[m.getMapListTo().size() * 2];
5812 Iterator<MapListTo> to = m.getMapListTo().iterator();// enumerateMapListTo();
5813 for (int _i = 0; to.hasNext(); _i += 2)
5815 MapListTo mf = to.next();
5816 fto[_i] = mf.getStart();
5817 fto[_i + 1] = mf.getEnd();
5819 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto, fr,
5820 fto, m.getMapFromUnit().intValue(),
5821 m.getMapToUnit().intValue());
5822 // if (m.getMappingChoice() != null)
5824 // MappingChoice mc = m.getMappingChoice();
5825 if (m.getDseqFor() != null)
5827 String dsfor = m.getDseqFor();
5828 if (seqRefIds.containsKey(dsfor))
5833 jmap.setTo(seqRefIds.get(dsfor));
5837 frefedSequence.add(newMappingRef(dsfor, jmap));
5843 * local sequence definition
5845 Sequence ms = m.getSequence();
5846 SequenceI djs = null;
5847 String sqid = ms.getDsseqid();
5848 if (sqid != null && sqid.length() > 0)
5851 * recover dataset sequence
5853 djs = seqRefIds.get(sqid);
5858 "Warning - making up dataset sequence id for DbRef sequence map reference");
5859 sqid = ((Object) ms).toString(); // make up a new hascode for
5860 // undefined dataset sequence hash
5861 // (unlikely to happen)
5867 * make a new dataset sequence and add it to refIds hash
5869 djs = new jalview.datamodel.Sequence(ms.getName(),
5871 djs.setStart(jmap.getMap().getToLowest());
5872 djs.setEnd(jmap.getMap().getToHighest());
5873 djs.setVamsasId(uniqueSetSuffix + sqid);
5875 incompleteSeqs.put(sqid, djs);
5876 seqRefIds.put(sqid, djs);
5879 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5888 * Provides a 'copy' of an alignment view (on action New View) by 'saving' the
5889 * view as XML (but not to file), and then reloading it
5894 public AlignmentPanel copyAlignPanel(AlignmentPanel ap)
5897 JalviewModel jm = saveState(ap, null, null, null);
5900 jm.getVamsasModel().getSequenceSet().get(0).getDatasetId(),
5901 ap.getAlignment().getDataset());
5903 uniqueSetSuffix = "";
5904 // jm.getJalviewModelSequence().getViewport(0).setId(null);
5905 jm.getViewport().get(0).setId(null);
5906 // we don't overwrite the view we just copied
5908 if (this.frefedSequence == null)
5910 frefedSequence = new Vector<>();
5913 viewportsAdded.clear();
5915 AlignFrame af = loadFromObject(jm, null, false, null);
5916 af.getAlignPanels().clear();
5917 af.closeMenuItem_actionPerformed(true);
5920 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5921 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5922 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5923 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5924 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5927 return af.alignPanel;
5930 private Hashtable jvids2vobj;
5932 private void warn(String msg)
5937 private void warn(String msg, Exception e)
5939 if (Cache.log != null)
5943 Cache.log.warn(msg, e);
5947 Cache.log.warn(msg);
5952 System.err.println("Warning: " + msg);
5955 e.printStackTrace();
5960 private void debug(String string)
5962 debug(string, null);
5965 private void debug(String msg, Exception e)
5967 if (Cache.log != null)
5971 Cache.log.debug(msg, e);
5975 Cache.log.debug(msg);
5980 System.err.println("Warning: " + msg);
5983 e.printStackTrace();
5989 * set the object to ID mapping tables used to write/recover objects and XML
5990 * ID strings for the jalview project. If external tables are provided then
5991 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
5992 * object goes out of scope. - also populates the datasetIds hashtable with
5993 * alignment objects containing dataset sequences
5996 * Map from ID strings to jalview datamodel
5998 * Map from jalview datamodel to ID strings
6002 public void setObjectMappingTables(Hashtable vobj2jv,
6003 IdentityHashMap jv2vobj)
6005 this.jv2vobj = jv2vobj;
6006 this.vobj2jv = vobj2jv;
6007 Iterator ds = jv2vobj.keySet().iterator();
6009 while (ds.hasNext())
6011 Object jvobj = ds.next();
6012 id = jv2vobj.get(jvobj).toString();
6013 if (jvobj instanceof jalview.datamodel.Alignment)
6015 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
6017 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
6020 else if (jvobj instanceof jalview.datamodel.Sequence)
6022 // register sequence object so the XML parser can recover it.
6023 if (seqRefIds == null)
6025 seqRefIds = new HashMap<>();
6027 if (seqsToIds == null)
6029 seqsToIds = new IdentityHashMap<>();
6031 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
6032 seqsToIds.put((SequenceI) jvobj, id);
6034 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
6037 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
6038 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
6039 if (jvann.annotationId == null)
6041 jvann.annotationId = anid;
6043 if (!jvann.annotationId.equals(anid))
6045 // TODO verify that this is the correct behaviour
6046 this.warn("Overriding Annotation ID for " + anid
6047 + " from different id : " + jvann.annotationId);
6048 jvann.annotationId = anid;
6051 else if (jvobj instanceof String)
6053 if (jvids2vobj == null)
6055 jvids2vobj = new Hashtable();
6056 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
6061 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
6067 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
6068 * objects created from the project archive. If string is null (default for
6069 * construction) then suffix will be set automatically.
6073 public void setUniqueSetSuffix(String string)
6075 uniqueSetSuffix = string;
6080 * uses skipList2 as the skipList for skipping views on sequence sets
6081 * associated with keys in the skipList
6085 public void setSkipList(Hashtable skipList2)
6087 skipList = skipList2;
6091 * Reads the jar entry of given name and returns its contents, or null if the
6092 * entry is not found.
6095 * @param jarEntryName
6098 protected String readJarEntry(jarInputStreamProvider jprovider,
6099 String jarEntryName)
6101 String result = null;
6102 BufferedReader in = null;
6107 * Reopen the jar input stream and traverse its entries to find a matching
6110 JarInputStream jin = jprovider.getJarInputStream();
6111 JarEntry entry = null;
6114 entry = jin.getNextJarEntry();
6115 } while (entry != null && !entry.getName().equals(jarEntryName));
6119 StringBuilder out = new StringBuilder(256);
6120 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
6123 while ((data = in.readLine()) != null)
6127 result = out.toString();
6131 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
6133 } catch (Exception ex)
6135 ex.printStackTrace();
6143 } catch (IOException e)
6154 * Returns an incrementing counter (0, 1, 2...)
6158 private synchronized int nextCounter()
6164 * Loads any saved PCA viewers
6169 protected void loadPCAViewers(JalviewModel model, AlignmentPanel ap)
6173 List<PcaViewer> pcaviewers = model.getPcaViewer();
6174 for (PcaViewer viewer : pcaviewers)
6176 String modelName = viewer.getScoreModelName();
6177 SimilarityParamsI params = new SimilarityParams(
6178 viewer.isIncludeGappedColumns(), viewer.isMatchGaps(),
6179 viewer.isIncludeGaps(),
6180 viewer.isDenominateByShortestLength());
6183 * create the panel (without computing the PCA)
6185 PCAPanel panel = new PCAPanel(ap, modelName, params);
6187 panel.setTitle(viewer.getTitle());
6188 panel.setBounds(new Rectangle(viewer.getXpos(), viewer.getYpos(),
6189 viewer.getWidth(), viewer.getHeight()));
6191 boolean showLabels = viewer.isShowLabels();
6192 panel.setShowLabels(showLabels);
6193 panel.getRotatableCanvas().setShowLabels(showLabels);
6194 panel.getRotatableCanvas()
6195 .setBgColour(new Color(viewer.getBgColour()));
6196 panel.getRotatableCanvas()
6197 .setApplyToAllViews(viewer.isLinkToAllViews());
6200 * load PCA output data
6202 ScoreModelI scoreModel = ScoreModels.getInstance()
6203 .getScoreModel(modelName, ap);
6204 PCA pca = new PCA(null, scoreModel, params);
6205 PcaDataType pcaData = viewer.getPcaData();
6207 MatrixI pairwise = loadDoubleMatrix(pcaData.getPairwiseMatrix());
6208 pca.setPairwiseScores(pairwise);
6210 MatrixI triDiag = loadDoubleMatrix(pcaData.getTridiagonalMatrix());
6211 pca.setTridiagonal(triDiag);
6213 MatrixI result = loadDoubleMatrix(pcaData.getEigenMatrix());
6214 pca.setEigenmatrix(result);
6216 panel.getPcaModel().setPCA(pca);
6219 * we haven't saved the input data! (JAL-2647 to do)
6221 panel.setInputData(null);
6224 * add the sequence points for the PCA display
6226 List<jalview.datamodel.SequencePoint> seqPoints = new ArrayList<>();
6227 for (SequencePoint sp : viewer.getSequencePoint())
6229 String seqId = sp.getSequenceRef();
6230 SequenceI seq = seqRefIds.get(seqId);
6233 throw new IllegalStateException(
6234 "Unmatched seqref for PCA: " + seqId);
6236 Point pt = new Point(sp.getXPos(), sp.getYPos(), sp.getZPos());
6237 jalview.datamodel.SequencePoint seqPoint = new jalview.datamodel.SequencePoint(
6239 seqPoints.add(seqPoint);
6241 panel.getRotatableCanvas().setPoints(seqPoints, seqPoints.size());
6244 * set min-max ranges and scale after setPoints (which recomputes them)
6246 panel.getRotatableCanvas().setScaleFactor(viewer.getScaleFactor());
6247 SeqPointMin spMin = viewer.getSeqPointMin();
6248 float[] min = new float[] { spMin.getXPos(), spMin.getYPos(),
6250 SeqPointMax spMax = viewer.getSeqPointMax();
6251 float[] max = new float[] { spMax.getXPos(), spMax.getYPos(),
6253 panel.getRotatableCanvas().setSeqMinMax(min, max);
6255 // todo: hold points list in PCAModel only
6256 panel.getPcaModel().setSequencePoints(seqPoints);
6258 panel.setSelectedDimensionIndex(viewer.getXDim(), X);
6259 panel.setSelectedDimensionIndex(viewer.getYDim(), Y);
6260 panel.setSelectedDimensionIndex(viewer.getZDim(), Z);
6262 // is this duplication needed?
6263 panel.setTop(seqPoints.size() - 1);
6264 panel.getPcaModel().setTop(seqPoints.size() - 1);
6267 * add the axes' end points for the display
6269 for (int i = 0; i < 3; i++)
6271 Axis axis = viewer.getAxis().get(i);
6272 panel.getRotatableCanvas().getAxisEndPoints()[i] = new Point(
6273 axis.getXPos(), axis.getYPos(), axis.getZPos());
6276 Desktop.addInternalFrame(panel, MessageManager.formatMessage(
6277 "label.calc_title", "PCA", modelName), 475, 450);
6279 } catch (Exception ex)
6281 Cache.log.error("Error loading PCA: " + ex.toString());
6286 * Populates an XML model of the feature colour scheme for one feature type
6288 * @param featureType
6292 public static Colour marshalColour(
6293 String featureType, FeatureColourI fcol)
6295 Colour col = new Colour();
6296 if (fcol.isSimpleColour())
6298 col.setRGB(Format.getHexString(fcol.getColour()));
6302 col.setRGB(Format.getHexString(fcol.getMaxColour()));
6303 col.setMin(fcol.getMin());
6304 col.setMax(fcol.getMax());
6305 col.setMinRGB(jalview.util.Format.getHexString(fcol.getMinColour()));
6306 col.setAutoScale(fcol.isAutoScaled());
6307 col.setThreshold(fcol.getThreshold());
6308 col.setColourByLabel(fcol.isColourByLabel());
6309 col.setThreshType(fcol.isAboveThreshold() ? ThresholdType.ABOVE
6310 : (fcol.isBelowThreshold() ? ThresholdType.BELOW
6311 : ThresholdType.NONE));
6312 if (fcol.isColourByAttribute())
6314 final String[] attName = fcol.getAttributeName();
6315 col.getAttributeName().add(attName[0]);
6316 if (attName.length > 1)
6318 col.getAttributeName().add(attName[1]);
6321 Color noColour = fcol.getNoColour();
6322 if (noColour == null)
6324 col.setNoValueColour(NoValueColour.NONE);
6326 else if (noColour == fcol.getMaxColour())
6328 col.setNoValueColour(NoValueColour.MAX);
6332 col.setNoValueColour(NoValueColour.MIN);
6335 col.setName(featureType);
6340 * Populates an XML model of the feature filter(s) for one feature type
6342 * @param firstMatcher
6343 * the first (or only) match condition)
6345 * remaining match conditions (if any)
6347 * if true, conditions are and-ed, else or-ed
6349 public static jalview.xml.binding.jalview.FeatureMatcherSet marshalFilter(
6350 FeatureMatcherI firstMatcher, Iterator<FeatureMatcherI> filters,
6353 jalview.xml.binding.jalview.FeatureMatcherSet result = new jalview.xml.binding.jalview.FeatureMatcherSet();
6355 if (filters.hasNext())
6360 CompoundMatcher compound = new CompoundMatcher();
6361 compound.setAnd(and);
6362 jalview.xml.binding.jalview.FeatureMatcherSet matcher1 = marshalFilter(
6363 firstMatcher, Collections.emptyIterator(), and);
6364 // compound.addMatcherSet(matcher1);
6365 compound.getMatcherSet().add(matcher1);
6366 FeatureMatcherI nextMatcher = filters.next();
6367 jalview.xml.binding.jalview.FeatureMatcherSet matcher2 = marshalFilter(
6368 nextMatcher, filters, and);
6369 // compound.addMatcherSet(matcher2);
6370 compound.getMatcherSet().add(matcher2);
6371 result.setCompoundMatcher(compound);
6376 * single condition matcher
6378 // MatchCondition matcherModel = new MatchCondition();
6379 jalview.xml.binding.jalview.FeatureMatcher matcherModel = new jalview.xml.binding.jalview.FeatureMatcher();
6380 matcherModel.setCondition(
6381 firstMatcher.getMatcher().getCondition().getStableName());
6382 matcherModel.setValue(firstMatcher.getMatcher().getPattern());
6383 if (firstMatcher.isByAttribute())
6385 matcherModel.setBy(FilterBy.BY_ATTRIBUTE);
6386 // matcherModel.setAttributeName(firstMatcher.getAttribute());
6387 String[] attName = firstMatcher.getAttribute();
6388 matcherModel.getAttributeName().add(attName[0]); // attribute
6389 if (attName.length > 1)
6391 matcherModel.getAttributeName().add(attName[1]); // sub-attribute
6394 else if (firstMatcher.isByLabel())
6396 matcherModel.setBy(FilterBy.BY_LABEL);
6398 else if (firstMatcher.isByScore())
6400 matcherModel.setBy(FilterBy.BY_SCORE);
6402 result.setMatchCondition(matcherModel);
6409 * Loads one XML model of a feature filter to a Jalview object
6411 * @param featureType
6412 * @param matcherSetModel
6415 public static FeatureMatcherSetI parseFilter(
6417 jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel)
6419 FeatureMatcherSetI result = new FeatureMatcherSet();
6422 parseFilterConditions(result, matcherSetModel, true);
6423 } catch (IllegalStateException e)
6425 // mixing AND and OR conditions perhaps
6427 String.format("Error reading filter conditions for '%s': %s",
6428 featureType, e.getMessage()));
6429 // return as much as was parsed up to the error
6436 * Adds feature match conditions to matcherSet as unmarshalled from XML
6437 * (possibly recursively for compound conditions)
6440 * @param matcherSetModel
6442 * if true, multiple conditions are AND-ed, else they are OR-ed
6443 * @throws IllegalStateException
6444 * if AND and OR conditions are mixed
6446 protected static void parseFilterConditions(
6447 FeatureMatcherSetI matcherSet,
6448 jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel,
6451 jalview.xml.binding.jalview.FeatureMatcher mc = matcherSetModel
6452 .getMatchCondition();
6458 FilterBy filterBy = mc.getBy();
6459 Condition cond = Condition.fromString(mc.getCondition());
6460 String pattern = mc.getValue();
6461 FeatureMatcherI matchCondition = null;
6462 if (filterBy == FilterBy.BY_LABEL)
6464 matchCondition = FeatureMatcher.byLabel(cond, pattern);
6466 else if (filterBy == FilterBy.BY_SCORE)
6468 matchCondition = FeatureMatcher.byScore(cond, pattern);
6471 else if (filterBy == FilterBy.BY_ATTRIBUTE)
6473 final List<String> attributeName = mc.getAttributeName();
6474 String[] attNames = attributeName
6475 .toArray(new String[attributeName.size()]);
6476 matchCondition = FeatureMatcher.byAttribute(cond, pattern,
6481 * note this throws IllegalStateException if AND-ing to a
6482 * previously OR-ed compound condition, or vice versa
6486 matcherSet.and(matchCondition);
6490 matcherSet.or(matchCondition);
6496 * compound condition
6498 List<jalview.xml.binding.jalview.FeatureMatcherSet> matchers = matcherSetModel
6499 .getCompoundMatcher().getMatcherSet();
6500 boolean anded = matcherSetModel.getCompoundMatcher().isAnd();
6501 if (matchers.size() == 2)
6503 parseFilterConditions(matcherSet, matchers.get(0), anded);
6504 parseFilterConditions(matcherSet, matchers.get(1), anded);
6508 System.err.println("Malformed compound filter condition");
6514 * Loads one XML model of a feature colour to a Jalview object
6516 * @param colourModel
6519 public static FeatureColourI parseColour(Colour colourModel)
6521 FeatureColourI colour = null;
6523 if (colourModel.getMax() != null)
6525 Color mincol = null;
6526 Color maxcol = null;
6527 Color noValueColour = null;
6531 mincol = new Color(Integer.parseInt(colourModel.getMinRGB(), 16));
6532 maxcol = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6533 } catch (Exception e)
6535 Cache.log.warn("Couldn't parse out graduated feature color.", e);
6538 NoValueColour noCol = colourModel.getNoValueColour();
6539 if (noCol == NoValueColour.MIN)
6541 noValueColour = mincol;
6543 else if (noCol == NoValueColour.MAX)
6545 noValueColour = maxcol;
6548 colour = new FeatureColour(mincol, maxcol, noValueColour,
6549 safeFloat(colourModel.getMin()),
6550 safeFloat(colourModel.getMax()));
6551 final List<String> attributeName = colourModel.getAttributeName();
6552 String[] attributes = attributeName
6553 .toArray(new String[attributeName.size()]);
6554 if (attributes != null && attributes.length > 0)
6556 colour.setAttributeName(attributes);
6558 if (colourModel.isAutoScale() != null)
6560 colour.setAutoScaled(colourModel.isAutoScale().booleanValue());
6562 if (colourModel.isColourByLabel() != null)
6564 colour.setColourByLabel(
6565 colourModel.isColourByLabel().booleanValue());
6567 if (colourModel.getThreshold() != null)
6569 colour.setThreshold(colourModel.getThreshold().floatValue());
6571 ThresholdType ttyp = colourModel.getThreshType();
6572 if (ttyp == ThresholdType.ABOVE)
6574 colour.setAboveThreshold(true);
6576 else if (ttyp == ThresholdType.BELOW)
6578 colour.setBelowThreshold(true);
6583 Color color = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6584 colour = new FeatureColour(color);