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 java.awt.Color;
29 import java.awt.FontMetrics;
30 import java.awt.Rectangle;
31 import java.io.BufferedReader;
32 import java.io.ByteArrayInputStream;
34 import java.io.FileInputStream;
35 import java.io.FileOutputStream;
36 import java.io.IOException;
37 import java.io.InputStream;
38 import java.io.InputStreamReader;
39 import java.io.OutputStream;
40 import java.io.OutputStreamWriter;
41 import java.io.PrintWriter;
42 import java.lang.reflect.InvocationTargetException;
43 import java.math.BigInteger;
44 import java.net.MalformedURLException;
46 import java.util.ArrayList;
47 import java.util.Arrays;
48 import java.util.BitSet;
49 import java.util.Collections;
50 import java.util.Enumeration;
51 import java.util.GregorianCalendar;
52 import java.util.HashMap;
53 import java.util.HashSet;
54 import java.util.Hashtable;
55 import java.util.IdentityHashMap;
56 import java.util.Iterator;
57 import java.util.LinkedHashMap;
58 import java.util.List;
59 import java.util.Locale;
61 import java.util.Map.Entry;
63 import java.util.Vector;
64 import java.util.jar.JarEntry;
65 import java.util.jar.JarInputStream;
66 import java.util.jar.JarOutputStream;
68 import javax.swing.JInternalFrame;
69 import javax.swing.SwingUtilities;
70 import javax.xml.bind.JAXBContext;
71 import javax.xml.bind.JAXBElement;
72 import javax.xml.bind.Marshaller;
73 import javax.xml.datatype.DatatypeConfigurationException;
74 import javax.xml.datatype.DatatypeFactory;
75 import javax.xml.datatype.XMLGregorianCalendar;
76 import javax.xml.stream.XMLInputFactory;
77 import javax.xml.stream.XMLStreamReader;
79 import jalview.analysis.Conservation;
80 import jalview.analysis.PCA;
81 import jalview.analysis.scoremodels.ScoreModels;
82 import jalview.analysis.scoremodels.SimilarityParams;
83 import jalview.api.FeatureColourI;
84 import jalview.api.ViewStyleI;
85 import jalview.api.analysis.ScoreModelI;
86 import jalview.api.analysis.SimilarityParamsI;
87 import jalview.api.structures.JalviewStructureDisplayI;
88 import jalview.bin.Cache;
89 import jalview.bin.Console;
90 import jalview.datamodel.AlignedCodonFrame;
91 import jalview.datamodel.Alignment;
92 import jalview.datamodel.AlignmentAnnotation;
93 import jalview.datamodel.AlignmentI;
94 import jalview.datamodel.ContactMatrix;
95 import jalview.datamodel.ContactMatrixI;
96 import jalview.datamodel.DBRefEntry;
97 import jalview.datamodel.GeneLocus;
98 import jalview.datamodel.GraphLine;
99 import jalview.datamodel.GroupSet;
100 import jalview.datamodel.PDBEntry;
101 import jalview.datamodel.Point;
102 import jalview.datamodel.RnaViewerModel;
103 import jalview.datamodel.SequenceFeature;
104 import jalview.datamodel.SequenceGroup;
105 import jalview.datamodel.SequenceI;
106 import jalview.datamodel.StructureViewerModel;
107 import jalview.datamodel.StructureViewerModel.StructureData;
108 import jalview.datamodel.features.FeatureMatcher;
109 import jalview.datamodel.features.FeatureMatcherI;
110 import jalview.datamodel.features.FeatureMatcherSet;
111 import jalview.datamodel.features.FeatureMatcherSetI;
112 import jalview.ext.varna.RnaModel;
113 import jalview.gui.AlignFrame;
114 import jalview.gui.AlignViewport;
115 import jalview.gui.AlignmentPanel;
116 import jalview.gui.AppVarna;
117 import jalview.gui.Desktop;
118 import jalview.gui.JvOptionPane;
119 import jalview.gui.OOMWarning;
120 import jalview.gui.OverviewPanel;
121 import jalview.gui.PCAPanel;
122 import jalview.gui.PaintRefresher;
123 import jalview.gui.SplitFrame;
124 import jalview.gui.StructureViewer;
125 import jalview.gui.StructureViewer.ViewerType;
126 import jalview.gui.StructureViewerBase;
127 import jalview.gui.TreePanel;
128 import jalview.io.BackupFiles;
129 import jalview.io.DataSourceType;
130 import jalview.io.FileFormat;
131 import jalview.io.NewickFile;
132 import jalview.math.Matrix;
133 import jalview.math.MatrixI;
134 import jalview.renderer.ResidueShaderI;
135 import jalview.schemes.AnnotationColourGradient;
136 import jalview.schemes.ColourSchemeI;
137 import jalview.schemes.ColourSchemeProperty;
138 import jalview.schemes.FeatureColour;
139 import jalview.schemes.ResidueProperties;
140 import jalview.schemes.UserColourScheme;
141 import jalview.structure.StructureSelectionManager;
142 import jalview.structures.models.AAStructureBindingModel;
143 import jalview.util.Format;
144 import jalview.util.HttpUtils;
145 import jalview.util.MessageManager;
146 import jalview.util.Platform;
147 import jalview.util.StringUtils;
148 import jalview.util.jarInputStreamProvider;
149 import jalview.util.matcher.Condition;
150 import jalview.viewmodel.AlignmentViewport;
151 import jalview.viewmodel.PCAModel;
152 import jalview.viewmodel.ViewportRanges;
153 import jalview.viewmodel.seqfeatures.FeatureRendererModel;
154 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
155 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
156 import jalview.ws.datamodel.MappableContactMatrixI;
157 import jalview.ws.datamodel.alphafold.PAEContactMatrix;
158 import jalview.ws.jws2.Jws2Discoverer;
159 import jalview.ws.jws2.dm.AAConSettings;
160 import jalview.ws.jws2.jabaws2.Jws2Instance;
161 import jalview.ws.params.ArgumentI;
162 import jalview.ws.params.AutoCalcSetting;
163 import jalview.ws.params.WsParamSetI;
164 import jalview.xml.binding.jalview.AlcodonFrame;
165 import jalview.xml.binding.jalview.AlcodonFrame.AlcodMap;
166 import jalview.xml.binding.jalview.Annotation;
167 import jalview.xml.binding.jalview.Annotation.ThresholdLine;
168 import jalview.xml.binding.jalview.AnnotationColourScheme;
169 import jalview.xml.binding.jalview.AnnotationElement;
170 import jalview.xml.binding.jalview.DoubleMatrix;
171 import jalview.xml.binding.jalview.DoubleVector;
172 import jalview.xml.binding.jalview.Feature;
173 import jalview.xml.binding.jalview.Feature.OtherData;
174 import jalview.xml.binding.jalview.FeatureMatcherSet.CompoundMatcher;
175 import jalview.xml.binding.jalview.FilterBy;
176 import jalview.xml.binding.jalview.JalviewModel;
177 import jalview.xml.binding.jalview.JalviewModel.FeatureSettings;
178 import jalview.xml.binding.jalview.JalviewModel.FeatureSettings.Group;
179 import jalview.xml.binding.jalview.JalviewModel.FeatureSettings.Setting;
180 import jalview.xml.binding.jalview.JalviewModel.JGroup;
181 import jalview.xml.binding.jalview.JalviewModel.JSeq;
182 import jalview.xml.binding.jalview.JalviewModel.JSeq.Pdbids;
183 import jalview.xml.binding.jalview.JalviewModel.JSeq.Pdbids.StructureState;
184 import jalview.xml.binding.jalview.JalviewModel.JSeq.RnaViewer;
185 import jalview.xml.binding.jalview.JalviewModel.JSeq.RnaViewer.SecondaryStructure;
186 import jalview.xml.binding.jalview.JalviewModel.PcaViewer;
187 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.Axis;
188 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.SeqPointMax;
189 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.SeqPointMin;
190 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.SequencePoint;
191 import jalview.xml.binding.jalview.JalviewModel.Tree;
192 import jalview.xml.binding.jalview.JalviewModel.UserColours;
193 import jalview.xml.binding.jalview.JalviewModel.Viewport;
194 import jalview.xml.binding.jalview.JalviewModel.Viewport.CalcIdParam;
195 import jalview.xml.binding.jalview.JalviewModel.Viewport.HiddenColumns;
196 import jalview.xml.binding.jalview.JalviewModel.Viewport.Overview;
197 import jalview.xml.binding.jalview.JalviewUserColours;
198 import jalview.xml.binding.jalview.JalviewUserColours.Colour;
199 import jalview.xml.binding.jalview.MapListType;
200 import jalview.xml.binding.jalview.MapListType.MapListFrom;
201 import jalview.xml.binding.jalview.MapListType.MapListTo;
202 import jalview.xml.binding.jalview.Mapping;
203 import jalview.xml.binding.jalview.MatrixType;
204 import jalview.xml.binding.jalview.NoValueColour;
205 import jalview.xml.binding.jalview.ObjectFactory;
206 import jalview.xml.binding.jalview.PcaDataType;
207 import jalview.xml.binding.jalview.Pdbentry.Property;
208 import jalview.xml.binding.jalview.Sequence;
209 import jalview.xml.binding.jalview.Sequence.DBRef;
210 import jalview.xml.binding.jalview.SequenceSet;
211 import jalview.xml.binding.jalview.SequenceSet.SequenceSetProperties;
212 import jalview.xml.binding.jalview.ThresholdType;
213 import jalview.xml.binding.jalview.VAMSAS;
216 * Write out the current jalview desktop state as a Jalview XML stream.
218 * Note: the vamsas objects referred to here are primitive versions of the
219 * VAMSAS project schema elements - they are not the same and most likely never
223 * @version $Revision: 1.134 $
225 public class Jalview2XML
228 // BH 2018 we add the .jvp binary extension to J2S so that
229 // it will declare that binary when we do the file save from the browser
233 Platform.addJ2SBinaryType(".jvp?");
236 private static final String VIEWER_PREFIX = "viewer_";
238 private static final String RNA_PREFIX = "rna_";
240 private static final String UTF_8 = "UTF-8";
243 * used in decision if quit confirmation should be issued
245 private static boolean stateSavedUpToDate = false;
248 * prefix for recovering datasets for alignments with multiple views where
249 * non-existent dataset IDs were written for some views
251 private static final String UNIQSEQSETID = "uniqueSeqSetId.";
253 // use this with nextCounter() to make unique names for entities
254 private int counter = 0;
257 * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
258 * of sequence objects are created.
260 IdentityHashMap<SequenceI, String> seqsToIds = null;
263 * jalview XML Sequence ID to jalview sequence object reference (both dataset
264 * and alignment sequences. Populated as XML reps of sequence objects are
267 Map<String, SequenceI> seqRefIds = null;
269 Map<String, SequenceI> incompleteSeqs = null;
271 List<SeqFref> frefedSequence = null;
273 boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
276 * Map of reconstructed AlignFrame objects that appear to have come from
277 * SplitFrame objects (have a dna/protein complement view).
279 private Map<Viewport, AlignFrame> splitFrameCandidates = new HashMap<>();
282 * Map from displayed rna structure models to their saved session state jar
285 private Map<RnaModel, String> rnaSessions = new HashMap<>();
288 * A helper method for safely using the value of an optional attribute that
289 * may be null if not present in the XML. Answers the boolean value, or false
295 public static boolean safeBoolean(Boolean b)
297 return b == null ? false : b.booleanValue();
301 * A helper method for safely using the value of an optional attribute that
302 * may be null if not present in the XML. Answers the integer value, or zero
308 public static int safeInt(Integer i)
310 return i == null ? 0 : i.intValue();
314 * A helper method for safely using the value of an optional attribute that
315 * may be null if not present in the XML. Answers the float value, or zero if
321 public static float safeFloat(Float f)
323 return f == null ? 0f : f.floatValue();
327 * create/return unique hash string for sq
330 * @return new or existing unique string for sq
332 String seqHash(SequenceI sq)
334 if (seqsToIds == null)
338 if (seqsToIds.containsKey(sq))
340 return seqsToIds.get(sq);
344 // create sequential key
345 String key = "sq" + (seqsToIds.size() + 1);
346 key = makeHashCode(sq, key); // check we don't have an external reference
348 seqsToIds.put(sq, key);
355 if (seqsToIds == null)
357 seqsToIds = new IdentityHashMap<>();
359 if (seqRefIds == null)
361 seqRefIds = new HashMap<>();
363 if (incompleteSeqs == null)
365 incompleteSeqs = new HashMap<>();
367 if (frefedSequence == null)
369 frefedSequence = new ArrayList<>();
377 public Jalview2XML(boolean raiseGUI)
379 this.raiseGUI = raiseGUI;
383 * base class for resolving forward references to sequences by their ID
388 abstract class SeqFref
394 public SeqFref(String _sref, String type)
400 public String getSref()
405 public SequenceI getSrefSeq()
407 return seqRefIds.get(sref);
410 public boolean isResolvable()
412 return seqRefIds.get(sref) != null;
415 public SequenceI getSrefDatasetSeq()
417 SequenceI sq = seqRefIds.get(sref);
420 while (sq.getDatasetSequence() != null)
422 sq = sq.getDatasetSequence();
429 * @return true if the forward reference was fully resolved
431 abstract boolean resolve();
434 public String toString()
436 return type + " reference to " + sref;
441 * create forward reference for a mapping
447 public SeqFref newMappingRef(final String sref,
448 final jalview.datamodel.Mapping _jmap)
450 SeqFref fref = new SeqFref(sref, "Mapping")
452 public jalview.datamodel.Mapping jmap = _jmap;
457 SequenceI seq = getSrefDatasetSeq();
469 public SeqFref newAlcodMapRef(final String sref,
470 final AlignedCodonFrame _cf,
471 final jalview.datamodel.Mapping _jmap)
474 SeqFref fref = new SeqFref(sref, "Codon Frame")
476 AlignedCodonFrame cf = _cf;
478 public jalview.datamodel.Mapping mp = _jmap;
481 public boolean isResolvable()
483 return super.isResolvable() && mp.getTo() != null;
489 SequenceI seq = getSrefDatasetSeq();
494 cf.addMap(seq, mp.getTo(), mp.getMap());
501 public void resolveFrefedSequences()
503 Iterator<SeqFref> nextFref = frefedSequence.iterator();
504 int toresolve = frefedSequence.size();
505 int unresolved = 0, failedtoresolve = 0;
506 while (nextFref.hasNext())
508 SeqFref ref = nextFref.next();
509 if (ref.isResolvable())
521 } catch (Exception x)
524 "IMPLEMENTATION ERROR: Failed to resolve forward reference for sequence "
537 System.err.println("Jalview Project Import: There were " + unresolved
538 + " forward references left unresolved on the stack.");
540 if (failedtoresolve > 0)
542 System.err.println("SERIOUS! " + failedtoresolve
543 + " resolvable forward references failed to resolve.");
545 if (incompleteSeqs != null && incompleteSeqs.size() > 0)
548 "Jalview Project Import: There are " + incompleteSeqs.size()
549 + " sequences which may have incomplete metadata.");
550 if (incompleteSeqs.size() < 10)
552 for (SequenceI s : incompleteSeqs.values())
554 System.err.println(s.toString());
560 "Too many to report. Skipping output of incomplete sequences.");
566 * This maintains a map of viewports, the key being the seqSetId. Important to
567 * set historyItem and redoList for multiple views
569 Map<String, AlignViewport> viewportsAdded = new HashMap<>();
571 Map<String, AlignmentAnnotation> annotationIds = new HashMap<>();
573 String uniqueSetSuffix = "";
576 * List of pdbfiles added to Jar
578 List<String> pdbfiles = null;
580 // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
581 public void saveState(File statefile)
583 FileOutputStream fos = null;
588 fos = new FileOutputStream(statefile);
590 JarOutputStream jout = new JarOutputStream(fos);
594 } catch (Exception e)
596 Console.error("Couln't write Jalview state to " + statefile, e);
597 // TODO: inform user of the problem - they need to know if their data was
599 if (errorMessage == null)
601 errorMessage = "Did't write Jalview Archive to output file '"
602 + statefile + "' - See console error log for details";
606 errorMessage += "(Didn't write Jalview Archive to output file '"
617 } catch (IOException e)
627 * Writes a jalview project archive to the given Jar output stream.
631 public void saveState(JarOutputStream jout)
633 AlignFrame[] frames = Desktop.getAlignFrames();
635 setStateSavedUpToDate(true);
637 if (Cache.getDefault("DEBUG_DELAY_SAVE", false))
639 int n = debugDelaySave;
643 Console.debug("***** debugging save sleep " + i + "/" + n);
647 } catch (InterruptedException e)
649 // TODO Auto-generated catch block
660 saveAllFrames(Arrays.asList(frames), jout);
664 * core method for storing state for a set of AlignFrames.
667 * - frames involving all data to be exported (including containing
670 * - project output stream
672 private void saveAllFrames(List<AlignFrame> frames, JarOutputStream jout)
674 Hashtable<String, AlignFrame> dsses = new Hashtable<>();
677 * ensure cached data is clear before starting
679 // todo tidy up seqRefIds, seqsToIds initialisation / reset
681 splitFrameCandidates.clear();
686 // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
687 // //////////////////////////////////////////////////
689 List<String> shortNames = new ArrayList<>();
690 List<String> viewIds = new ArrayList<>();
693 for (int i = frames.size() - 1; i > -1; i--)
695 AlignFrame af = frames.get(i);
697 if (skipList != null && skipList
698 .containsKey(af.getViewport().getSequenceSetId()))
703 String shortName = makeFilename(af, shortNames);
705 int apSize = af.getAlignPanels().size();
707 for (int ap = 0; ap < apSize; ap++)
709 AlignmentPanel apanel = (AlignmentPanel) af.getAlignPanels()
711 String fileName = apSize == 1 ? shortName : ap + shortName;
712 if (!fileName.endsWith(".xml"))
714 fileName = fileName + ".xml";
717 saveState(apanel, fileName, jout, viewIds);
719 String dssid = getDatasetIdRef(
720 af.getViewport().getAlignment().getDataset());
721 if (!dsses.containsKey(dssid))
723 dsses.put(dssid, af);
728 writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix,
734 } catch (Exception foo)
738 } catch (Exception ex)
740 // TODO: inform user of the problem - they need to know if their data was
742 if (errorMessage == null)
744 errorMessage = "Couldn't write Jalview Archive - see error output for details";
746 ex.printStackTrace();
751 * Generates a distinct file name, based on the title of the AlignFrame, by
752 * appending _n for increasing n until an unused name is generated. The new
753 * name (without its extension) is added to the list.
757 * @return the generated name, with .xml extension
759 protected String makeFilename(AlignFrame af, List<String> namesUsed)
761 String shortName = af.getTitle();
763 if (shortName.indexOf(File.separatorChar) > -1)
765 shortName = shortName
766 .substring(shortName.lastIndexOf(File.separatorChar) + 1);
771 while (namesUsed.contains(shortName))
773 if (shortName.endsWith("_" + (count - 1)))
775 shortName = shortName.substring(0, shortName.lastIndexOf("_"));
778 shortName = shortName.concat("_" + count);
782 namesUsed.add(shortName);
784 if (!shortName.endsWith(".xml"))
786 shortName = shortName + ".xml";
791 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
792 public boolean saveAlignment(AlignFrame af, String jarFile,
797 // create backupfiles object and get new temp filename destination
798 boolean doBackup = BackupFiles.getEnabled();
799 BackupFiles backupfiles = doBackup ? new BackupFiles(jarFile) : null;
800 FileOutputStream fos = new FileOutputStream(
801 doBackup ? backupfiles.getTempFilePath() : jarFile);
803 if (Cache.getDefault("DEBUG_DELAY_SAVE", false))
805 int n = debugDelaySave;
809 Console.debug("***** debugging save sleep " + i + "/" + n);
813 } catch (InterruptedException e)
815 // TODO Auto-generated catch block
822 JarOutputStream jout = new JarOutputStream(fos);
823 List<AlignFrame> frames = new ArrayList<>();
825 // resolve splitframes
826 if (af.getViewport().getCodingComplement() != null)
828 frames = ((SplitFrame) af.getSplitViewContainer()).getAlignFrames();
834 saveAllFrames(frames, jout);
838 } catch (Exception foo)
842 boolean success = true;
846 backupfiles.setWriteSuccess(success);
847 success = backupfiles.rollBackupsAndRenameTempFile();
851 } catch (Exception ex)
853 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
854 ex.printStackTrace();
859 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
860 String fileName, JarOutputStream jout)
863 for (String dssids : dsses.keySet())
865 AlignFrame _af = dsses.get(dssids);
866 String jfileName = fileName + " Dataset for " + _af.getTitle();
867 if (!jfileName.endsWith(".xml"))
869 jfileName = jfileName + ".xml";
871 saveState(_af.alignPanel, jfileName, true, jout, null);
876 * create a JalviewModel from an alignment view and marshall it to a
880 * panel to create jalview model for
882 * name of alignment panel written to output stream
889 public JalviewModel saveState(AlignmentPanel ap, String fileName,
890 JarOutputStream jout, List<String> viewIds)
892 return saveState(ap, fileName, false, jout, viewIds);
896 * create a JalviewModel from an alignment view and marshall it to a
900 * panel to create jalview model for
902 * name of alignment panel written to output stream
904 * when true, only write the dataset for the alignment, not the data
905 * associated with the view.
911 public JalviewModel saveState(AlignmentPanel ap, String fileName,
912 boolean storeDS, JarOutputStream jout, List<String> viewIds)
916 viewIds = new ArrayList<>();
921 List<UserColourScheme> userColours = new ArrayList<>();
923 AlignViewport av = ap.av;
924 ViewportRanges vpRanges = av.getRanges();
926 final ObjectFactory objectFactory = new ObjectFactory();
927 JalviewModel object = objectFactory.createJalviewModel();
928 object.setVamsasModel(new VAMSAS());
930 // object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
933 GregorianCalendar c = new GregorianCalendar();
934 DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
935 XMLGregorianCalendar now = datatypeFactory.newXMLGregorianCalendar(c);// gregorianCalendar);
936 object.setCreationDate(now);
937 } catch (DatatypeConfigurationException e)
939 System.err.println("error writing date: " + e.toString());
941 object.setVersion(Cache.getDefault("VERSION", "Development Build"));
944 * rjal is full height alignment, jal is actual alignment with full metadata
945 * but excludes hidden sequences.
947 jalview.datamodel.AlignmentI rjal = av.getAlignment(), jal = rjal;
949 if (av.hasHiddenRows())
951 rjal = jal.getHiddenSequences().getFullAlignment();
954 SequenceSet vamsasSet = new SequenceSet();
956 // JalviewModelSequence jms = new JalviewModelSequence();
958 vamsasSet.setGapChar(jal.getGapCharacter() + "");
960 if (jal.getDataset() != null)
962 // dataset id is the dataset's hashcode
963 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
966 // switch jal and the dataset
967 jal = jal.getDataset();
971 if (jal.getProperties() != null)
973 Enumeration en = jal.getProperties().keys();
974 while (en.hasMoreElements())
976 String key = en.nextElement().toString();
977 SequenceSetProperties ssp = new SequenceSetProperties();
979 ssp.setValue(jal.getProperties().get(key).toString());
980 // vamsasSet.addSequenceSetProperties(ssp);
981 vamsasSet.getSequenceSetProperties().add(ssp);
986 Set<String> calcIdSet = new HashSet<>();
987 // record the set of vamsas sequence XML POJO we create.
988 HashMap<String, Sequence> vamsasSetIds = new HashMap<>();
990 for (final SequenceI jds : rjal.getSequences())
992 final SequenceI jdatasq = jds.getDatasetSequence() == null ? jds
993 : jds.getDatasetSequence();
994 String id = seqHash(jds);
995 if (vamsasSetIds.get(id) == null)
997 if (seqRefIds.get(id) != null && !storeDS)
999 // This happens for two reasons: 1. multiple views are being
1001 // 2. the hashCode has collided with another sequence's code. This
1003 // HAPPEN! (PF00072.15.stk does this)
1004 // JBPNote: Uncomment to debug writing out of files that do not read
1005 // back in due to ArrayOutOfBoundExceptions.
1006 // System.err.println("vamsasSeq backref: "+id+"");
1007 // System.err.println(jds.getName()+"
1008 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
1009 // System.err.println("Hashcode: "+seqHash(jds));
1010 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
1011 // System.err.println(rsq.getName()+"
1012 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
1013 // System.err.println("Hashcode: "+seqHash(rsq));
1017 vamsasSeq = createVamsasSequence(id, jds);
1018 // vamsasSet.addSequence(vamsasSeq);
1019 vamsasSet.getSequence().add(vamsasSeq);
1020 vamsasSetIds.put(id, vamsasSeq);
1021 seqRefIds.put(id, jds);
1025 jseq.setStart(jds.getStart());
1026 jseq.setEnd(jds.getEnd());
1027 jseq.setColour(av.getSequenceColour(jds).getRGB());
1029 jseq.setId(id); // jseq id should be a string not a number
1032 // Store any sequences this sequence represents
1033 if (av.hasHiddenRows())
1035 // use rjal, contains the full height alignment
1037 av.getAlignment().getHiddenSequences().isHidden(jds));
1039 if (av.isHiddenRepSequence(jds))
1041 jalview.datamodel.SequenceI[] reps = av
1042 .getRepresentedSequences(jds).getSequencesInOrder(rjal);
1044 for (int h = 0; h < reps.length; h++)
1048 // jseq.addHiddenSequences(rjal.findIndex(reps[h]));
1049 jseq.getHiddenSequences().add(rjal.findIndex(reps[h]));
1054 // mark sequence as reference - if it is the reference for this view
1055 if (jal.hasSeqrep())
1057 jseq.setViewreference(jds == jal.getSeqrep());
1061 // TODO: omit sequence features from each alignment view's XML dump if we
1062 // are storing dataset
1063 List<SequenceFeature> sfs = jds.getSequenceFeatures();
1064 for (SequenceFeature sf : sfs)
1066 // Features features = new Features();
1067 Feature features = new Feature();
1069 features.setBegin(sf.getBegin());
1070 features.setEnd(sf.getEnd());
1071 features.setDescription(sf.getDescription());
1072 features.setType(sf.getType());
1073 features.setFeatureGroup(sf.getFeatureGroup());
1074 features.setScore(sf.getScore());
1075 if (sf.links != null)
1077 for (int l = 0; l < sf.links.size(); l++)
1079 OtherData keyValue = new OtherData();
1080 keyValue.setKey("LINK_" + l);
1081 keyValue.setValue(sf.links.elementAt(l).toString());
1082 // features.addOtherData(keyValue);
1083 features.getOtherData().add(keyValue);
1086 if (sf.otherDetails != null)
1089 * save feature attributes, which may be simple strings or
1090 * map valued (have sub-attributes)
1092 for (Entry<String, Object> entry : sf.otherDetails.entrySet())
1094 String key = entry.getKey();
1095 Object value = entry.getValue();
1096 if (value instanceof Map<?, ?>)
1098 for (Entry<String, Object> subAttribute : ((Map<String, Object>) value)
1101 OtherData otherData = new OtherData();
1102 otherData.setKey(key);
1103 otherData.setKey2(subAttribute.getKey());
1104 otherData.setValue(subAttribute.getValue().toString());
1105 // features.addOtherData(otherData);
1106 features.getOtherData().add(otherData);
1111 OtherData otherData = new OtherData();
1112 otherData.setKey(key);
1113 otherData.setValue(value.toString());
1114 // features.addOtherData(otherData);
1115 features.getOtherData().add(otherData);
1120 // jseq.addFeatures(features);
1121 jseq.getFeatures().add(features);
1124 if (jdatasq.getAllPDBEntries() != null)
1126 Enumeration<PDBEntry> en = jdatasq.getAllPDBEntries().elements();
1127 while (en.hasMoreElements())
1129 Pdbids pdb = new Pdbids();
1130 jalview.datamodel.PDBEntry entry = en.nextElement();
1132 String pdbId = entry.getId();
1134 pdb.setType(entry.getType());
1137 * Store any structure views associated with this sequence. This
1138 * section copes with duplicate entries in the project, so a dataset
1139 * only view *should* be coped with sensibly.
1141 // This must have been loaded, is it still visible?
1142 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1143 String matchedFile = null;
1144 for (int f = frames.length - 1; f > -1; f--)
1146 if (frames[f] instanceof StructureViewerBase)
1148 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
1149 matchedFile = saveStructureViewer(ap, jds, pdb, entry,
1150 viewIds, matchedFile, viewFrame);
1152 * Only store each structure viewer's state once in the project
1153 * jar. First time through only (storeDS==false)
1155 String viewId = viewFrame.getViewId();
1156 String viewerType = viewFrame.getViewerType().toString();
1157 if (!storeDS && !viewIds.contains(viewId))
1159 viewIds.add(viewId);
1160 File viewerState = viewFrame.saveSession();
1161 if (viewerState != null)
1163 copyFileToJar(jout, viewerState.getPath(),
1164 getViewerJarEntryName(viewId), viewerType);
1169 "Failed to save viewer state for " + viewerType);
1175 if (matchedFile != null || entry.getFile() != null)
1177 if (entry.getFile() != null)
1180 matchedFile = entry.getFile();
1182 pdb.setFile(matchedFile); // entry.getFile());
1183 if (pdbfiles == null)
1185 pdbfiles = new ArrayList<>();
1188 if (!pdbfiles.contains(pdbId))
1190 pdbfiles.add(pdbId);
1191 copyFileToJar(jout, matchedFile, pdbId, pdbId);
1195 Enumeration<String> props = entry.getProperties();
1196 if (props.hasMoreElements())
1198 // PdbentryItem item = new PdbentryItem();
1199 while (props.hasMoreElements())
1201 Property prop = new Property();
1202 String key = props.nextElement();
1204 prop.setValue(entry.getProperty(key).toString());
1205 // item.addProperty(prop);
1206 pdb.getProperty().add(prop);
1208 // pdb.addPdbentryItem(item);
1211 // jseq.addPdbids(pdb);
1212 jseq.getPdbids().add(pdb);
1216 saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
1218 // jms.addJSeq(jseq);
1219 object.getJSeq().add(jseq);
1222 if (!storeDS && av.hasHiddenRows())
1224 jal = av.getAlignment();
1228 if (storeDS && jal.getCodonFrames() != null)
1230 List<AlignedCodonFrame> jac = jal.getCodonFrames();
1231 for (AlignedCodonFrame acf : jac)
1233 AlcodonFrame alc = new AlcodonFrame();
1234 if (acf.getProtMappings() != null
1235 && acf.getProtMappings().length > 0)
1237 boolean hasMap = false;
1238 SequenceI[] dnas = acf.getdnaSeqs();
1239 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1240 for (int m = 0; m < pmaps.length; m++)
1242 AlcodMap alcmap = new AlcodMap();
1243 alcmap.setDnasq(seqHash(dnas[m]));
1245 createVamsasMapping(pmaps[m], dnas[m], null, false));
1246 // alc.addAlcodMap(alcmap);
1247 alc.getAlcodMap().add(alcmap);
1252 // vamsasSet.addAlcodonFrame(alc);
1253 vamsasSet.getAlcodonFrame().add(alc);
1256 // TODO: delete this ? dead code from 2.8.3->2.9 ?
1258 // AlcodonFrame alc = new AlcodonFrame();
1259 // vamsasSet.addAlcodonFrame(alc);
1260 // for (int p = 0; p < acf.aaWidth; p++)
1262 // Alcodon cmap = new Alcodon();
1263 // if (acf.codons[p] != null)
1265 // // Null codons indicate a gapped column in the translated peptide
1267 // cmap.setPos1(acf.codons[p][0]);
1268 // cmap.setPos2(acf.codons[p][1]);
1269 // cmap.setPos3(acf.codons[p][2]);
1271 // alc.addAlcodon(cmap);
1273 // if (acf.getProtMappings() != null
1274 // && acf.getProtMappings().length > 0)
1276 // SequenceI[] dnas = acf.getdnaSeqs();
1277 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1278 // for (int m = 0; m < pmaps.length; m++)
1280 // AlcodMap alcmap = new AlcodMap();
1281 // alcmap.setDnasq(seqHash(dnas[m]));
1282 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
1284 // alc.addAlcodMap(alcmap);
1291 // /////////////////////////////////
1292 if (!storeDS && av.getCurrentTree() != null)
1294 // FIND ANY ASSOCIATED TREES
1295 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
1296 if (Desktop.desktop != null)
1298 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1300 for (int t = 0; t < frames.length; t++)
1302 if (frames[t] instanceof TreePanel)
1304 TreePanel tp = (TreePanel) frames[t];
1306 if (tp.getTreeCanvas().getViewport().getAlignment() == jal)
1308 JalviewModel.Tree tree = new JalviewModel.Tree();
1309 tree.setTitle(tp.getTitle());
1310 tree.setCurrentTree((av.getCurrentTree() == tp.getTree()));
1311 tree.setNewick(tp.getTree().print());
1312 tree.setThreshold(tp.getTreeCanvas().getThreshold());
1314 tree.setFitToWindow(tp.fitToWindow.getState());
1315 tree.setFontName(tp.getTreeFont().getName());
1316 tree.setFontSize(tp.getTreeFont().getSize());
1317 tree.setFontStyle(tp.getTreeFont().getStyle());
1318 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
1320 tree.setShowBootstrap(tp.bootstrapMenu.getState());
1321 tree.setShowDistances(tp.distanceMenu.getState());
1323 tree.setHeight(tp.getHeight());
1324 tree.setWidth(tp.getWidth());
1325 tree.setXpos(tp.getX());
1326 tree.setYpos(tp.getY());
1327 tree.setId(makeHashCode(tp, null));
1328 tree.setLinkToAllViews(
1329 tp.getTreeCanvas().isApplyToAllViews());
1332 if (tp.isColumnWise())
1334 tree.setColumnWise(true);
1335 String annId = tp.getAssocAnnotation().annotationId;
1336 tree.setColumnReference(annId);
1338 // jms.addTree(tree);
1339 object.getTree().add(tree);
1349 if (!storeDS && Desktop.desktop != null)
1351 for (JInternalFrame frame : Desktop.desktop.getAllFrames())
1353 if (frame instanceof PCAPanel)
1355 PCAPanel panel = (PCAPanel) frame;
1356 if (panel.getAlignViewport().getAlignment() == jal)
1358 savePCA(panel, object);
1366 * store forward refs from an annotationRow to any groups
1368 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<>();
1371 for (SequenceI sq : jal.getSequences())
1373 // Store annotation on dataset sequences only
1374 AlignmentAnnotation[] aa = sq.getAnnotation();
1375 if (aa != null && aa.length > 0)
1377 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1384 if (jal.getAlignmentAnnotation() != null)
1386 // Store the annotation shown on the alignment.
1387 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1388 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1393 if (jal.getGroups() != null)
1395 JGroup[] groups = new JGroup[jal.getGroups().size()];
1397 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1399 JGroup jGroup = new JGroup();
1400 groups[++i] = jGroup;
1402 jGroup.setStart(sg.getStartRes());
1403 jGroup.setEnd(sg.getEndRes());
1404 jGroup.setName(sg.getName());
1405 if (groupRefs.containsKey(sg))
1407 // group has references so set its ID field
1408 jGroup.setId(groupRefs.get(sg));
1410 ColourSchemeI colourScheme = sg.getColourScheme();
1411 if (colourScheme != null)
1413 ResidueShaderI groupColourScheme = sg.getGroupColourScheme();
1414 if (groupColourScheme.conservationApplied())
1416 jGroup.setConsThreshold(groupColourScheme.getConservationInc());
1418 if (colourScheme instanceof jalview.schemes.UserColourScheme)
1420 jGroup.setColour(setUserColourScheme(colourScheme,
1421 userColours, object));
1425 jGroup.setColour(colourScheme.getSchemeName());
1428 else if (colourScheme instanceof jalview.schemes.AnnotationColourGradient)
1430 jGroup.setColour("AnnotationColourGradient");
1431 jGroup.setAnnotationColours(constructAnnotationColours(
1432 (jalview.schemes.AnnotationColourGradient) colourScheme,
1433 userColours, object));
1435 else if (colourScheme instanceof jalview.schemes.UserColourScheme)
1438 setUserColourScheme(colourScheme, userColours, object));
1442 jGroup.setColour(colourScheme.getSchemeName());
1445 jGroup.setPidThreshold(groupColourScheme.getThreshold());
1448 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1449 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1450 jGroup.setDisplayText(sg.getDisplayText());
1451 jGroup.setColourText(sg.getColourText());
1452 jGroup.setTextCol1(sg.textColour.getRGB());
1453 jGroup.setTextCol2(sg.textColour2.getRGB());
1454 jGroup.setTextColThreshold(sg.thresholdTextColour);
1455 jGroup.setShowUnconserved(sg.getShowNonconserved());
1456 jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1457 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1458 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1459 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1460 for (SequenceI seq : sg.getSequences())
1462 // jGroup.addSeq(seqHash(seq));
1463 jGroup.getSeq().add(seqHash(seq));
1467 // jms.setJGroup(groups);
1469 for (JGroup grp : groups)
1471 object.getJGroup().add(grp);
1476 // /////////SAVE VIEWPORT
1477 Viewport view = new Viewport();
1478 view.setTitle(ap.alignFrame.getTitle());
1479 view.setSequenceSetId(
1480 makeHashCode(av.getSequenceSetId(), av.getSequenceSetId()));
1481 view.setId(av.getViewId());
1482 if (av.getCodingComplement() != null)
1484 view.setComplementId(av.getCodingComplement().getViewId());
1486 view.setViewName(av.getViewName());
1487 view.setGatheredViews(av.isGatherViewsHere());
1489 Rectangle size = ap.av.getExplodedGeometry();
1490 Rectangle position = size;
1493 size = ap.alignFrame.getBounds();
1494 if (av.getCodingComplement() != null)
1496 position = ((SplitFrame) ap.alignFrame.getSplitViewContainer())
1504 view.setXpos(position.x);
1505 view.setYpos(position.y);
1507 view.setWidth(size.width);
1508 view.setHeight(size.height);
1510 view.setStartRes(vpRanges.getStartRes());
1511 view.setStartSeq(vpRanges.getStartSeq());
1513 OverviewPanel ov = ap.getOverviewPanel();
1516 Overview overview = new Overview();
1517 overview.setTitle(ov.getTitle());
1518 Rectangle bounds = ov.getFrameBounds();
1519 overview.setXpos(bounds.x);
1520 overview.setYpos(bounds.y);
1521 overview.setWidth(bounds.width);
1522 overview.setHeight(bounds.height);
1523 overview.setShowHidden(ov.isShowHiddenRegions());
1524 overview.setGapColour(ov.getCanvas().getGapColour().getRGB());
1525 overview.setResidueColour(
1526 ov.getCanvas().getResidueColour().getRGB());
1527 overview.setHiddenColour(ov.getCanvas().getHiddenColour().getRGB());
1528 view.setOverview(overview);
1530 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1532 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1533 userColours, object));
1536 .getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1538 AnnotationColourScheme ac = constructAnnotationColours(
1539 (jalview.schemes.AnnotationColourGradient) av
1540 .getGlobalColourScheme(),
1541 userColours, object);
1543 view.setAnnotationColours(ac);
1544 view.setBgColour("AnnotationColourGradient");
1548 view.setBgColour(ColourSchemeProperty
1549 .getColourName(av.getGlobalColourScheme()));
1552 ResidueShaderI vcs = av.getResidueShading();
1553 ColourSchemeI cs = av.getGlobalColourScheme();
1557 if (vcs.conservationApplied())
1559 view.setConsThreshold(vcs.getConservationInc());
1560 if (cs instanceof jalview.schemes.UserColourScheme)
1562 view.setBgColour(setUserColourScheme(cs, userColours, object));
1565 view.setPidThreshold(vcs.getThreshold());
1568 view.setConservationSelected(av.getConservationSelected());
1569 view.setPidSelected(av.getAbovePIDThreshold());
1570 view.setCharHeight(av.getCharHeight());
1571 view.setCharWidth(av.getCharWidth());
1572 final Font font = av.getFont();
1573 view.setFontName(font.getName());
1574 view.setFontSize(font.getSize());
1575 view.setFontStyle(font.getStyle());
1576 view.setScaleProteinAsCdna(av.getViewStyle().isScaleProteinAsCdna());
1577 view.setRenderGaps(av.isRenderGaps());
1578 view.setShowAnnotation(av.isShowAnnotation());
1579 view.setShowBoxes(av.getShowBoxes());
1580 view.setShowColourText(av.getColourText());
1581 view.setShowFullId(av.getShowJVSuffix());
1582 view.setRightAlignIds(av.isRightAlignIds());
1583 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1584 view.setShowText(av.getShowText());
1585 view.setShowUnconserved(av.getShowUnconserved());
1586 view.setWrapAlignment(av.getWrapAlignment());
1587 view.setTextCol1(av.getTextColour().getRGB());
1588 view.setTextCol2(av.getTextColour2().getRGB());
1589 view.setTextColThreshold(av.getThresholdTextColour());
1590 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1591 view.setShowSequenceLogo(av.isShowSequenceLogo());
1592 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1593 view.setShowGroupConsensus(av.isShowGroupConsensus());
1594 view.setShowGroupConservation(av.isShowGroupConservation());
1595 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1596 view.setShowDbRefTooltip(av.isShowDBRefs());
1597 view.setFollowHighlight(av.isFollowHighlight());
1598 view.setFollowSelection(av.followSelection);
1599 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1600 view.setShowComplementFeatures(av.isShowComplementFeatures());
1601 view.setShowComplementFeaturesOnTop(
1602 av.isShowComplementFeaturesOnTop());
1603 if (av.getFeaturesDisplayed() != null)
1605 FeatureSettings fs = new FeatureSettings();
1607 FeatureRendererModel fr = ap.getSeqPanel().seqCanvas
1608 .getFeatureRenderer();
1609 String[] renderOrder = fr.getRenderOrder().toArray(new String[0]);
1611 Vector<String> settingsAdded = new Vector<>();
1612 if (renderOrder != null)
1614 for (String featureType : renderOrder)
1616 FeatureSettings.Setting setting = new FeatureSettings.Setting();
1617 setting.setType(featureType);
1620 * save any filter for the feature type
1622 FeatureMatcherSetI filter = fr.getFeatureFilter(featureType);
1625 Iterator<FeatureMatcherI> filters = filter.getMatchers()
1627 FeatureMatcherI firstFilter = filters.next();
1628 setting.setMatcherSet(Jalview2XML.marshalFilter(firstFilter,
1629 filters, filter.isAnded()));
1633 * save colour scheme for the feature type
1635 FeatureColourI fcol = fr.getFeatureStyle(featureType);
1636 if (!fcol.isSimpleColour())
1638 setting.setColour(fcol.getMaxColour().getRGB());
1639 setting.setMincolour(fcol.getMinColour().getRGB());
1640 setting.setMin(fcol.getMin());
1641 setting.setMax(fcol.getMax());
1642 setting.setColourByLabel(fcol.isColourByLabel());
1643 if (fcol.isColourByAttribute())
1645 String[] attName = fcol.getAttributeName();
1646 setting.getAttributeName().add(attName[0]);
1647 if (attName.length > 1)
1649 setting.getAttributeName().add(attName[1]);
1652 setting.setAutoScale(fcol.isAutoScaled());
1653 setting.setThreshold(fcol.getThreshold());
1654 Color noColour = fcol.getNoColour();
1655 if (noColour == null)
1657 setting.setNoValueColour(NoValueColour.NONE);
1659 else if (noColour.equals(fcol.getMaxColour()))
1661 setting.setNoValueColour(NoValueColour.MAX);
1665 setting.setNoValueColour(NoValueColour.MIN);
1667 // -1 = No threshold, 0 = Below, 1 = Above
1668 setting.setThreshstate(fcol.isAboveThreshold() ? 1
1669 : (fcol.isBelowThreshold() ? 0 : -1));
1673 setting.setColour(fcol.getColour().getRGB());
1677 av.getFeaturesDisplayed().isVisible(featureType));
1678 float rorder = fr.getOrder(featureType);
1681 setting.setOrder(rorder);
1683 /// fs.addSetting(setting);
1684 fs.getSetting().add(setting);
1685 settingsAdded.addElement(featureType);
1689 // is groups actually supposed to be a map here ?
1690 Iterator<String> en = fr.getFeatureGroups().iterator();
1691 Vector<String> groupsAdded = new Vector<>();
1692 while (en.hasNext())
1694 String grp = en.next();
1695 if (groupsAdded.contains(grp))
1699 Group g = new Group();
1701 g.setDisplay(((Boolean) fr.checkGroupVisibility(grp, false))
1704 fs.getGroup().add(g);
1705 groupsAdded.addElement(grp);
1707 // jms.setFeatureSettings(fs);
1708 object.setFeatureSettings(fs);
1711 if (av.hasHiddenColumns())
1713 jalview.datamodel.HiddenColumns hidden = av.getAlignment()
1714 .getHiddenColumns();
1718 "REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1722 Iterator<int[]> hiddenRegions = hidden.iterator();
1723 while (hiddenRegions.hasNext())
1725 int[] region = hiddenRegions.next();
1726 HiddenColumns hc = new HiddenColumns();
1727 hc.setStart(region[0]);
1728 hc.setEnd(region[1]);
1729 // view.addHiddenColumns(hc);
1730 view.getHiddenColumns().add(hc);
1734 if (calcIdSet.size() > 0)
1736 for (String calcId : calcIdSet)
1738 if (calcId.trim().length() > 0)
1740 CalcIdParam cidp = createCalcIdParam(calcId, av);
1741 // Some calcIds have no parameters.
1744 // view.addCalcIdParam(cidp);
1745 view.getCalcIdParam().add(cidp);
1751 // jms.addViewport(view);
1752 object.getViewport().add(view);
1754 // object.setJalviewModelSequence(jms);
1755 // object.getVamsasModel().addSequenceSet(vamsasSet);
1756 object.getVamsasModel().getSequenceSet().add(vamsasSet);
1758 if (jout != null && fileName != null)
1760 // We may not want to write the object to disk,
1761 // eg we can copy the alignViewport to a new view object
1762 // using save and then load
1765 fileName = fileName.replace('\\', '/');
1766 System.out.println("Writing jar entry " + fileName);
1767 JarEntry entry = new JarEntry(fileName);
1768 jout.putNextEntry(entry);
1769 PrintWriter pout = new PrintWriter(
1770 new OutputStreamWriter(jout, UTF_8));
1771 JAXBContext jaxbContext = JAXBContext
1772 .newInstance(JalviewModel.class);
1773 Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
1775 // output pretty printed
1776 // jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
1777 jaxbMarshaller.marshal(
1778 new ObjectFactory().createJalviewModel(object), pout);
1780 // jaxbMarshaller.marshal(object, pout);
1781 // marshaller.marshal(object);
1784 } catch (Exception ex)
1786 // TODO: raise error in GUI if marshalling failed.
1787 System.err.println("Error writing Jalview project");
1788 ex.printStackTrace();
1795 * Writes PCA viewer attributes and computed values to an XML model object and
1796 * adds it to the JalviewModel. Any exceptions are reported by logging.
1798 protected void savePCA(PCAPanel panel, JalviewModel object)
1802 PcaViewer viewer = new PcaViewer();
1803 viewer.setHeight(panel.getHeight());
1804 viewer.setWidth(panel.getWidth());
1805 viewer.setXpos(panel.getX());
1806 viewer.setYpos(panel.getY());
1807 viewer.setTitle(panel.getTitle());
1808 PCAModel pcaModel = panel.getPcaModel();
1809 viewer.setScoreModelName(pcaModel.getScoreModelName());
1810 viewer.setXDim(panel.getSelectedDimensionIndex(X));
1811 viewer.setYDim(panel.getSelectedDimensionIndex(Y));
1812 viewer.setZDim(panel.getSelectedDimensionIndex(Z));
1814 panel.getRotatableCanvas().getBackgroundColour().getRGB());
1815 viewer.setScaleFactor(panel.getRotatableCanvas().getScaleFactor());
1816 float[] spMin = panel.getRotatableCanvas().getSeqMin();
1817 SeqPointMin spmin = new SeqPointMin();
1818 spmin.setXPos(spMin[0]);
1819 spmin.setYPos(spMin[1]);
1820 spmin.setZPos(spMin[2]);
1821 viewer.setSeqPointMin(spmin);
1822 float[] spMax = panel.getRotatableCanvas().getSeqMax();
1823 SeqPointMax spmax = new SeqPointMax();
1824 spmax.setXPos(spMax[0]);
1825 spmax.setYPos(spMax[1]);
1826 spmax.setZPos(spMax[2]);
1827 viewer.setSeqPointMax(spmax);
1828 viewer.setShowLabels(panel.getRotatableCanvas().isShowLabels());
1829 viewer.setLinkToAllViews(
1830 panel.getRotatableCanvas().isApplyToAllViews());
1831 SimilarityParamsI sp = pcaModel.getSimilarityParameters();
1832 viewer.setIncludeGaps(sp.includeGaps());
1833 viewer.setMatchGaps(sp.matchGaps());
1834 viewer.setIncludeGappedColumns(sp.includeGappedColumns());
1835 viewer.setDenominateByShortestLength(sp.denominateByShortestLength());
1838 * sequence points on display
1840 for (jalview.datamodel.SequencePoint spt : pcaModel
1841 .getSequencePoints())
1843 SequencePoint point = new SequencePoint();
1844 point.setSequenceRef(seqHash(spt.getSequence()));
1845 point.setXPos(spt.coord.x);
1846 point.setYPos(spt.coord.y);
1847 point.setZPos(spt.coord.z);
1848 viewer.getSequencePoint().add(point);
1852 * (end points of) axes on display
1854 for (Point p : panel.getRotatableCanvas().getAxisEndPoints())
1857 Axis axis = new Axis();
1861 viewer.getAxis().add(axis);
1865 * raw PCA data (note we are not restoring PCA inputs here -
1866 * alignment view, score model, similarity parameters)
1868 PcaDataType data = new PcaDataType();
1869 viewer.setPcaData(data);
1870 PCA pca = pcaModel.getPcaData();
1872 DoubleMatrix pm = new DoubleMatrix();
1873 saveDoubleMatrix(pca.getPairwiseScores(), pm);
1874 data.setPairwiseMatrix(pm);
1876 DoubleMatrix tm = new DoubleMatrix();
1877 saveDoubleMatrix(pca.getTridiagonal(), tm);
1878 data.setTridiagonalMatrix(tm);
1880 DoubleMatrix eigenMatrix = new DoubleMatrix();
1881 data.setEigenMatrix(eigenMatrix);
1882 saveDoubleMatrix(pca.getEigenmatrix(), eigenMatrix);
1884 object.getPcaViewer().add(viewer);
1885 } catch (Throwable t)
1887 Console.error("Error saving PCA: " + t.getMessage());
1892 * Stores values from a matrix into an XML element, including (if present) the
1897 * @see #loadDoubleMatrix(DoubleMatrix)
1899 protected void saveDoubleMatrix(MatrixI m, DoubleMatrix xmlMatrix)
1901 xmlMatrix.setRows(m.height());
1902 xmlMatrix.setColumns(m.width());
1903 for (int i = 0; i < m.height(); i++)
1905 DoubleVector row = new DoubleVector();
1906 for (int j = 0; j < m.width(); j++)
1908 row.getV().add(m.getValue(i, j));
1910 xmlMatrix.getRow().add(row);
1912 if (m.getD() != null)
1914 DoubleVector dVector = new DoubleVector();
1915 for (double d : m.getD())
1917 dVector.getV().add(d);
1919 xmlMatrix.setD(dVector);
1921 if (m.getE() != null)
1923 DoubleVector eVector = new DoubleVector();
1924 for (double e : m.getE())
1926 eVector.getV().add(e);
1928 xmlMatrix.setE(eVector);
1933 * Loads XML matrix data into a new Matrix object, including the D and/or E
1934 * vectors (if present)
1938 * @see Jalview2XML#saveDoubleMatrix(MatrixI, DoubleMatrix)
1940 protected MatrixI loadDoubleMatrix(DoubleMatrix mData)
1942 int rows = mData.getRows();
1943 double[][] vals = new double[rows][];
1945 for (int i = 0; i < rows; i++)
1947 List<Double> dVector = mData.getRow().get(i).getV();
1948 vals[i] = new double[dVector.size()];
1950 for (Double d : dVector)
1956 MatrixI m = new Matrix(vals);
1958 if (mData.getD() != null)
1960 List<Double> dVector = mData.getD().getV();
1961 double[] vec = new double[dVector.size()];
1963 for (Double d : dVector)
1969 if (mData.getE() != null)
1971 List<Double> dVector = mData.getE().getV();
1972 double[] vec = new double[dVector.size()];
1974 for (Double d : dVector)
1985 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1986 * for each viewer, with
1988 * <li>viewer geometry (position, size, split pane divider location)</li>
1989 * <li>index of the selected structure in the viewer (currently shows gapped
1991 * <li>the id of the annotation holding RNA secondary structure</li>
1992 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1994 * Varna viewer state is also written out (in native Varna XML) to separate
1995 * project jar entries. A separate entry is written for each RNA structure
1996 * displayed, with the naming convention
1998 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
2006 * @param storeDataset
2008 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
2009 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
2010 boolean storeDataset)
2012 if (Desktop.desktop == null)
2016 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
2017 for (int f = frames.length - 1; f > -1; f--)
2019 if (frames[f] instanceof AppVarna)
2021 AppVarna varna = (AppVarna) frames[f];
2023 * link the sequence to every viewer that is showing it and is linked to
2024 * its alignment panel
2026 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
2028 String viewId = varna.getViewId();
2029 RnaViewer rna = new RnaViewer();
2030 rna.setViewId(viewId);
2031 rna.setTitle(varna.getTitle());
2032 rna.setXpos(varna.getX());
2033 rna.setYpos(varna.getY());
2034 rna.setWidth(varna.getWidth());
2035 rna.setHeight(varna.getHeight());
2036 rna.setDividerLocation(varna.getDividerLocation());
2037 rna.setSelectedRna(varna.getSelectedIndex());
2038 // jseq.addRnaViewer(rna);
2039 jseq.getRnaViewer().add(rna);
2042 * Store each Varna panel's state once in the project per sequence.
2043 * First time through only (storeDataset==false)
2045 // boolean storeSessions = false;
2046 // String sequenceViewId = viewId + seqsToIds.get(jds);
2047 // if (!storeDataset && !viewIds.contains(sequenceViewId))
2049 // viewIds.add(sequenceViewId);
2050 // storeSessions = true;
2052 for (RnaModel model : varna.getModels())
2054 if (model.seq == jds)
2057 * VARNA saves each view (sequence or alignment secondary
2058 * structure, gapped or trimmed) as a separate XML file
2060 String jarEntryName = rnaSessions.get(model);
2061 if (jarEntryName == null)
2064 String varnaStateFile = varna.getStateInfo(model.rna);
2065 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
2066 copyFileToJar(jout, varnaStateFile, jarEntryName, "Varna");
2067 rnaSessions.put(model, jarEntryName);
2069 SecondaryStructure ss = new SecondaryStructure();
2070 String annotationId = varna.getAnnotation(jds).annotationId;
2071 ss.setAnnotationId(annotationId);
2072 ss.setViewerState(jarEntryName);
2073 ss.setGapped(model.gapped);
2074 ss.setTitle(model.title);
2075 // rna.addSecondaryStructure(ss);
2076 rna.getSecondaryStructure().add(ss);
2085 * Copy the contents of a file to a new entry added to the output jar
2089 * @param jarEntryName
2091 * additional identifying info to log to the console
2093 protected void copyFileToJar(JarOutputStream jout, String infilePath,
2094 String jarEntryName, String msg)
2096 try (InputStream is = new FileInputStream(infilePath))
2098 File file = new File(infilePath);
2099 if (file.exists() && jout != null)
2102 "Writing jar entry " + jarEntryName + " (" + msg + ")");
2103 jout.putNextEntry(new JarEntry(jarEntryName));
2106 // dis = new DataInputStream(new FileInputStream(file));
2107 // byte[] data = new byte[(int) file.length()];
2108 // dis.readFully(data);
2109 // writeJarEntry(jout, jarEntryName, data);
2111 } catch (Exception ex)
2113 ex.printStackTrace();
2118 * Copies input to output, in 4K buffers; handles any data (text or binary)
2122 * @throws IOException
2124 protected void copyAll(InputStream in, OutputStream out)
2127 byte[] buffer = new byte[4096];
2129 while ((bytesRead = in.read(buffer)) != -1)
2131 out.write(buffer, 0, bytesRead);
2136 * Save the state of a structure viewer
2141 * the archive XML element under which to save the state
2144 * @param matchedFile
2148 protected String saveStructureViewer(AlignmentPanel ap, SequenceI jds,
2149 Pdbids pdb, PDBEntry entry, List<String> viewIds,
2150 String matchedFile, StructureViewerBase viewFrame)
2152 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
2155 * Look for any bindings for this viewer to the PDB file of interest
2156 * (including part matches excluding chain id)
2158 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
2160 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
2161 final String pdbId = pdbentry.getId();
2162 if (!pdbId.equals(entry.getId()) && !(entry.getId().length() > 4
2163 && entry.getId().toLowerCase(Locale.ROOT)
2164 .startsWith(pdbId.toLowerCase(Locale.ROOT))))
2167 * not interested in a binding to a different PDB entry here
2171 if (matchedFile == null)
2173 matchedFile = pdbentry.getFile();
2175 else if (!matchedFile.equals(pdbentry.getFile()))
2178 "Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
2179 + pdbentry.getFile());
2183 // can get at it if the ID
2184 // match is ambiguous (e.g.
2187 for (int smap = 0; smap < viewFrame.getBinding()
2188 .getSequence()[peid].length; smap++)
2190 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
2191 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
2193 StructureState state = new StructureState();
2194 state.setVisible(true);
2195 state.setXpos(viewFrame.getX());
2196 state.setYpos(viewFrame.getY());
2197 state.setWidth(viewFrame.getWidth());
2198 state.setHeight(viewFrame.getHeight());
2199 final String viewId = viewFrame.getViewId();
2200 state.setViewId(viewId);
2201 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
2202 state.setColourwithAlignPanel(viewFrame.isUsedForColourBy(ap));
2203 state.setColourByJmol(viewFrame.isColouredByViewer());
2204 state.setType(viewFrame.getViewerType().toString());
2205 // pdb.addStructureState(state);
2206 pdb.getStructureState().add(state);
2214 * Populates the AnnotationColourScheme xml for save. This captures the
2215 * settings of the options in the 'Colour by Annotation' dialog.
2218 * @param userColours
2222 private AnnotationColourScheme constructAnnotationColours(
2223 AnnotationColourGradient acg, List<UserColourScheme> userColours,
2226 AnnotationColourScheme ac = new AnnotationColourScheme();
2227 ac.setAboveThreshold(acg.getAboveThreshold());
2228 ac.setThreshold(acg.getAnnotationThreshold());
2229 // 2.10.2 save annotationId (unique) not annotation label
2230 ac.setAnnotation(acg.getAnnotation().annotationId);
2231 if (acg.getBaseColour() instanceof UserColourScheme)
2234 setUserColourScheme(acg.getBaseColour(), userColours, jm));
2239 ColourSchemeProperty.getColourName(acg.getBaseColour()));
2242 ac.setMaxColour(acg.getMaxColour().getRGB());
2243 ac.setMinColour(acg.getMinColour().getRGB());
2244 ac.setPerSequence(acg.isSeqAssociated());
2245 ac.setPredefinedColours(acg.isPredefinedColours());
2249 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
2250 IdentityHashMap<SequenceGroup, String> groupRefs,
2251 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
2252 SequenceSet vamsasSet)
2255 for (int i = 0; i < aa.length; i++)
2257 Annotation an = new Annotation();
2259 AlignmentAnnotation annotation = aa[i];
2260 if (annotation.annotationId != null)
2262 annotationIds.put(annotation.annotationId, annotation);
2265 an.setId(annotation.annotationId);
2267 an.setVisible(annotation.visible);
2269 an.setDescription(annotation.description);
2271 if (annotation.sequenceRef != null)
2273 // 2.9 JAL-1781 xref on sequence id rather than name
2274 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
2276 if (annotation.groupRef != null)
2278 String groupIdr = groupRefs.get(annotation.groupRef);
2279 if (groupIdr == null)
2281 // make a locally unique String
2282 groupRefs.put(annotation.groupRef,
2283 groupIdr = ("" + System.currentTimeMillis()
2284 + annotation.groupRef.getName()
2285 + groupRefs.size()));
2287 an.setGroupRef(groupIdr.toString());
2290 // store all visualization attributes for annotation
2291 an.setGraphHeight(annotation.graphHeight);
2292 an.setCentreColLabels(annotation.centreColLabels);
2293 an.setScaleColLabels(annotation.scaleColLabel);
2294 an.setShowAllColLabels(annotation.showAllColLabels);
2295 an.setBelowAlignment(annotation.belowAlignment);
2297 if (annotation.graph > 0)
2300 an.setGraphType(annotation.graph);
2301 an.setGraphGroup(annotation.graphGroup);
2302 if (annotation.getThreshold() != null)
2304 ThresholdLine line = new ThresholdLine();
2305 line.setLabel(annotation.getThreshold().label);
2306 line.setValue(annotation.getThreshold().value);
2307 line.setColour(annotation.getThreshold().colour.getRGB());
2308 an.setThresholdLine(line);
2310 if (annotation.graph == AlignmentAnnotation.CONTACT_MAP)
2312 if (annotation.sequenceRef.getContactMaps() != null)
2314 ContactMatrixI cm = annotation.sequenceRef
2315 .getContactMatrixFor(annotation);
2318 MatrixType xmlmat = new MatrixType();
2319 xmlmat.setType(cm.getType());
2320 xmlmat.setRows(BigInteger.valueOf(cm.getWidth()));
2321 xmlmat.setCols(BigInteger.valueOf(cm.getHeight()));
2322 // consider using an opaque to/from -> allow instance to control
2323 // its representation ?
2324 xmlmat.setElements(ContactMatrix.contactToFloatString(cm));
2327 for (BitSet gp : cm.getGroups())
2329 xmlmat.getGroups().add(stringifyBitset(gp));
2334 // provenance object for tree ?
2335 xmlmat.getNewick().add(cm.getNewick());
2336 xmlmat.setTreeMethod(cm.getTreeMethod());
2338 if (cm.hasCutHeight())
2340 xmlmat.setCutHeight(cm.getCutHeight());
2343 // set/get properties
2344 if (cm instanceof MappableContactMatrixI)
2346 jalview.util.MapList mlst = ((MappableContactMatrixI) cm)
2347 .getMapFor(annotation.sequenceRef);
2350 MapListType mp = new MapListType();
2351 List<int[]> r = mlst.getFromRanges();
2352 for (int[] range : r)
2354 MapListFrom mfrom = new MapListFrom();
2355 mfrom.setStart(range[0]);
2356 mfrom.setEnd(range[1]);
2357 // mp.addMapListFrom(mfrom);
2358 mp.getMapListFrom().add(mfrom);
2360 r = mlst.getToRanges();
2361 for (int[] range : r)
2363 MapListTo mto = new MapListTo();
2364 mto.setStart(range[0]);
2365 mto.setEnd(range[1]);
2366 // mp.addMapListTo(mto);
2367 mp.getMapListTo().add(mto);
2370 BigInteger.valueOf(mlst.getFromRatio()));
2371 mp.setMapToUnit(BigInteger.valueOf(mlst.getToRatio()));
2372 xmlmat.setMapping(mp);
2376 an.getContactmatrix().add(xmlmat);
2386 an.setLabel(annotation.label);
2388 if (annotation == av.getAlignmentQualityAnnot()
2389 || annotation == av.getAlignmentConservationAnnotation()
2390 || annotation == av.getAlignmentConsensusAnnotation()
2391 || annotation.autoCalculated)
2393 // new way of indicating autocalculated annotation -
2394 an.setAutoCalculated(annotation.autoCalculated);
2396 if (annotation.hasScore())
2398 an.setScore(annotation.getScore());
2401 if (annotation.getCalcId() != null)
2403 calcIdSet.add(annotation.getCalcId());
2404 an.setCalcId(annotation.getCalcId());
2406 if (annotation.hasProperties())
2408 for (String pr : annotation.getProperties())
2410 jalview.xml.binding.jalview.Property prop = new jalview.xml.binding.jalview.Property();
2412 prop.setValue(annotation.getProperty(pr));
2413 an.getProperty().add(prop);
2417 AnnotationElement ae;
2418 if (annotation.annotations != null)
2420 an.setScoreOnly(false);
2421 for (int a = 0; a < annotation.annotations.length; a++)
2423 if ((annotation == null) || (annotation.annotations[a] == null))
2428 ae = new AnnotationElement();
2429 if (annotation.annotations[a].description != null)
2431 ae.setDescription(annotation.annotations[a].description);
2433 if (annotation.annotations[a].displayCharacter != null)
2435 ae.setDisplayCharacter(
2436 annotation.annotations[a].displayCharacter);
2439 if (!Float.isNaN(annotation.annotations[a].value))
2441 ae.setValue(annotation.annotations[a].value);
2445 if (annotation.annotations[a].secondaryStructure > ' ')
2447 ae.setSecondaryStructure(
2448 annotation.annotations[a].secondaryStructure + "");
2451 if (annotation.annotations[a].colour != null
2452 && annotation.annotations[a].colour != java.awt.Color.black)
2454 ae.setColour(annotation.annotations[a].colour.getRGB());
2457 // an.addAnnotationElement(ae);
2458 an.getAnnotationElement().add(ae);
2459 if (annotation.autoCalculated)
2461 // only write one non-null entry into the annotation row -
2462 // sufficient to get the visualization attributes necessary to
2470 an.setScoreOnly(true);
2472 if (!storeDS || (storeDS && !annotation.autoCalculated))
2474 // skip autocalculated annotation - these are only provided for
2476 // vamsasSet.addAnnotation(an);
2477 vamsasSet.getAnnotation().add(an);
2483 private String stringifyBitset(BitSet gp)
2485 StringBuilder sb = new StringBuilder();
2486 for (long val : gp.toLongArray())
2488 if (sb.length() > 0)
2494 return sb.toString();
2497 private BitSet deStringifyBitset(String stringified)
2499 if ("".equals(stringified) || stringified == null)
2501 return new BitSet();
2503 String[] longvals = stringified.split(",");
2504 long[] newlongvals = new long[longvals.length];
2505 for (int lv = 0; lv < longvals.length; lv++)
2509 newlongvals[lv] = Long.valueOf(longvals[lv]);
2510 } catch (Exception x)
2512 errorMessage += "Couldn't destringify bitset from: '" + stringified
2514 newlongvals[lv] = 0;
2517 return BitSet.valueOf(newlongvals);
2521 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
2523 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
2524 if (settings != null)
2526 CalcIdParam vCalcIdParam = new CalcIdParam();
2527 vCalcIdParam.setCalcId(calcId);
2528 // vCalcIdParam.addServiceURL(settings.getServiceURI());
2529 vCalcIdParam.getServiceURL().add(settings.getServiceURI());
2530 // generic URI allowing a third party to resolve another instance of the
2531 // service used for this calculation
2532 for (String url : settings.getServiceURLs())
2534 // vCalcIdParam.addServiceURL(urls);
2535 vCalcIdParam.getServiceURL().add(url);
2537 vCalcIdParam.setVersion("1.0");
2538 if (settings.getPreset() != null)
2540 WsParamSetI setting = settings.getPreset();
2541 vCalcIdParam.setName(setting.getName());
2542 vCalcIdParam.setDescription(setting.getDescription());
2546 vCalcIdParam.setName("");
2547 vCalcIdParam.setDescription("Last used parameters");
2549 // need to be able to recover 1) settings 2) user-defined presets or
2550 // recreate settings from preset 3) predefined settings provided by
2551 // service - or settings that can be transferred (or discarded)
2552 vCalcIdParam.setParameters(
2553 settings.getWsParamFile().replace("\n", "|\\n|"));
2554 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
2555 // todo - decide if updateImmediately is needed for any projects.
2557 return vCalcIdParam;
2562 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
2565 if (calcIdParam.getVersion().equals("1.0"))
2567 final String[] calcIds = calcIdParam.getServiceURL()
2568 .toArray(new String[0]);
2569 Jws2Instance service = Jws2Discoverer.getDiscoverer()
2570 .getPreferredServiceFor(calcIds);
2571 if (service != null)
2573 WsParamSetI parmSet = null;
2576 parmSet = service.getParamStore().parseServiceParameterFile(
2577 calcIdParam.getName(), calcIdParam.getDescription(),
2579 calcIdParam.getParameters().replace("|\\n|", "\n"));
2580 } catch (IOException x)
2582 Console.warn("Couldn't parse parameter data for "
2583 + calcIdParam.getCalcId(), x);
2586 List<ArgumentI> argList = null;
2587 if (calcIdParam.getName().length() > 0)
2589 parmSet = service.getParamStore()
2590 .getPreset(calcIdParam.getName());
2591 if (parmSet != null)
2593 // TODO : check we have a good match with settings in AACon -
2594 // otherwise we'll need to create a new preset
2599 argList = parmSet.getArguments();
2602 AAConSettings settings = new AAConSettings(
2603 calcIdParam.isAutoUpdate(), service, parmSet, argList);
2604 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
2605 calcIdParam.isNeedsUpdate());
2611 "Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
2615 throw new Error(MessageManager.formatMessage(
2616 "error.unsupported_version_calcIdparam", new Object[]
2617 { calcIdParam.toString() }));
2621 * External mapping between jalview objects and objects yielding a valid and
2622 * unique object ID string. This is null for normal Jalview project IO, but
2623 * non-null when a jalview project is being read or written as part of a
2626 IdentityHashMap jv2vobj = null;
2629 * Construct a unique ID for jvobj using either existing bindings or if none
2630 * exist, the result of the hashcode call for the object.
2633 * jalview data object
2634 * @return unique ID for referring to jvobj
2636 private String makeHashCode(Object jvobj, String altCode)
2638 if (jv2vobj != null)
2640 Object id = jv2vobj.get(jvobj);
2643 return id.toString();
2645 // check string ID mappings
2646 if (jvids2vobj != null && jvobj instanceof String)
2648 id = jvids2vobj.get(jvobj);
2652 return id.toString();
2654 // give up and warn that something has gone wrong
2656 "Cannot find ID for object in external mapping : " + jvobj);
2662 * return local jalview object mapped to ID, if it exists
2666 * @return null or object bound to idcode
2668 private Object retrieveExistingObj(String idcode)
2670 if (idcode != null && vobj2jv != null)
2672 return vobj2jv.get(idcode);
2678 * binding from ID strings from external mapping table to jalview data model
2681 private Hashtable vobj2jv;
2683 private Sequence createVamsasSequence(String id, SequenceI jds)
2685 return createVamsasSequence(true, id, jds, null);
2688 private Sequence createVamsasSequence(boolean recurse, String id,
2689 SequenceI jds, SequenceI parentseq)
2691 Sequence vamsasSeq = new Sequence();
2692 vamsasSeq.setId(id);
2693 vamsasSeq.setName(jds.getName());
2694 vamsasSeq.setSequence(jds.getSequenceAsString());
2695 vamsasSeq.setDescription(jds.getDescription());
2696 List<DBRefEntry> dbrefs = null;
2697 if (jds.getDatasetSequence() != null)
2699 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
2703 // seqId==dsseqid so we can tell which sequences really are
2704 // dataset sequences only
2705 vamsasSeq.setDsseqid(id);
2706 dbrefs = jds.getDBRefs();
2707 if (parentseq == null)
2714 * save any dbrefs; special subclass GeneLocus is flagged as 'locus'
2718 for (int d = 0, nd = dbrefs.size(); d < nd; d++)
2720 DBRef dbref = new DBRef();
2721 DBRefEntry ref = dbrefs.get(d);
2722 dbref.setSource(ref.getSource());
2723 dbref.setVersion(ref.getVersion());
2724 dbref.setAccessionId(ref.getAccessionId());
2725 dbref.setCanonical(ref.isCanonical());
2726 if (ref instanceof GeneLocus)
2728 dbref.setLocus(true);
2732 Mapping mp = createVamsasMapping(ref.getMap(), parentseq, jds,
2734 dbref.setMapping(mp);
2736 vamsasSeq.getDBRef().add(dbref);
2742 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
2743 SequenceI parentseq, SequenceI jds, boolean recurse)
2746 if (jmp.getMap() != null)
2750 jalview.util.MapList mlst = jmp.getMap();
2751 List<int[]> r = mlst.getFromRanges();
2752 for (int[] range : r)
2754 MapListFrom mfrom = new MapListFrom();
2755 mfrom.setStart(range[0]);
2756 mfrom.setEnd(range[1]);
2757 // mp.addMapListFrom(mfrom);
2758 mp.getMapListFrom().add(mfrom);
2760 r = mlst.getToRanges();
2761 for (int[] range : r)
2763 MapListTo mto = new MapListTo();
2764 mto.setStart(range[0]);
2765 mto.setEnd(range[1]);
2766 // mp.addMapListTo(mto);
2767 mp.getMapListTo().add(mto);
2769 mp.setMapFromUnit(BigInteger.valueOf(mlst.getFromRatio()));
2770 mp.setMapToUnit(BigInteger.valueOf(mlst.getToRatio()));
2771 if (jmp.getTo() != null)
2773 // MappingChoice mpc = new MappingChoice();
2775 // check/create ID for the sequence referenced by getTo()
2778 SequenceI ps = null;
2779 if (parentseq != jmp.getTo()
2780 && parentseq.getDatasetSequence() != jmp.getTo())
2782 // chaining dbref rather than a handshaking one
2783 jmpid = seqHash(ps = jmp.getTo());
2787 jmpid = seqHash(ps = parentseq);
2789 // mpc.setDseqFor(jmpid);
2790 mp.setDseqFor(jmpid);
2791 if (!seqRefIds.containsKey(jmpid))
2793 Console.debug("creatign new DseqFor ID");
2794 seqRefIds.put(jmpid, ps);
2798 Console.debug("reusing DseqFor ID");
2801 // mp.setMappingChoice(mpc);
2807 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2808 List<UserColourScheme> userColours, JalviewModel jm)
2811 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2812 boolean newucs = false;
2813 if (!userColours.contains(ucs))
2815 userColours.add(ucs);
2818 id = "ucs" + userColours.indexOf(ucs);
2821 // actually create the scheme's entry in the XML model
2822 java.awt.Color[] colours = ucs.getColours();
2823 UserColours uc = new UserColours();
2824 // UserColourScheme jbucs = new UserColourScheme();
2825 JalviewUserColours jbucs = new JalviewUserColours();
2827 for (int i = 0; i < colours.length; i++)
2829 Colour col = new Colour();
2830 col.setName(ResidueProperties.aa[i]);
2831 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2832 // jbucs.addColour(col);
2833 jbucs.getColour().add(col);
2835 if (ucs.getLowerCaseColours() != null)
2837 colours = ucs.getLowerCaseColours();
2838 for (int i = 0; i < colours.length; i++)
2840 Colour col = new Colour();
2841 col.setName(ResidueProperties.aa[i].toLowerCase(Locale.ROOT));
2842 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2843 // jbucs.addColour(col);
2844 jbucs.getColour().add(col);
2849 uc.setUserColourScheme(jbucs);
2850 // jm.addUserColours(uc);
2851 jm.getUserColours().add(uc);
2857 jalview.schemes.UserColourScheme getUserColourScheme(JalviewModel jm,
2860 List<UserColours> uc = jm.getUserColours();
2861 UserColours colours = null;
2863 for (int i = 0; i < uc.length; i++)
2865 if (uc[i].getId().equals(id))
2872 for (UserColours c : uc)
2874 if (c.getId().equals(id))
2881 java.awt.Color[] newColours = new java.awt.Color[24];
2883 for (int i = 0; i < 24; i++)
2885 newColours[i] = new java.awt.Color(Integer.parseInt(
2886 // colours.getUserColourScheme().getColour(i).getRGB(), 16));
2887 colours.getUserColourScheme().getColour().get(i).getRGB(),
2891 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2894 if (colours.getUserColourScheme().getColour().size()/*Count()*/ > 24)
2896 newColours = new java.awt.Color[23];
2897 for (int i = 0; i < 23; i++)
2899 newColours[i] = new java.awt.Color(
2900 Integer.parseInt(colours.getUserColourScheme().getColour()
2901 .get(i + 24).getRGB(), 16));
2903 ucs.setLowerCaseColours(newColours);
2910 * contains last error message (if any) encountered by XML loader.
2912 String errorMessage = null;
2915 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2916 * exceptions are raised during project XML parsing
2918 public boolean attemptversion1parse = false;
2921 * Load a jalview project archive from a jar file
2924 * - HTTP URL or filename
2926 public AlignFrame loadJalviewAlign(final Object file)
2929 jalview.gui.AlignFrame af = null;
2933 // create list to store references for any new Jmol viewers created
2934 newStructureViewers = new Vector<>();
2935 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2936 // Workaround is to make sure caller implements the JarInputStreamProvider
2938 // so we can re-open the jar input stream for each entry.
2940 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2941 af = loadJalviewAlign(jprovider);
2944 af.setMenusForViewport();
2946 } catch (MalformedURLException e)
2948 errorMessage = "Invalid URL format for '" + file + "'";
2954 SwingUtilities.invokeAndWait(new Runnable()
2959 setLoadingFinishedForNewStructureViewers();
2962 } catch (Exception x)
2964 System.err.println("Error loading alignment: " + x.getMessage());
2970 @SuppressWarnings("unused")
2971 private jarInputStreamProvider createjarInputStreamProvider(
2972 final Object ofile) throws MalformedURLException
2975 // BH 2018 allow for bytes already attached to File object
2978 String file = (ofile instanceof File
2979 ? ((File) ofile).getCanonicalPath()
2980 : ofile.toString());
2981 byte[] bytes = Platform.isJS() ? Platform.getFileBytes((File) ofile)
2984 errorMessage = null;
2985 uniqueSetSuffix = null;
2987 viewportsAdded.clear();
2988 frefedSequence = null;
2990 if (HttpUtils.startsWithHttpOrHttps(file))
2992 url = new URL(file);
2994 final URL _url = url;
2995 return new jarInputStreamProvider()
2999 public JarInputStream getJarInputStream() throws IOException
3003 // System.out.println("Jalview2XML: opening byte jarInputStream for
3004 // bytes.length=" + bytes.length);
3005 return new JarInputStream(new ByteArrayInputStream(bytes));
3009 // System.out.println("Jalview2XML: opening url jarInputStream for "
3011 return new JarInputStream(_url.openStream());
3015 // System.out.println("Jalview2XML: opening file jarInputStream for
3017 return new JarInputStream(new FileInputStream(file));
3022 public String getFilename()
3027 } catch (IOException e)
3029 e.printStackTrace();
3035 * Recover jalview session from a jalview project archive. Caller may
3036 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
3037 * themselves. Any null fields will be initialised with default values,
3038 * non-null fields are left alone.
3043 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
3045 errorMessage = null;
3046 if (uniqueSetSuffix == null)
3048 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
3050 if (seqRefIds == null)
3054 AlignFrame af = null, _af = null;
3055 IdentityHashMap<AlignmentI, AlignmentI> importedDatasets = new IdentityHashMap<>();
3056 Map<String, AlignFrame> gatherToThisFrame = new HashMap<>();
3057 final String file = jprovider.getFilename();
3060 JarInputStream jin = null;
3061 JarEntry jarentry = null;
3066 jin = jprovider.getJarInputStream();
3067 for (int i = 0; i < entryCount; i++)
3069 jarentry = jin.getNextJarEntry();
3072 if (jarentry != null && jarentry.getName().endsWith(".xml"))
3074 JAXBContext jc = JAXBContext
3075 .newInstance("jalview.xml.binding.jalview");
3076 XMLStreamReader streamReader = XMLInputFactory.newInstance()
3077 .createXMLStreamReader(jin);
3078 javax.xml.bind.Unmarshaller um = jc.createUnmarshaller();
3079 JAXBElement<JalviewModel> jbe = um.unmarshal(streamReader,
3080 JalviewModel.class);
3081 JalviewModel object = jbe.getValue();
3083 if (true) // !skipViewport(object))
3085 _af = loadFromObject(object, file, true, jprovider);
3086 if (_af != null && object.getViewport().size() > 0)
3087 // getJalviewModelSequence().getViewportCount() > 0)
3091 // store a reference to the first view
3094 if (_af.getViewport().isGatherViewsHere())
3096 // if this is a gathered view, keep its reference since
3097 // after gathering views, only this frame will remain
3099 gatherToThisFrame.put(_af.getViewport().getSequenceSetId(),
3102 // Save dataset to register mappings once all resolved
3103 importedDatasets.put(
3104 af.getViewport().getAlignment().getDataset(),
3105 af.getViewport().getAlignment().getDataset());
3110 else if (jarentry != null)
3112 // Some other file here.
3115 } while (jarentry != null);
3117 resolveFrefedSequences();
3118 } catch (IOException ex)
3120 ex.printStackTrace();
3121 errorMessage = "Couldn't locate Jalview XML file : " + file;
3123 "Exception whilst loading jalview XML file : " + ex + "\n");
3124 } catch (Exception ex)
3126 System.err.println("Parsing as Jalview Version 2 file failed.");
3127 ex.printStackTrace(System.err);
3128 if (attemptversion1parse)
3130 // used to attempt to parse as V1 castor-generated xml
3132 if (Desktop.instance != null)
3134 Desktop.instance.stopLoading();
3138 System.out.println("Successfully loaded archive file");
3141 ex.printStackTrace();
3144 "Exception whilst loading jalview XML file : " + ex + "\n");
3145 } catch (OutOfMemoryError e)
3147 // Don't use the OOM Window here
3148 errorMessage = "Out of memory loading jalview XML file";
3149 System.err.println("Out of memory whilst loading jalview XML file");
3150 e.printStackTrace();
3154 * Regather multiple views (with the same sequence set id) to the frame (if
3155 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
3156 * views instead of separate frames. Note this doesn't restore a state where
3157 * some expanded views in turn have tabbed views - the last "first tab" read
3158 * in will play the role of gatherer for all.
3160 for (AlignFrame fr : gatherToThisFrame.values())
3162 Desktop.instance.gatherViews(fr);
3165 restoreSplitFrames();
3166 for (AlignmentI ds : importedDatasets.keySet())
3168 if (ds.getCodonFrames() != null)
3170 StructureSelectionManager
3171 .getStructureSelectionManager(Desktop.instance)
3172 .registerMappings(ds.getCodonFrames());
3175 if (errorMessage != null)
3180 if (Desktop.instance != null)
3182 Desktop.instance.stopLoading();
3189 * Try to reconstruct and display SplitFrame windows, where each contains
3190 * complementary dna and protein alignments. Done by pairing up AlignFrame
3191 * objects (created earlier) which have complementary viewport ids associated.
3193 protected void restoreSplitFrames()
3195 List<SplitFrame> gatherTo = new ArrayList<>();
3196 List<AlignFrame> addedToSplitFrames = new ArrayList<>();
3197 Map<String, AlignFrame> dna = new HashMap<>();
3200 * Identify the DNA alignments
3202 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
3205 AlignFrame af = candidate.getValue();
3206 if (af.getViewport().getAlignment().isNucleotide())
3208 dna.put(candidate.getKey().getId(), af);
3213 * Try to match up the protein complements
3215 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
3218 AlignFrame af = candidate.getValue();
3219 if (!af.getViewport().getAlignment().isNucleotide())
3221 String complementId = candidate.getKey().getComplementId();
3222 // only non-null complements should be in the Map
3223 if (complementId != null && dna.containsKey(complementId))
3225 final AlignFrame dnaFrame = dna.get(complementId);
3226 SplitFrame sf = createSplitFrame(dnaFrame, af);
3227 addedToSplitFrames.add(dnaFrame);
3228 addedToSplitFrames.add(af);
3229 dnaFrame.setMenusForViewport();
3230 af.setMenusForViewport();
3231 if (af.getViewport().isGatherViewsHere())
3240 * Open any that we failed to pair up (which shouldn't happen!) as
3241 * standalone AlignFrame's.
3243 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
3246 AlignFrame af = candidate.getValue();
3247 if (!addedToSplitFrames.contains(af))
3249 Viewport view = candidate.getKey();
3250 Desktop.addInternalFrame(af, view.getTitle(),
3251 safeInt(view.getWidth()), safeInt(view.getHeight()));
3252 af.setMenusForViewport();
3253 System.err.println("Failed to restore view " + view.getTitle()
3254 + " to split frame");
3259 * Gather back into tabbed views as flagged.
3261 for (SplitFrame sf : gatherTo)
3263 Desktop.instance.gatherViews(sf);
3266 splitFrameCandidates.clear();
3270 * Construct and display one SplitFrame holding DNA and protein alignments.
3273 * @param proteinFrame
3276 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
3277 AlignFrame proteinFrame)
3279 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
3280 String title = MessageManager.getString("label.linked_view_title");
3281 int width = (int) dnaFrame.getBounds().getWidth();
3282 int height = (int) (dnaFrame.getBounds().getHeight()
3283 + proteinFrame.getBounds().getHeight() + 50);
3286 * SplitFrame location is saved to both enclosed frames
3288 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
3289 Desktop.addInternalFrame(splitFrame, title, width, height);
3292 * And compute cDNA consensus (couldn't do earlier with consensus as
3293 * mappings were not yet present)
3295 proteinFrame.getViewport().alignmentChanged(proteinFrame.alignPanel);
3301 * check errorMessage for a valid error message and raise an error box in the
3302 * GUI or write the current errorMessage to stderr and then clear the error
3305 protected void reportErrors()
3307 reportErrors(false);
3310 protected void reportErrors(final boolean saving)
3312 if (errorMessage != null)
3314 final String finalErrorMessage = errorMessage;
3317 javax.swing.SwingUtilities.invokeLater(new Runnable()
3322 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
3324 "Error " + (saving ? "saving" : "loading")
3326 JvOptionPane.WARNING_MESSAGE);
3332 System.err.println("Problem loading Jalview file: " + errorMessage);
3335 errorMessage = null;
3338 Map<String, String> alreadyLoadedPDB = new HashMap<>();
3341 * when set, local views will be updated from view stored in JalviewXML
3342 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
3343 * sync if this is set to true.
3345 private final boolean updateLocalViews = false;
3348 * Returns the path to a temporary file holding the PDB file for the given PDB
3349 * id. The first time of asking, searches for a file of that name in the
3350 * Jalview project jar, and copies it to a new temporary file. Any repeat
3351 * requests just return the path to the file previously created.
3357 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId,
3360 if (alreadyLoadedPDB.containsKey(pdbId))
3362 return alreadyLoadedPDB.get(pdbId).toString();
3365 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb",
3367 if (tempFile != null)
3369 alreadyLoadedPDB.put(pdbId, tempFile);
3375 * Copies the jar entry of given name to a new temporary file and returns the
3376 * path to the file, or null if the entry is not found.
3379 * @param jarEntryName
3381 * a prefix for the temporary file name, must be at least three
3383 * @param suffixModel
3384 * null or original file - so new file can be given the same suffix
3388 protected String copyJarEntry(jarInputStreamProvider jprovider,
3389 String jarEntryName, String prefix, String suffixModel)
3391 String suffix = ".tmp";
3392 if (suffixModel == null)
3394 suffixModel = jarEntryName;
3396 int sfpos = suffixModel.lastIndexOf(".");
3397 if (sfpos > -1 && sfpos < (suffixModel.length() - 1))
3399 suffix = "." + suffixModel.substring(sfpos + 1);
3402 try (JarInputStream jin = jprovider.getJarInputStream())
3404 JarEntry entry = null;
3407 entry = jin.getNextJarEntry();
3408 } while (entry != null && !entry.getName().equals(jarEntryName));
3412 // in = new BufferedReader(new InputStreamReader(jin, UTF_8));
3413 File outFile = File.createTempFile(prefix, suffix);
3414 outFile.deleteOnExit();
3415 try (OutputStream os = new FileOutputStream(outFile))
3419 String t = outFile.getAbsolutePath();
3425 "Couldn't find entry in Jalview Jar for " + jarEntryName);
3427 } catch (Exception ex)
3429 ex.printStackTrace();
3435 private class JvAnnotRow
3437 public JvAnnotRow(int i, AlignmentAnnotation jaa)
3444 * persisted version of annotation row from which to take vis properties
3446 public jalview.datamodel.AlignmentAnnotation template;
3449 * original position of the annotation row in the alignment
3455 * Load alignment frame from jalview XML DOM object
3457 * @param jalviewModel
3460 * filename source string
3461 * @param loadTreesAndStructures
3462 * when false only create Viewport
3464 * data source provider
3465 * @return alignment frame created from view stored in DOM
3467 AlignFrame loadFromObject(JalviewModel jalviewModel, String file,
3468 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
3470 SequenceSet vamsasSet = jalviewModel.getVamsasModel().getSequenceSet()
3472 List<Sequence> vamsasSeqs = vamsasSet.getSequence();
3474 // JalviewModelSequence jms = object.getJalviewModelSequence();
3476 // Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
3478 Viewport view = (jalviewModel.getViewport().size() > 0)
3479 ? jalviewModel.getViewport().get(0)
3482 // ////////////////////////////////
3483 // INITIALISE ALIGNMENT SEQUENCESETID AND VIEWID
3486 // If we just load in the same jar file again, the sequenceSetId
3487 // will be the same, and we end up with multiple references
3488 // to the same sequenceSet. We must modify this id on load
3489 // so that each load of the file gives a unique id
3492 * used to resolve correct alignment dataset for alignments with multiple
3495 String uniqueSeqSetId = null;
3496 String viewId = null;
3499 uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3500 viewId = (view.getId() == null ? null
3501 : view.getId() + uniqueSetSuffix);
3504 // ////////////////////////////////
3507 List<SequenceI> hiddenSeqs = null;
3509 List<SequenceI> tmpseqs = new ArrayList<>();
3511 boolean multipleView = false;
3512 SequenceI referenceseqForView = null;
3513 // JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
3514 List<JSeq> jseqs = jalviewModel.getJSeq();
3515 int vi = 0; // counter in vamsasSeq array
3516 for (int i = 0; i < jseqs.size(); i++)
3518 JSeq jseq = jseqs.get(i);
3519 String seqId = jseq.getId();
3521 SequenceI tmpSeq = seqRefIds.get(seqId);
3524 if (!incompleteSeqs.containsKey(seqId))
3526 // may not need this check, but keep it for at least 2.9,1 release
3527 if (tmpSeq.getStart() != jseq.getStart()
3528 || tmpSeq.getEnd() != jseq.getEnd())
3530 System.err.println(String.format(
3531 "Warning JAL-2154 regression: updating start/end for sequence %s from %d/%d to %d/%d",
3532 tmpSeq.getName(), tmpSeq.getStart(), tmpSeq.getEnd(),
3533 jseq.getStart(), jseq.getEnd()));
3538 incompleteSeqs.remove(seqId);
3540 if (vamsasSeqs.size() > vi
3541 && vamsasSeqs.get(vi).getId().equals(seqId))
3543 // most likely we are reading a dataset XML document so
3544 // update from vamsasSeq section of XML for this sequence
3545 tmpSeq.setName(vamsasSeqs.get(vi).getName());
3546 tmpSeq.setDescription(vamsasSeqs.get(vi).getDescription());
3547 tmpSeq.setSequence(vamsasSeqs.get(vi).getSequence());
3552 // reading multiple views, so vamsasSeq set is a subset of JSeq
3553 multipleView = true;
3555 tmpSeq.setStart(jseq.getStart());
3556 tmpSeq.setEnd(jseq.getEnd());
3557 tmpseqs.add(tmpSeq);
3561 Sequence vamsasSeq = vamsasSeqs.get(vi);
3562 tmpSeq = new jalview.datamodel.Sequence(vamsasSeq.getName(),
3563 vamsasSeq.getSequence());
3564 tmpSeq.setDescription(vamsasSeq.getDescription());
3565 tmpSeq.setStart(jseq.getStart());
3566 tmpSeq.setEnd(jseq.getEnd());
3567 tmpSeq.setVamsasId(uniqueSetSuffix + seqId);
3568 seqRefIds.put(vamsasSeq.getId(), tmpSeq);
3569 tmpseqs.add(tmpSeq);
3573 if (safeBoolean(jseq.isViewreference()))
3575 referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
3578 if (jseq.isHidden() != null && jseq.isHidden().booleanValue())
3580 if (hiddenSeqs == null)
3582 hiddenSeqs = new ArrayList<>();
3585 hiddenSeqs.add(tmpSeq);
3590 // Create the alignment object from the sequence set
3591 // ///////////////////////////////
3592 SequenceI[] orderedSeqs = tmpseqs
3593 .toArray(new SequenceI[tmpseqs.size()]);
3595 AlignmentI al = null;
3596 // so we must create or recover the dataset alignment before going further
3597 // ///////////////////////////////
3598 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
3600 // older jalview projects do not have a dataset - so creat alignment and
3602 al = new Alignment(orderedSeqs);
3603 al.setDataset(null);
3607 boolean isdsal = jalviewModel.getViewport().isEmpty();
3610 // we are importing a dataset record, so
3611 // recover reference to an alignment already materialsed as dataset
3612 al = getDatasetFor(vamsasSet.getDatasetId());
3616 // materialse the alignment
3617 al = new Alignment(orderedSeqs);
3621 addDatasetRef(vamsasSet.getDatasetId(), al);
3624 // finally, verify all data in vamsasSet is actually present in al
3625 // passing on flag indicating if it is actually a stored dataset
3626 recoverDatasetFor(vamsasSet, al, isdsal, uniqueSeqSetId);
3629 if (referenceseqForView != null)
3631 al.setSeqrep(referenceseqForView);
3633 // / Add the alignment properties
3634 for (int i = 0; i < vamsasSet.getSequenceSetProperties().size(); i++)
3636 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties()
3638 al.setProperty(ssp.getKey(), ssp.getValue());
3641 // ///////////////////////////////
3643 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
3646 // load sequence features, database references and any associated PDB
3647 // structures for the alignment
3649 // prior to 2.10, this part would only be executed the first time a
3650 // sequence was encountered, but not afterwards.
3651 // now, for 2.10 projects, this is also done if the xml doc includes
3652 // dataset sequences not actually present in any particular view.
3654 for (int i = 0; i < vamsasSeqs.size(); i++)
3656 JSeq jseq = jseqs.get(i);
3657 if (jseq.getFeatures().size() > 0)
3659 List<Feature> features = jseq.getFeatures();
3660 for (int f = 0; f < features.size(); f++)
3662 Feature feat = features.get(f);
3663 SequenceFeature sf = new SequenceFeature(feat.getType(),
3664 feat.getDescription(), feat.getBegin(), feat.getEnd(),
3665 safeFloat(feat.getScore()), feat.getFeatureGroup());
3666 sf.setStatus(feat.getStatus());
3669 * load any feature attributes - include map-valued attributes
3671 Map<String, Map<String, String>> mapAttributes = new HashMap<>();
3672 for (int od = 0; od < feat.getOtherData().size(); od++)
3674 OtherData keyValue = feat.getOtherData().get(od);
3675 String attributeName = keyValue.getKey();
3676 String attributeValue = keyValue.getValue();
3677 if (attributeName.startsWith("LINK"))
3679 sf.addLink(attributeValue);
3683 String subAttribute = keyValue.getKey2();
3684 if (subAttribute == null)
3686 // simple string-valued attribute
3687 sf.setValue(attributeName, attributeValue);
3691 // attribute 'key' has sub-attribute 'key2'
3692 if (!mapAttributes.containsKey(attributeName))
3694 mapAttributes.put(attributeName, new HashMap<>());
3696 mapAttributes.get(attributeName).put(subAttribute,
3701 for (Entry<String, Map<String, String>> mapAttribute : mapAttributes
3704 sf.setValue(mapAttribute.getKey(), mapAttribute.getValue());
3707 // adds feature to datasequence's feature set (since Jalview 2.10)
3708 al.getSequenceAt(i).addSequenceFeature(sf);
3711 if (vamsasSeqs.get(i).getDBRef().size() > 0)
3713 // adds dbrefs to datasequence's set (since Jalview 2.10)
3715 al.getSequenceAt(i).getDatasetSequence() == null
3716 ? al.getSequenceAt(i)
3717 : al.getSequenceAt(i).getDatasetSequence(),
3720 if (jseq.getPdbids().size() > 0)
3722 List<Pdbids> ids = jseq.getPdbids();
3723 for (int p = 0; p < ids.size(); p++)
3725 Pdbids pdbid = ids.get(p);
3726 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
3727 entry.setId(pdbid.getId());
3728 if (pdbid.getType() != null)
3730 if (PDBEntry.Type.getType(pdbid.getType()) != null)
3732 entry.setType(PDBEntry.Type.getType(pdbid.getType()));
3736 entry.setType(PDBEntry.Type.FILE);
3739 // jprovider is null when executing 'New View'
3740 if (pdbid.getFile() != null && jprovider != null)
3742 if (!pdbloaded.containsKey(pdbid.getFile()))
3744 entry.setFile(loadPDBFile(jprovider, pdbid.getId(),
3749 entry.setFile(pdbloaded.get(pdbid.getId()).toString());
3753 if (pdbid.getPdbentryItem() != null)
3755 for (PdbentryItem item : pdbid.getPdbentryItem())
3757 for (Property pr : item.getProperty())
3759 entry.setProperty(pr.getName(), pr.getValue());
3764 for (Property prop : pdbid.getProperty())
3766 entry.setProperty(prop.getName(), prop.getValue());
3768 StructureSelectionManager
3769 .getStructureSelectionManager(Desktop.instance)
3770 .registerPDBEntry(entry);
3771 // adds PDBEntry to datasequence's set (since Jalview 2.10)
3772 if (al.getSequenceAt(i).getDatasetSequence() != null)
3774 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
3778 al.getSequenceAt(i).addPDBId(entry);
3783 } // end !multipleview
3785 // ///////////////////////////////
3786 // LOAD SEQUENCE MAPPINGS
3788 if (vamsasSet.getAlcodonFrame().size() > 0)
3790 // TODO Potentially this should only be done once for all views of an
3792 List<AlcodonFrame> alc = vamsasSet.getAlcodonFrame();
3793 for (int i = 0; i < alc.size(); i++)
3795 AlignedCodonFrame cf = new AlignedCodonFrame();
3796 if (alc.get(i).getAlcodMap().size() > 0)
3798 List<AlcodMap> maps = alc.get(i).getAlcodMap();
3799 for (int m = 0; m < maps.size(); m++)
3801 AlcodMap map = maps.get(m);
3802 SequenceI dnaseq = seqRefIds.get(map.getDnasq());
3804 jalview.datamodel.Mapping mapping = null;
3805 // attach to dna sequence reference.
3806 if (map.getMapping() != null)
3808 mapping = addMapping(map.getMapping());
3809 if (dnaseq != null && mapping.getTo() != null)
3811 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
3817 .add(newAlcodMapRef(map.getDnasq(), cf, mapping));
3821 al.addCodonFrame(cf);
3826 // ////////////////////////////////
3828 List<JvAnnotRow> autoAlan = new ArrayList<>();
3831 * store any annotations which forward reference a group's ID
3833 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<>();
3835 if (vamsasSet.getAnnotation().size()/*Count()*/ > 0)
3837 List<Annotation> an = vamsasSet.getAnnotation();
3839 for (int i = 0; i < an.size(); i++)
3841 Annotation annotation = an.get(i);
3844 * test if annotation is automatically calculated for this view only
3846 boolean autoForView = false;
3847 if (annotation.getLabel().equals("Quality")
3848 || annotation.getLabel().equals("Conservation")
3849 || annotation.getLabel().equals("Consensus"))
3851 // Kludge for pre 2.5 projects which lacked the autocalculated flag
3853 // JAXB has no has() test; schema defaults value to false
3854 // if (!annotation.hasAutoCalculated())
3856 // annotation.setAutoCalculated(true);
3859 if (autoForView || annotation.isAutoCalculated())
3861 // remove ID - we don't recover annotation from other views for
3862 // view-specific annotation
3863 annotation.setId(null);
3866 // set visibility for other annotation in this view
3867 String annotationId = annotation.getId();
3868 if (annotationId != null && annotationIds.containsKey(annotationId))
3870 AlignmentAnnotation jda = annotationIds.get(annotationId);
3871 // in principle Visible should always be true for annotation displayed
3872 // in multiple views
3873 if (annotation.isVisible() != null)
3875 jda.visible = annotation.isVisible();
3878 al.addAnnotation(jda);
3882 // Construct new annotation from model.
3883 List<AnnotationElement> ae = annotation.getAnnotationElement();
3884 jalview.datamodel.Annotation[] anot = null;
3885 java.awt.Color firstColour = null;
3887 if (!annotation.isScoreOnly())
3889 anot = new jalview.datamodel.Annotation[al.getWidth()];
3890 for (int aa = 0; aa < ae.size() && aa < anot.length; aa++)
3892 AnnotationElement annElement = ae.get(aa);
3893 anpos = annElement.getPosition();
3895 if (anpos >= anot.length)
3900 float value = safeFloat(annElement.getValue());
3901 anot[anpos] = new jalview.datamodel.Annotation(
3902 annElement.getDisplayCharacter(),
3903 annElement.getDescription(),
3904 (annElement.getSecondaryStructure() == null
3905 || annElement.getSecondaryStructure()
3909 .getSecondaryStructure()
3912 anot[anpos].colour = new Color(safeInt(annElement.getColour()));
3913 if (firstColour == null)
3915 firstColour = anot[anpos].colour;
3919 jalview.datamodel.AlignmentAnnotation jaa = null;
3921 if (annotation.isGraph())
3923 float llim = 0, hlim = 0;
3924 // if (autoForView || an[i].isAutoCalculated()) {
3927 jaa = new jalview.datamodel.AlignmentAnnotation(
3928 annotation.getLabel(), annotation.getDescription(), anot,
3929 llim, hlim, safeInt(annotation.getGraphType()));
3931 jaa.graphGroup = safeInt(annotation.getGraphGroup());
3932 jaa._linecolour = firstColour;
3933 if (annotation.getThresholdLine() != null)
3935 jaa.setThreshold(new jalview.datamodel.GraphLine(
3936 safeFloat(annotation.getThresholdLine().getValue()),
3937 annotation.getThresholdLine().getLabel(),
3938 new java.awt.Color(safeInt(
3939 annotation.getThresholdLine().getColour()))));
3941 if (autoForView || annotation.isAutoCalculated())
3943 // Hardwire the symbol display line to ensure that labels for
3944 // histograms are displayed
3950 jaa = new jalview.datamodel.AlignmentAnnotation(
3951 annotation.getLabel(), annotation.getDescription(), anot);
3952 jaa._linecolour = firstColour;
3954 // register new annotation
3955 if (annotation.getId() != null)
3957 annotationIds.put(annotation.getId(), jaa);
3958 jaa.annotationId = annotation.getId();
3960 // recover sequence association
3961 String sequenceRef = annotation.getSequenceRef();
3962 if (sequenceRef != null)
3964 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3965 SequenceI sequence = seqRefIds.get(sequenceRef);
3966 if (sequence == null)
3968 // in pre-2.9 projects sequence ref is to sequence name
3969 sequence = al.findName(sequenceRef);
3971 if (sequence != null)
3973 jaa.createSequenceMapping(sequence, 1, true);
3974 sequence.addAlignmentAnnotation(jaa);
3977 // and make a note of any group association
3978 if (annotation.getGroupRef() != null
3979 && annotation.getGroupRef().length() > 0)
3981 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3982 .get(annotation.getGroupRef());
3985 aal = new ArrayList<>();
3986 groupAnnotRefs.put(annotation.getGroupRef(), aal);
3991 if (annotation.getScore() != null)
3993 jaa.setScore(annotation.getScore().doubleValue());
3995 if (annotation.isVisible() != null)
3997 jaa.visible = annotation.isVisible().booleanValue();
4000 if (annotation.isCentreColLabels() != null)
4002 jaa.centreColLabels = annotation.isCentreColLabels()
4006 if (annotation.isScaleColLabels() != null)
4008 jaa.scaleColLabel = annotation.isScaleColLabels().booleanValue();
4010 if (annotation.isAutoCalculated())
4012 // newer files have an 'autoCalculated' flag and store calculation
4013 // state in viewport properties
4014 jaa.autoCalculated = true; // means annotation will be marked for
4015 // update at end of load.
4017 if (annotation.getGraphHeight() != null)
4019 jaa.graphHeight = annotation.getGraphHeight().intValue();
4021 jaa.belowAlignment = annotation.isBelowAlignment();
4022 jaa.setCalcId(annotation.getCalcId());
4023 if (annotation.getProperty().size() > 0)
4025 for (jalview.xml.binding.jalview.Property prop : annotation
4028 jaa.setProperty(prop.getName(), prop.getValue());
4031 if (jaa.graph == AlignmentAnnotation.CONTACT_MAP)
4033 if (annotation.getContactmatrix() != null
4034 && annotation.getContactmatrix().size() > 0)
4036 for (MatrixType xmlmat : annotation.getContactmatrix())
4038 if (PAEContactMatrix.PAEMATRIX.equals(xmlmat.getType()))
4040 if (!xmlmat.getRows().equals(xmlmat.getCols()))
4042 Console.error("Can't handle non square PAE Matrices");
4046 float[][] elements = ContactMatrix
4047 .fromFloatStringToContacts(xmlmat.getElements(),
4048 xmlmat.getCols().intValue(),
4049 xmlmat.getRows().intValue());
4050 jalview.util.MapList mapping = null;
4051 if (xmlmat.getMapping() != null)
4053 MapListType m = xmlmat.getMapping();
4054 // Mapping m = dr.getMapping();
4055 int fr[] = new int[m.getMapListFrom().size() * 2];
4056 Iterator<MapListFrom> from = m.getMapListFrom()
4057 .iterator();// enumerateMapListFrom();
4058 for (int _i = 0; from.hasNext(); _i += 2)
4060 MapListFrom mf = from.next();
4061 fr[_i] = mf.getStart();
4062 fr[_i + 1] = mf.getEnd();
4064 int fto[] = new int[m.getMapListTo().size() * 2];
4065 Iterator<MapListTo> to = m.getMapListTo().iterator();// enumerateMapListTo();
4066 for (int _i = 0; to.hasNext(); _i += 2)
4068 MapListTo mf = to.next();
4069 fto[_i] = mf.getStart();
4070 fto[_i + 1] = mf.getEnd();
4073 mapping = new jalview.util.MapList(fr, fto,
4074 m.getMapFromUnit().intValue(),
4075 m.getMapToUnit().intValue());
4077 List<BitSet> newgroups = new ArrayList<BitSet>();
4078 if (xmlmat.getGroups().size() > 0)
4080 for (String sgroup : xmlmat.getGroups())
4082 newgroups.add(deStringifyBitset(sgroup));
4085 String nwk = xmlmat.getNewick().size() > 0
4086 ? xmlmat.getNewick().get(0)
4088 if (xmlmat.getNewick().size() > 1)
4091 "Ignoring additional clusterings for contact matrix");
4094 String treeMethod = xmlmat.getTreeMethod();
4095 double thresh = xmlmat.getCutHeight() != null
4096 ? xmlmat.getCutHeight()
4098 GroupSet grpset = new GroupSet();
4099 grpset.restoreGroups(newgroups, treeMethod, nwk, thresh);
4100 PAEContactMatrix newpae = new PAEContactMatrix(
4101 jaa.sequenceRef, mapping, elements, grpset);
4102 jaa.sequenceRef.addContactListFor(jaa, newpae);
4107 Console.error("Ignoring CONTACT_MAP annotation with type "
4108 + xmlmat.getType());
4114 if (jaa.autoCalculated)
4116 autoAlan.add(new JvAnnotRow(i, jaa));
4119 // if (!autoForView)
4121 // add autocalculated group annotation and any user created annotation
4123 al.addAnnotation(jaa);
4127 // ///////////////////////
4129 // Create alignment markup and styles for this view
4130 if (jalviewModel.getJGroup().size() > 0)
4132 List<JGroup> groups = jalviewModel.getJGroup();
4133 boolean addAnnotSchemeGroup = false;
4134 for (int i = 0; i < groups.size(); i++)
4136 JGroup jGroup = groups.get(i);
4137 ColourSchemeI cs = null;
4138 if (jGroup.getColour() != null)
4140 if (jGroup.getColour().startsWith("ucs"))
4142 cs = getUserColourScheme(jalviewModel, jGroup.getColour());
4144 else if (jGroup.getColour().equals("AnnotationColourGradient")
4145 && jGroup.getAnnotationColours() != null)
4147 addAnnotSchemeGroup = true;
4151 cs = ColourSchemeProperty.getColourScheme(null, al,
4152 jGroup.getColour());
4155 int pidThreshold = safeInt(jGroup.getPidThreshold());
4157 Vector<SequenceI> seqs = new Vector<>();
4159 for (int s = 0; s < jGroup.getSeq().size(); s++)
4161 String seqId = jGroup.getSeq().get(s);
4162 SequenceI ts = seqRefIds.get(seqId);
4166 seqs.addElement(ts);
4170 if (seqs.size() < 1)
4175 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
4176 safeBoolean(jGroup.isDisplayBoxes()),
4177 safeBoolean(jGroup.isDisplayText()),
4178 safeBoolean(jGroup.isColourText()),
4179 safeInt(jGroup.getStart()), safeInt(jGroup.getEnd()));
4180 sg.getGroupColourScheme().setThreshold(pidThreshold, true);
4181 sg.getGroupColourScheme()
4182 .setConservationInc(safeInt(jGroup.getConsThreshold()));
4183 sg.setOutlineColour(new Color(safeInt(jGroup.getOutlineColour())));
4185 sg.textColour = new Color(safeInt(jGroup.getTextCol1()));
4186 sg.textColour2 = new Color(safeInt(jGroup.getTextCol2()));
4187 sg.setShowNonconserved(safeBoolean(jGroup.isShowUnconserved()));
4188 sg.thresholdTextColour = safeInt(jGroup.getTextColThreshold());
4189 // attributes with a default in the schema are never null
4190 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
4191 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
4192 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
4193 sg.setIgnoreGapsConsensus(jGroup.isIgnoreGapsinConsensus());
4194 if (jGroup.getConsThreshold() != null
4195 && jGroup.getConsThreshold().intValue() != 0)
4197 Conservation c = new Conservation("All", sg.getSequences(null), 0,
4200 c.verdict(false, 25);
4201 sg.cs.setConservation(c);
4204 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
4206 // re-instate unique group/annotation row reference
4207 List<AlignmentAnnotation> jaal = groupAnnotRefs
4208 .get(jGroup.getId());
4211 for (AlignmentAnnotation jaa : jaal)
4214 if (jaa.autoCalculated)
4216 // match up and try to set group autocalc alignment row for this
4218 if (jaa.label.startsWith("Consensus for "))
4220 sg.setConsensus(jaa);
4222 // match up and try to set group autocalc alignment row for this
4224 if (jaa.label.startsWith("Conservation for "))
4226 sg.setConservationRow(jaa);
4233 if (addAnnotSchemeGroup)
4235 // reconstruct the annotation colourscheme
4237 constructAnnotationColour(jGroup.getAnnotationColours(),
4238 null, al, jalviewModel, false));
4244 // only dataset in this model, so just return.
4247 // ///////////////////////////////
4250 AlignFrame af = null;
4251 AlignViewport av = null;
4252 // now check to see if we really need to create a new viewport.
4253 if (multipleView && viewportsAdded.size() == 0)
4255 // We recovered an alignment for which a viewport already exists.
4256 // TODO: fix up any settings necessary for overlaying stored state onto
4257 // state recovered from another document. (may not be necessary).
4258 // we may need a binding from a viewport in memory to one recovered from
4260 // and then recover its containing af to allow the settings to be applied.
4261 // TODO: fix for vamsas demo
4263 "About to recover a viewport for existing alignment: Sequence set ID is "
4265 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
4266 if (seqsetobj != null)
4268 if (seqsetobj instanceof String)
4270 uniqueSeqSetId = (String) seqsetobj;
4272 "Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
4278 "Warning : Collision between sequence set ID string and existing jalview object mapping.");
4284 * indicate that annotation colours are applied across all groups (pre
4285 * Jalview 2.8.1 behaviour)
4287 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan("2.8.1",
4288 jalviewModel.getVersion());
4290 AlignmentPanel ap = null;
4291 boolean isnewview = true;
4294 // Check to see if this alignment already has a view id == viewId
4295 jalview.gui.AlignmentPanel views[] = Desktop
4296 .getAlignmentPanels(uniqueSeqSetId);
4297 if (views != null && views.length > 0)
4299 for (int v = 0; v < views.length; v++)
4301 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
4303 // recover the existing alignpanel, alignframe, viewport
4304 af = views[v].alignFrame;
4307 // TODO: could even skip resetting view settings if we don't want to
4308 // change the local settings from other jalview processes
4317 af = loadViewport(file, jseqs, hiddenSeqs, al, jalviewModel, view,
4318 uniqueSeqSetId, viewId, autoAlan);
4319 av = af.getViewport();
4324 * Load any trees, PDB structures and viewers, Overview
4326 * Not done if flag is false (when this method is used for New View)
4328 if (loadTreesAndStructures)
4330 loadTrees(jalviewModel, view, af, av, ap);
4331 loadPCAViewers(jalviewModel, ap);
4332 loadPDBStructures(jprovider, jseqs, af, ap);
4333 loadRnaViewers(jprovider, jseqs, ap);
4334 loadOverview(view, jalviewModel.getVersion(), af);
4336 // and finally return.
4341 * Load Overview window, restoring colours, 'show hidden regions' flag, title
4342 * and geometry as saved
4347 protected void loadOverview(Viewport view, String version, AlignFrame af)
4349 if (!isVersionStringLaterThan("2.11.3", version)
4350 && view.getOverview() == null)
4355 * first close any Overview that was opened automatically
4356 * (if so configured in Preferences) so that the view is
4357 * restored in the same state as saved
4359 af.alignPanel.closeOverviewPanel();
4361 Overview overview = view.getOverview();
4362 if (overview != null)
4364 OverviewPanel overviewPanel = af
4365 .openOverviewPanel(overview.isShowHidden());
4366 overviewPanel.setTitle(overview.getTitle());
4367 overviewPanel.setFrameBounds(overview.getXpos(), overview.getYpos(),
4368 overview.getWidth(), overview.getHeight());
4369 Color gap = new Color(overview.getGapColour());
4370 Color residue = new Color(overview.getResidueColour());
4371 Color hidden = new Color(overview.getHiddenColour());
4372 overviewPanel.getCanvas().setColours(gap, residue, hidden);
4377 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
4378 * panel is restored from separate jar entries, two (gapped and trimmed) per
4379 * sequence and secondary structure.
4381 * Currently each viewer shows just one sequence and structure (gapped and
4382 * trimmed), however this method is designed to support multiple sequences or
4383 * structures in viewers if wanted in future.
4389 private void loadRnaViewers(jarInputStreamProvider jprovider,
4390 List<JSeq> jseqs, AlignmentPanel ap)
4393 * scan the sequences for references to viewers; create each one the first
4394 * time it is referenced, add Rna models to existing viewers
4396 for (JSeq jseq : jseqs)
4398 for (int i = 0; i < jseq.getRnaViewer().size(); i++)
4400 RnaViewer viewer = jseq.getRnaViewer().get(i);
4401 AppVarna appVarna = findOrCreateVarnaViewer(viewer, uniqueSetSuffix,
4404 for (int j = 0; j < viewer.getSecondaryStructure().size(); j++)
4406 SecondaryStructure ss = viewer.getSecondaryStructure().get(j);
4407 SequenceI seq = seqRefIds.get(jseq.getId());
4408 AlignmentAnnotation ann = this.annotationIds
4409 .get(ss.getAnnotationId());
4412 * add the structure to the Varna display (with session state copied
4413 * from the jar to a temporary file)
4415 boolean gapped = safeBoolean(ss.isGapped());
4416 String rnaTitle = ss.getTitle();
4417 String sessionState = ss.getViewerState();
4418 String tempStateFile = copyJarEntry(jprovider, sessionState,
4420 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
4421 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
4423 appVarna.setInitialSelection(safeInt(viewer.getSelectedRna()));
4429 * Locate and return an already instantiated matching AppVarna, or create one
4433 * @param viewIdSuffix
4437 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
4438 String viewIdSuffix, AlignmentPanel ap)
4441 * on each load a suffix is appended to the saved viewId, to avoid conflicts
4442 * if load is repeated
4444 String postLoadId = viewer.getViewId() + viewIdSuffix;
4445 for (JInternalFrame frame : getAllFrames())
4447 if (frame instanceof AppVarna)
4449 AppVarna varna = (AppVarna) frame;
4450 if (postLoadId.equals(varna.getViewId()))
4452 // this viewer is already instantiated
4453 // could in future here add ap as another 'parent' of the
4454 // AppVarna window; currently just 1-to-many
4461 * viewer not found - make it
4463 RnaViewerModel model = new RnaViewerModel(postLoadId, viewer.getTitle(),
4464 safeInt(viewer.getXpos()), safeInt(viewer.getYpos()),
4465 safeInt(viewer.getWidth()), safeInt(viewer.getHeight()),
4466 safeInt(viewer.getDividerLocation()));
4467 AppVarna varna = new AppVarna(model, ap);
4473 * Load any saved trees
4481 protected void loadTrees(JalviewModel jm, Viewport view, AlignFrame af,
4482 AlignViewport av, AlignmentPanel ap)
4484 // TODO result of automated refactoring - are all these parameters needed?
4487 for (int t = 0; t < jm.getTree().size(); t++)
4490 Tree tree = jm.getTree().get(t);
4492 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
4495 if (tree.isColumnWise())
4497 AlignmentAnnotation aa = (AlignmentAnnotation) annotationIds
4498 .get(tree.getColumnReference());
4502 "Null alignment annotation when restoring columnwise tree");
4504 tp = af.showColumnWiseTree(new NewickFile(tree.getNewick()), aa,
4505 tree.getTitle(), safeInt(tree.getWidth()),
4506 safeInt(tree.getHeight()), safeInt(tree.getXpos()),
4507 safeInt(tree.getYpos()));
4512 tp = af.showNewickTree(new NewickFile(tree.getNewick()),
4513 tree.getTitle(), safeInt(tree.getWidth()),
4514 safeInt(tree.getHeight()), safeInt(tree.getXpos()),
4515 safeInt(tree.getYpos()));
4517 if (tree.getId() != null)
4519 // perhaps bind the tree id to something ?
4524 // update local tree attributes ?
4525 // TODO: should check if tp has been manipulated by user - if so its
4526 // settings shouldn't be modified
4527 tp.setTitle(tree.getTitle());
4528 tp.setBounds(new Rectangle(safeInt(tree.getXpos()),
4529 safeInt(tree.getYpos()), safeInt(tree.getWidth()),
4530 safeInt(tree.getHeight())));
4531 tp.setViewport(av); // af.viewport;
4532 // TODO: verify 'associate with all views' works still
4533 tp.getTreeCanvas().setViewport(av); // af.viewport;
4534 tp.getTreeCanvas().setAssociatedPanel(ap); // af.alignPanel;
4536 tp.getTreeCanvas().setApplyToAllViews(tree.isLinkToAllViews());
4540 "There was a problem recovering stored Newick tree: \n"
4541 + tree.getNewick());
4545 tp.fitToWindow.setState(safeBoolean(tree.isFitToWindow()));
4546 tp.fitToWindow_actionPerformed(null);
4548 if (tree.getFontName() != null)
4551 new Font(tree.getFontName(), safeInt(tree.getFontStyle()),
4552 safeInt(tree.getFontSize())));
4557 new Font(view.getFontName(), safeInt(view.getFontStyle()),
4558 safeInt(view.getFontSize())));
4561 tp.showPlaceholders(safeBoolean(tree.isMarkUnlinked()));
4562 tp.showBootstrap(safeBoolean(tree.isShowBootstrap()));
4563 tp.showDistances(safeBoolean(tree.isShowDistances()));
4565 tp.getTreeCanvas().setThreshold(safeFloat(tree.getThreshold()));
4567 if (safeBoolean(tree.isCurrentTree()))
4569 af.getViewport().setCurrentTree(tp.getTree());
4573 } catch (Exception ex)
4575 ex.printStackTrace();
4580 * Load and link any saved structure viewers.
4587 protected void loadPDBStructures(jarInputStreamProvider jprovider,
4588 List<JSeq> jseqs, AlignFrame af, AlignmentPanel ap)
4591 * Run through all PDB ids on the alignment, and collect mappings between
4592 * distinct view ids and all sequences referring to that view.
4594 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<>();
4596 for (int i = 0; i < jseqs.size(); i++)
4598 JSeq jseq = jseqs.get(i);
4599 if (jseq.getPdbids().size() > 0)
4601 List<Pdbids> ids = jseq.getPdbids();
4602 for (int p = 0; p < ids.size(); p++)
4604 Pdbids pdbid = ids.get(p);
4605 final int structureStateCount = pdbid.getStructureState().size();
4606 for (int s = 0; s < structureStateCount; s++)
4608 // check to see if we haven't already created this structure view
4609 final StructureState structureState = pdbid.getStructureState()
4611 String sviewid = (structureState.getViewId() == null) ? null
4612 : structureState.getViewId() + uniqueSetSuffix;
4613 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
4614 // Originally : pdbid.getFile()
4615 // : TODO: verify external PDB file recovery still works in normal
4616 // jalview project load
4618 loadPDBFile(jprovider, pdbid.getId(), pdbid.getFile()));
4619 jpdb.setId(pdbid.getId());
4621 int x = safeInt(structureState.getXpos());
4622 int y = safeInt(structureState.getYpos());
4623 int width = safeInt(structureState.getWidth());
4624 int height = safeInt(structureState.getHeight());
4626 // Probably don't need to do this anymore...
4627 // Desktop.desktop.getComponentAt(x, y);
4628 // TODO: NOW: check that this recovers the PDB file correctly.
4629 String pdbFile = loadPDBFile(jprovider, pdbid.getId(),
4631 jalview.datamodel.SequenceI seq = seqRefIds
4632 .get(jseq.getId() + "");
4633 if (sviewid == null)
4635 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width + ","
4638 if (!structureViewers.containsKey(sviewid))
4640 String viewerType = structureState.getType();
4641 if (viewerType == null) // pre Jalview 2.9
4643 viewerType = ViewerType.JMOL.toString();
4645 structureViewers.put(sviewid,
4646 new StructureViewerModel(x, y, width, height, false,
4647 false, true, structureState.getViewId(),
4649 // Legacy pre-2.7 conversion JAL-823 :
4650 // do not assume any view has to be linked for colour by
4654 // assemble String[] { pdb files }, String[] { id for each
4655 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
4656 // seqs_file 2}, boolean[] {
4657 // linkAlignPanel,superposeWithAlignpanel}} from hash
4658 StructureViewerModel jmoldat = structureViewers.get(sviewid);
4659 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
4660 || structureState.isAlignwithAlignPanel());
4663 * Default colour by linked panel to false if not specified (e.g.
4664 * for pre-2.7 projects)
4666 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
4667 colourWithAlignPanel |= structureState.isColourwithAlignPanel();
4668 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
4671 * Default colour by viewer to true if not specified (e.g. for
4674 boolean colourByViewer = jmoldat.isColourByViewer();
4675 colourByViewer &= structureState.isColourByJmol();
4676 jmoldat.setColourByViewer(colourByViewer);
4678 if (jmoldat.getStateData().length() < structureState.getValue()
4679 /*Content()*/.length())
4681 jmoldat.setStateData(structureState.getValue());// Content());
4683 if (pdbid.getFile() != null)
4685 File mapkey = new File(pdbid.getFile());
4686 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
4687 if (seqstrmaps == null)
4689 jmoldat.getFileData().put(mapkey,
4690 seqstrmaps = jmoldat.new StructureData(pdbFile,
4693 if (!seqstrmaps.getSeqList().contains(seq))
4695 seqstrmaps.getSeqList().add(seq);
4701 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");
4702 Console.warn(errorMessage);
4708 // Instantiate the associated structure views
4709 for (Entry<String, StructureViewerModel> entry : structureViewers
4714 createOrLinkStructureViewer(entry, af, ap, jprovider);
4715 } catch (Exception e)
4718 "Error loading structure viewer: " + e.getMessage());
4719 // failed - try the next one
4731 protected void createOrLinkStructureViewer(
4732 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4733 AlignmentPanel ap, jarInputStreamProvider jprovider)
4735 final StructureViewerModel stateData = viewerData.getValue();
4738 * Search for any viewer windows already open from other alignment views
4739 * that exactly match the stored structure state
4741 StructureViewerBase comp = findMatchingViewer(viewerData);
4745 linkStructureViewer(ap, comp, stateData);
4749 String type = stateData.getType();
4752 ViewerType viewerType = ViewerType.valueOf(type);
4753 createStructureViewer(viewerType, viewerData, af, jprovider);
4754 } catch (IllegalArgumentException | NullPointerException e)
4756 // TODO JAL-3619 show error dialog / offer an alternative viewer
4757 Console.error("Invalid structure viewer type: " + type);
4762 * Generates a name for the entry in the project jar file to hold state
4763 * information for a structure viewer
4768 protected String getViewerJarEntryName(String viewId)
4770 return VIEWER_PREFIX + viewId;
4774 * Returns any open frame that matches given structure viewer data. The match
4775 * is based on the unique viewId, or (for older project versions) the frame's
4781 protected StructureViewerBase findMatchingViewer(
4782 Entry<String, StructureViewerModel> viewerData)
4784 final String sviewid = viewerData.getKey();
4785 final StructureViewerModel svattrib = viewerData.getValue();
4786 StructureViewerBase comp = null;
4787 JInternalFrame[] frames = getAllFrames();
4788 for (JInternalFrame frame : frames)
4790 if (frame instanceof StructureViewerBase)
4793 * Post jalview 2.4 schema includes structure view id
4795 if (sviewid != null && ((StructureViewerBase) frame).getViewId()
4798 comp = (StructureViewerBase) frame;
4799 break; // break added in 2.9
4802 * Otherwise test for matching position and size of viewer frame
4804 else if (frame.getX() == svattrib.getX()
4805 && frame.getY() == svattrib.getY()
4806 && frame.getHeight() == svattrib.getHeight()
4807 && frame.getWidth() == svattrib.getWidth())
4809 comp = (StructureViewerBase) frame;
4810 // no break in faint hope of an exact match on viewId
4818 * Link an AlignmentPanel to an existing structure viewer.
4823 * @param useinViewerSuperpos
4824 * @param usetoColourbyseq
4825 * @param viewerColouring
4827 protected void linkStructureViewer(AlignmentPanel ap,
4828 StructureViewerBase viewer, StructureViewerModel stateData)
4830 // NOTE: if the jalview project is part of a shared session then
4831 // view synchronization should/could be done here.
4833 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4834 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4835 final boolean viewerColouring = stateData.isColourByViewer();
4836 Map<File, StructureData> oldFiles = stateData.getFileData();
4839 * Add mapping for sequences in this view to an already open viewer
4841 final AAStructureBindingModel binding = viewer.getBinding();
4842 for (File id : oldFiles.keySet())
4844 // add this and any other pdb files that should be present in the
4846 StructureData filedat = oldFiles.get(id);
4847 String pdbFile = filedat.getFilePath();
4848 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4849 binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE,
4851 binding.addSequenceForStructFile(pdbFile, seq);
4853 // and add the AlignmentPanel's reference to the view panel
4854 viewer.addAlignmentPanel(ap);
4855 if (useinViewerSuperpos)
4857 viewer.useAlignmentPanelForSuperposition(ap);
4861 viewer.excludeAlignmentPanelForSuperposition(ap);
4863 if (usetoColourbyseq)
4865 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4869 viewer.excludeAlignmentPanelForColourbyseq(ap);
4874 * Get all frames within the Desktop.
4878 protected JInternalFrame[] getAllFrames()
4880 JInternalFrame[] frames = null;
4881 // TODO is this necessary - is it safe - risk of hanging?
4886 frames = Desktop.desktop.getAllFrames();
4887 } catch (ArrayIndexOutOfBoundsException e)
4889 // occasional No such child exceptions are thrown here...
4893 } catch (InterruptedException f)
4897 } while (frames == null);
4902 * Answers true if 'version' is equal to or later than 'supported', where each
4903 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4904 * changes. Development and test values for 'version' are leniently treated
4908 * - minimum version we are comparing against
4910 * - version of data being processsed
4911 * @return true if version is equal to or later than supported
4913 public static boolean isVersionStringLaterThan(String supported,
4916 if (supported == null || version == null
4917 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4918 || version.equalsIgnoreCase("Test")
4919 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4921 System.err.println("Assuming project file with "
4922 + (version == null ? "null" : version)
4923 + " is compatible with Jalview version " + supported);
4928 return StringUtils.compareVersions(version, supported, "b") >= 0;
4932 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4934 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4936 if (newStructureViewers != null)
4938 sview.getBinding().setFinishedLoadingFromArchive(false);
4939 newStructureViewers.add(sview);
4943 protected void setLoadingFinishedForNewStructureViewers()
4945 if (newStructureViewers != null)
4947 for (JalviewStructureDisplayI sview : newStructureViewers)
4949 sview.getBinding().setFinishedLoadingFromArchive(true);
4951 newStructureViewers.clear();
4952 newStructureViewers = null;
4956 AlignFrame loadViewport(String file, List<JSeq> JSEQ,
4957 List<SequenceI> hiddenSeqs, AlignmentI al, JalviewModel jm,
4958 Viewport view, String uniqueSeqSetId, String viewId,
4959 List<JvAnnotRow> autoAlan)
4961 AlignFrame af = null;
4962 af = new AlignFrame(al, safeInt(view.getWidth()),
4963 safeInt(view.getHeight()), uniqueSeqSetId, viewId)
4967 // protected void processKeyEvent(java.awt.event.KeyEvent e) {
4968 // System.out.println("Jalview2XML AF " + e);
4969 // super.processKeyEvent(e);
4976 af.setFileName(file, FileFormat.Jalview);
4978 final AlignViewport viewport = af.getViewport();
4979 for (int i = 0; i < JSEQ.size(); i++)
4981 int colour = safeInt(JSEQ.get(i).getColour());
4982 viewport.setSequenceColour(viewport.getAlignment().getSequenceAt(i),
4988 viewport.setColourByReferenceSeq(true);
4989 viewport.setDisplayReferenceSeq(true);
4992 viewport.setGatherViewsHere(safeBoolean(view.isGatheredViews()));
4994 if (view.getSequenceSetId() != null)
4996 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4998 viewport.setSequenceSetId(uniqueSeqSetId);
5001 // propagate shared settings to this new view
5002 viewport.setHistoryList(av.getHistoryList());
5003 viewport.setRedoList(av.getRedoList());
5007 viewportsAdded.put(uniqueSeqSetId, viewport);
5009 // TODO: check if this method can be called repeatedly without
5010 // side-effects if alignpanel already registered.
5011 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
5013 // apply Hidden regions to view.
5014 if (hiddenSeqs != null)
5016 for (int s = 0; s < JSEQ.size(); s++)
5018 SequenceGroup hidden = new SequenceGroup();
5019 boolean isRepresentative = false;
5020 for (int r = 0; r < JSEQ.get(s).getHiddenSequences().size(); r++)
5022 isRepresentative = true;
5023 SequenceI sequenceToHide = al
5024 .getSequenceAt(JSEQ.get(s).getHiddenSequences().get(r));
5025 hidden.addSequence(sequenceToHide, false);
5026 // remove from hiddenSeqs list so we don't try to hide it twice
5027 hiddenSeqs.remove(sequenceToHide);
5029 if (isRepresentative)
5031 SequenceI representativeSequence = al.getSequenceAt(s);
5032 hidden.addSequence(representativeSequence, false);
5033 viewport.hideRepSequences(representativeSequence, hidden);
5037 SequenceI[] hseqs = hiddenSeqs
5038 .toArray(new SequenceI[hiddenSeqs.size()]);
5039 viewport.hideSequence(hseqs);
5042 // recover view properties and display parameters
5044 viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
5045 viewport.setAbovePIDThreshold(safeBoolean(view.isPidSelected()));
5046 final int pidThreshold = safeInt(view.getPidThreshold());
5047 viewport.setThreshold(pidThreshold);
5049 viewport.setColourText(safeBoolean(view.isShowColourText()));
5051 viewport.setConservationSelected(
5052 safeBoolean(view.isConservationSelected()));
5053 viewport.setIncrement(safeInt(view.getConsThreshold()));
5054 viewport.setShowJVSuffix(safeBoolean(view.isShowFullId()));
5055 viewport.setRightAlignIds(safeBoolean(view.isRightAlignIds()));
5057 new Font(view.getFontName(), safeInt(view.getFontStyle()),
5058 safeInt(view.getFontSize())),
5059 (view.getCharWidth() != null) ? false : true);
5060 if (view.getCharWidth() != null)
5062 viewport.setCharWidth(view.getCharWidth());
5063 viewport.setCharHeight(view.getCharHeight());
5065 ViewStyleI vs = viewport.getViewStyle();
5066 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
5067 viewport.setViewStyle(vs);
5068 // TODO: allow custom charWidth/Heights to be restored by updating them
5069 // after setting font - which means set above to false
5070 viewport.setRenderGaps(safeBoolean(view.isRenderGaps()));
5071 viewport.setWrapAlignment(safeBoolean(view.isWrapAlignment()));
5072 viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
5074 viewport.setShowBoxes(safeBoolean(view.isShowBoxes()));
5076 viewport.setShowText(safeBoolean(view.isShowText()));
5078 viewport.setTextColour(new Color(safeInt(view.getTextCol1())));
5079 viewport.setTextColour2(new Color(safeInt(view.getTextCol2())));
5080 viewport.setThresholdTextColour(safeInt(view.getTextColThreshold()));
5081 viewport.setShowUnconserved(view.isShowUnconserved());
5082 viewport.getRanges().setStartRes(safeInt(view.getStartRes()));
5084 if (view.getViewName() != null)
5086 viewport.setViewName(view.getViewName());
5087 af.setInitialTabVisible();
5089 af.setBounds(safeInt(view.getXpos()), safeInt(view.getYpos()),
5090 safeInt(view.getWidth()), safeInt(view.getHeight()));
5091 // startSeq set in af.alignPanel.updateLayout below
5092 af.alignPanel.updateLayout();
5093 ColourSchemeI cs = null;
5094 // apply colourschemes
5095 if (view.getBgColour() != null)
5097 if (view.getBgColour().startsWith("ucs"))
5099 cs = getUserColourScheme(jm, view.getBgColour());
5101 else if (view.getBgColour().startsWith("Annotation"))
5103 AnnotationColourScheme viewAnnColour = view.getAnnotationColours();
5104 cs = constructAnnotationColour(viewAnnColour, af, al, jm, true);
5111 cs = ColourSchemeProperty.getColourScheme(af.getViewport(), al,
5112 view.getBgColour());
5117 * turn off 'alignment colour applies to all groups'
5118 * while restoring global colour scheme
5120 viewport.setColourAppliesToAllGroups(false);
5121 viewport.setGlobalColourScheme(cs);
5122 viewport.getResidueShading().setThreshold(pidThreshold,
5123 view.isIgnoreGapsinConsensus());
5124 viewport.getResidueShading()
5125 .setConsensus(viewport.getSequenceConsensusHash());
5126 if (safeBoolean(view.isConservationSelected()) && cs != null)
5128 viewport.getResidueShading()
5129 .setConservationInc(safeInt(view.getConsThreshold()));
5131 af.changeColour(cs);
5132 viewport.setColourAppliesToAllGroups(true);
5134 viewport.setShowSequenceFeatures(
5135 safeBoolean(view.isShowSequenceFeatures()));
5137 viewport.setCentreColumnLabels(view.isCentreColumnLabels());
5138 viewport.setIgnoreGapsConsensus(view.isIgnoreGapsinConsensus(), null);
5139 viewport.setFollowHighlight(view.isFollowHighlight());
5140 viewport.followSelection = view.isFollowSelection();
5141 viewport.setShowConsensusHistogram(view.isShowConsensusHistogram());
5142 viewport.setShowSequenceLogo(view.isShowSequenceLogo());
5143 viewport.setNormaliseSequenceLogo(view.isNormaliseSequenceLogo());
5144 viewport.setShowDBRefs(safeBoolean(view.isShowDbRefTooltip()));
5145 viewport.setShowNPFeats(safeBoolean(view.isShowNPfeatureTooltip()));
5146 viewport.setShowGroupConsensus(view.isShowGroupConsensus());
5147 viewport.setShowGroupConservation(view.isShowGroupConservation());
5148 viewport.setShowComplementFeatures(view.isShowComplementFeatures());
5149 viewport.setShowComplementFeaturesOnTop(
5150 view.isShowComplementFeaturesOnTop());
5152 // recover feature settings
5153 if (jm.getFeatureSettings() != null)
5155 FeatureRendererModel fr = af.alignPanel.getSeqPanel().seqCanvas
5156 .getFeatureRenderer();
5157 FeaturesDisplayed fdi;
5158 viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
5159 String[] renderOrder = new String[jm.getFeatureSettings().getSetting()
5161 Map<String, FeatureColourI> featureColours = new Hashtable<>();
5162 Map<String, Float> featureOrder = new Hashtable<>();
5164 for (int fs = 0; fs < jm.getFeatureSettings().getSetting()
5167 Setting setting = jm.getFeatureSettings().getSetting().get(fs);
5168 String featureType = setting.getType();
5171 * restore feature filters (if any)
5173 jalview.xml.binding.jalview.FeatureMatcherSet filters = setting
5175 if (filters != null)
5177 FeatureMatcherSetI filter = Jalview2XML.parseFilter(featureType,
5179 if (!filter.isEmpty())
5181 fr.setFeatureFilter(featureType, filter);
5186 * restore feature colour scheme
5188 Color maxColour = new Color(setting.getColour());
5189 if (setting.getMincolour() != null)
5192 * minColour is always set unless a simple colour
5193 * (including for colour by label though it doesn't use it)
5195 Color minColour = new Color(setting.getMincolour().intValue());
5196 Color noValueColour = minColour;
5197 NoValueColour noColour = setting.getNoValueColour();
5198 if (noColour == NoValueColour.NONE)
5200 noValueColour = null;
5202 else if (noColour == NoValueColour.MAX)
5204 noValueColour = maxColour;
5206 float min = safeFloat(safeFloat(setting.getMin()));
5207 float max = setting.getMax() == null ? 1f
5208 : setting.getMax().floatValue();
5209 FeatureColourI gc = new FeatureColour(maxColour, minColour,
5210 maxColour, noValueColour, min, max);
5211 if (setting.getAttributeName().size() > 0)
5213 gc.setAttributeName(setting.getAttributeName().toArray(
5214 new String[setting.getAttributeName().size()]));
5216 if (setting.getThreshold() != null)
5218 gc.setThreshold(setting.getThreshold().floatValue());
5219 int threshstate = safeInt(setting.getThreshstate());
5220 // -1 = None, 0 = Below, 1 = Above threshold
5221 if (threshstate == 0)
5223 gc.setBelowThreshold(true);
5225 else if (threshstate == 1)
5227 gc.setAboveThreshold(true);
5230 gc.setAutoScaled(true); // default
5231 if (setting.isAutoScale() != null)
5233 gc.setAutoScaled(setting.isAutoScale());
5235 if (setting.isColourByLabel() != null)
5237 gc.setColourByLabel(setting.isColourByLabel());
5239 // and put in the feature colour table.
5240 featureColours.put(featureType, gc);
5244 featureColours.put(featureType, new FeatureColour(maxColour));
5246 renderOrder[fs] = featureType;
5247 if (setting.getOrder() != null)
5249 featureOrder.put(featureType, setting.getOrder().floatValue());
5253 featureOrder.put(featureType, Float.valueOf(
5254 fs / jm.getFeatureSettings().getSetting().size()));
5256 if (safeBoolean(setting.isDisplay()))
5258 fdi.setVisible(featureType);
5261 Map<String, Boolean> fgtable = new Hashtable<>();
5262 for (int gs = 0; gs < jm.getFeatureSettings().getGroup().size(); gs++)
5264 Group grp = jm.getFeatureSettings().getGroup().get(gs);
5265 fgtable.put(grp.getName(), Boolean.valueOf(grp.isDisplay()));
5267 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
5268 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
5269 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
5270 FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
5271 fgtable, featureColours, 1.0f, featureOrder);
5272 fr.transferSettings(frs);
5275 if (view.getHiddenColumns().size() > 0)
5277 for (int c = 0; c < view.getHiddenColumns().size(); c++)
5279 final HiddenColumns hc = view.getHiddenColumns().get(c);
5280 viewport.hideColumns(safeInt(hc.getStart()),
5281 safeInt(hc.getEnd()) /* +1 */);
5284 if (view.getCalcIdParam() != null)
5286 for (CalcIdParam calcIdParam : view.getCalcIdParam())
5288 if (calcIdParam != null)
5290 if (recoverCalcIdParam(calcIdParam, viewport))
5295 Console.warn("Couldn't recover parameters for "
5296 + calcIdParam.getCalcId());
5301 af.setMenusFromViewport(viewport);
5302 af.setTitle(view.getTitle());
5303 // TODO: we don't need to do this if the viewport is aready visible.
5305 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
5306 * has a 'cdna/protein complement' view, in which case save it in order to
5307 * populate a SplitFrame once all views have been read in.
5309 String complementaryViewId = view.getComplementId();
5310 if (complementaryViewId == null)
5312 Desktop.addInternalFrame(af, view.getTitle(),
5313 safeInt(view.getWidth()), safeInt(view.getHeight()));
5314 // recompute any autoannotation
5315 af.alignPanel.updateAnnotation(false, true);
5316 reorderAutoannotation(af, al, autoAlan);
5317 af.alignPanel.alignmentChanged();
5321 splitFrameCandidates.put(view, af);
5328 * Reads saved data to restore Colour by Annotation settings
5330 * @param viewAnnColour
5334 * @param checkGroupAnnColour
5337 private ColourSchemeI constructAnnotationColour(
5338 AnnotationColourScheme viewAnnColour, AlignFrame af,
5339 AlignmentI al, JalviewModel model, boolean checkGroupAnnColour)
5341 boolean propagateAnnColour = false;
5342 AlignmentI annAlignment = af != null ? af.getViewport().getAlignment()
5344 if (checkGroupAnnColour && al.getGroups() != null
5345 && al.getGroups().size() > 0)
5347 // pre 2.8.1 behaviour
5348 // check to see if we should transfer annotation colours
5349 propagateAnnColour = true;
5350 for (SequenceGroup sg : al.getGroups())
5352 if (sg.getColourScheme() instanceof AnnotationColourGradient)
5354 propagateAnnColour = false;
5360 * 2.10.2- : saved annotationId is AlignmentAnnotation.annotationId
5362 String annotationId = viewAnnColour.getAnnotation();
5363 AlignmentAnnotation matchedAnnotation = annotationIds.get(annotationId);
5366 * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
5368 if (matchedAnnotation == null
5369 && annAlignment.getAlignmentAnnotation() != null)
5371 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
5374 .equals(annAlignment.getAlignmentAnnotation()[i].label))
5376 matchedAnnotation = annAlignment.getAlignmentAnnotation()[i];
5381 if (matchedAnnotation == null)
5383 System.err.println("Failed to match annotation colour scheme for "
5387 // belt-and-braces create a threshold line if the
5388 // colourscheme needs one but the matchedAnnotation doesn't have one
5389 if (safeInt(viewAnnColour.getAboveThreshold()) != 0
5390 && matchedAnnotation.getThreshold() == null)
5392 matchedAnnotation.setThreshold(
5393 new GraphLine(safeFloat(viewAnnColour.getThreshold()),
5394 "Threshold", Color.black));
5397 AnnotationColourGradient cs = null;
5398 if (viewAnnColour.getColourScheme().equals("None"))
5400 cs = new AnnotationColourGradient(matchedAnnotation,
5401 new Color(safeInt(viewAnnColour.getMinColour())),
5402 new Color(safeInt(viewAnnColour.getMaxColour())),
5403 safeInt(viewAnnColour.getAboveThreshold()));
5405 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
5407 cs = new AnnotationColourGradient(matchedAnnotation,
5408 getUserColourScheme(model, viewAnnColour.getColourScheme()),
5409 safeInt(viewAnnColour.getAboveThreshold()));
5413 cs = new AnnotationColourGradient(matchedAnnotation,
5414 ColourSchemeProperty.getColourScheme(af.getViewport(), al,
5415 viewAnnColour.getColourScheme()),
5416 safeInt(viewAnnColour.getAboveThreshold()));
5419 boolean perSequenceOnly = safeBoolean(viewAnnColour.isPerSequence());
5420 boolean useOriginalColours = safeBoolean(
5421 viewAnnColour.isPredefinedColours());
5422 cs.setSeqAssociated(perSequenceOnly);
5423 cs.setPredefinedColours(useOriginalColours);
5425 if (propagateAnnColour && al.getGroups() != null)
5427 // Also use these settings for all the groups
5428 for (int g = 0; g < al.getGroups().size(); g++)
5430 SequenceGroup sg = al.getGroups().get(g);
5431 if (sg.getGroupColourScheme() == null)
5436 AnnotationColourGradient groupScheme = new AnnotationColourGradient(
5437 matchedAnnotation, sg.getColourScheme(),
5438 safeInt(viewAnnColour.getAboveThreshold()));
5439 sg.setColourScheme(groupScheme);
5440 groupScheme.setSeqAssociated(perSequenceOnly);
5441 groupScheme.setPredefinedColours(useOriginalColours);
5447 private void reorderAutoannotation(AlignFrame af, AlignmentI al,
5448 List<JvAnnotRow> autoAlan)
5450 // copy over visualization settings for autocalculated annotation in the
5452 if (al.getAlignmentAnnotation() != null)
5455 * Kludge for magic autoannotation names (see JAL-811)
5457 String[] magicNames = new String[] { "Consensus", "Quality",
5459 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
5460 Hashtable<String, JvAnnotRow> visan = new Hashtable<>();
5461 for (String nm : magicNames)
5463 visan.put(nm, nullAnnot);
5465 for (JvAnnotRow auan : autoAlan)
5467 visan.put(auan.template.label
5468 + (auan.template.getCalcId() == null ? ""
5469 : "\t" + auan.template.getCalcId()),
5472 int hSize = al.getAlignmentAnnotation().length;
5473 List<JvAnnotRow> reorder = new ArrayList<>();
5474 // work through any autoCalculated annotation already on the view
5475 // removing it if it should be placed in a different location on the
5476 // annotation panel.
5477 List<String> remains = new ArrayList<>(visan.keySet());
5478 for (int h = 0; h < hSize; h++)
5480 jalview.datamodel.AlignmentAnnotation jalan = al
5481 .getAlignmentAnnotation()[h];
5482 if (jalan.autoCalculated)
5485 JvAnnotRow valan = visan.get(k = jalan.label);
5486 if (jalan.getCalcId() != null)
5488 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
5493 // delete the auto calculated row from the alignment
5494 al.deleteAnnotation(jalan, false);
5498 if (valan != nullAnnot)
5500 if (jalan != valan.template)
5502 // newly created autoannotation row instance
5503 // so keep a reference to the visible annotation row
5504 // and copy over all relevant attributes
5505 if (valan.template.graphHeight >= 0)
5508 jalan.graphHeight = valan.template.graphHeight;
5510 jalan.visible = valan.template.visible;
5512 reorder.add(new JvAnnotRow(valan.order, jalan));
5517 // Add any (possibly stale) autocalculated rows that were not appended to
5518 // the view during construction
5519 for (String other : remains)
5521 JvAnnotRow othera = visan.get(other);
5522 if (othera != nullAnnot && othera.template.getCalcId() != null
5523 && othera.template.getCalcId().length() > 0)
5525 reorder.add(othera);
5528 // now put the automatic annotation in its correct place
5529 int s = 0, srt[] = new int[reorder.size()];
5530 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
5531 for (JvAnnotRow jvar : reorder)
5534 srt[s++] = jvar.order;
5537 jalview.util.QuickSort.sort(srt, rws);
5538 // and re-insert the annotation at its correct position
5539 for (JvAnnotRow jvar : rws)
5541 al.addAnnotation(jvar.template, jvar.order);
5543 af.alignPanel.adjustAnnotationHeight();
5547 Hashtable skipList = null;
5550 * TODO remove this method
5553 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
5554 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
5555 * throw new Error("Implementation Error. No skipList defined for this
5556 * Jalview2XML instance."); } return (AlignFrame)
5557 * skipList.get(view.getSequenceSetId()); }
5561 * Check if the Jalview view contained in object should be skipped or not.
5564 * @return true if view's sequenceSetId is a key in skipList
5566 private boolean skipViewport(JalviewModel object)
5568 if (skipList == null)
5572 String id = object.getViewport().get(0).getSequenceSetId();
5573 if (skipList.containsKey(id))
5575 Console.debug("Skipping seuqence set id " + id);
5581 public void addToSkipList(AlignFrame af)
5583 if (skipList == null)
5585 skipList = new Hashtable();
5587 skipList.put(af.getViewport().getSequenceSetId(), af);
5590 public void clearSkipList()
5592 if (skipList != null)
5599 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
5600 boolean ignoreUnrefed, String uniqueSeqSetId)
5602 jalview.datamodel.AlignmentI ds = getDatasetFor(
5603 vamsasSet.getDatasetId());
5604 AlignmentI xtant_ds = ds;
5605 if (xtant_ds == null)
5607 // good chance we are about to create a new dataset, but check if we've
5608 // seen some of the dataset sequence IDs before.
5609 // TODO: skip this check if we are working with project generated by
5610 // version 2.11 or later
5611 xtant_ds = checkIfHasDataset(vamsasSet.getSequence());
5612 if (xtant_ds != null)
5615 addDatasetRef(vamsasSet.getDatasetId(), ds);
5618 Vector<SequenceI> dseqs = null;
5621 // recovering an alignment View
5622 AlignmentI seqSetDS = getDatasetFor(UNIQSEQSETID + uniqueSeqSetId);
5623 if (seqSetDS != null)
5625 if (ds != null && ds != seqSetDS)
5628 "JAL-3171 regression: Overwriting a dataset reference for an alignment"
5629 + " - CDS/Protein crossreference data may be lost");
5630 if (xtant_ds != null)
5632 // This can only happen if the unique sequence set ID was bound to a
5633 // dataset that did not contain any of the sequences in the view
5634 // currently being restored.
5636 "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.");
5640 addDatasetRef(vamsasSet.getDatasetId(), ds);
5645 // try even harder to restore dataset
5646 AlignmentI xtantDS = checkIfHasDataset(vamsasSet.getSequence());
5647 // create a list of new dataset sequences
5648 dseqs = new Vector<>();
5650 for (int i = 0, iSize = vamsasSet.getSequence().size(); i < iSize; i++)
5652 Sequence vamsasSeq = vamsasSet.getSequence().get(i);
5653 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
5655 // create a new dataset
5658 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
5659 dseqs.copyInto(dsseqs);
5660 ds = new jalview.datamodel.Alignment(dsseqs);
5661 Console.debug("Created new dataset " + vamsasSet.getDatasetId()
5662 + " for alignment " + System.identityHashCode(al));
5663 addDatasetRef(vamsasSet.getDatasetId(), ds);
5665 // set the dataset for the newly imported alignment.
5666 if (al.getDataset() == null && !ignoreUnrefed)
5669 // register dataset for the alignment's uniqueSeqSetId for legacy projects
5670 addDatasetRef(UNIQSEQSETID + uniqueSeqSetId, ds);
5672 updateSeqDatasetBinding(vamsasSet.getSequence(), ds);
5676 * XML dataset sequence ID to materialised dataset reference
5678 HashMap<String, AlignmentI> seqToDataset = new HashMap<>();
5681 * @return the first materialised dataset reference containing a dataset
5682 * sequence referenced in the given view
5684 * - sequences from the view
5686 AlignmentI checkIfHasDataset(List<Sequence> list)
5688 for (Sequence restoredSeq : list)
5690 AlignmentI datasetFor = seqToDataset.get(restoredSeq.getDsseqid());
5691 if (datasetFor != null)
5700 * Register ds as the containing dataset for the dataset sequences referenced
5701 * by sequences in list
5704 * - sequences in a view
5707 void updateSeqDatasetBinding(List<Sequence> list, AlignmentI ds)
5709 for (Sequence restoredSeq : list)
5711 AlignmentI prevDS = seqToDataset.put(restoredSeq.getDsseqid(), ds);
5712 if (prevDS != null && prevDS != ds)
5714 Console.warn("Dataset sequence appears in many datasets: "
5715 + restoredSeq.getDsseqid());
5716 // TODO: try to merge!
5724 * sequence definition to create/merge dataset sequence for
5728 * vector to add new dataset sequence to
5729 * @param ignoreUnrefed
5730 * - when true, don't create new sequences from vamsasSeq if it's id
5731 * doesn't already have an asssociated Jalview sequence.
5733 * - used to reorder the sequence in the alignment according to the
5734 * vamsasSeq array ordering, to preserve ordering of dataset
5736 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
5737 AlignmentI ds, Vector<SequenceI> dseqs, boolean ignoreUnrefed,
5740 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
5742 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
5743 boolean reorder = false;
5744 SequenceI dsq = null;
5745 if (sq != null && sq.getDatasetSequence() != null)
5747 dsq = sq.getDatasetSequence();
5753 if (sq == null && ignoreUnrefed)
5757 String sqid = vamsasSeq.getDsseqid();
5760 // need to create or add a new dataset sequence reference to this sequence
5763 dsq = seqRefIds.get(sqid);
5768 // make a new dataset sequence
5769 dsq = sq.createDatasetSequence();
5772 // make up a new dataset reference for this sequence
5773 sqid = seqHash(dsq);
5775 dsq.setVamsasId(uniqueSetSuffix + sqid);
5776 seqRefIds.put(sqid, dsq);
5781 dseqs.addElement(dsq);
5786 ds.addSequence(dsq);
5792 { // make this dataset sequence sq's dataset sequence
5793 sq.setDatasetSequence(dsq);
5794 // and update the current dataset alignment
5799 if (!dseqs.contains(dsq))
5806 if (ds.findIndex(dsq) < 0)
5808 ds.addSequence(dsq);
5815 // TODO: refactor this as a merge dataset sequence function
5816 // now check that sq (the dataset sequence) sequence really is the union of
5817 // all references to it
5818 // boolean pre = sq.getStart() < dsq.getStart();
5819 // boolean post = sq.getEnd() > dsq.getEnd();
5823 // StringBuffer sb = new StringBuffer();
5824 String newres = jalview.analysis.AlignSeq.extractGaps(
5825 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
5826 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
5827 && newres.length() > dsq.getLength())
5829 // Update with the longer sequence.
5833 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
5834 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
5835 * sb.append(newres.substring(newres.length() - sq.getEnd() -
5836 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
5838 dsq.setSequence(newres);
5840 // TODO: merges will never happen if we 'know' we have the real dataset
5841 // sequence - this should be detected when id==dssid
5843 "DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
5844 // + (pre ? "prepended" : "") + " "
5845 // + (post ? "appended" : ""));
5850 // sequence refs are identical. We may need to update the existing dataset
5851 // alignment with this one, though.
5852 if (ds != null && dseqs == null)
5854 int opos = ds.findIndex(dsq);
5855 SequenceI tseq = null;
5856 if (opos != -1 && vseqpos != opos)
5858 // remove from old position
5859 ds.deleteSequence(dsq);
5861 if (vseqpos < ds.getHeight())
5863 if (vseqpos != opos)
5865 // save sequence at destination position
5866 tseq = ds.getSequenceAt(vseqpos);
5867 ds.replaceSequenceAt(vseqpos, dsq);
5868 ds.addSequence(tseq);
5873 ds.addSequence(dsq);
5880 * TODO use AlignmentI here and in related methods - needs
5881 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
5883 Hashtable<String, AlignmentI> datasetIds = null;
5885 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
5887 private AlignmentI getDatasetFor(String datasetId)
5889 if (datasetIds == null)
5891 datasetIds = new Hashtable<>();
5894 if (datasetIds.containsKey(datasetId))
5896 return datasetIds.get(datasetId);
5901 private void addDatasetRef(String datasetId, AlignmentI dataset)
5903 if (datasetIds == null)
5905 datasetIds = new Hashtable<>();
5907 datasetIds.put(datasetId, dataset);
5911 * make a new dataset ID for this jalview dataset alignment
5916 private String getDatasetIdRef(AlignmentI dataset)
5918 if (dataset.getDataset() != null)
5921 "Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
5923 String datasetId = makeHashCode(dataset, null);
5924 if (datasetId == null)
5926 // make a new datasetId and record it
5927 if (dataset2Ids == null)
5929 dataset2Ids = new IdentityHashMap<>();
5933 datasetId = dataset2Ids.get(dataset);
5935 if (datasetId == null)
5937 datasetId = "ds" + dataset2Ids.size() + 1;
5938 dataset2Ids.put(dataset, datasetId);
5945 * Add any saved DBRefEntry's to the sequence. An entry flagged as 'locus' is
5946 * constructed as a special subclass GeneLocus.
5948 * @param datasetSequence
5951 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5953 for (int d = 0; d < sequence.getDBRef().size(); d++)
5955 DBRef dr = sequence.getDBRef().get(d);
5959 entry = new GeneLocus(dr.getSource(), dr.getVersion(),
5960 dr.getAccessionId());
5964 entry = new DBRefEntry(dr.getSource(), dr.getVersion(),
5965 dr.getAccessionId());
5967 if (dr.getMapping() != null)
5969 entry.setMap(addMapping(dr.getMapping()));
5971 entry.setCanonical(dr.isCanonical());
5972 datasetSequence.addDBRef(entry);
5976 private jalview.datamodel.Mapping addMapping(Mapping m)
5978 SequenceI dsto = null;
5979 // Mapping m = dr.getMapping();
5980 int fr[] = new int[m.getMapListFrom().size() * 2];
5981 Iterator<MapListFrom> from = m.getMapListFrom().iterator();// enumerateMapListFrom();
5982 for (int _i = 0; from.hasNext(); _i += 2)
5984 MapListFrom mf = from.next();
5985 fr[_i] = mf.getStart();
5986 fr[_i + 1] = mf.getEnd();
5988 int fto[] = new int[m.getMapListTo().size() * 2];
5989 Iterator<MapListTo> to = m.getMapListTo().iterator();// enumerateMapListTo();
5990 for (int _i = 0; to.hasNext(); _i += 2)
5992 MapListTo mf = to.next();
5993 fto[_i] = mf.getStart();
5994 fto[_i + 1] = mf.getEnd();
5996 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto, fr,
5997 fto, m.getMapFromUnit().intValue(),
5998 m.getMapToUnit().intValue());
6001 * (optional) choice of dseqFor or Sequence
6003 if (m.getDseqFor() != null)
6005 String dsfor = m.getDseqFor();
6006 if (seqRefIds.containsKey(dsfor))
6011 jmap.setTo(seqRefIds.get(dsfor));
6015 frefedSequence.add(newMappingRef(dsfor, jmap));
6018 else if (m.getSequence() != null)
6021 * local sequence definition
6023 Sequence ms = m.getSequence();
6024 SequenceI djs = null;
6025 String sqid = ms.getDsseqid();
6026 if (sqid != null && sqid.length() > 0)
6029 * recover dataset sequence
6031 djs = seqRefIds.get(sqid);
6036 "Warning - making up dataset sequence id for DbRef sequence map reference");
6037 sqid = ((Object) ms).toString(); // make up a new hascode for
6038 // undefined dataset sequence hash
6039 // (unlikely to happen)
6045 * make a new dataset sequence and add it to refIds hash
6047 djs = new jalview.datamodel.Sequence(ms.getName(),
6049 djs.setStart(jmap.getMap().getToLowest());
6050 djs.setEnd(jmap.getMap().getToHighest());
6051 djs.setVamsasId(uniqueSetSuffix + sqid);
6053 incompleteSeqs.put(sqid, djs);
6054 seqRefIds.put(sqid, djs);
6057 Console.debug("about to recurse on addDBRefs.");
6066 * Provides a 'copy' of an alignment view (on action New View) by 'saving' the
6067 * view as XML (but not to file), and then reloading it
6072 public AlignmentPanel copyAlignPanel(AlignmentPanel ap)
6075 JalviewModel jm = saveState(ap, null, null, null);
6078 jm.getVamsasModel().getSequenceSet().get(0).getDatasetId(),
6079 ap.getAlignment().getDataset());
6081 uniqueSetSuffix = "";
6082 // jm.getJalviewModelSequence().getViewport(0).setId(null);
6083 jm.getViewport().get(0).setId(null);
6084 // we don't overwrite the view we just copied
6086 if (this.frefedSequence == null)
6088 frefedSequence = new Vector<>();
6091 viewportsAdded.clear();
6093 AlignFrame af = loadFromObject(jm, null, false, null);
6094 af.getAlignPanels().clear();
6095 af.closeMenuItem_actionPerformed(true);
6098 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
6099 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
6100 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
6101 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
6102 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
6105 return af.alignPanel;
6108 private Hashtable jvids2vobj;
6111 * set the object to ID mapping tables used to write/recover objects and XML
6112 * ID strings for the jalview project. If external tables are provided then
6113 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
6114 * object goes out of scope. - also populates the datasetIds hashtable with
6115 * alignment objects containing dataset sequences
6118 * Map from ID strings to jalview datamodel
6120 * Map from jalview datamodel to ID strings
6124 public void setObjectMappingTables(Hashtable vobj2jv,
6125 IdentityHashMap jv2vobj)
6127 this.jv2vobj = jv2vobj;
6128 this.vobj2jv = vobj2jv;
6129 Iterator ds = jv2vobj.keySet().iterator();
6131 while (ds.hasNext())
6133 Object jvobj = ds.next();
6134 id = jv2vobj.get(jvobj).toString();
6135 if (jvobj instanceof jalview.datamodel.Alignment)
6137 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
6139 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
6142 else if (jvobj instanceof jalview.datamodel.Sequence)
6144 // register sequence object so the XML parser can recover it.
6145 if (seqRefIds == null)
6147 seqRefIds = new HashMap<>();
6149 if (seqsToIds == null)
6151 seqsToIds = new IdentityHashMap<>();
6153 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
6154 seqsToIds.put((SequenceI) jvobj, id);
6156 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
6159 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
6160 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
6161 if (jvann.annotationId == null)
6163 jvann.annotationId = anid;
6165 if (!jvann.annotationId.equals(anid))
6167 // TODO verify that this is the correct behaviour
6168 Console.warn("Overriding Annotation ID for " + anid
6169 + " from different id : " + jvann.annotationId);
6170 jvann.annotationId = anid;
6173 else if (jvobj instanceof String)
6175 if (jvids2vobj == null)
6177 jvids2vobj = new Hashtable();
6178 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
6183 Console.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
6189 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
6190 * objects created from the project archive. If string is null (default for
6191 * construction) then suffix will be set automatically.
6195 public void setUniqueSetSuffix(String string)
6197 uniqueSetSuffix = string;
6202 * uses skipList2 as the skipList for skipping views on sequence sets
6203 * associated with keys in the skipList
6207 public void setSkipList(Hashtable skipList2)
6209 skipList = skipList2;
6213 * Reads the jar entry of given name and returns its contents, or null if the
6214 * entry is not found.
6217 * @param jarEntryName
6220 protected String readJarEntry(jarInputStreamProvider jprovider,
6221 String jarEntryName)
6223 String result = null;
6224 BufferedReader in = null;
6229 * Reopen the jar input stream and traverse its entries to find a matching
6232 JarInputStream jin = jprovider.getJarInputStream();
6233 JarEntry entry = null;
6236 entry = jin.getNextJarEntry();
6237 } while (entry != null && !entry.getName().equals(jarEntryName));
6241 StringBuilder out = new StringBuilder(256);
6242 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
6245 while ((data = in.readLine()) != null)
6249 result = out.toString();
6254 "Couldn't find entry in Jalview Jar for " + jarEntryName);
6256 } catch (Exception ex)
6258 ex.printStackTrace();
6266 } catch (IOException e)
6277 * Returns an incrementing counter (0, 1, 2...)
6281 private synchronized int nextCounter()
6287 * Loads any saved PCA viewers
6292 protected void loadPCAViewers(JalviewModel model, AlignmentPanel ap)
6296 List<PcaViewer> pcaviewers = model.getPcaViewer();
6297 for (PcaViewer viewer : pcaviewers)
6299 String modelName = viewer.getScoreModelName();
6300 SimilarityParamsI params = new SimilarityParams(
6301 viewer.isIncludeGappedColumns(), viewer.isMatchGaps(),
6302 viewer.isIncludeGaps(),
6303 viewer.isDenominateByShortestLength());
6306 * create the panel (without computing the PCA)
6308 PCAPanel panel = new PCAPanel(ap, modelName, params);
6310 panel.setTitle(viewer.getTitle());
6311 panel.setBounds(new Rectangle(viewer.getXpos(), viewer.getYpos(),
6312 viewer.getWidth(), viewer.getHeight()));
6314 boolean showLabels = viewer.isShowLabels();
6315 panel.setShowLabels(showLabels);
6316 panel.getRotatableCanvas().setShowLabels(showLabels);
6317 panel.getRotatableCanvas()
6318 .setBgColour(new Color(viewer.getBgColour()));
6319 panel.getRotatableCanvas()
6320 .setApplyToAllViews(viewer.isLinkToAllViews());
6323 * load PCA output data
6325 ScoreModelI scoreModel = ScoreModels.getInstance()
6326 .getScoreModel(modelName, ap);
6327 PCA pca = new PCA(null, scoreModel, params);
6328 PcaDataType pcaData = viewer.getPcaData();
6330 MatrixI pairwise = loadDoubleMatrix(pcaData.getPairwiseMatrix());
6331 pca.setPairwiseScores(pairwise);
6333 MatrixI triDiag = loadDoubleMatrix(pcaData.getTridiagonalMatrix());
6334 pca.setTridiagonal(triDiag);
6336 MatrixI result = loadDoubleMatrix(pcaData.getEigenMatrix());
6337 pca.setEigenmatrix(result);
6339 panel.getPcaModel().setPCA(pca);
6342 * we haven't saved the input data! (JAL-2647 to do)
6344 panel.setInputData(null);
6347 * add the sequence points for the PCA display
6349 List<jalview.datamodel.SequencePoint> seqPoints = new ArrayList<>();
6350 for (SequencePoint sp : viewer.getSequencePoint())
6352 String seqId = sp.getSequenceRef();
6353 SequenceI seq = seqRefIds.get(seqId);
6356 throw new IllegalStateException(
6357 "Unmatched seqref for PCA: " + seqId);
6359 Point pt = new Point(sp.getXPos(), sp.getYPos(), sp.getZPos());
6360 jalview.datamodel.SequencePoint seqPoint = new jalview.datamodel.SequencePoint(
6362 seqPoints.add(seqPoint);
6364 panel.getRotatableCanvas().setPoints(seqPoints, seqPoints.size());
6367 * set min-max ranges and scale after setPoints (which recomputes them)
6369 panel.getRotatableCanvas().setScaleFactor(viewer.getScaleFactor());
6370 SeqPointMin spMin = viewer.getSeqPointMin();
6371 float[] min = new float[] { spMin.getXPos(), spMin.getYPos(),
6373 SeqPointMax spMax = viewer.getSeqPointMax();
6374 float[] max = new float[] { spMax.getXPos(), spMax.getYPos(),
6376 panel.getRotatableCanvas().setSeqMinMax(min, max);
6378 // todo: hold points list in PCAModel only
6379 panel.getPcaModel().setSequencePoints(seqPoints);
6381 panel.setSelectedDimensionIndex(viewer.getXDim(), X);
6382 panel.setSelectedDimensionIndex(viewer.getYDim(), Y);
6383 panel.setSelectedDimensionIndex(viewer.getZDim(), Z);
6385 // is this duplication needed?
6386 panel.setTop(seqPoints.size() - 1);
6387 panel.getPcaModel().setTop(seqPoints.size() - 1);
6390 * add the axes' end points for the display
6392 for (int i = 0; i < 3; i++)
6394 Axis axis = viewer.getAxis().get(i);
6395 panel.getRotatableCanvas().getAxisEndPoints()[i] = new Point(
6396 axis.getXPos(), axis.getYPos(), axis.getZPos());
6399 Desktop.addInternalFrame(panel, MessageManager.formatMessage(
6400 "label.calc_title", "PCA", modelName), 475, 450);
6402 } catch (Exception ex)
6404 Console.error("Error loading PCA: " + ex.toString());
6409 * Creates a new structure viewer window
6416 protected void createStructureViewer(ViewerType viewerType,
6417 final Entry<String, StructureViewerModel> viewerData,
6418 AlignFrame af, jarInputStreamProvider jprovider)
6420 final StructureViewerModel viewerModel = viewerData.getValue();
6421 String sessionFilePath = null;
6423 if (viewerType == ViewerType.JMOL)
6425 sessionFilePath = rewriteJmolSession(viewerModel, jprovider);
6429 String viewerJarEntryName = getViewerJarEntryName(
6430 viewerModel.getViewId());
6431 sessionFilePath = copyJarEntry(jprovider, viewerJarEntryName,
6432 "viewerSession", ".tmp");
6434 final String sessionPath = sessionFilePath;
6435 final String sviewid = viewerData.getKey();
6438 SwingUtilities.invokeAndWait(new Runnable()
6443 JalviewStructureDisplayI sview = null;
6446 sview = StructureViewer.createView(viewerType, af.alignPanel,
6447 viewerModel, sessionPath, sviewid);
6448 addNewStructureViewer(sview);
6449 } catch (OutOfMemoryError ex)
6451 new OOMWarning("Restoring structure view for " + viewerType,
6452 (OutOfMemoryError) ex.getCause());
6453 if (sview != null && sview.isVisible())
6455 sview.closeViewer(false);
6456 sview.setVisible(false);
6462 } catch (InvocationTargetException | InterruptedException ex)
6464 Console.warn("Unexpected error when opening " + viewerType
6465 + " structure viewer", ex);
6470 * Rewrites a Jmol session script, saves it to a temporary file, and returns
6471 * the path of the file. "load file" commands are rewritten to change the
6472 * original PDB file names to those created as the Jalview project is loaded.
6478 private String rewriteJmolSession(StructureViewerModel svattrib,
6479 jarInputStreamProvider jprovider)
6481 String state = svattrib.getStateData(); // Jalview < 2.9
6482 if (state == null || state.isEmpty()) // Jalview >= 2.9
6484 String jarEntryName = getViewerJarEntryName(svattrib.getViewId());
6485 state = readJarEntry(jprovider, jarEntryName);
6487 // TODO or simpler? for each key in oldFiles,
6488 // replace key.getPath() in state with oldFiles.get(key).getFilePath()
6489 // (allowing for different path escapings)
6490 StringBuilder rewritten = new StringBuilder(state.length());
6491 int cp = 0, ncp, ecp;
6492 Map<File, StructureData> oldFiles = svattrib.getFileData();
6493 while ((ncp = state.indexOf("load ", cp)) > -1)
6497 // look for next filename in load statement
6498 rewritten.append(state.substring(cp,
6499 ncp = (state.indexOf("\"", ncp + 1) + 1)));
6500 String oldfilenam = state.substring(ncp,
6501 ecp = state.indexOf("\"", ncp));
6502 // recover the new mapping data for this old filename
6503 // have to normalize filename - since Jmol and jalview do
6504 // filename translation differently.
6505 StructureData filedat = oldFiles.get(new File(oldfilenam));
6506 if (filedat == null)
6508 String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\");
6509 filedat = oldFiles.get(new File(reformatedOldFilename));
6511 rewritten.append(Platform.escapeBackslashes(filedat.getFilePath()));
6512 rewritten.append("\"");
6513 cp = ecp + 1; // advance beyond last \" and set cursor so we can
6514 // look for next file statement.
6515 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
6519 // just append rest of state
6520 rewritten.append(state.substring(cp));
6524 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
6525 rewritten = new StringBuilder(state);
6526 rewritten.append("; load append ");
6527 for (File id : oldFiles.keySet())
6529 // add pdb files that should be present in the viewer
6530 StructureData filedat = oldFiles.get(id);
6531 rewritten.append(" \"").append(filedat.getFilePath()).append("\"");
6533 rewritten.append(";");
6536 if (rewritten.length() == 0)
6540 final String history = "history = ";
6541 int historyIndex = rewritten.indexOf(history);
6542 if (historyIndex > -1)
6545 * change "history = [true|false];" to "history = [1|0];"
6547 historyIndex += history.length();
6548 String val = rewritten.substring(historyIndex, historyIndex + 5);
6549 if (val.startsWith("true"))
6551 rewritten.replace(historyIndex, historyIndex + 4, "1");
6553 else if (val.startsWith("false"))
6555 rewritten.replace(historyIndex, historyIndex + 5, "0");
6561 File tmp = File.createTempFile("viewerSession", ".tmp");
6562 try (OutputStream os = new FileOutputStream(tmp))
6564 InputStream is = new ByteArrayInputStream(
6565 rewritten.toString().getBytes());
6567 return tmp.getAbsolutePath();
6569 } catch (IOException e)
6571 Console.error("Error restoring Jmol session: " + e.toString());
6577 * Populates an XML model of the feature colour scheme for one feature type
6579 * @param featureType
6583 public static Colour marshalColour(String featureType,
6584 FeatureColourI fcol)
6586 Colour col = new Colour();
6587 if (fcol.isSimpleColour())
6589 col.setRGB(Format.getHexString(fcol.getColour()));
6593 col.setRGB(Format.getHexString(fcol.getMaxColour()));
6594 col.setMin(fcol.getMin());
6595 col.setMax(fcol.getMax());
6596 col.setMinRGB(jalview.util.Format.getHexString(fcol.getMinColour()));
6597 col.setAutoScale(fcol.isAutoScaled());
6598 col.setThreshold(fcol.getThreshold());
6599 col.setColourByLabel(fcol.isColourByLabel());
6600 col.setThreshType(fcol.isAboveThreshold() ? ThresholdType.ABOVE
6601 : (fcol.isBelowThreshold() ? ThresholdType.BELOW
6602 : ThresholdType.NONE));
6603 if (fcol.isColourByAttribute())
6605 final String[] attName = fcol.getAttributeName();
6606 col.getAttributeName().add(attName[0]);
6607 if (attName.length > 1)
6609 col.getAttributeName().add(attName[1]);
6612 Color noColour = fcol.getNoColour();
6613 if (noColour == null)
6615 col.setNoValueColour(NoValueColour.NONE);
6617 else if (noColour == fcol.getMaxColour())
6619 col.setNoValueColour(NoValueColour.MAX);
6623 col.setNoValueColour(NoValueColour.MIN);
6626 col.setName(featureType);
6631 * Populates an XML model of the feature filter(s) for one feature type
6633 * @param firstMatcher
6634 * the first (or only) match condition)
6636 * remaining match conditions (if any)
6638 * if true, conditions are and-ed, else or-ed
6640 public static jalview.xml.binding.jalview.FeatureMatcherSet marshalFilter(
6641 FeatureMatcherI firstMatcher, Iterator<FeatureMatcherI> filters,
6644 jalview.xml.binding.jalview.FeatureMatcherSet result = new jalview.xml.binding.jalview.FeatureMatcherSet();
6646 if (filters.hasNext())
6651 CompoundMatcher compound = new CompoundMatcher();
6652 compound.setAnd(and);
6653 jalview.xml.binding.jalview.FeatureMatcherSet matcher1 = marshalFilter(
6654 firstMatcher, Collections.emptyIterator(), and);
6655 // compound.addMatcherSet(matcher1);
6656 compound.getMatcherSet().add(matcher1);
6657 FeatureMatcherI nextMatcher = filters.next();
6658 jalview.xml.binding.jalview.FeatureMatcherSet matcher2 = marshalFilter(
6659 nextMatcher, filters, and);
6660 // compound.addMatcherSet(matcher2);
6661 compound.getMatcherSet().add(matcher2);
6662 result.setCompoundMatcher(compound);
6667 * single condition matcher
6669 // MatchCondition matcherModel = new MatchCondition();
6670 jalview.xml.binding.jalview.FeatureMatcher matcherModel = new jalview.xml.binding.jalview.FeatureMatcher();
6671 matcherModel.setCondition(
6672 firstMatcher.getMatcher().getCondition().getStableName());
6673 matcherModel.setValue(firstMatcher.getMatcher().getPattern());
6674 if (firstMatcher.isByAttribute())
6676 matcherModel.setBy(FilterBy.BY_ATTRIBUTE);
6677 // matcherModel.setAttributeName(firstMatcher.getAttribute());
6678 String[] attName = firstMatcher.getAttribute();
6679 matcherModel.getAttributeName().add(attName[0]); // attribute
6680 if (attName.length > 1)
6682 matcherModel.getAttributeName().add(attName[1]); // sub-attribute
6685 else if (firstMatcher.isByLabel())
6687 matcherModel.setBy(FilterBy.BY_LABEL);
6689 else if (firstMatcher.isByScore())
6691 matcherModel.setBy(FilterBy.BY_SCORE);
6693 result.setMatchCondition(matcherModel);
6700 * Loads one XML model of a feature filter to a Jalview object
6702 * @param featureType
6703 * @param matcherSetModel
6706 public static FeatureMatcherSetI parseFilter(String featureType,
6707 jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel)
6709 FeatureMatcherSetI result = new FeatureMatcherSet();
6712 parseFilterConditions(result, matcherSetModel, true);
6713 } catch (IllegalStateException e)
6715 // mixing AND and OR conditions perhaps
6717 String.format("Error reading filter conditions for '%s': %s",
6718 featureType, e.getMessage()));
6719 // return as much as was parsed up to the error
6726 * Adds feature match conditions to matcherSet as unmarshalled from XML
6727 * (possibly recursively for compound conditions)
6730 * @param matcherSetModel
6732 * if true, multiple conditions are AND-ed, else they are OR-ed
6733 * @throws IllegalStateException
6734 * if AND and OR conditions are mixed
6736 protected static void parseFilterConditions(FeatureMatcherSetI matcherSet,
6737 jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel,
6740 jalview.xml.binding.jalview.FeatureMatcher mc = matcherSetModel
6741 .getMatchCondition();
6747 FilterBy filterBy = mc.getBy();
6748 Condition cond = Condition.fromString(mc.getCondition());
6749 String pattern = mc.getValue();
6750 FeatureMatcherI matchCondition = null;
6751 if (filterBy == FilterBy.BY_LABEL)
6753 matchCondition = FeatureMatcher.byLabel(cond, pattern);
6755 else if (filterBy == FilterBy.BY_SCORE)
6757 matchCondition = FeatureMatcher.byScore(cond, pattern);
6760 else if (filterBy == FilterBy.BY_ATTRIBUTE)
6762 final List<String> attributeName = mc.getAttributeName();
6763 String[] attNames = attributeName
6764 .toArray(new String[attributeName.size()]);
6765 matchCondition = FeatureMatcher.byAttribute(cond, pattern,
6770 * note this throws IllegalStateException if AND-ing to a
6771 * previously OR-ed compound condition, or vice versa
6775 matcherSet.and(matchCondition);
6779 matcherSet.or(matchCondition);
6785 * compound condition
6787 List<jalview.xml.binding.jalview.FeatureMatcherSet> matchers = matcherSetModel
6788 .getCompoundMatcher().getMatcherSet();
6789 boolean anded = matcherSetModel.getCompoundMatcher().isAnd();
6790 if (matchers.size() == 2)
6792 parseFilterConditions(matcherSet, matchers.get(0), anded);
6793 parseFilterConditions(matcherSet, matchers.get(1), anded);
6797 System.err.println("Malformed compound filter condition");
6803 * Loads one XML model of a feature colour to a Jalview object
6805 * @param colourModel
6808 public static FeatureColourI parseColour(Colour colourModel)
6810 FeatureColourI colour = null;
6812 if (colourModel.getMax() != null)
6814 Color mincol = null;
6815 Color maxcol = null;
6816 Color noValueColour = null;
6820 mincol = new Color(Integer.parseInt(colourModel.getMinRGB(), 16));
6821 maxcol = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6822 } catch (Exception e)
6824 Console.warn("Couldn't parse out graduated feature color.", e);
6827 NoValueColour noCol = colourModel.getNoValueColour();
6828 if (noCol == NoValueColour.MIN)
6830 noValueColour = mincol;
6832 else if (noCol == NoValueColour.MAX)
6834 noValueColour = maxcol;
6837 colour = new FeatureColour(maxcol, mincol, maxcol, noValueColour,
6838 safeFloat(colourModel.getMin()),
6839 safeFloat(colourModel.getMax()));
6840 final List<String> attributeName = colourModel.getAttributeName();
6841 String[] attributes = attributeName
6842 .toArray(new String[attributeName.size()]);
6843 if (attributes != null && attributes.length > 0)
6845 colour.setAttributeName(attributes);
6847 if (colourModel.isAutoScale() != null)
6849 colour.setAutoScaled(colourModel.isAutoScale().booleanValue());
6851 if (colourModel.isColourByLabel() != null)
6853 colour.setColourByLabel(
6854 colourModel.isColourByLabel().booleanValue());
6856 if (colourModel.getThreshold() != null)
6858 colour.setThreshold(colourModel.getThreshold().floatValue());
6860 ThresholdType ttyp = colourModel.getThreshType();
6861 if (ttyp == ThresholdType.ABOVE)
6863 colour.setAboveThreshold(true);
6865 else if (ttyp == ThresholdType.BELOW)
6867 colour.setBelowThreshold(true);
6872 Color color = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6873 colour = new FeatureColour(color);
6879 public static void setStateSavedUpToDate(boolean s)
6881 Console.debug("Setting overall stateSavedUpToDate to " + s);
6882 stateSavedUpToDate = s;
6885 public static boolean stateSavedUpToDate()
6887 Console.debug("Returning overall stateSavedUpToDate value: "
6888 + stateSavedUpToDate);
6889 return stateSavedUpToDate;
6892 public static boolean allSavedUpToDate()
6894 if (stateSavedUpToDate()) // nothing happened since last project save
6897 AlignFrame[] frames = Desktop.getAlignFrames();
6900 for (int i = 0; i < frames.length; i++)
6902 if (frames[i] == null)
6904 if (!frames[i].getViewport().savedUpToDate())
6905 return false; // at least one alignment is not individually saved
6911 // used for debugging and tests
6912 private static int debugDelaySave = 20;
6914 public static void setDebugDelaySave(int n)