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.getContactMatrixFor(annotation);
2317 MatrixType xmlmat = new MatrixType();
2318 xmlmat.setType(cm.getType());
2319 xmlmat.setRows(BigInteger.valueOf(cm.getWidth()));
2320 xmlmat.setCols(BigInteger.valueOf(cm.getHeight()));
2321 // consider using an opaque to/from -> allow instance to control its representation ?
2322 xmlmat.setElements(ContactMatrix.contactToFloatString(cm));
2325 for (BitSet gp: cm.getGroups())
2327 xmlmat.getGroups().add(stringifyBitset(gp));
2332 // provenance object for tree ?
2333 xmlmat.getNewick().add(cm.getNewick());
2334 xmlmat.setTreeMethod(cm.getTreeMethod());
2336 if (cm.hasCutHeight())
2338 xmlmat.setCutHeight(cm.getCutHeight());
2341 // set/get properties
2342 if (cm instanceof MappableContactMatrixI)
2344 jalview.util.MapList mlst = ((MappableContactMatrixI) cm)
2345 .getMapFor(annotation.sequenceRef);
2348 MapListType mp = new MapListType();
2349 List<int[]> r = mlst.getFromRanges();
2350 for (int[] range : r)
2352 MapListFrom mfrom = new MapListFrom();
2353 mfrom.setStart(range[0]);
2354 mfrom.setEnd(range[1]);
2355 // mp.addMapListFrom(mfrom);
2356 mp.getMapListFrom().add(mfrom);
2358 r = mlst.getToRanges();
2359 for (int[] range : r)
2361 MapListTo mto = new MapListTo();
2362 mto.setStart(range[0]);
2363 mto.setEnd(range[1]);
2364 // mp.addMapListTo(mto);
2365 mp.getMapListTo().add(mto);
2368 BigInteger.valueOf(mlst.getFromRatio()));
2369 mp.setMapToUnit(BigInteger.valueOf(mlst.getToRatio()));
2370 xmlmat.setMapping(mp);
2374 an.getContactmatrix().add(xmlmat);
2384 an.setLabel(annotation.label);
2386 if (annotation == av.getAlignmentQualityAnnot()
2387 || annotation == av.getAlignmentConservationAnnotation()
2388 || annotation == av.getAlignmentConsensusAnnotation()
2389 || annotation.autoCalculated)
2391 // new way of indicating autocalculated annotation -
2392 an.setAutoCalculated(annotation.autoCalculated);
2394 if (annotation.hasScore())
2396 an.setScore(annotation.getScore());
2399 if (annotation.getCalcId() != null)
2401 calcIdSet.add(annotation.getCalcId());
2402 an.setCalcId(annotation.getCalcId());
2404 if (annotation.hasProperties())
2406 for (String pr : annotation.getProperties())
2408 jalview.xml.binding.jalview.Property prop = new jalview.xml.binding.jalview.Property();
2410 prop.setValue(annotation.getProperty(pr));
2411 an.getProperty().add(prop);
2415 AnnotationElement ae;
2416 if (annotation.annotations != null)
2418 an.setScoreOnly(false);
2419 for (int a = 0; a < annotation.annotations.length; a++)
2421 if ((annotation == null) || (annotation.annotations[a] == null))
2426 ae = new AnnotationElement();
2427 if (annotation.annotations[a].description != null)
2429 ae.setDescription(annotation.annotations[a].description);
2431 if (annotation.annotations[a].displayCharacter != null)
2433 ae.setDisplayCharacter(
2434 annotation.annotations[a].displayCharacter);
2437 if (!Float.isNaN(annotation.annotations[a].value))
2439 ae.setValue(annotation.annotations[a].value);
2443 if (annotation.annotations[a].secondaryStructure > ' ')
2445 ae.setSecondaryStructure(
2446 annotation.annotations[a].secondaryStructure + "");
2449 if (annotation.annotations[a].colour != null
2450 && annotation.annotations[a].colour != java.awt.Color.black)
2452 ae.setColour(annotation.annotations[a].colour.getRGB());
2455 // an.addAnnotationElement(ae);
2456 an.getAnnotationElement().add(ae);
2457 if (annotation.autoCalculated)
2459 // only write one non-null entry into the annotation row -
2460 // sufficient to get the visualization attributes necessary to
2468 an.setScoreOnly(true);
2470 if (!storeDS || (storeDS && !annotation.autoCalculated))
2472 // skip autocalculated annotation - these are only provided for
2474 // vamsasSet.addAnnotation(an);
2475 vamsasSet.getAnnotation().add(an);
2481 private String stringifyBitset(BitSet gp) {
2482 StringBuilder sb = new StringBuilder();
2483 for (long val:gp.toLongArray())
2485 if (sb.length()>0) {
2490 return sb.toString();
2492 private BitSet deStringifyBitset(String stringified) {
2493 if ("".equals(stringified) || stringified==null)
2495 return new BitSet();
2497 String[] longvals = stringified.split(",");
2498 long[] newlongvals = new long[longvals.length];
2499 for (int lv=0;lv<longvals.length;lv++)
2502 newlongvals[lv]=Long.valueOf(longvals[lv]);
2503 } catch (Exception x)
2505 errorMessage+="Couldn't destringify bitset from: '"+stringified+"'";
2509 return BitSet.valueOf(newlongvals);
2513 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
2515 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
2516 if (settings != null)
2518 CalcIdParam vCalcIdParam = new CalcIdParam();
2519 vCalcIdParam.setCalcId(calcId);
2520 // vCalcIdParam.addServiceURL(settings.getServiceURI());
2521 vCalcIdParam.getServiceURL().add(settings.getServiceURI());
2522 // generic URI allowing a third party to resolve another instance of the
2523 // service used for this calculation
2524 for (String url : settings.getServiceURLs())
2526 // vCalcIdParam.addServiceURL(urls);
2527 vCalcIdParam.getServiceURL().add(url);
2529 vCalcIdParam.setVersion("1.0");
2530 if (settings.getPreset() != null)
2532 WsParamSetI setting = settings.getPreset();
2533 vCalcIdParam.setName(setting.getName());
2534 vCalcIdParam.setDescription(setting.getDescription());
2538 vCalcIdParam.setName("");
2539 vCalcIdParam.setDescription("Last used parameters");
2541 // need to be able to recover 1) settings 2) user-defined presets or
2542 // recreate settings from preset 3) predefined settings provided by
2543 // service - or settings that can be transferred (or discarded)
2544 vCalcIdParam.setParameters(
2545 settings.getWsParamFile().replace("\n", "|\\n|"));
2546 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
2547 // todo - decide if updateImmediately is needed for any projects.
2549 return vCalcIdParam;
2554 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
2557 if (calcIdParam.getVersion().equals("1.0"))
2559 final String[] calcIds = calcIdParam.getServiceURL()
2560 .toArray(new String[0]);
2561 Jws2Instance service = Jws2Discoverer.getDiscoverer()
2562 .getPreferredServiceFor(calcIds);
2563 if (service != null)
2565 WsParamSetI parmSet = null;
2568 parmSet = service.getParamStore().parseServiceParameterFile(
2569 calcIdParam.getName(), calcIdParam.getDescription(),
2571 calcIdParam.getParameters().replace("|\\n|", "\n"));
2572 } catch (IOException x)
2574 Console.warn("Couldn't parse parameter data for "
2575 + calcIdParam.getCalcId(), x);
2578 List<ArgumentI> argList = null;
2579 if (calcIdParam.getName().length() > 0)
2581 parmSet = service.getParamStore()
2582 .getPreset(calcIdParam.getName());
2583 if (parmSet != null)
2585 // TODO : check we have a good match with settings in AACon -
2586 // otherwise we'll need to create a new preset
2591 argList = parmSet.getArguments();
2594 AAConSettings settings = new AAConSettings(
2595 calcIdParam.isAutoUpdate(), service, parmSet, argList);
2596 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
2597 calcIdParam.isNeedsUpdate());
2603 "Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
2607 throw new Error(MessageManager.formatMessage(
2608 "error.unsupported_version_calcIdparam", new Object[]
2609 { calcIdParam.toString() }));
2613 * External mapping between jalview objects and objects yielding a valid and
2614 * unique object ID string. This is null for normal Jalview project IO, but
2615 * non-null when a jalview project is being read or written as part of a
2618 IdentityHashMap jv2vobj = null;
2621 * Construct a unique ID for jvobj using either existing bindings or if none
2622 * exist, the result of the hashcode call for the object.
2625 * jalview data object
2626 * @return unique ID for referring to jvobj
2628 private String makeHashCode(Object jvobj, String altCode)
2630 if (jv2vobj != null)
2632 Object id = jv2vobj.get(jvobj);
2635 return id.toString();
2637 // check string ID mappings
2638 if (jvids2vobj != null && jvobj instanceof String)
2640 id = jvids2vobj.get(jvobj);
2644 return id.toString();
2646 // give up and warn that something has gone wrong
2648 "Cannot find ID for object in external mapping : " + jvobj);
2654 * return local jalview object mapped to ID, if it exists
2658 * @return null or object bound to idcode
2660 private Object retrieveExistingObj(String idcode)
2662 if (idcode != null && vobj2jv != null)
2664 return vobj2jv.get(idcode);
2670 * binding from ID strings from external mapping table to jalview data model
2673 private Hashtable vobj2jv;
2675 private Sequence createVamsasSequence(String id, SequenceI jds)
2677 return createVamsasSequence(true, id, jds, null);
2680 private Sequence createVamsasSequence(boolean recurse, String id,
2681 SequenceI jds, SequenceI parentseq)
2683 Sequence vamsasSeq = new Sequence();
2684 vamsasSeq.setId(id);
2685 vamsasSeq.setName(jds.getName());
2686 vamsasSeq.setSequence(jds.getSequenceAsString());
2687 vamsasSeq.setDescription(jds.getDescription());
2688 List<DBRefEntry> dbrefs = null;
2689 if (jds.getDatasetSequence() != null)
2691 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
2695 // seqId==dsseqid so we can tell which sequences really are
2696 // dataset sequences only
2697 vamsasSeq.setDsseqid(id);
2698 dbrefs = jds.getDBRefs();
2699 if (parentseq == null)
2706 * save any dbrefs; special subclass GeneLocus is flagged as 'locus'
2710 for (int d = 0, nd = dbrefs.size(); d < nd; d++)
2712 DBRef dbref = new DBRef();
2713 DBRefEntry ref = dbrefs.get(d);
2714 dbref.setSource(ref.getSource());
2715 dbref.setVersion(ref.getVersion());
2716 dbref.setAccessionId(ref.getAccessionId());
2717 dbref.setCanonical(ref.isCanonical());
2718 if (ref instanceof GeneLocus)
2720 dbref.setLocus(true);
2724 Mapping mp = createVamsasMapping(ref.getMap(), parentseq, jds,
2726 dbref.setMapping(mp);
2728 vamsasSeq.getDBRef().add(dbref);
2734 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
2735 SequenceI parentseq, SequenceI jds, boolean recurse)
2738 if (jmp.getMap() != null)
2742 jalview.util.MapList mlst = jmp.getMap();
2743 List<int[]> r = mlst.getFromRanges();
2744 for (int[] range : r)
2746 MapListFrom mfrom = new MapListFrom();
2747 mfrom.setStart(range[0]);
2748 mfrom.setEnd(range[1]);
2749 // mp.addMapListFrom(mfrom);
2750 mp.getMapListFrom().add(mfrom);
2752 r = mlst.getToRanges();
2753 for (int[] range : r)
2755 MapListTo mto = new MapListTo();
2756 mto.setStart(range[0]);
2757 mto.setEnd(range[1]);
2758 // mp.addMapListTo(mto);
2759 mp.getMapListTo().add(mto);
2761 mp.setMapFromUnit(BigInteger.valueOf(mlst.getFromRatio()));
2762 mp.setMapToUnit(BigInteger.valueOf(mlst.getToRatio()));
2763 if (jmp.getTo() != null)
2765 // MappingChoice mpc = new MappingChoice();
2767 // check/create ID for the sequence referenced by getTo()
2770 SequenceI ps = null;
2771 if (parentseq != jmp.getTo()
2772 && parentseq.getDatasetSequence() != jmp.getTo())
2774 // chaining dbref rather than a handshaking one
2775 jmpid = seqHash(ps = jmp.getTo());
2779 jmpid = seqHash(ps = parentseq);
2781 // mpc.setDseqFor(jmpid);
2782 mp.setDseqFor(jmpid);
2783 if (!seqRefIds.containsKey(jmpid))
2785 Console.debug("creatign new DseqFor ID");
2786 seqRefIds.put(jmpid, ps);
2790 Console.debug("reusing DseqFor ID");
2793 // mp.setMappingChoice(mpc);
2799 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2800 List<UserColourScheme> userColours, JalviewModel jm)
2803 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2804 boolean newucs = false;
2805 if (!userColours.contains(ucs))
2807 userColours.add(ucs);
2810 id = "ucs" + userColours.indexOf(ucs);
2813 // actually create the scheme's entry in the XML model
2814 java.awt.Color[] colours = ucs.getColours();
2815 UserColours uc = new UserColours();
2816 // UserColourScheme jbucs = new UserColourScheme();
2817 JalviewUserColours jbucs = new JalviewUserColours();
2819 for (int i = 0; i < colours.length; i++)
2821 Colour col = new Colour();
2822 col.setName(ResidueProperties.aa[i]);
2823 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2824 // jbucs.addColour(col);
2825 jbucs.getColour().add(col);
2827 if (ucs.getLowerCaseColours() != null)
2829 colours = ucs.getLowerCaseColours();
2830 for (int i = 0; i < colours.length; i++)
2832 Colour col = new Colour();
2833 col.setName(ResidueProperties.aa[i].toLowerCase(Locale.ROOT));
2834 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2835 // jbucs.addColour(col);
2836 jbucs.getColour().add(col);
2841 uc.setUserColourScheme(jbucs);
2842 // jm.addUserColours(uc);
2843 jm.getUserColours().add(uc);
2849 jalview.schemes.UserColourScheme getUserColourScheme(JalviewModel jm,
2852 List<UserColours> uc = jm.getUserColours();
2853 UserColours colours = null;
2855 for (int i = 0; i < uc.length; i++)
2857 if (uc[i].getId().equals(id))
2864 for (UserColours c : uc)
2866 if (c.getId().equals(id))
2873 java.awt.Color[] newColours = new java.awt.Color[24];
2875 for (int i = 0; i < 24; i++)
2877 newColours[i] = new java.awt.Color(Integer.parseInt(
2878 // colours.getUserColourScheme().getColour(i).getRGB(), 16));
2879 colours.getUserColourScheme().getColour().get(i).getRGB(),
2883 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2886 if (colours.getUserColourScheme().getColour().size()/*Count()*/ > 24)
2888 newColours = new java.awt.Color[23];
2889 for (int i = 0; i < 23; i++)
2891 newColours[i] = new java.awt.Color(
2892 Integer.parseInt(colours.getUserColourScheme().getColour()
2893 .get(i + 24).getRGB(), 16));
2895 ucs.setLowerCaseColours(newColours);
2902 * contains last error message (if any) encountered by XML loader.
2904 String errorMessage = null;
2907 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2908 * exceptions are raised during project XML parsing
2910 public boolean attemptversion1parse = false;
2913 * Load a jalview project archive from a jar file
2916 * - HTTP URL or filename
2918 public AlignFrame loadJalviewAlign(final Object file)
2921 jalview.gui.AlignFrame af = null;
2925 // create list to store references for any new Jmol viewers created
2926 newStructureViewers = new Vector<>();
2927 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2928 // Workaround is to make sure caller implements the JarInputStreamProvider
2930 // so we can re-open the jar input stream for each entry.
2932 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2933 af = loadJalviewAlign(jprovider);
2936 af.setMenusForViewport();
2938 } catch (MalformedURLException e)
2940 errorMessage = "Invalid URL format for '" + file + "'";
2946 SwingUtilities.invokeAndWait(new Runnable()
2951 setLoadingFinishedForNewStructureViewers();
2954 } catch (Exception x)
2956 System.err.println("Error loading alignment: " + x.getMessage());
2962 @SuppressWarnings("unused")
2963 private jarInputStreamProvider createjarInputStreamProvider(
2964 final Object ofile) throws MalformedURLException
2967 // BH 2018 allow for bytes already attached to File object
2970 String file = (ofile instanceof File
2971 ? ((File) ofile).getCanonicalPath()
2972 : ofile.toString());
2973 byte[] bytes = Platform.isJS() ? Platform.getFileBytes((File) ofile)
2976 errorMessage = null;
2977 uniqueSetSuffix = null;
2979 viewportsAdded.clear();
2980 frefedSequence = null;
2982 if (HttpUtils.startsWithHttpOrHttps(file))
2984 url = new URL(file);
2986 final URL _url = url;
2987 return new jarInputStreamProvider()
2991 public JarInputStream getJarInputStream() throws IOException
2995 // System.out.println("Jalview2XML: opening byte jarInputStream for
2996 // bytes.length=" + bytes.length);
2997 return new JarInputStream(new ByteArrayInputStream(bytes));
3001 // System.out.println("Jalview2XML: opening url jarInputStream for "
3003 return new JarInputStream(_url.openStream());
3007 // System.out.println("Jalview2XML: opening file jarInputStream for
3009 return new JarInputStream(new FileInputStream(file));
3014 public String getFilename()
3019 } catch (IOException e)
3021 e.printStackTrace();
3027 * Recover jalview session from a jalview project archive. Caller may
3028 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
3029 * themselves. Any null fields will be initialised with default values,
3030 * non-null fields are left alone.
3035 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
3037 errorMessage = null;
3038 if (uniqueSetSuffix == null)
3040 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
3042 if (seqRefIds == null)
3046 AlignFrame af = null, _af = null;
3047 IdentityHashMap<AlignmentI, AlignmentI> importedDatasets = new IdentityHashMap<>();
3048 Map<String, AlignFrame> gatherToThisFrame = new HashMap<>();
3049 final String file = jprovider.getFilename();
3052 JarInputStream jin = null;
3053 JarEntry jarentry = null;
3058 jin = jprovider.getJarInputStream();
3059 for (int i = 0; i < entryCount; i++)
3061 jarentry = jin.getNextJarEntry();
3064 if (jarentry != null && jarentry.getName().endsWith(".xml"))
3066 JAXBContext jc = JAXBContext
3067 .newInstance("jalview.xml.binding.jalview");
3068 XMLStreamReader streamReader = XMLInputFactory.newInstance()
3069 .createXMLStreamReader(jin);
3070 javax.xml.bind.Unmarshaller um = jc.createUnmarshaller();
3071 JAXBElement<JalviewModel> jbe = um.unmarshal(streamReader,
3072 JalviewModel.class);
3073 JalviewModel object = jbe.getValue();
3075 if (true) // !skipViewport(object))
3077 _af = loadFromObject(object, file, true, jprovider);
3078 if (_af != null && object.getViewport().size() > 0)
3079 // getJalviewModelSequence().getViewportCount() > 0)
3083 // store a reference to the first view
3086 if (_af.getViewport().isGatherViewsHere())
3088 // if this is a gathered view, keep its reference since
3089 // after gathering views, only this frame will remain
3091 gatherToThisFrame.put(_af.getViewport().getSequenceSetId(),
3094 // Save dataset to register mappings once all resolved
3095 importedDatasets.put(
3096 af.getViewport().getAlignment().getDataset(),
3097 af.getViewport().getAlignment().getDataset());
3102 else if (jarentry != null)
3104 // Some other file here.
3107 } while (jarentry != null);
3109 resolveFrefedSequences();
3110 } catch (IOException ex)
3112 ex.printStackTrace();
3113 errorMessage = "Couldn't locate Jalview XML file : " + file;
3115 "Exception whilst loading jalview XML file : " + ex + "\n");
3116 } catch (Exception ex)
3118 System.err.println("Parsing as Jalview Version 2 file failed.");
3119 ex.printStackTrace(System.err);
3120 if (attemptversion1parse)
3122 // used to attempt to parse as V1 castor-generated xml
3124 if (Desktop.instance != null)
3126 Desktop.instance.stopLoading();
3130 System.out.println("Successfully loaded archive file");
3133 ex.printStackTrace();
3136 "Exception whilst loading jalview XML file : " + ex + "\n");
3137 } catch (OutOfMemoryError e)
3139 // Don't use the OOM Window here
3140 errorMessage = "Out of memory loading jalview XML file";
3141 System.err.println("Out of memory whilst loading jalview XML file");
3142 e.printStackTrace();
3146 * Regather multiple views (with the same sequence set id) to the frame (if
3147 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
3148 * views instead of separate frames. Note this doesn't restore a state where
3149 * some expanded views in turn have tabbed views - the last "first tab" read
3150 * in will play the role of gatherer for all.
3152 for (AlignFrame fr : gatherToThisFrame.values())
3154 Desktop.instance.gatherViews(fr);
3157 restoreSplitFrames();
3158 for (AlignmentI ds : importedDatasets.keySet())
3160 if (ds.getCodonFrames() != null)
3162 StructureSelectionManager
3163 .getStructureSelectionManager(Desktop.instance)
3164 .registerMappings(ds.getCodonFrames());
3167 if (errorMessage != null)
3172 if (Desktop.instance != null)
3174 Desktop.instance.stopLoading();
3181 * Try to reconstruct and display SplitFrame windows, where each contains
3182 * complementary dna and protein alignments. Done by pairing up AlignFrame
3183 * objects (created earlier) which have complementary viewport ids associated.
3185 protected void restoreSplitFrames()
3187 List<SplitFrame> gatherTo = new ArrayList<>();
3188 List<AlignFrame> addedToSplitFrames = new ArrayList<>();
3189 Map<String, AlignFrame> dna = new HashMap<>();
3192 * Identify the DNA alignments
3194 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
3197 AlignFrame af = candidate.getValue();
3198 if (af.getViewport().getAlignment().isNucleotide())
3200 dna.put(candidate.getKey().getId(), af);
3205 * Try to match up the protein complements
3207 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
3210 AlignFrame af = candidate.getValue();
3211 if (!af.getViewport().getAlignment().isNucleotide())
3213 String complementId = candidate.getKey().getComplementId();
3214 // only non-null complements should be in the Map
3215 if (complementId != null && dna.containsKey(complementId))
3217 final AlignFrame dnaFrame = dna.get(complementId);
3218 SplitFrame sf = createSplitFrame(dnaFrame, af);
3219 addedToSplitFrames.add(dnaFrame);
3220 addedToSplitFrames.add(af);
3221 dnaFrame.setMenusForViewport();
3222 af.setMenusForViewport();
3223 if (af.getViewport().isGatherViewsHere())
3232 * Open any that we failed to pair up (which shouldn't happen!) as
3233 * standalone AlignFrame's.
3235 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
3238 AlignFrame af = candidate.getValue();
3239 if (!addedToSplitFrames.contains(af))
3241 Viewport view = candidate.getKey();
3242 Desktop.addInternalFrame(af, view.getTitle(),
3243 safeInt(view.getWidth()), safeInt(view.getHeight()));
3244 af.setMenusForViewport();
3245 System.err.println("Failed to restore view " + view.getTitle()
3246 + " to split frame");
3251 * Gather back into tabbed views as flagged.
3253 for (SplitFrame sf : gatherTo)
3255 Desktop.instance.gatherViews(sf);
3258 splitFrameCandidates.clear();
3262 * Construct and display one SplitFrame holding DNA and protein alignments.
3265 * @param proteinFrame
3268 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
3269 AlignFrame proteinFrame)
3271 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
3272 String title = MessageManager.getString("label.linked_view_title");
3273 int width = (int) dnaFrame.getBounds().getWidth();
3274 int height = (int) (dnaFrame.getBounds().getHeight()
3275 + proteinFrame.getBounds().getHeight() + 50);
3278 * SplitFrame location is saved to both enclosed frames
3280 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
3281 Desktop.addInternalFrame(splitFrame, title, width, height);
3284 * And compute cDNA consensus (couldn't do earlier with consensus as
3285 * mappings were not yet present)
3287 proteinFrame.getViewport().alignmentChanged(proteinFrame.alignPanel);
3293 * check errorMessage for a valid error message and raise an error box in the
3294 * GUI or write the current errorMessage to stderr and then clear the error
3297 protected void reportErrors()
3299 reportErrors(false);
3302 protected void reportErrors(final boolean saving)
3304 if (errorMessage != null)
3306 final String finalErrorMessage = errorMessage;
3309 javax.swing.SwingUtilities.invokeLater(new Runnable()
3314 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
3316 "Error " + (saving ? "saving" : "loading")
3318 JvOptionPane.WARNING_MESSAGE);
3324 System.err.println("Problem loading Jalview file: " + errorMessage);
3327 errorMessage = null;
3330 Map<String, String> alreadyLoadedPDB = new HashMap<>();
3333 * when set, local views will be updated from view stored in JalviewXML
3334 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
3335 * sync if this is set to true.
3337 private final boolean updateLocalViews = false;
3340 * Returns the path to a temporary file holding the PDB file for the given PDB
3341 * id. The first time of asking, searches for a file of that name in the
3342 * Jalview project jar, and copies it to a new temporary file. Any repeat
3343 * requests just return the path to the file previously created.
3349 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId,
3352 if (alreadyLoadedPDB.containsKey(pdbId))
3354 return alreadyLoadedPDB.get(pdbId).toString();
3357 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb",
3359 if (tempFile != null)
3361 alreadyLoadedPDB.put(pdbId, tempFile);
3367 * Copies the jar entry of given name to a new temporary file and returns the
3368 * path to the file, or null if the entry is not found.
3371 * @param jarEntryName
3373 * a prefix for the temporary file name, must be at least three
3375 * @param suffixModel
3376 * null or original file - so new file can be given the same suffix
3380 protected String copyJarEntry(jarInputStreamProvider jprovider,
3381 String jarEntryName, String prefix, String suffixModel)
3383 String suffix = ".tmp";
3384 if (suffixModel == null)
3386 suffixModel = jarEntryName;
3388 int sfpos = suffixModel.lastIndexOf(".");
3389 if (sfpos > -1 && sfpos < (suffixModel.length() - 1))
3391 suffix = "." + suffixModel.substring(sfpos + 1);
3394 try (JarInputStream jin = jprovider.getJarInputStream())
3396 JarEntry entry = null;
3399 entry = jin.getNextJarEntry();
3400 } while (entry != null && !entry.getName().equals(jarEntryName));
3404 // in = new BufferedReader(new InputStreamReader(jin, UTF_8));
3405 File outFile = File.createTempFile(prefix, suffix);
3406 outFile.deleteOnExit();
3407 try (OutputStream os = new FileOutputStream(outFile))
3411 String t = outFile.getAbsolutePath();
3417 "Couldn't find entry in Jalview Jar for " + jarEntryName);
3419 } catch (Exception ex)
3421 ex.printStackTrace();
3427 private class JvAnnotRow
3429 public JvAnnotRow(int i, AlignmentAnnotation jaa)
3436 * persisted version of annotation row from which to take vis properties
3438 public jalview.datamodel.AlignmentAnnotation template;
3441 * original position of the annotation row in the alignment
3447 * Load alignment frame from jalview XML DOM object
3449 * @param jalviewModel
3452 * filename source string
3453 * @param loadTreesAndStructures
3454 * when false only create Viewport
3456 * data source provider
3457 * @return alignment frame created from view stored in DOM
3459 AlignFrame loadFromObject(JalviewModel jalviewModel, String file,
3460 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
3462 SequenceSet vamsasSet = jalviewModel.getVamsasModel().getSequenceSet()
3464 List<Sequence> vamsasSeqs = vamsasSet.getSequence();
3466 // JalviewModelSequence jms = object.getJalviewModelSequence();
3468 // Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
3470 Viewport view = (jalviewModel.getViewport().size() > 0)
3471 ? jalviewModel.getViewport().get(0)
3474 // ////////////////////////////////
3475 // INITIALISE ALIGNMENT SEQUENCESETID AND VIEWID
3478 // If we just load in the same jar file again, the sequenceSetId
3479 // will be the same, and we end up with multiple references
3480 // to the same sequenceSet. We must modify this id on load
3481 // so that each load of the file gives a unique id
3484 * used to resolve correct alignment dataset for alignments with multiple
3487 String uniqueSeqSetId = null;
3488 String viewId = null;
3491 uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3492 viewId = (view.getId() == null ? null
3493 : view.getId() + uniqueSetSuffix);
3496 // ////////////////////////////////
3499 List<SequenceI> hiddenSeqs = null;
3501 List<SequenceI> tmpseqs = new ArrayList<>();
3503 boolean multipleView = false;
3504 SequenceI referenceseqForView = null;
3505 // JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
3506 List<JSeq> jseqs = jalviewModel.getJSeq();
3507 int vi = 0; // counter in vamsasSeq array
3508 for (int i = 0; i < jseqs.size(); i++)
3510 JSeq jseq = jseqs.get(i);
3511 String seqId = jseq.getId();
3513 SequenceI tmpSeq = seqRefIds.get(seqId);
3516 if (!incompleteSeqs.containsKey(seqId))
3518 // may not need this check, but keep it for at least 2.9,1 release
3519 if (tmpSeq.getStart() != jseq.getStart()
3520 || tmpSeq.getEnd() != jseq.getEnd())
3522 System.err.println(String.format(
3523 "Warning JAL-2154 regression: updating start/end for sequence %s from %d/%d to %d/%d",
3524 tmpSeq.getName(), tmpSeq.getStart(), tmpSeq.getEnd(),
3525 jseq.getStart(), jseq.getEnd()));
3530 incompleteSeqs.remove(seqId);
3532 if (vamsasSeqs.size() > vi
3533 && vamsasSeqs.get(vi).getId().equals(seqId))
3535 // most likely we are reading a dataset XML document so
3536 // update from vamsasSeq section of XML for this sequence
3537 tmpSeq.setName(vamsasSeqs.get(vi).getName());
3538 tmpSeq.setDescription(vamsasSeqs.get(vi).getDescription());
3539 tmpSeq.setSequence(vamsasSeqs.get(vi).getSequence());
3544 // reading multiple views, so vamsasSeq set is a subset of JSeq
3545 multipleView = true;
3547 tmpSeq.setStart(jseq.getStart());
3548 tmpSeq.setEnd(jseq.getEnd());
3549 tmpseqs.add(tmpSeq);
3553 Sequence vamsasSeq = vamsasSeqs.get(vi);
3554 tmpSeq = new jalview.datamodel.Sequence(vamsasSeq.getName(),
3555 vamsasSeq.getSequence());
3556 tmpSeq.setDescription(vamsasSeq.getDescription());
3557 tmpSeq.setStart(jseq.getStart());
3558 tmpSeq.setEnd(jseq.getEnd());
3559 tmpSeq.setVamsasId(uniqueSetSuffix + seqId);
3560 seqRefIds.put(vamsasSeq.getId(), tmpSeq);
3561 tmpseqs.add(tmpSeq);
3565 if (safeBoolean(jseq.isViewreference()))
3567 referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
3570 if (jseq.isHidden() != null && jseq.isHidden().booleanValue())
3572 if (hiddenSeqs == null)
3574 hiddenSeqs = new ArrayList<>();
3577 hiddenSeqs.add(tmpSeq);
3582 // Create the alignment object from the sequence set
3583 // ///////////////////////////////
3584 SequenceI[] orderedSeqs = tmpseqs
3585 .toArray(new SequenceI[tmpseqs.size()]);
3587 AlignmentI al = null;
3588 // so we must create or recover the dataset alignment before going further
3589 // ///////////////////////////////
3590 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
3592 // older jalview projects do not have a dataset - so creat alignment and
3594 al = new Alignment(orderedSeqs);
3595 al.setDataset(null);
3599 boolean isdsal = jalviewModel.getViewport().isEmpty();
3602 // we are importing a dataset record, so
3603 // recover reference to an alignment already materialsed as dataset
3604 al = getDatasetFor(vamsasSet.getDatasetId());
3608 // materialse the alignment
3609 al = new Alignment(orderedSeqs);
3613 addDatasetRef(vamsasSet.getDatasetId(), al);
3616 // finally, verify all data in vamsasSet is actually present in al
3617 // passing on flag indicating if it is actually a stored dataset
3618 recoverDatasetFor(vamsasSet, al, isdsal, uniqueSeqSetId);
3621 if (referenceseqForView != null)
3623 al.setSeqrep(referenceseqForView);
3625 // / Add the alignment properties
3626 for (int i = 0; i < vamsasSet.getSequenceSetProperties().size(); i++)
3628 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties()
3630 al.setProperty(ssp.getKey(), ssp.getValue());
3633 // ///////////////////////////////
3635 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
3638 // load sequence features, database references and any associated PDB
3639 // structures for the alignment
3641 // prior to 2.10, this part would only be executed the first time a
3642 // sequence was encountered, but not afterwards.
3643 // now, for 2.10 projects, this is also done if the xml doc includes
3644 // dataset sequences not actually present in any particular view.
3646 for (int i = 0; i < vamsasSeqs.size(); i++)
3648 JSeq jseq = jseqs.get(i);
3649 if (jseq.getFeatures().size() > 0)
3651 List<Feature> features = jseq.getFeatures();
3652 for (int f = 0; f < features.size(); f++)
3654 Feature feat = features.get(f);
3655 SequenceFeature sf = new SequenceFeature(feat.getType(),
3656 feat.getDescription(), feat.getBegin(), feat.getEnd(),
3657 safeFloat(feat.getScore()), feat.getFeatureGroup());
3658 sf.setStatus(feat.getStatus());
3661 * load any feature attributes - include map-valued attributes
3663 Map<String, Map<String, String>> mapAttributes = new HashMap<>();
3664 for (int od = 0; od < feat.getOtherData().size(); od++)
3666 OtherData keyValue = feat.getOtherData().get(od);
3667 String attributeName = keyValue.getKey();
3668 String attributeValue = keyValue.getValue();
3669 if (attributeName.startsWith("LINK"))
3671 sf.addLink(attributeValue);
3675 String subAttribute = keyValue.getKey2();
3676 if (subAttribute == null)
3678 // simple string-valued attribute
3679 sf.setValue(attributeName, attributeValue);
3683 // attribute 'key' has sub-attribute 'key2'
3684 if (!mapAttributes.containsKey(attributeName))
3686 mapAttributes.put(attributeName, new HashMap<>());
3688 mapAttributes.get(attributeName).put(subAttribute,
3693 for (Entry<String, Map<String, String>> mapAttribute : mapAttributes
3696 sf.setValue(mapAttribute.getKey(), mapAttribute.getValue());
3699 // adds feature to datasequence's feature set (since Jalview 2.10)
3700 al.getSequenceAt(i).addSequenceFeature(sf);
3703 if (vamsasSeqs.get(i).getDBRef().size() > 0)
3705 // adds dbrefs to datasequence's set (since Jalview 2.10)
3707 al.getSequenceAt(i).getDatasetSequence() == null
3708 ? al.getSequenceAt(i)
3709 : al.getSequenceAt(i).getDatasetSequence(),
3712 if (jseq.getPdbids().size() > 0)
3714 List<Pdbids> ids = jseq.getPdbids();
3715 for (int p = 0; p < ids.size(); p++)
3717 Pdbids pdbid = ids.get(p);
3718 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
3719 entry.setId(pdbid.getId());
3720 if (pdbid.getType() != null)
3722 if (PDBEntry.Type.getType(pdbid.getType()) != null)
3724 entry.setType(PDBEntry.Type.getType(pdbid.getType()));
3728 entry.setType(PDBEntry.Type.FILE);
3731 // jprovider is null when executing 'New View'
3732 if (pdbid.getFile() != null && jprovider != null)
3734 if (!pdbloaded.containsKey(pdbid.getFile()))
3736 entry.setFile(loadPDBFile(jprovider, pdbid.getId(),
3741 entry.setFile(pdbloaded.get(pdbid.getId()).toString());
3745 if (pdbid.getPdbentryItem() != null)
3747 for (PdbentryItem item : pdbid.getPdbentryItem())
3749 for (Property pr : item.getProperty())
3751 entry.setProperty(pr.getName(), pr.getValue());
3756 for (Property prop : pdbid.getProperty())
3758 entry.setProperty(prop.getName(), prop.getValue());
3760 StructureSelectionManager
3761 .getStructureSelectionManager(Desktop.instance)
3762 .registerPDBEntry(entry);
3763 // adds PDBEntry to datasequence's set (since Jalview 2.10)
3764 if (al.getSequenceAt(i).getDatasetSequence() != null)
3766 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
3770 al.getSequenceAt(i).addPDBId(entry);
3775 } // end !multipleview
3777 // ///////////////////////////////
3778 // LOAD SEQUENCE MAPPINGS
3780 if (vamsasSet.getAlcodonFrame().size() > 0)
3782 // TODO Potentially this should only be done once for all views of an
3784 List<AlcodonFrame> alc = vamsasSet.getAlcodonFrame();
3785 for (int i = 0; i < alc.size(); i++)
3787 AlignedCodonFrame cf = new AlignedCodonFrame();
3788 if (alc.get(i).getAlcodMap().size() > 0)
3790 List<AlcodMap> maps = alc.get(i).getAlcodMap();
3791 for (int m = 0; m < maps.size(); m++)
3793 AlcodMap map = maps.get(m);
3794 SequenceI dnaseq = seqRefIds.get(map.getDnasq());
3796 jalview.datamodel.Mapping mapping = null;
3797 // attach to dna sequence reference.
3798 if (map.getMapping() != null)
3800 mapping = addMapping(map.getMapping());
3801 if (dnaseq != null && mapping.getTo() != null)
3803 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
3809 .add(newAlcodMapRef(map.getDnasq(), cf, mapping));
3813 al.addCodonFrame(cf);
3818 // ////////////////////////////////
3820 List<JvAnnotRow> autoAlan = new ArrayList<>();
3823 * store any annotations which forward reference a group's ID
3825 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<>();
3827 if (vamsasSet.getAnnotation().size()/*Count()*/ > 0)
3829 List<Annotation> an = vamsasSet.getAnnotation();
3831 for (int i = 0; i < an.size(); i++)
3833 Annotation annotation = an.get(i);
3836 * test if annotation is automatically calculated for this view only
3838 boolean autoForView = false;
3839 if (annotation.getLabel().equals("Quality")
3840 || annotation.getLabel().equals("Conservation")
3841 || annotation.getLabel().equals("Consensus"))
3843 // Kludge for pre 2.5 projects which lacked the autocalculated flag
3845 // JAXB has no has() test; schema defaults value to false
3846 // if (!annotation.hasAutoCalculated())
3848 // annotation.setAutoCalculated(true);
3851 if (autoForView || annotation.isAutoCalculated())
3853 // remove ID - we don't recover annotation from other views for
3854 // view-specific annotation
3855 annotation.setId(null);
3858 // set visibility for other annotation in this view
3859 String annotationId = annotation.getId();
3860 if (annotationId != null && annotationIds.containsKey(annotationId))
3862 AlignmentAnnotation jda = annotationIds.get(annotationId);
3863 // in principle Visible should always be true for annotation displayed
3864 // in multiple views
3865 if (annotation.isVisible() != null)
3867 jda.visible = annotation.isVisible();
3870 al.addAnnotation(jda);
3874 // Construct new annotation from model.
3875 List<AnnotationElement> ae = annotation.getAnnotationElement();
3876 jalview.datamodel.Annotation[] anot = null;
3877 java.awt.Color firstColour = null;
3879 if (!annotation.isScoreOnly())
3881 anot = new jalview.datamodel.Annotation[al.getWidth()];
3882 for (int aa = 0; aa < ae.size() && aa < anot.length; aa++)
3884 AnnotationElement annElement = ae.get(aa);
3885 anpos = annElement.getPosition();
3887 if (anpos >= anot.length)
3892 float value = safeFloat(annElement.getValue());
3893 anot[anpos] = new jalview.datamodel.Annotation(
3894 annElement.getDisplayCharacter(),
3895 annElement.getDescription(),
3896 (annElement.getSecondaryStructure() == null
3897 || annElement.getSecondaryStructure()
3901 .getSecondaryStructure()
3904 anot[anpos].colour = new Color(safeInt(annElement.getColour()));
3905 if (firstColour == null)
3907 firstColour = anot[anpos].colour;
3911 jalview.datamodel.AlignmentAnnotation jaa = null;
3913 if (annotation.isGraph())
3915 float llim = 0, hlim = 0;
3916 // if (autoForView || an[i].isAutoCalculated()) {
3919 jaa = new jalview.datamodel.AlignmentAnnotation(
3920 annotation.getLabel(), annotation.getDescription(), anot,
3921 llim, hlim, safeInt(annotation.getGraphType()));
3923 jaa.graphGroup = safeInt(annotation.getGraphGroup());
3924 jaa._linecolour = firstColour;
3925 if (annotation.getThresholdLine() != null)
3927 jaa.setThreshold(new jalview.datamodel.GraphLine(
3928 safeFloat(annotation.getThresholdLine().getValue()),
3929 annotation.getThresholdLine().getLabel(),
3930 new java.awt.Color(safeInt(
3931 annotation.getThresholdLine().getColour()))));
3933 if (autoForView || annotation.isAutoCalculated())
3935 // Hardwire the symbol display line to ensure that labels for
3936 // histograms are displayed
3942 jaa = new jalview.datamodel.AlignmentAnnotation(
3943 annotation.getLabel(), annotation.getDescription(), anot);
3944 jaa._linecolour = firstColour;
3946 // register new annotation
3947 if (annotation.getId() != null)
3949 annotationIds.put(annotation.getId(), jaa);
3950 jaa.annotationId = annotation.getId();
3952 // recover sequence association
3953 String sequenceRef = annotation.getSequenceRef();
3954 if (sequenceRef != null)
3956 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3957 SequenceI sequence = seqRefIds.get(sequenceRef);
3958 if (sequence == null)
3960 // in pre-2.9 projects sequence ref is to sequence name
3961 sequence = al.findName(sequenceRef);
3963 if (sequence != null)
3965 jaa.createSequenceMapping(sequence, 1, true);
3966 sequence.addAlignmentAnnotation(jaa);
3969 // and make a note of any group association
3970 if (annotation.getGroupRef() != null
3971 && annotation.getGroupRef().length() > 0)
3973 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3974 .get(annotation.getGroupRef());
3977 aal = new ArrayList<>();
3978 groupAnnotRefs.put(annotation.getGroupRef(), aal);
3983 if (annotation.getScore() != null)
3985 jaa.setScore(annotation.getScore().doubleValue());
3987 if (annotation.isVisible() != null)
3989 jaa.visible = annotation.isVisible().booleanValue();
3992 if (annotation.isCentreColLabels() != null)
3994 jaa.centreColLabels = annotation.isCentreColLabels()
3998 if (annotation.isScaleColLabels() != null)
4000 jaa.scaleColLabel = annotation.isScaleColLabels().booleanValue();
4002 if (annotation.isAutoCalculated())
4004 // newer files have an 'autoCalculated' flag and store calculation
4005 // state in viewport properties
4006 jaa.autoCalculated = true; // means annotation will be marked for
4007 // update at end of load.
4009 if (annotation.getGraphHeight() != null)
4011 jaa.graphHeight = annotation.getGraphHeight().intValue();
4013 jaa.belowAlignment = annotation.isBelowAlignment();
4014 jaa.setCalcId(annotation.getCalcId());
4015 if (annotation.getProperty().size() > 0)
4017 for (jalview.xml.binding.jalview.Property prop : annotation.getProperty())
4019 jaa.setProperty(prop.getName(), prop.getValue());
4022 if (jaa.graph == AlignmentAnnotation.CONTACT_MAP)
4024 if (annotation.getContactmatrix() != null
4025 && annotation.getContactmatrix().size() > 0)
4027 for (MatrixType xmlmat : annotation.getContactmatrix())
4029 if (PAEContactMatrix.PAEMATRIX.equals(xmlmat.getType()))
4031 if (!xmlmat.getRows().equals(xmlmat.getCols()))
4033 Console.error("Can't handle non square PAE Matrices");
4037 float[][] elements = ContactMatrix
4038 .fromFloatStringToContacts(xmlmat.getElements(),
4039 xmlmat.getCols().intValue(),
4040 xmlmat.getRows().intValue());
4041 jalview.util.MapList mapping = null;
4042 if (xmlmat.getMapping()!=null)
4044 MapListType m = xmlmat.getMapping();
4045 // Mapping m = dr.getMapping();
4046 int fr[] = new int[m.getMapListFrom().size() * 2];
4047 Iterator<MapListFrom> from = m.getMapListFrom().iterator();// enumerateMapListFrom();
4048 for (int _i = 0; from.hasNext(); _i += 2)
4050 MapListFrom mf = from.next();
4051 fr[_i] = mf.getStart();
4052 fr[_i + 1] = mf.getEnd();
4054 int fto[] = new int[m.getMapListTo().size() * 2];
4055 Iterator<MapListTo> to = m.getMapListTo().iterator();// enumerateMapListTo();
4056 for (int _i = 0; to.hasNext(); _i += 2)
4058 MapListTo mf = to.next();
4059 fto[_i] = mf.getStart();
4060 fto[_i + 1] = mf.getEnd();
4063 mapping = new jalview.util.MapList(fr, fto, m.getMapFromUnit().intValue(),m.getMapToUnit().intValue());
4065 List<BitSet> newgroups=new ArrayList<BitSet>();
4066 if (xmlmat.getGroups().size()>0)
4068 for (String sgroup:xmlmat.getGroups())
4070 newgroups.add(deStringifyBitset(sgroup));
4073 String nwk=xmlmat.getNewick().size()>0 ? xmlmat.getNewick().get(0):null;
4074 if (xmlmat.getNewick().size()>1)
4077 "Ignoring additional clusterings for contact matrix");
4080 String treeMethod = xmlmat.getTreeMethod();
4081 double thresh = xmlmat.getCutHeight()!=null ? xmlmat.getCutHeight() : 0;
4082 GroupSet grpset = new GroupSet();
4083 grpset.restoreGroups(newgroups, treeMethod, nwk, thresh);
4084 PAEContactMatrix newpae = new PAEContactMatrix(
4085 jaa.sequenceRef, mapping, elements,grpset);
4086 jaa.sequenceRef.addContactListFor(jaa, newpae);
4091 Console.error("Ignoring CONTACT_MAP annotation with type "
4092 + xmlmat.getType());
4098 if (jaa.autoCalculated)
4100 autoAlan.add(new JvAnnotRow(i, jaa));
4103 // if (!autoForView)
4105 // add autocalculated group annotation and any user created annotation
4107 al.addAnnotation(jaa);
4111 // ///////////////////////
4113 // Create alignment markup and styles for this view
4114 if (jalviewModel.getJGroup().size() > 0)
4116 List<JGroup> groups = jalviewModel.getJGroup();
4117 boolean addAnnotSchemeGroup = false;
4118 for (int i = 0; i < groups.size(); i++)
4120 JGroup jGroup = groups.get(i);
4121 ColourSchemeI cs = null;
4122 if (jGroup.getColour() != null)
4124 if (jGroup.getColour().startsWith("ucs"))
4126 cs = getUserColourScheme(jalviewModel, jGroup.getColour());
4128 else if (jGroup.getColour().equals("AnnotationColourGradient")
4129 && jGroup.getAnnotationColours() != null)
4131 addAnnotSchemeGroup = true;
4135 cs = ColourSchemeProperty.getColourScheme(null, al,
4136 jGroup.getColour());
4139 int pidThreshold = safeInt(jGroup.getPidThreshold());
4141 Vector<SequenceI> seqs = new Vector<>();
4143 for (int s = 0; s < jGroup.getSeq().size(); s++)
4145 String seqId = jGroup.getSeq().get(s);
4146 SequenceI ts = seqRefIds.get(seqId);
4150 seqs.addElement(ts);
4154 if (seqs.size() < 1)
4159 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
4160 safeBoolean(jGroup.isDisplayBoxes()),
4161 safeBoolean(jGroup.isDisplayText()),
4162 safeBoolean(jGroup.isColourText()),
4163 safeInt(jGroup.getStart()), safeInt(jGroup.getEnd()));
4164 sg.getGroupColourScheme().setThreshold(pidThreshold, true);
4165 sg.getGroupColourScheme()
4166 .setConservationInc(safeInt(jGroup.getConsThreshold()));
4167 sg.setOutlineColour(new Color(safeInt(jGroup.getOutlineColour())));
4169 sg.textColour = new Color(safeInt(jGroup.getTextCol1()));
4170 sg.textColour2 = new Color(safeInt(jGroup.getTextCol2()));
4171 sg.setShowNonconserved(safeBoolean(jGroup.isShowUnconserved()));
4172 sg.thresholdTextColour = safeInt(jGroup.getTextColThreshold());
4173 // attributes with a default in the schema are never null
4174 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
4175 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
4176 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
4177 sg.setIgnoreGapsConsensus(jGroup.isIgnoreGapsinConsensus());
4178 if (jGroup.getConsThreshold() != null
4179 && jGroup.getConsThreshold().intValue() != 0)
4181 Conservation c = new Conservation("All", sg.getSequences(null), 0,
4184 c.verdict(false, 25);
4185 sg.cs.setConservation(c);
4188 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
4190 // re-instate unique group/annotation row reference
4191 List<AlignmentAnnotation> jaal = groupAnnotRefs
4192 .get(jGroup.getId());
4195 for (AlignmentAnnotation jaa : jaal)
4198 if (jaa.autoCalculated)
4200 // match up and try to set group autocalc alignment row for this
4202 if (jaa.label.startsWith("Consensus for "))
4204 sg.setConsensus(jaa);
4206 // match up and try to set group autocalc alignment row for this
4208 if (jaa.label.startsWith("Conservation for "))
4210 sg.setConservationRow(jaa);
4217 if (addAnnotSchemeGroup)
4219 // reconstruct the annotation colourscheme
4221 constructAnnotationColour(jGroup.getAnnotationColours(),
4222 null, al, jalviewModel, false));
4228 // only dataset in this model, so just return.
4231 // ///////////////////////////////
4234 AlignFrame af = null;
4235 AlignViewport av = null;
4236 // now check to see if we really need to create a new viewport.
4237 if (multipleView && viewportsAdded.size() == 0)
4239 // We recovered an alignment for which a viewport already exists.
4240 // TODO: fix up any settings necessary for overlaying stored state onto
4241 // state recovered from another document. (may not be necessary).
4242 // we may need a binding from a viewport in memory to one recovered from
4244 // and then recover its containing af to allow the settings to be applied.
4245 // TODO: fix for vamsas demo
4247 "About to recover a viewport for existing alignment: Sequence set ID is "
4249 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
4250 if (seqsetobj != null)
4252 if (seqsetobj instanceof String)
4254 uniqueSeqSetId = (String) seqsetobj;
4256 "Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
4262 "Warning : Collision between sequence set ID string and existing jalview object mapping.");
4268 * indicate that annotation colours are applied across all groups (pre
4269 * Jalview 2.8.1 behaviour)
4271 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan("2.8.1",
4272 jalviewModel.getVersion());
4274 AlignmentPanel ap = null;
4275 boolean isnewview = true;
4278 // Check to see if this alignment already has a view id == viewId
4279 jalview.gui.AlignmentPanel views[] = Desktop
4280 .getAlignmentPanels(uniqueSeqSetId);
4281 if (views != null && views.length > 0)
4283 for (int v = 0; v < views.length; v++)
4285 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
4287 // recover the existing alignpanel, alignframe, viewport
4288 af = views[v].alignFrame;
4291 // TODO: could even skip resetting view settings if we don't want to
4292 // change the local settings from other jalview processes
4301 af = loadViewport(file, jseqs, hiddenSeqs, al, jalviewModel, view,
4302 uniqueSeqSetId, viewId, autoAlan);
4303 av = af.getViewport();
4308 * Load any trees, PDB structures and viewers, Overview
4310 * Not done if flag is false (when this method is used for New View)
4312 if (loadTreesAndStructures)
4314 loadTrees(jalviewModel, view, af, av, ap);
4315 loadPCAViewers(jalviewModel, ap);
4316 loadPDBStructures(jprovider, jseqs, af, ap);
4317 loadRnaViewers(jprovider, jseqs, ap);
4318 loadOverview(view, jalviewModel.getVersion(), af);
4320 // and finally return.
4325 * Load Overview window, restoring colours, 'show hidden regions' flag, title
4326 * and geometry as saved
4331 protected void loadOverview(Viewport view, String version, AlignFrame af)
4333 if (!isVersionStringLaterThan("2.11.3",
4334 version) && view.getOverview()==null)
4339 * first close any Overview that was opened automatically
4340 * (if so configured in Preferences) so that the view is
4341 * restored in the same state as saved
4343 af.alignPanel.closeOverviewPanel();
4345 Overview overview = view.getOverview();
4346 if (overview != null)
4348 OverviewPanel overviewPanel = af
4349 .openOverviewPanel(overview.isShowHidden());
4350 overviewPanel.setTitle(overview.getTitle());
4351 overviewPanel.setFrameBounds(overview.getXpos(), overview.getYpos(),
4352 overview.getWidth(), overview.getHeight());
4353 Color gap = new Color(overview.getGapColour());
4354 Color residue = new Color(overview.getResidueColour());
4355 Color hidden = new Color(overview.getHiddenColour());
4356 overviewPanel.getCanvas().setColours(gap, residue, hidden);
4361 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
4362 * panel is restored from separate jar entries, two (gapped and trimmed) per
4363 * sequence and secondary structure.
4365 * Currently each viewer shows just one sequence and structure (gapped and
4366 * trimmed), however this method is designed to support multiple sequences or
4367 * structures in viewers if wanted in future.
4373 private void loadRnaViewers(jarInputStreamProvider jprovider,
4374 List<JSeq> jseqs, AlignmentPanel ap)
4377 * scan the sequences for references to viewers; create each one the first
4378 * time it is referenced, add Rna models to existing viewers
4380 for (JSeq jseq : jseqs)
4382 for (int i = 0; i < jseq.getRnaViewer().size(); i++)
4384 RnaViewer viewer = jseq.getRnaViewer().get(i);
4385 AppVarna appVarna = findOrCreateVarnaViewer(viewer, uniqueSetSuffix,
4388 for (int j = 0; j < viewer.getSecondaryStructure().size(); j++)
4390 SecondaryStructure ss = viewer.getSecondaryStructure().get(j);
4391 SequenceI seq = seqRefIds.get(jseq.getId());
4392 AlignmentAnnotation ann = this.annotationIds
4393 .get(ss.getAnnotationId());
4396 * add the structure to the Varna display (with session state copied
4397 * from the jar to a temporary file)
4399 boolean gapped = safeBoolean(ss.isGapped());
4400 String rnaTitle = ss.getTitle();
4401 String sessionState = ss.getViewerState();
4402 String tempStateFile = copyJarEntry(jprovider, sessionState,
4404 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
4405 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
4407 appVarna.setInitialSelection(safeInt(viewer.getSelectedRna()));
4413 * Locate and return an already instantiated matching AppVarna, or create one
4417 * @param viewIdSuffix
4421 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
4422 String viewIdSuffix, AlignmentPanel ap)
4425 * on each load a suffix is appended to the saved viewId, to avoid conflicts
4426 * if load is repeated
4428 String postLoadId = viewer.getViewId() + viewIdSuffix;
4429 for (JInternalFrame frame : getAllFrames())
4431 if (frame instanceof AppVarna)
4433 AppVarna varna = (AppVarna) frame;
4434 if (postLoadId.equals(varna.getViewId()))
4436 // this viewer is already instantiated
4437 // could in future here add ap as another 'parent' of the
4438 // AppVarna window; currently just 1-to-many
4445 * viewer not found - make it
4447 RnaViewerModel model = new RnaViewerModel(postLoadId, viewer.getTitle(),
4448 safeInt(viewer.getXpos()), safeInt(viewer.getYpos()),
4449 safeInt(viewer.getWidth()), safeInt(viewer.getHeight()),
4450 safeInt(viewer.getDividerLocation()));
4451 AppVarna varna = new AppVarna(model, ap);
4457 * Load any saved trees
4465 protected void loadTrees(JalviewModel jm, Viewport view, AlignFrame af,
4466 AlignViewport av, AlignmentPanel ap)
4468 // TODO result of automated refactoring - are all these parameters needed?
4471 for (int t = 0; t < jm.getTree().size(); t++)
4474 Tree tree = jm.getTree().get(t);
4476 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
4479 if (tree.isColumnWise())
4481 AlignmentAnnotation aa = (AlignmentAnnotation) annotationIds.get(tree
4482 .getColumnReference());
4486 "Null alignment annotation when restoring columnwise tree");
4488 tp = af.showColumnWiseTree(new NewickFile(tree.getNewick()), aa,
4489 tree.getTitle(), safeInt(tree.getWidth()),
4490 safeInt(tree.getHeight()), safeInt(tree.getXpos()),
4491 safeInt(tree.getYpos()));
4496 tp = af.showNewickTree(new NewickFile(tree.getNewick()),
4497 tree.getTitle(), safeInt(tree.getWidth()),
4498 safeInt(tree.getHeight()), safeInt(tree.getXpos()),
4499 safeInt(tree.getYpos()));
4501 if (tree.getId() != null)
4503 // perhaps bind the tree id to something ?
4508 // update local tree attributes ?
4509 // TODO: should check if tp has been manipulated by user - if so its
4510 // settings shouldn't be modified
4511 tp.setTitle(tree.getTitle());
4512 tp.setBounds(new Rectangle(safeInt(tree.getXpos()),
4513 safeInt(tree.getYpos()), safeInt(tree.getWidth()),
4514 safeInt(tree.getHeight())));
4515 tp.setViewport(av); // af.viewport;
4516 // TODO: verify 'associate with all views' works still
4517 tp.getTreeCanvas().setViewport(av); // af.viewport;
4518 tp.getTreeCanvas().setAssociatedPanel(ap); // af.alignPanel;
4520 tp.getTreeCanvas().setApplyToAllViews(tree.isLinkToAllViews());
4524 "There was a problem recovering stored Newick tree: \n"
4525 + tree.getNewick());
4529 tp.fitToWindow.setState(safeBoolean(tree.isFitToWindow()));
4530 tp.fitToWindow_actionPerformed(null);
4532 if (tree.getFontName() != null)
4535 new Font(tree.getFontName(), safeInt(tree.getFontStyle()),
4536 safeInt(tree.getFontSize())));
4541 new Font(view.getFontName(), safeInt(view.getFontStyle()),
4542 safeInt(view.getFontSize())));
4545 tp.showPlaceholders(safeBoolean(tree.isMarkUnlinked()));
4546 tp.showBootstrap(safeBoolean(tree.isShowBootstrap()));
4547 tp.showDistances(safeBoolean(tree.isShowDistances()));
4549 tp.getTreeCanvas().setThreshold(safeFloat(tree.getThreshold()));
4551 if (safeBoolean(tree.isCurrentTree()))
4553 af.getViewport().setCurrentTree(tp.getTree());
4557 } catch (Exception ex)
4559 ex.printStackTrace();
4564 * Load and link any saved structure viewers.
4571 protected void loadPDBStructures(jarInputStreamProvider jprovider,
4572 List<JSeq> jseqs, AlignFrame af, AlignmentPanel ap)
4575 * Run through all PDB ids on the alignment, and collect mappings between
4576 * distinct view ids and all sequences referring to that view.
4578 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<>();
4580 for (int i = 0; i < jseqs.size(); i++)
4582 JSeq jseq = jseqs.get(i);
4583 if (jseq.getPdbids().size() > 0)
4585 List<Pdbids> ids = jseq.getPdbids();
4586 for (int p = 0; p < ids.size(); p++)
4588 Pdbids pdbid = ids.get(p);
4589 final int structureStateCount = pdbid.getStructureState().size();
4590 for (int s = 0; s < structureStateCount; s++)
4592 // check to see if we haven't already created this structure view
4593 final StructureState structureState = pdbid.getStructureState()
4595 String sviewid = (structureState.getViewId() == null) ? null
4596 : structureState.getViewId() + uniqueSetSuffix;
4597 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
4598 // Originally : pdbid.getFile()
4599 // : TODO: verify external PDB file recovery still works in normal
4600 // jalview project load
4602 loadPDBFile(jprovider, pdbid.getId(), pdbid.getFile()));
4603 jpdb.setId(pdbid.getId());
4605 int x = safeInt(structureState.getXpos());
4606 int y = safeInt(structureState.getYpos());
4607 int width = safeInt(structureState.getWidth());
4608 int height = safeInt(structureState.getHeight());
4610 // Probably don't need to do this anymore...
4611 // Desktop.desktop.getComponentAt(x, y);
4612 // TODO: NOW: check that this recovers the PDB file correctly.
4613 String pdbFile = loadPDBFile(jprovider, pdbid.getId(),
4615 jalview.datamodel.SequenceI seq = seqRefIds
4616 .get(jseq.getId() + "");
4617 if (sviewid == null)
4619 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width + ","
4622 if (!structureViewers.containsKey(sviewid))
4624 String viewerType = structureState.getType();
4625 if (viewerType == null) // pre Jalview 2.9
4627 viewerType = ViewerType.JMOL.toString();
4629 structureViewers.put(sviewid,
4630 new StructureViewerModel(x, y, width, height, false,
4631 false, true, structureState.getViewId(),
4633 // Legacy pre-2.7 conversion JAL-823 :
4634 // do not assume any view has to be linked for colour by
4638 // assemble String[] { pdb files }, String[] { id for each
4639 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
4640 // seqs_file 2}, boolean[] {
4641 // linkAlignPanel,superposeWithAlignpanel}} from hash
4642 StructureViewerModel jmoldat = structureViewers.get(sviewid);
4643 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
4644 || structureState.isAlignwithAlignPanel());
4647 * Default colour by linked panel to false if not specified (e.g.
4648 * for pre-2.7 projects)
4650 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
4651 colourWithAlignPanel |= structureState.isColourwithAlignPanel();
4652 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
4655 * Default colour by viewer to true if not specified (e.g. for
4658 boolean colourByViewer = jmoldat.isColourByViewer();
4659 colourByViewer &= structureState.isColourByJmol();
4660 jmoldat.setColourByViewer(colourByViewer);
4662 if (jmoldat.getStateData().length() < structureState.getValue()
4663 /*Content()*/.length())
4665 jmoldat.setStateData(structureState.getValue());// Content());
4667 if (pdbid.getFile() != null)
4669 File mapkey = new File(pdbid.getFile());
4670 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
4671 if (seqstrmaps == null)
4673 jmoldat.getFileData().put(mapkey,
4674 seqstrmaps = jmoldat.new StructureData(pdbFile,
4677 if (!seqstrmaps.getSeqList().contains(seq))
4679 seqstrmaps.getSeqList().add(seq);
4685 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");
4686 Console.warn(errorMessage);
4692 // Instantiate the associated structure views
4693 for (Entry<String, StructureViewerModel> entry : structureViewers
4698 createOrLinkStructureViewer(entry, af, ap, jprovider);
4699 } catch (Exception e)
4702 "Error loading structure viewer: " + e.getMessage());
4703 // failed - try the next one
4715 protected void createOrLinkStructureViewer(
4716 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4717 AlignmentPanel ap, jarInputStreamProvider jprovider)
4719 final StructureViewerModel stateData = viewerData.getValue();
4722 * Search for any viewer windows already open from other alignment views
4723 * that exactly match the stored structure state
4725 StructureViewerBase comp = findMatchingViewer(viewerData);
4729 linkStructureViewer(ap, comp, stateData);
4733 String type = stateData.getType();
4736 ViewerType viewerType = ViewerType.valueOf(type);
4737 createStructureViewer(viewerType, viewerData, af, jprovider);
4738 } catch (IllegalArgumentException | NullPointerException e)
4740 // TODO JAL-3619 show error dialog / offer an alternative viewer
4741 Console.error("Invalid structure viewer type: " + type);
4746 * Generates a name for the entry in the project jar file to hold state
4747 * information for a structure viewer
4752 protected String getViewerJarEntryName(String viewId)
4754 return VIEWER_PREFIX + viewId;
4758 * Returns any open frame that matches given structure viewer data. The match
4759 * is based on the unique viewId, or (for older project versions) the frame's
4765 protected StructureViewerBase findMatchingViewer(
4766 Entry<String, StructureViewerModel> viewerData)
4768 final String sviewid = viewerData.getKey();
4769 final StructureViewerModel svattrib = viewerData.getValue();
4770 StructureViewerBase comp = null;
4771 JInternalFrame[] frames = getAllFrames();
4772 for (JInternalFrame frame : frames)
4774 if (frame instanceof StructureViewerBase)
4777 * Post jalview 2.4 schema includes structure view id
4779 if (sviewid != null && ((StructureViewerBase) frame).getViewId()
4782 comp = (StructureViewerBase) frame;
4783 break; // break added in 2.9
4786 * Otherwise test for matching position and size of viewer frame
4788 else if (frame.getX() == svattrib.getX()
4789 && frame.getY() == svattrib.getY()
4790 && frame.getHeight() == svattrib.getHeight()
4791 && frame.getWidth() == svattrib.getWidth())
4793 comp = (StructureViewerBase) frame;
4794 // no break in faint hope of an exact match on viewId
4802 * Link an AlignmentPanel to an existing structure viewer.
4807 * @param useinViewerSuperpos
4808 * @param usetoColourbyseq
4809 * @param viewerColouring
4811 protected void linkStructureViewer(AlignmentPanel ap,
4812 StructureViewerBase viewer, StructureViewerModel stateData)
4814 // NOTE: if the jalview project is part of a shared session then
4815 // view synchronization should/could be done here.
4817 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4818 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4819 final boolean viewerColouring = stateData.isColourByViewer();
4820 Map<File, StructureData> oldFiles = stateData.getFileData();
4823 * Add mapping for sequences in this view to an already open viewer
4825 final AAStructureBindingModel binding = viewer.getBinding();
4826 for (File id : oldFiles.keySet())
4828 // add this and any other pdb files that should be present in the
4830 StructureData filedat = oldFiles.get(id);
4831 String pdbFile = filedat.getFilePath();
4832 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4833 binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE,
4835 binding.addSequenceForStructFile(pdbFile, seq);
4837 // and add the AlignmentPanel's reference to the view panel
4838 viewer.addAlignmentPanel(ap);
4839 if (useinViewerSuperpos)
4841 viewer.useAlignmentPanelForSuperposition(ap);
4845 viewer.excludeAlignmentPanelForSuperposition(ap);
4847 if (usetoColourbyseq)
4849 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4853 viewer.excludeAlignmentPanelForColourbyseq(ap);
4858 * Get all frames within the Desktop.
4862 protected JInternalFrame[] getAllFrames()
4864 JInternalFrame[] frames = null;
4865 // TODO is this necessary - is it safe - risk of hanging?
4870 frames = Desktop.desktop.getAllFrames();
4871 } catch (ArrayIndexOutOfBoundsException e)
4873 // occasional No such child exceptions are thrown here...
4877 } catch (InterruptedException f)
4881 } while (frames == null);
4886 * Answers true if 'version' is equal to or later than 'supported', where each
4887 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4888 * changes. Development and test values for 'version' are leniently treated
4892 * - minimum version we are comparing against
4894 * - version of data being processsed
4895 * @return true if version is equal to or later than supported
4897 public static boolean isVersionStringLaterThan(String supported,
4900 if (supported == null || version == null
4901 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4902 || version.equalsIgnoreCase("Test")
4903 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4905 System.err.println("Assuming project file with "
4906 + (version == null ? "null" : version)
4907 + " is compatible with Jalview version " + supported);
4912 return StringUtils.compareVersions(version, supported, "b") >= 0;
4916 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4918 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4920 if (newStructureViewers != null)
4922 sview.getBinding().setFinishedLoadingFromArchive(false);
4923 newStructureViewers.add(sview);
4927 protected void setLoadingFinishedForNewStructureViewers()
4929 if (newStructureViewers != null)
4931 for (JalviewStructureDisplayI sview : newStructureViewers)
4933 sview.getBinding().setFinishedLoadingFromArchive(true);
4935 newStructureViewers.clear();
4936 newStructureViewers = null;
4940 AlignFrame loadViewport(String file, List<JSeq> JSEQ,
4941 List<SequenceI> hiddenSeqs, AlignmentI al, JalviewModel jm,
4942 Viewport view, String uniqueSeqSetId, String viewId,
4943 List<JvAnnotRow> autoAlan)
4945 AlignFrame af = null;
4946 af = new AlignFrame(al, safeInt(view.getWidth()),
4947 safeInt(view.getHeight()), uniqueSeqSetId, viewId)
4951 // protected void processKeyEvent(java.awt.event.KeyEvent e) {
4952 // System.out.println("Jalview2XML AF " + e);
4953 // super.processKeyEvent(e);
4960 af.setFileName(file, FileFormat.Jalview);
4962 final AlignViewport viewport = af.getViewport();
4963 for (int i = 0; i < JSEQ.size(); i++)
4965 int colour = safeInt(JSEQ.get(i).getColour());
4966 viewport.setSequenceColour(viewport.getAlignment().getSequenceAt(i),
4972 viewport.setColourByReferenceSeq(true);
4973 viewport.setDisplayReferenceSeq(true);
4976 viewport.setGatherViewsHere(safeBoolean(view.isGatheredViews()));
4978 if (view.getSequenceSetId() != null)
4980 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4982 viewport.setSequenceSetId(uniqueSeqSetId);
4985 // propagate shared settings to this new view
4986 viewport.setHistoryList(av.getHistoryList());
4987 viewport.setRedoList(av.getRedoList());
4991 viewportsAdded.put(uniqueSeqSetId, viewport);
4993 // TODO: check if this method can be called repeatedly without
4994 // side-effects if alignpanel already registered.
4995 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4997 // apply Hidden regions to view.
4998 if (hiddenSeqs != null)
5000 for (int s = 0; s < JSEQ.size(); s++)
5002 SequenceGroup hidden = new SequenceGroup();
5003 boolean isRepresentative = false;
5004 for (int r = 0; r < JSEQ.get(s).getHiddenSequences().size(); r++)
5006 isRepresentative = true;
5007 SequenceI sequenceToHide = al
5008 .getSequenceAt(JSEQ.get(s).getHiddenSequences().get(r));
5009 hidden.addSequence(sequenceToHide, false);
5010 // remove from hiddenSeqs list so we don't try to hide it twice
5011 hiddenSeqs.remove(sequenceToHide);
5013 if (isRepresentative)
5015 SequenceI representativeSequence = al.getSequenceAt(s);
5016 hidden.addSequence(representativeSequence, false);
5017 viewport.hideRepSequences(representativeSequence, hidden);
5021 SequenceI[] hseqs = hiddenSeqs
5022 .toArray(new SequenceI[hiddenSeqs.size()]);
5023 viewport.hideSequence(hseqs);
5026 // recover view properties and display parameters
5028 viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
5029 viewport.setAbovePIDThreshold(safeBoolean(view.isPidSelected()));
5030 final int pidThreshold = safeInt(view.getPidThreshold());
5031 viewport.setThreshold(pidThreshold);
5033 viewport.setColourText(safeBoolean(view.isShowColourText()));
5035 viewport.setConservationSelected(
5036 safeBoolean(view.isConservationSelected()));
5037 viewport.setIncrement(safeInt(view.getConsThreshold()));
5038 viewport.setShowJVSuffix(safeBoolean(view.isShowFullId()));
5039 viewport.setRightAlignIds(safeBoolean(view.isRightAlignIds()));
5040 viewport.setFont(new Font(view.getFontName(),
5041 safeInt(view.getFontStyle()), safeInt(view.getFontSize())),
5042 (view.getCharWidth()!=null) ? false : true);
5043 if (view.getCharWidth()!=null)
5045 viewport.setCharWidth(view.getCharWidth());
5046 viewport.setCharHeight(view.getCharHeight());
5048 ViewStyleI vs = viewport.getViewStyle();
5049 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
5050 viewport.setViewStyle(vs);
5051 // TODO: allow custom charWidth/Heights to be restored by updating them
5052 // after setting font - which means set above to false
5053 viewport.setRenderGaps(safeBoolean(view.isRenderGaps()));
5054 viewport.setWrapAlignment(safeBoolean(view.isWrapAlignment()));
5055 viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
5057 viewport.setShowBoxes(safeBoolean(view.isShowBoxes()));
5059 viewport.setShowText(safeBoolean(view.isShowText()));
5061 viewport.setTextColour(new Color(safeInt(view.getTextCol1())));
5062 viewport.setTextColour2(new Color(safeInt(view.getTextCol2())));
5063 viewport.setThresholdTextColour(safeInt(view.getTextColThreshold()));
5064 viewport.setShowUnconserved(view.isShowUnconserved());
5065 viewport.getRanges().setStartRes(safeInt(view.getStartRes()));
5067 if (view.getViewName() != null)
5069 viewport.setViewName(view.getViewName());
5070 af.setInitialTabVisible();
5072 af.setBounds(safeInt(view.getXpos()), safeInt(view.getYpos()),
5073 safeInt(view.getWidth()), safeInt(view.getHeight()));
5074 // startSeq set in af.alignPanel.updateLayout below
5075 af.alignPanel.updateLayout();
5076 ColourSchemeI cs = null;
5077 // apply colourschemes
5078 if (view.getBgColour() != null)
5080 if (view.getBgColour().startsWith("ucs"))
5082 cs = getUserColourScheme(jm, view.getBgColour());
5084 else if (view.getBgColour().startsWith("Annotation"))
5086 AnnotationColourScheme viewAnnColour = view.getAnnotationColours();
5087 cs = constructAnnotationColour(viewAnnColour, af, al, jm, true);
5094 cs = ColourSchemeProperty.getColourScheme(af.getViewport(), al,
5095 view.getBgColour());
5100 * turn off 'alignment colour applies to all groups'
5101 * while restoring global colour scheme
5103 viewport.setColourAppliesToAllGroups(false);
5104 viewport.setGlobalColourScheme(cs);
5105 viewport.getResidueShading().setThreshold(pidThreshold,
5106 view.isIgnoreGapsinConsensus());
5107 viewport.getResidueShading()
5108 .setConsensus(viewport.getSequenceConsensusHash());
5109 if (safeBoolean(view.isConservationSelected()) && cs != null)
5111 viewport.getResidueShading()
5112 .setConservationInc(safeInt(view.getConsThreshold()));
5114 af.changeColour(cs);
5115 viewport.setColourAppliesToAllGroups(true);
5117 viewport.setShowSequenceFeatures(
5118 safeBoolean(view.isShowSequenceFeatures()));
5120 viewport.setCentreColumnLabels(view.isCentreColumnLabels());
5121 viewport.setIgnoreGapsConsensus(view.isIgnoreGapsinConsensus(), null);
5122 viewport.setFollowHighlight(view.isFollowHighlight());
5123 viewport.followSelection = view.isFollowSelection();
5124 viewport.setShowConsensusHistogram(view.isShowConsensusHistogram());
5125 viewport.setShowSequenceLogo(view.isShowSequenceLogo());
5126 viewport.setNormaliseSequenceLogo(view.isNormaliseSequenceLogo());
5127 viewport.setShowDBRefs(safeBoolean(view.isShowDbRefTooltip()));
5128 viewport.setShowNPFeats(safeBoolean(view.isShowNPfeatureTooltip()));
5129 viewport.setShowGroupConsensus(view.isShowGroupConsensus());
5130 viewport.setShowGroupConservation(view.isShowGroupConservation());
5131 viewport.setShowComplementFeatures(view.isShowComplementFeatures());
5132 viewport.setShowComplementFeaturesOnTop(
5133 view.isShowComplementFeaturesOnTop());
5135 // recover feature settings
5136 if (jm.getFeatureSettings() != null)
5138 FeatureRendererModel fr = af.alignPanel.getSeqPanel().seqCanvas
5139 .getFeatureRenderer();
5140 FeaturesDisplayed fdi;
5141 viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
5142 String[] renderOrder = new String[jm.getFeatureSettings().getSetting()
5144 Map<String, FeatureColourI> featureColours = new Hashtable<>();
5145 Map<String, Float> featureOrder = new Hashtable<>();
5147 for (int fs = 0; fs < jm.getFeatureSettings().getSetting()
5150 Setting setting = jm.getFeatureSettings().getSetting().get(fs);
5151 String featureType = setting.getType();
5154 * restore feature filters (if any)
5156 jalview.xml.binding.jalview.FeatureMatcherSet filters = setting
5158 if (filters != null)
5160 FeatureMatcherSetI filter = Jalview2XML.parseFilter(featureType,
5162 if (!filter.isEmpty())
5164 fr.setFeatureFilter(featureType, filter);
5169 * restore feature colour scheme
5171 Color maxColour = new Color(setting.getColour());
5172 if (setting.getMincolour() != null)
5175 * minColour is always set unless a simple colour
5176 * (including for colour by label though it doesn't use it)
5178 Color minColour = new Color(setting.getMincolour().intValue());
5179 Color noValueColour = minColour;
5180 NoValueColour noColour = setting.getNoValueColour();
5181 if (noColour == NoValueColour.NONE)
5183 noValueColour = null;
5185 else if (noColour == NoValueColour.MAX)
5187 noValueColour = maxColour;
5189 float min = safeFloat(safeFloat(setting.getMin()));
5190 float max = setting.getMax() == null ? 1f
5191 : setting.getMax().floatValue();
5192 FeatureColourI gc = new FeatureColour(maxColour, minColour,
5193 maxColour, noValueColour, min, max);
5194 if (setting.getAttributeName().size() > 0)
5196 gc.setAttributeName(setting.getAttributeName().toArray(
5197 new String[setting.getAttributeName().size()]));
5199 if (setting.getThreshold() != null)
5201 gc.setThreshold(setting.getThreshold().floatValue());
5202 int threshstate = safeInt(setting.getThreshstate());
5203 // -1 = None, 0 = Below, 1 = Above threshold
5204 if (threshstate == 0)
5206 gc.setBelowThreshold(true);
5208 else if (threshstate == 1)
5210 gc.setAboveThreshold(true);
5213 gc.setAutoScaled(true); // default
5214 if (setting.isAutoScale() != null)
5216 gc.setAutoScaled(setting.isAutoScale());
5218 if (setting.isColourByLabel() != null)
5220 gc.setColourByLabel(setting.isColourByLabel());
5222 // and put in the feature colour table.
5223 featureColours.put(featureType, gc);
5227 featureColours.put(featureType, new FeatureColour(maxColour));
5229 renderOrder[fs] = featureType;
5230 if (setting.getOrder() != null)
5232 featureOrder.put(featureType, setting.getOrder().floatValue());
5236 featureOrder.put(featureType, Float.valueOf(
5237 fs / jm.getFeatureSettings().getSetting().size()));
5239 if (safeBoolean(setting.isDisplay()))
5241 fdi.setVisible(featureType);
5244 Map<String, Boolean> fgtable = new Hashtable<>();
5245 for (int gs = 0; gs < jm.getFeatureSettings().getGroup().size(); gs++)
5247 Group grp = jm.getFeatureSettings().getGroup().get(gs);
5248 fgtable.put(grp.getName(), Boolean.valueOf(grp.isDisplay()));
5250 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
5251 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
5252 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
5253 FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
5254 fgtable, featureColours, 1.0f, featureOrder);
5255 fr.transferSettings(frs);
5258 if (view.getHiddenColumns().size() > 0)
5260 for (int c = 0; c < view.getHiddenColumns().size(); c++)
5262 final HiddenColumns hc = view.getHiddenColumns().get(c);
5263 viewport.hideColumns(safeInt(hc.getStart()),
5264 safeInt(hc.getEnd()) /* +1 */);
5267 if (view.getCalcIdParam() != null)
5269 for (CalcIdParam calcIdParam : view.getCalcIdParam())
5271 if (calcIdParam != null)
5273 if (recoverCalcIdParam(calcIdParam, viewport))
5278 Console.warn("Couldn't recover parameters for "
5279 + calcIdParam.getCalcId());
5284 af.setMenusFromViewport(viewport);
5285 af.setTitle(view.getTitle());
5286 // TODO: we don't need to do this if the viewport is aready visible.
5288 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
5289 * has a 'cdna/protein complement' view, in which case save it in order to
5290 * populate a SplitFrame once all views have been read in.
5292 String complementaryViewId = view.getComplementId();
5293 if (complementaryViewId == null)
5295 Desktop.addInternalFrame(af, view.getTitle(),
5296 safeInt(view.getWidth()), safeInt(view.getHeight()));
5297 // recompute any autoannotation
5298 af.alignPanel.updateAnnotation(false, true);
5299 reorderAutoannotation(af, al, autoAlan);
5300 af.alignPanel.alignmentChanged();
5304 splitFrameCandidates.put(view, af);
5311 * Reads saved data to restore Colour by Annotation settings
5313 * @param viewAnnColour
5317 * @param checkGroupAnnColour
5320 private ColourSchemeI constructAnnotationColour(
5321 AnnotationColourScheme viewAnnColour, AlignFrame af,
5322 AlignmentI al, JalviewModel model, boolean checkGroupAnnColour)
5324 boolean propagateAnnColour = false;
5325 AlignmentI annAlignment = af != null ? af.getViewport().getAlignment()
5327 if (checkGroupAnnColour && al.getGroups() != null
5328 && al.getGroups().size() > 0)
5330 // pre 2.8.1 behaviour
5331 // check to see if we should transfer annotation colours
5332 propagateAnnColour = true;
5333 for (SequenceGroup sg : al.getGroups())
5335 if (sg.getColourScheme() instanceof AnnotationColourGradient)
5337 propagateAnnColour = false;
5343 * 2.10.2- : saved annotationId is AlignmentAnnotation.annotationId
5345 String annotationId = viewAnnColour.getAnnotation();
5346 AlignmentAnnotation matchedAnnotation = annotationIds.get(annotationId);
5349 * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
5351 if (matchedAnnotation == null
5352 && annAlignment.getAlignmentAnnotation() != null)
5354 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
5357 .equals(annAlignment.getAlignmentAnnotation()[i].label))
5359 matchedAnnotation = annAlignment.getAlignmentAnnotation()[i];
5364 if (matchedAnnotation == null)
5366 System.err.println("Failed to match annotation colour scheme for "
5370 // belt-and-braces create a threshold line if the
5371 // colourscheme needs one but the matchedAnnotation doesn't have one
5372 if (safeInt(viewAnnColour.getAboveThreshold()) != 0
5373 && matchedAnnotation.getThreshold() == null)
5375 matchedAnnotation.setThreshold(
5376 new GraphLine(safeFloat(viewAnnColour.getThreshold()),
5377 "Threshold", Color.black));
5380 AnnotationColourGradient cs = null;
5381 if (viewAnnColour.getColourScheme().equals("None"))
5383 cs = new AnnotationColourGradient(matchedAnnotation,
5384 new Color(safeInt(viewAnnColour.getMinColour())),
5385 new Color(safeInt(viewAnnColour.getMaxColour())),
5386 safeInt(viewAnnColour.getAboveThreshold()));
5388 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
5390 cs = new AnnotationColourGradient(matchedAnnotation,
5391 getUserColourScheme(model, viewAnnColour.getColourScheme()),
5392 safeInt(viewAnnColour.getAboveThreshold()));
5396 cs = new AnnotationColourGradient(matchedAnnotation,
5397 ColourSchemeProperty.getColourScheme(af.getViewport(), al,
5398 viewAnnColour.getColourScheme()),
5399 safeInt(viewAnnColour.getAboveThreshold()));
5402 boolean perSequenceOnly = safeBoolean(viewAnnColour.isPerSequence());
5403 boolean useOriginalColours = safeBoolean(
5404 viewAnnColour.isPredefinedColours());
5405 cs.setSeqAssociated(perSequenceOnly);
5406 cs.setPredefinedColours(useOriginalColours);
5408 if (propagateAnnColour && al.getGroups() != null)
5410 // Also use these settings for all the groups
5411 for (int g = 0; g < al.getGroups().size(); g++)
5413 SequenceGroup sg = al.getGroups().get(g);
5414 if (sg.getGroupColourScheme() == null)
5419 AnnotationColourGradient groupScheme = new AnnotationColourGradient(
5420 matchedAnnotation, sg.getColourScheme(),
5421 safeInt(viewAnnColour.getAboveThreshold()));
5422 sg.setColourScheme(groupScheme);
5423 groupScheme.setSeqAssociated(perSequenceOnly);
5424 groupScheme.setPredefinedColours(useOriginalColours);
5430 private void reorderAutoannotation(AlignFrame af, AlignmentI al,
5431 List<JvAnnotRow> autoAlan)
5433 // copy over visualization settings for autocalculated annotation in the
5435 if (al.getAlignmentAnnotation() != null)
5438 * Kludge for magic autoannotation names (see JAL-811)
5440 String[] magicNames = new String[] { "Consensus", "Quality",
5442 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
5443 Hashtable<String, JvAnnotRow> visan = new Hashtable<>();
5444 for (String nm : magicNames)
5446 visan.put(nm, nullAnnot);
5448 for (JvAnnotRow auan : autoAlan)
5450 visan.put(auan.template.label
5451 + (auan.template.getCalcId() == null ? ""
5452 : "\t" + auan.template.getCalcId()),
5455 int hSize = al.getAlignmentAnnotation().length;
5456 List<JvAnnotRow> reorder = new ArrayList<>();
5457 // work through any autoCalculated annotation already on the view
5458 // removing it if it should be placed in a different location on the
5459 // annotation panel.
5460 List<String> remains = new ArrayList<>(visan.keySet());
5461 for (int h = 0; h < hSize; h++)
5463 jalview.datamodel.AlignmentAnnotation jalan = al
5464 .getAlignmentAnnotation()[h];
5465 if (jalan.autoCalculated)
5468 JvAnnotRow valan = visan.get(k = jalan.label);
5469 if (jalan.getCalcId() != null)
5471 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
5476 // delete the auto calculated row from the alignment
5477 al.deleteAnnotation(jalan, false);
5481 if (valan != nullAnnot)
5483 if (jalan != valan.template)
5485 // newly created autoannotation row instance
5486 // so keep a reference to the visible annotation row
5487 // and copy over all relevant attributes
5488 if (valan.template.graphHeight >= 0)
5491 jalan.graphHeight = valan.template.graphHeight;
5493 jalan.visible = valan.template.visible;
5495 reorder.add(new JvAnnotRow(valan.order, jalan));
5500 // Add any (possibly stale) autocalculated rows that were not appended to
5501 // the view during construction
5502 for (String other : remains)
5504 JvAnnotRow othera = visan.get(other);
5505 if (othera != nullAnnot && othera.template.getCalcId() != null
5506 && othera.template.getCalcId().length() > 0)
5508 reorder.add(othera);
5511 // now put the automatic annotation in its correct place
5512 int s = 0, srt[] = new int[reorder.size()];
5513 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
5514 for (JvAnnotRow jvar : reorder)
5517 srt[s++] = jvar.order;
5520 jalview.util.QuickSort.sort(srt, rws);
5521 // and re-insert the annotation at its correct position
5522 for (JvAnnotRow jvar : rws)
5524 al.addAnnotation(jvar.template, jvar.order);
5526 af.alignPanel.adjustAnnotationHeight();
5530 Hashtable skipList = null;
5533 * TODO remove this method
5536 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
5537 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
5538 * throw new Error("Implementation Error. No skipList defined for this
5539 * Jalview2XML instance."); } return (AlignFrame)
5540 * skipList.get(view.getSequenceSetId()); }
5544 * Check if the Jalview view contained in object should be skipped or not.
5547 * @return true if view's sequenceSetId is a key in skipList
5549 private boolean skipViewport(JalviewModel object)
5551 if (skipList == null)
5555 String id = object.getViewport().get(0).getSequenceSetId();
5556 if (skipList.containsKey(id))
5558 Console.debug("Skipping seuqence set id " + id);
5564 public void addToSkipList(AlignFrame af)
5566 if (skipList == null)
5568 skipList = new Hashtable();
5570 skipList.put(af.getViewport().getSequenceSetId(), af);
5573 public void clearSkipList()
5575 if (skipList != null)
5582 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
5583 boolean ignoreUnrefed, String uniqueSeqSetId)
5585 jalview.datamodel.AlignmentI ds = getDatasetFor(
5586 vamsasSet.getDatasetId());
5587 AlignmentI xtant_ds = ds;
5588 if (xtant_ds == null)
5590 // good chance we are about to create a new dataset, but check if we've
5591 // seen some of the dataset sequence IDs before.
5592 // TODO: skip this check if we are working with project generated by
5593 // version 2.11 or later
5594 xtant_ds = checkIfHasDataset(vamsasSet.getSequence());
5595 if (xtant_ds != null)
5598 addDatasetRef(vamsasSet.getDatasetId(), ds);
5601 Vector<SequenceI> dseqs = null;
5604 // recovering an alignment View
5605 AlignmentI seqSetDS = getDatasetFor(UNIQSEQSETID + uniqueSeqSetId);
5606 if (seqSetDS != null)
5608 if (ds != null && ds != seqSetDS)
5611 "JAL-3171 regression: Overwriting a dataset reference for an alignment"
5612 + " - CDS/Protein crossreference data may be lost");
5613 if (xtant_ds != null)
5615 // This can only happen if the unique sequence set ID was bound to a
5616 // dataset that did not contain any of the sequences in the view
5617 // currently being restored.
5619 "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.");
5623 addDatasetRef(vamsasSet.getDatasetId(), ds);
5628 // try even harder to restore dataset
5629 AlignmentI xtantDS = checkIfHasDataset(vamsasSet.getSequence());
5630 // create a list of new dataset sequences
5631 dseqs = new Vector<>();
5633 for (int i = 0, iSize = vamsasSet.getSequence().size(); i < iSize; i++)
5635 Sequence vamsasSeq = vamsasSet.getSequence().get(i);
5636 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
5638 // create a new dataset
5641 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
5642 dseqs.copyInto(dsseqs);
5643 ds = new jalview.datamodel.Alignment(dsseqs);
5644 Console.debug("Created new dataset " + vamsasSet.getDatasetId()
5645 + " for alignment " + System.identityHashCode(al));
5646 addDatasetRef(vamsasSet.getDatasetId(), ds);
5648 // set the dataset for the newly imported alignment.
5649 if (al.getDataset() == null && !ignoreUnrefed)
5652 // register dataset for the alignment's uniqueSeqSetId for legacy projects
5653 addDatasetRef(UNIQSEQSETID + uniqueSeqSetId, ds);
5655 updateSeqDatasetBinding(vamsasSet.getSequence(), ds);
5659 * XML dataset sequence ID to materialised dataset reference
5661 HashMap<String, AlignmentI> seqToDataset = new HashMap<>();
5664 * @return the first materialised dataset reference containing a dataset
5665 * sequence referenced in the given view
5667 * - sequences from the view
5669 AlignmentI checkIfHasDataset(List<Sequence> list)
5671 for (Sequence restoredSeq : list)
5673 AlignmentI datasetFor = seqToDataset.get(restoredSeq.getDsseqid());
5674 if (datasetFor != null)
5683 * Register ds as the containing dataset for the dataset sequences referenced
5684 * by sequences in list
5687 * - sequences in a view
5690 void updateSeqDatasetBinding(List<Sequence> list, AlignmentI ds)
5692 for (Sequence restoredSeq : list)
5694 AlignmentI prevDS = seqToDataset.put(restoredSeq.getDsseqid(), ds);
5695 if (prevDS != null && prevDS != ds)
5697 Console.warn("Dataset sequence appears in many datasets: "
5698 + restoredSeq.getDsseqid());
5699 // TODO: try to merge!
5707 * sequence definition to create/merge dataset sequence for
5711 * vector to add new dataset sequence to
5712 * @param ignoreUnrefed
5713 * - when true, don't create new sequences from vamsasSeq if it's id
5714 * doesn't already have an asssociated Jalview sequence.
5716 * - used to reorder the sequence in the alignment according to the
5717 * vamsasSeq array ordering, to preserve ordering of dataset
5719 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
5720 AlignmentI ds, Vector<SequenceI> dseqs, boolean ignoreUnrefed,
5723 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
5725 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
5726 boolean reorder = false;
5727 SequenceI dsq = null;
5728 if (sq != null && sq.getDatasetSequence() != null)
5730 dsq = sq.getDatasetSequence();
5736 if (sq == null && ignoreUnrefed)
5740 String sqid = vamsasSeq.getDsseqid();
5743 // need to create or add a new dataset sequence reference to this sequence
5746 dsq = seqRefIds.get(sqid);
5751 // make a new dataset sequence
5752 dsq = sq.createDatasetSequence();
5755 // make up a new dataset reference for this sequence
5756 sqid = seqHash(dsq);
5758 dsq.setVamsasId(uniqueSetSuffix + sqid);
5759 seqRefIds.put(sqid, dsq);
5764 dseqs.addElement(dsq);
5769 ds.addSequence(dsq);
5775 { // make this dataset sequence sq's dataset sequence
5776 sq.setDatasetSequence(dsq);
5777 // and update the current dataset alignment
5782 if (!dseqs.contains(dsq))
5789 if (ds.findIndex(dsq) < 0)
5791 ds.addSequence(dsq);
5798 // TODO: refactor this as a merge dataset sequence function
5799 // now check that sq (the dataset sequence) sequence really is the union of
5800 // all references to it
5801 // boolean pre = sq.getStart() < dsq.getStart();
5802 // boolean post = sq.getEnd() > dsq.getEnd();
5806 // StringBuffer sb = new StringBuffer();
5807 String newres = jalview.analysis.AlignSeq.extractGaps(
5808 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
5809 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
5810 && newres.length() > dsq.getLength())
5812 // Update with the longer sequence.
5816 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
5817 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
5818 * sb.append(newres.substring(newres.length() - sq.getEnd() -
5819 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
5821 dsq.setSequence(newres);
5823 // TODO: merges will never happen if we 'know' we have the real dataset
5824 // sequence - this should be detected when id==dssid
5826 "DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
5827 // + (pre ? "prepended" : "") + " "
5828 // + (post ? "appended" : ""));
5833 // sequence refs are identical. We may need to update the existing dataset
5834 // alignment with this one, though.
5835 if (ds != null && dseqs == null)
5837 int opos = ds.findIndex(dsq);
5838 SequenceI tseq = null;
5839 if (opos != -1 && vseqpos != opos)
5841 // remove from old position
5842 ds.deleteSequence(dsq);
5844 if (vseqpos < ds.getHeight())
5846 if (vseqpos != opos)
5848 // save sequence at destination position
5849 tseq = ds.getSequenceAt(vseqpos);
5850 ds.replaceSequenceAt(vseqpos, dsq);
5851 ds.addSequence(tseq);
5856 ds.addSequence(dsq);
5863 * TODO use AlignmentI here and in related methods - needs
5864 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
5866 Hashtable<String, AlignmentI> datasetIds = null;
5868 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
5870 private AlignmentI getDatasetFor(String datasetId)
5872 if (datasetIds == null)
5874 datasetIds = new Hashtable<>();
5877 if (datasetIds.containsKey(datasetId))
5879 return datasetIds.get(datasetId);
5884 private void addDatasetRef(String datasetId, AlignmentI dataset)
5886 if (datasetIds == null)
5888 datasetIds = new Hashtable<>();
5890 datasetIds.put(datasetId, dataset);
5894 * make a new dataset ID for this jalview dataset alignment
5899 private String getDatasetIdRef(AlignmentI dataset)
5901 if (dataset.getDataset() != null)
5904 "Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
5906 String datasetId = makeHashCode(dataset, null);
5907 if (datasetId == null)
5909 // make a new datasetId and record it
5910 if (dataset2Ids == null)
5912 dataset2Ids = new IdentityHashMap<>();
5916 datasetId = dataset2Ids.get(dataset);
5918 if (datasetId == null)
5920 datasetId = "ds" + dataset2Ids.size() + 1;
5921 dataset2Ids.put(dataset, datasetId);
5928 * Add any saved DBRefEntry's to the sequence. An entry flagged as 'locus' is
5929 * constructed as a special subclass GeneLocus.
5931 * @param datasetSequence
5934 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5936 for (int d = 0; d < sequence.getDBRef().size(); d++)
5938 DBRef dr = sequence.getDBRef().get(d);
5942 entry = new GeneLocus(dr.getSource(), dr.getVersion(),
5943 dr.getAccessionId());
5947 entry = new DBRefEntry(dr.getSource(), dr.getVersion(),
5948 dr.getAccessionId());
5950 if (dr.getMapping() != null)
5952 entry.setMap(addMapping(dr.getMapping()));
5954 entry.setCanonical(dr.isCanonical());
5955 datasetSequence.addDBRef(entry);
5959 private jalview.datamodel.Mapping addMapping(Mapping m)
5961 SequenceI dsto = null;
5962 // Mapping m = dr.getMapping();
5963 int fr[] = new int[m.getMapListFrom().size() * 2];
5964 Iterator<MapListFrom> from = m.getMapListFrom().iterator();// enumerateMapListFrom();
5965 for (int _i = 0; from.hasNext(); _i += 2)
5967 MapListFrom mf = from.next();
5968 fr[_i] = mf.getStart();
5969 fr[_i + 1] = mf.getEnd();
5971 int fto[] = new int[m.getMapListTo().size() * 2];
5972 Iterator<MapListTo> to = m.getMapListTo().iterator();// enumerateMapListTo();
5973 for (int _i = 0; to.hasNext(); _i += 2)
5975 MapListTo mf = to.next();
5976 fto[_i] = mf.getStart();
5977 fto[_i + 1] = mf.getEnd();
5979 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto, fr,
5980 fto, m.getMapFromUnit().intValue(),
5981 m.getMapToUnit().intValue());
5984 * (optional) choice of dseqFor or Sequence
5986 if (m.getDseqFor() != null)
5988 String dsfor = m.getDseqFor();
5989 if (seqRefIds.containsKey(dsfor))
5994 jmap.setTo(seqRefIds.get(dsfor));
5998 frefedSequence.add(newMappingRef(dsfor, jmap));
6001 else if (m.getSequence() != null)
6004 * local sequence definition
6006 Sequence ms = m.getSequence();
6007 SequenceI djs = null;
6008 String sqid = ms.getDsseqid();
6009 if (sqid != null && sqid.length() > 0)
6012 * recover dataset sequence
6014 djs = seqRefIds.get(sqid);
6019 "Warning - making up dataset sequence id for DbRef sequence map reference");
6020 sqid = ((Object) ms).toString(); // make up a new hascode for
6021 // undefined dataset sequence hash
6022 // (unlikely to happen)
6028 * make a new dataset sequence and add it to refIds hash
6030 djs = new jalview.datamodel.Sequence(ms.getName(),
6032 djs.setStart(jmap.getMap().getToLowest());
6033 djs.setEnd(jmap.getMap().getToHighest());
6034 djs.setVamsasId(uniqueSetSuffix + sqid);
6036 incompleteSeqs.put(sqid, djs);
6037 seqRefIds.put(sqid, djs);
6040 Console.debug("about to recurse on addDBRefs.");
6049 * Provides a 'copy' of an alignment view (on action New View) by 'saving' the
6050 * view as XML (but not to file), and then reloading it
6055 public AlignmentPanel copyAlignPanel(AlignmentPanel ap)
6058 JalviewModel jm = saveState(ap, null, null, null);
6061 jm.getVamsasModel().getSequenceSet().get(0).getDatasetId(),
6062 ap.getAlignment().getDataset());
6064 uniqueSetSuffix = "";
6065 // jm.getJalviewModelSequence().getViewport(0).setId(null);
6066 jm.getViewport().get(0).setId(null);
6067 // we don't overwrite the view we just copied
6069 if (this.frefedSequence == null)
6071 frefedSequence = new Vector<>();
6074 viewportsAdded.clear();
6076 AlignFrame af = loadFromObject(jm, null, false, null);
6077 af.getAlignPanels().clear();
6078 af.closeMenuItem_actionPerformed(true);
6081 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
6082 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
6083 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
6084 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
6085 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
6088 return af.alignPanel;
6091 private Hashtable jvids2vobj;
6094 * set the object to ID mapping tables used to write/recover objects and XML
6095 * ID strings for the jalview project. If external tables are provided then
6096 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
6097 * object goes out of scope. - also populates the datasetIds hashtable with
6098 * alignment objects containing dataset sequences
6101 * Map from ID strings to jalview datamodel
6103 * Map from jalview datamodel to ID strings
6107 public void setObjectMappingTables(Hashtable vobj2jv,
6108 IdentityHashMap jv2vobj)
6110 this.jv2vobj = jv2vobj;
6111 this.vobj2jv = vobj2jv;
6112 Iterator ds = jv2vobj.keySet().iterator();
6114 while (ds.hasNext())
6116 Object jvobj = ds.next();
6117 id = jv2vobj.get(jvobj).toString();
6118 if (jvobj instanceof jalview.datamodel.Alignment)
6120 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
6122 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
6125 else if (jvobj instanceof jalview.datamodel.Sequence)
6127 // register sequence object so the XML parser can recover it.
6128 if (seqRefIds == null)
6130 seqRefIds = new HashMap<>();
6132 if (seqsToIds == null)
6134 seqsToIds = new IdentityHashMap<>();
6136 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
6137 seqsToIds.put((SequenceI) jvobj, id);
6139 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
6142 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
6143 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
6144 if (jvann.annotationId == null)
6146 jvann.annotationId = anid;
6148 if (!jvann.annotationId.equals(anid))
6150 // TODO verify that this is the correct behaviour
6151 Console.warn("Overriding Annotation ID for " + anid
6152 + " from different id : " + jvann.annotationId);
6153 jvann.annotationId = anid;
6156 else if (jvobj instanceof String)
6158 if (jvids2vobj == null)
6160 jvids2vobj = new Hashtable();
6161 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
6166 Console.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
6172 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
6173 * objects created from the project archive. If string is null (default for
6174 * construction) then suffix will be set automatically.
6178 public void setUniqueSetSuffix(String string)
6180 uniqueSetSuffix = string;
6185 * uses skipList2 as the skipList for skipping views on sequence sets
6186 * associated with keys in the skipList
6190 public void setSkipList(Hashtable skipList2)
6192 skipList = skipList2;
6196 * Reads the jar entry of given name and returns its contents, or null if the
6197 * entry is not found.
6200 * @param jarEntryName
6203 protected String readJarEntry(jarInputStreamProvider jprovider,
6204 String jarEntryName)
6206 String result = null;
6207 BufferedReader in = null;
6212 * Reopen the jar input stream and traverse its entries to find a matching
6215 JarInputStream jin = jprovider.getJarInputStream();
6216 JarEntry entry = null;
6219 entry = jin.getNextJarEntry();
6220 } while (entry != null && !entry.getName().equals(jarEntryName));
6224 StringBuilder out = new StringBuilder(256);
6225 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
6228 while ((data = in.readLine()) != null)
6232 result = out.toString();
6237 "Couldn't find entry in Jalview Jar for " + jarEntryName);
6239 } catch (Exception ex)
6241 ex.printStackTrace();
6249 } catch (IOException e)
6260 * Returns an incrementing counter (0, 1, 2...)
6264 private synchronized int nextCounter()
6270 * Loads any saved PCA viewers
6275 protected void loadPCAViewers(JalviewModel model, AlignmentPanel ap)
6279 List<PcaViewer> pcaviewers = model.getPcaViewer();
6280 for (PcaViewer viewer : pcaviewers)
6282 String modelName = viewer.getScoreModelName();
6283 SimilarityParamsI params = new SimilarityParams(
6284 viewer.isIncludeGappedColumns(), viewer.isMatchGaps(),
6285 viewer.isIncludeGaps(),
6286 viewer.isDenominateByShortestLength());
6289 * create the panel (without computing the PCA)
6291 PCAPanel panel = new PCAPanel(ap, modelName, params);
6293 panel.setTitle(viewer.getTitle());
6294 panel.setBounds(new Rectangle(viewer.getXpos(), viewer.getYpos(),
6295 viewer.getWidth(), viewer.getHeight()));
6297 boolean showLabels = viewer.isShowLabels();
6298 panel.setShowLabels(showLabels);
6299 panel.getRotatableCanvas().setShowLabels(showLabels);
6300 panel.getRotatableCanvas()
6301 .setBgColour(new Color(viewer.getBgColour()));
6302 panel.getRotatableCanvas()
6303 .setApplyToAllViews(viewer.isLinkToAllViews());
6306 * load PCA output data
6308 ScoreModelI scoreModel = ScoreModels.getInstance()
6309 .getScoreModel(modelName, ap);
6310 PCA pca = new PCA(null, scoreModel, params);
6311 PcaDataType pcaData = viewer.getPcaData();
6313 MatrixI pairwise = loadDoubleMatrix(pcaData.getPairwiseMatrix());
6314 pca.setPairwiseScores(pairwise);
6316 MatrixI triDiag = loadDoubleMatrix(pcaData.getTridiagonalMatrix());
6317 pca.setTridiagonal(triDiag);
6319 MatrixI result = loadDoubleMatrix(pcaData.getEigenMatrix());
6320 pca.setEigenmatrix(result);
6322 panel.getPcaModel().setPCA(pca);
6325 * we haven't saved the input data! (JAL-2647 to do)
6327 panel.setInputData(null);
6330 * add the sequence points for the PCA display
6332 List<jalview.datamodel.SequencePoint> seqPoints = new ArrayList<>();
6333 for (SequencePoint sp : viewer.getSequencePoint())
6335 String seqId = sp.getSequenceRef();
6336 SequenceI seq = seqRefIds.get(seqId);
6339 throw new IllegalStateException(
6340 "Unmatched seqref for PCA: " + seqId);
6342 Point pt = new Point(sp.getXPos(), sp.getYPos(), sp.getZPos());
6343 jalview.datamodel.SequencePoint seqPoint = new jalview.datamodel.SequencePoint(
6345 seqPoints.add(seqPoint);
6347 panel.getRotatableCanvas().setPoints(seqPoints, seqPoints.size());
6350 * set min-max ranges and scale after setPoints (which recomputes them)
6352 panel.getRotatableCanvas().setScaleFactor(viewer.getScaleFactor());
6353 SeqPointMin spMin = viewer.getSeqPointMin();
6354 float[] min = new float[] { spMin.getXPos(), spMin.getYPos(),
6356 SeqPointMax spMax = viewer.getSeqPointMax();
6357 float[] max = new float[] { spMax.getXPos(), spMax.getYPos(),
6359 panel.getRotatableCanvas().setSeqMinMax(min, max);
6361 // todo: hold points list in PCAModel only
6362 panel.getPcaModel().setSequencePoints(seqPoints);
6364 panel.setSelectedDimensionIndex(viewer.getXDim(), X);
6365 panel.setSelectedDimensionIndex(viewer.getYDim(), Y);
6366 panel.setSelectedDimensionIndex(viewer.getZDim(), Z);
6368 // is this duplication needed?
6369 panel.setTop(seqPoints.size() - 1);
6370 panel.getPcaModel().setTop(seqPoints.size() - 1);
6373 * add the axes' end points for the display
6375 for (int i = 0; i < 3; i++)
6377 Axis axis = viewer.getAxis().get(i);
6378 panel.getRotatableCanvas().getAxisEndPoints()[i] = new Point(
6379 axis.getXPos(), axis.getYPos(), axis.getZPos());
6382 Desktop.addInternalFrame(panel, MessageManager.formatMessage(
6383 "label.calc_title", "PCA", modelName), 475, 450);
6385 } catch (Exception ex)
6387 Console.error("Error loading PCA: " + ex.toString());
6392 * Creates a new structure viewer window
6399 protected void createStructureViewer(ViewerType viewerType,
6400 final Entry<String, StructureViewerModel> viewerData,
6401 AlignFrame af, jarInputStreamProvider jprovider)
6403 final StructureViewerModel viewerModel = viewerData.getValue();
6404 String sessionFilePath = null;
6406 if (viewerType == ViewerType.JMOL)
6408 sessionFilePath = rewriteJmolSession(viewerModel, jprovider);
6412 String viewerJarEntryName = getViewerJarEntryName(
6413 viewerModel.getViewId());
6414 sessionFilePath = copyJarEntry(jprovider, viewerJarEntryName,
6415 "viewerSession", ".tmp");
6417 final String sessionPath = sessionFilePath;
6418 final String sviewid = viewerData.getKey();
6421 SwingUtilities.invokeAndWait(new Runnable()
6426 JalviewStructureDisplayI sview = null;
6429 sview = StructureViewer.createView(viewerType, af.alignPanel,
6430 viewerModel, sessionPath, sviewid);
6431 addNewStructureViewer(sview);
6432 } catch (OutOfMemoryError ex)
6434 new OOMWarning("Restoring structure view for " + viewerType,
6435 (OutOfMemoryError) ex.getCause());
6436 if (sview != null && sview.isVisible())
6438 sview.closeViewer(false);
6439 sview.setVisible(false);
6445 } catch (InvocationTargetException | InterruptedException ex)
6447 Console.warn("Unexpected error when opening " + viewerType
6448 + " structure viewer", ex);
6453 * Rewrites a Jmol session script, saves it to a temporary file, and returns
6454 * the path of the file. "load file" commands are rewritten to change the
6455 * original PDB file names to those created as the Jalview project is loaded.
6461 private String rewriteJmolSession(StructureViewerModel svattrib,
6462 jarInputStreamProvider jprovider)
6464 String state = svattrib.getStateData(); // Jalview < 2.9
6465 if (state == null || state.isEmpty()) // Jalview >= 2.9
6467 String jarEntryName = getViewerJarEntryName(svattrib.getViewId());
6468 state = readJarEntry(jprovider, jarEntryName);
6470 // TODO or simpler? for each key in oldFiles,
6471 // replace key.getPath() in state with oldFiles.get(key).getFilePath()
6472 // (allowing for different path escapings)
6473 StringBuilder rewritten = new StringBuilder(state.length());
6474 int cp = 0, ncp, ecp;
6475 Map<File, StructureData> oldFiles = svattrib.getFileData();
6476 while ((ncp = state.indexOf("load ", cp)) > -1)
6480 // look for next filename in load statement
6481 rewritten.append(state.substring(cp,
6482 ncp = (state.indexOf("\"", ncp + 1) + 1)));
6483 String oldfilenam = state.substring(ncp,
6484 ecp = state.indexOf("\"", ncp));
6485 // recover the new mapping data for this old filename
6486 // have to normalize filename - since Jmol and jalview do
6487 // filename translation differently.
6488 StructureData filedat = oldFiles.get(new File(oldfilenam));
6489 if (filedat == null)
6491 String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\");
6492 filedat = oldFiles.get(new File(reformatedOldFilename));
6494 rewritten.append(Platform.escapeBackslashes(filedat.getFilePath()));
6495 rewritten.append("\"");
6496 cp = ecp + 1; // advance beyond last \" and set cursor so we can
6497 // look for next file statement.
6498 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
6502 // just append rest of state
6503 rewritten.append(state.substring(cp));
6507 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
6508 rewritten = new StringBuilder(state);
6509 rewritten.append("; load append ");
6510 for (File id : oldFiles.keySet())
6512 // add pdb files that should be present in the viewer
6513 StructureData filedat = oldFiles.get(id);
6514 rewritten.append(" \"").append(filedat.getFilePath()).append("\"");
6516 rewritten.append(";");
6519 if (rewritten.length() == 0)
6523 final String history = "history = ";
6524 int historyIndex = rewritten.indexOf(history);
6525 if (historyIndex > -1)
6528 * change "history = [true|false];" to "history = [1|0];"
6530 historyIndex += history.length();
6531 String val = rewritten.substring(historyIndex, historyIndex + 5);
6532 if (val.startsWith("true"))
6534 rewritten.replace(historyIndex, historyIndex + 4, "1");
6536 else if (val.startsWith("false"))
6538 rewritten.replace(historyIndex, historyIndex + 5, "0");
6544 File tmp = File.createTempFile("viewerSession", ".tmp");
6545 try (OutputStream os = new FileOutputStream(tmp))
6547 InputStream is = new ByteArrayInputStream(
6548 rewritten.toString().getBytes());
6550 return tmp.getAbsolutePath();
6552 } catch (IOException e)
6554 Console.error("Error restoring Jmol session: " + e.toString());
6560 * Populates an XML model of the feature colour scheme for one feature type
6562 * @param featureType
6566 public static Colour marshalColour(String featureType,
6567 FeatureColourI fcol)
6569 Colour col = new Colour();
6570 if (fcol.isSimpleColour())
6572 col.setRGB(Format.getHexString(fcol.getColour()));
6576 col.setRGB(Format.getHexString(fcol.getMaxColour()));
6577 col.setMin(fcol.getMin());
6578 col.setMax(fcol.getMax());
6579 col.setMinRGB(jalview.util.Format.getHexString(fcol.getMinColour()));
6580 col.setAutoScale(fcol.isAutoScaled());
6581 col.setThreshold(fcol.getThreshold());
6582 col.setColourByLabel(fcol.isColourByLabel());
6583 col.setThreshType(fcol.isAboveThreshold() ? ThresholdType.ABOVE
6584 : (fcol.isBelowThreshold() ? ThresholdType.BELOW
6585 : ThresholdType.NONE));
6586 if (fcol.isColourByAttribute())
6588 final String[] attName = fcol.getAttributeName();
6589 col.getAttributeName().add(attName[0]);
6590 if (attName.length > 1)
6592 col.getAttributeName().add(attName[1]);
6595 Color noColour = fcol.getNoColour();
6596 if (noColour == null)
6598 col.setNoValueColour(NoValueColour.NONE);
6600 else if (noColour == fcol.getMaxColour())
6602 col.setNoValueColour(NoValueColour.MAX);
6606 col.setNoValueColour(NoValueColour.MIN);
6609 col.setName(featureType);
6614 * Populates an XML model of the feature filter(s) for one feature type
6616 * @param firstMatcher
6617 * the first (or only) match condition)
6619 * remaining match conditions (if any)
6621 * if true, conditions are and-ed, else or-ed
6623 public static jalview.xml.binding.jalview.FeatureMatcherSet marshalFilter(
6624 FeatureMatcherI firstMatcher, Iterator<FeatureMatcherI> filters,
6627 jalview.xml.binding.jalview.FeatureMatcherSet result = new jalview.xml.binding.jalview.FeatureMatcherSet();
6629 if (filters.hasNext())
6634 CompoundMatcher compound = new CompoundMatcher();
6635 compound.setAnd(and);
6636 jalview.xml.binding.jalview.FeatureMatcherSet matcher1 = marshalFilter(
6637 firstMatcher, Collections.emptyIterator(), and);
6638 // compound.addMatcherSet(matcher1);
6639 compound.getMatcherSet().add(matcher1);
6640 FeatureMatcherI nextMatcher = filters.next();
6641 jalview.xml.binding.jalview.FeatureMatcherSet matcher2 = marshalFilter(
6642 nextMatcher, filters, and);
6643 // compound.addMatcherSet(matcher2);
6644 compound.getMatcherSet().add(matcher2);
6645 result.setCompoundMatcher(compound);
6650 * single condition matcher
6652 // MatchCondition matcherModel = new MatchCondition();
6653 jalview.xml.binding.jalview.FeatureMatcher matcherModel = new jalview.xml.binding.jalview.FeatureMatcher();
6654 matcherModel.setCondition(
6655 firstMatcher.getMatcher().getCondition().getStableName());
6656 matcherModel.setValue(firstMatcher.getMatcher().getPattern());
6657 if (firstMatcher.isByAttribute())
6659 matcherModel.setBy(FilterBy.BY_ATTRIBUTE);
6660 // matcherModel.setAttributeName(firstMatcher.getAttribute());
6661 String[] attName = firstMatcher.getAttribute();
6662 matcherModel.getAttributeName().add(attName[0]); // attribute
6663 if (attName.length > 1)
6665 matcherModel.getAttributeName().add(attName[1]); // sub-attribute
6668 else if (firstMatcher.isByLabel())
6670 matcherModel.setBy(FilterBy.BY_LABEL);
6672 else if (firstMatcher.isByScore())
6674 matcherModel.setBy(FilterBy.BY_SCORE);
6676 result.setMatchCondition(matcherModel);
6683 * Loads one XML model of a feature filter to a Jalview object
6685 * @param featureType
6686 * @param matcherSetModel
6689 public static FeatureMatcherSetI parseFilter(String featureType,
6690 jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel)
6692 FeatureMatcherSetI result = new FeatureMatcherSet();
6695 parseFilterConditions(result, matcherSetModel, true);
6696 } catch (IllegalStateException e)
6698 // mixing AND and OR conditions perhaps
6700 String.format("Error reading filter conditions for '%s': %s",
6701 featureType, e.getMessage()));
6702 // return as much as was parsed up to the error
6709 * Adds feature match conditions to matcherSet as unmarshalled from XML
6710 * (possibly recursively for compound conditions)
6713 * @param matcherSetModel
6715 * if true, multiple conditions are AND-ed, else they are OR-ed
6716 * @throws IllegalStateException
6717 * if AND and OR conditions are mixed
6719 protected static void parseFilterConditions(FeatureMatcherSetI matcherSet,
6720 jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel,
6723 jalview.xml.binding.jalview.FeatureMatcher mc = matcherSetModel
6724 .getMatchCondition();
6730 FilterBy filterBy = mc.getBy();
6731 Condition cond = Condition.fromString(mc.getCondition());
6732 String pattern = mc.getValue();
6733 FeatureMatcherI matchCondition = null;
6734 if (filterBy == FilterBy.BY_LABEL)
6736 matchCondition = FeatureMatcher.byLabel(cond, pattern);
6738 else if (filterBy == FilterBy.BY_SCORE)
6740 matchCondition = FeatureMatcher.byScore(cond, pattern);
6743 else if (filterBy == FilterBy.BY_ATTRIBUTE)
6745 final List<String> attributeName = mc.getAttributeName();
6746 String[] attNames = attributeName
6747 .toArray(new String[attributeName.size()]);
6748 matchCondition = FeatureMatcher.byAttribute(cond, pattern,
6753 * note this throws IllegalStateException if AND-ing to a
6754 * previously OR-ed compound condition, or vice versa
6758 matcherSet.and(matchCondition);
6762 matcherSet.or(matchCondition);
6768 * compound condition
6770 List<jalview.xml.binding.jalview.FeatureMatcherSet> matchers = matcherSetModel
6771 .getCompoundMatcher().getMatcherSet();
6772 boolean anded = matcherSetModel.getCompoundMatcher().isAnd();
6773 if (matchers.size() == 2)
6775 parseFilterConditions(matcherSet, matchers.get(0), anded);
6776 parseFilterConditions(matcherSet, matchers.get(1), anded);
6780 System.err.println("Malformed compound filter condition");
6786 * Loads one XML model of a feature colour to a Jalview object
6788 * @param colourModel
6791 public static FeatureColourI parseColour(Colour colourModel)
6793 FeatureColourI colour = null;
6795 if (colourModel.getMax() != null)
6797 Color mincol = null;
6798 Color maxcol = null;
6799 Color noValueColour = null;
6803 mincol = new Color(Integer.parseInt(colourModel.getMinRGB(), 16));
6804 maxcol = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6805 } catch (Exception e)
6807 Console.warn("Couldn't parse out graduated feature color.", e);
6810 NoValueColour noCol = colourModel.getNoValueColour();
6811 if (noCol == NoValueColour.MIN)
6813 noValueColour = mincol;
6815 else if (noCol == NoValueColour.MAX)
6817 noValueColour = maxcol;
6820 colour = new FeatureColour(maxcol, mincol, maxcol, noValueColour,
6821 safeFloat(colourModel.getMin()),
6822 safeFloat(colourModel.getMax()));
6823 final List<String> attributeName = colourModel.getAttributeName();
6824 String[] attributes = attributeName
6825 .toArray(new String[attributeName.size()]);
6826 if (attributes != null && attributes.length > 0)
6828 colour.setAttributeName(attributes);
6830 if (colourModel.isAutoScale() != null)
6832 colour.setAutoScaled(colourModel.isAutoScale().booleanValue());
6834 if (colourModel.isColourByLabel() != null)
6836 colour.setColourByLabel(
6837 colourModel.isColourByLabel().booleanValue());
6839 if (colourModel.getThreshold() != null)
6841 colour.setThreshold(colourModel.getThreshold().floatValue());
6843 ThresholdType ttyp = colourModel.getThreshType();
6844 if (ttyp == ThresholdType.ABOVE)
6846 colour.setAboveThreshold(true);
6848 else if (ttyp == ThresholdType.BELOW)
6850 colour.setBelowThreshold(true);
6855 Color color = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6856 colour = new FeatureColour(color);
6862 public static void setStateSavedUpToDate(boolean s)
6864 Console.debug("Setting overall stateSavedUpToDate to " + s);
6865 stateSavedUpToDate = s;
6868 public static boolean stateSavedUpToDate()
6870 Console.debug("Returning overall stateSavedUpToDate value: "
6871 + stateSavedUpToDate);
6872 return stateSavedUpToDate;
6875 public static boolean allSavedUpToDate()
6877 if (stateSavedUpToDate()) // nothing happened since last project save
6880 AlignFrame[] frames = Desktop.getAlignFrames();
6883 for (int i = 0; i < frames.length; i++)
6885 if (frames[i] == null)
6887 if (!frames[i].getViewport().savedUpToDate())
6888 return false; // at least one alignment is not individually saved
6894 // used for debugging and tests
6895 private static int debugDelaySave = 20;
6897 public static void setDebugDelaySave(int n)