2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
21 package jalview.project;
23 import static jalview.math.RotatableMatrix.Axis.X;
24 import static jalview.math.RotatableMatrix.Axis.Y;
25 import static jalview.math.RotatableMatrix.Axis.Z;
27 import jalview.analysis.Conservation;
28 import jalview.analysis.PCA;
29 import jalview.analysis.scoremodels.ScoreModels;
30 import jalview.analysis.scoremodels.SimilarityParams;
31 import jalview.api.FeatureColourI;
32 import jalview.api.ViewStyleI;
33 import jalview.api.analysis.ScoreModelI;
34 import jalview.api.analysis.SimilarityParamsI;
35 import jalview.api.structures.JalviewStructureDisplayI;
36 import jalview.bin.Cache;
37 import jalview.datamodel.AlignedCodonFrame;
38 import jalview.datamodel.Alignment;
39 import jalview.datamodel.AlignmentAnnotation;
40 import jalview.datamodel.AlignmentI;
41 import jalview.datamodel.DBRefEntry;
42 import jalview.datamodel.GraphLine;
43 import jalview.datamodel.PDBEntry;
44 import jalview.datamodel.Point;
45 import jalview.datamodel.RnaViewerModel;
46 import jalview.datamodel.SequenceFeature;
47 import jalview.datamodel.SequenceGroup;
48 import jalview.datamodel.SequenceI;
49 import jalview.datamodel.StructureViewerModel;
50 import jalview.datamodel.StructureViewerModel.StructureData;
51 import jalview.datamodel.features.FeatureMatcher;
52 import jalview.datamodel.features.FeatureMatcherI;
53 import jalview.datamodel.features.FeatureMatcherSet;
54 import jalview.datamodel.features.FeatureMatcherSetI;
55 import jalview.ext.varna.RnaModel;
56 import jalview.gui.AlignFrame;
57 import jalview.gui.AlignViewport;
58 import jalview.gui.AlignmentPanel;
59 import jalview.gui.AppVarna;
60 import jalview.gui.ChimeraViewFrame;
61 import jalview.gui.Desktop;
62 import jalview.gui.FeatureRenderer;
63 import jalview.gui.JvOptionPane;
64 import jalview.gui.OOMWarning;
65 import jalview.gui.PCAPanel;
66 import jalview.gui.PaintRefresher;
67 import jalview.gui.SplitFrame;
68 import jalview.gui.StructureViewer;
69 import jalview.gui.StructureViewer.ViewerType;
70 import jalview.gui.StructureViewerBase;
71 import jalview.gui.TreePanel;
72 import jalview.io.BackupFiles;
73 import jalview.io.DataSourceType;
74 import jalview.io.FileFormat;
75 import jalview.io.NewickFile;
76 import jalview.math.Matrix;
77 import jalview.math.MatrixI;
78 import jalview.renderer.ResidueShaderI;
79 import jalview.schemes.AnnotationColourGradient;
80 import jalview.schemes.ColourSchemeI;
81 import jalview.schemes.ColourSchemeProperty;
82 import jalview.schemes.FeatureColour;
83 import jalview.schemes.ResidueProperties;
84 import jalview.schemes.UserColourScheme;
85 import jalview.structure.StructureSelectionManager;
86 import jalview.structures.models.AAStructureBindingModel;
87 import jalview.util.Format;
88 import jalview.util.MessageManager;
89 import jalview.util.Platform;
90 import jalview.util.StringUtils;
91 import jalview.util.jarInputStreamProvider;
92 import jalview.util.matcher.Condition;
93 import jalview.viewmodel.AlignmentViewport;
94 import jalview.viewmodel.PCAModel;
95 import jalview.viewmodel.ViewportRanges;
96 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
97 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
98 import jalview.ws.jws2.Jws2Discoverer;
99 import jalview.ws.jws2.dm.AAConSettings;
100 import jalview.ws.jws2.jabaws2.Jws2Instance;
101 import jalview.ws.params.ArgumentI;
102 import jalview.ws.params.AutoCalcSetting;
103 import jalview.ws.params.WsParamSetI;
104 import jalview.xml.binding.jalview.AlcodonFrame;
105 import jalview.xml.binding.jalview.AlcodonFrame.AlcodMap;
106 import jalview.xml.binding.jalview.Annotation;
107 import jalview.xml.binding.jalview.Annotation.ThresholdLine;
108 import jalview.xml.binding.jalview.AnnotationColourScheme;
109 import jalview.xml.binding.jalview.AnnotationElement;
110 import jalview.xml.binding.jalview.DoubleMatrix;
111 import jalview.xml.binding.jalview.DoubleVector;
112 import jalview.xml.binding.jalview.Feature;
113 import jalview.xml.binding.jalview.Feature.OtherData;
114 import jalview.xml.binding.jalview.FeatureMatcherSet.CompoundMatcher;
115 import jalview.xml.binding.jalview.FilterBy;
116 import jalview.xml.binding.jalview.JalviewModel;
117 import jalview.xml.binding.jalview.JalviewModel.FeatureSettings;
118 import jalview.xml.binding.jalview.JalviewModel.FeatureSettings.Group;
119 import jalview.xml.binding.jalview.JalviewModel.FeatureSettings.Setting;
120 import jalview.xml.binding.jalview.JalviewModel.JGroup;
121 import jalview.xml.binding.jalview.JalviewModel.JSeq;
122 import jalview.xml.binding.jalview.JalviewModel.JSeq.Pdbids;
123 import jalview.xml.binding.jalview.JalviewModel.JSeq.Pdbids.StructureState;
124 import jalview.xml.binding.jalview.JalviewModel.JSeq.RnaViewer;
125 import jalview.xml.binding.jalview.JalviewModel.JSeq.RnaViewer.SecondaryStructure;
126 import jalview.xml.binding.jalview.JalviewModel.PcaViewer;
127 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.Axis;
128 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.SeqPointMax;
129 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.SeqPointMin;
130 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.SequencePoint;
131 import jalview.xml.binding.jalview.JalviewModel.Tree;
132 import jalview.xml.binding.jalview.JalviewModel.UserColours;
133 import jalview.xml.binding.jalview.JalviewModel.Viewport;
134 import jalview.xml.binding.jalview.JalviewModel.Viewport.CalcIdParam;
135 import jalview.xml.binding.jalview.JalviewModel.Viewport.HiddenColumns;
136 import jalview.xml.binding.jalview.JalviewUserColours;
137 import jalview.xml.binding.jalview.JalviewUserColours.Colour;
138 import jalview.xml.binding.jalview.MapListType.MapListFrom;
139 import jalview.xml.binding.jalview.MapListType.MapListTo;
140 import jalview.xml.binding.jalview.Mapping;
141 import jalview.xml.binding.jalview.NoValueColour;
142 import jalview.xml.binding.jalview.ObjectFactory;
143 import jalview.xml.binding.jalview.PcaDataType;
144 import jalview.xml.binding.jalview.Pdbentry.Property;
145 import jalview.xml.binding.jalview.Sequence;
146 import jalview.xml.binding.jalview.Sequence.DBRef;
147 import jalview.xml.binding.jalview.SequenceSet;
148 import jalview.xml.binding.jalview.SequenceSet.SequenceSetProperties;
149 import jalview.xml.binding.jalview.ThresholdType;
150 import jalview.xml.binding.jalview.VAMSAS;
152 import java.awt.Color;
153 import java.awt.Font;
154 import java.awt.Rectangle;
155 import java.io.BufferedReader;
156 import java.io.ByteArrayInputStream;
157 import java.io.DataInputStream;
158 import java.io.DataOutputStream;
160 import java.io.FileInputStream;
161 import java.io.FileOutputStream;
162 import java.io.IOException;
163 import java.io.InputStreamReader;
164 import java.io.OutputStreamWriter;
165 import java.io.PrintWriter;
166 import java.lang.reflect.InvocationTargetException;
167 import java.math.BigInteger;
168 import java.net.MalformedURLException;
170 import java.util.ArrayList;
171 import java.util.Arrays;
172 import java.util.Collections;
173 import java.util.Enumeration;
174 import java.util.GregorianCalendar;
175 import java.util.HashMap;
176 import java.util.HashSet;
177 import java.util.Hashtable;
178 import java.util.IdentityHashMap;
179 import java.util.Iterator;
180 import java.util.LinkedHashMap;
181 import java.util.List;
182 import java.util.Map;
183 import java.util.Map.Entry;
184 import java.util.Set;
185 import java.util.Vector;
186 import java.util.jar.JarEntry;
187 import java.util.jar.JarInputStream;
188 import java.util.jar.JarOutputStream;
190 import javax.swing.JInternalFrame;
191 import javax.swing.SwingUtilities;
192 import javax.xml.bind.JAXBContext;
193 import javax.xml.bind.JAXBElement;
194 import javax.xml.bind.Marshaller;
195 import javax.xml.datatype.DatatypeConfigurationException;
196 import javax.xml.datatype.DatatypeFactory;
197 import javax.xml.datatype.XMLGregorianCalendar;
198 import javax.xml.stream.XMLInputFactory;
199 import javax.xml.stream.XMLStreamReader;
202 * Write out the current jalview desktop state as a Jalview XML stream.
204 * Note: the vamsas objects referred to here are primitive versions of the
205 * VAMSAS project schema elements - they are not the same and most likely never
209 * @version $Revision: 1.134 $
211 public class Jalview2XML
214 // BH 2018 we add the .jvp binary extension to J2S so that
215 // it will declare that binary when we do the file save from the browser
219 Platform.addJ2SBinaryType(".jvp?");
222 private static final String VIEWER_PREFIX = "viewer_";
224 private static final String RNA_PREFIX = "rna_";
226 private static final String UTF_8 = "UTF-8";
229 * prefix for recovering datasets for alignments with multiple views where
230 * non-existent dataset IDs were written for some views
232 private static final String UNIQSEQSETID = "uniqueSeqSetId.";
234 // use this with nextCounter() to make unique names for entities
235 private int counter = 0;
238 * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
239 * of sequence objects are created.
241 IdentityHashMap<SequenceI, String> seqsToIds = null;
244 * jalview XML Sequence ID to jalview sequence object reference (both dataset
245 * and alignment sequences. Populated as XML reps of sequence objects are
248 Map<String, SequenceI> seqRefIds = null;
250 Map<String, SequenceI> incompleteSeqs = null;
252 List<SeqFref> frefedSequence = null;
254 boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
257 * Map of reconstructed AlignFrame objects that appear to have come from
258 * SplitFrame objects (have a dna/protein complement view).
260 private Map<Viewport, AlignFrame> splitFrameCandidates = new HashMap<>();
263 * Map from displayed rna structure models to their saved session state jar
266 private Map<RnaModel, String> rnaSessions = new HashMap<>();
269 * A helper method for safely using the value of an optional attribute that
270 * may be null if not present in the XML. Answers the boolean value, or false
276 public static boolean safeBoolean(Boolean b)
278 return b == null ? false : b.booleanValue();
282 * A helper method for safely using the value of an optional attribute that
283 * may be null if not present in the XML. Answers the integer value, or zero
289 public static int safeInt(Integer i)
291 return i == null ? 0 : i.intValue();
295 * A helper method for safely using the value of an optional attribute that
296 * may be null if not present in the XML. Answers the float value, or zero if
302 public static float safeFloat(Float f)
304 return f == null ? 0f : f.floatValue();
308 * create/return unique hash string for sq
311 * @return new or existing unique string for sq
313 String seqHash(SequenceI sq)
315 if (seqsToIds == null)
319 if (seqsToIds.containsKey(sq))
321 return seqsToIds.get(sq);
325 // create sequential key
326 String key = "sq" + (seqsToIds.size() + 1);
327 key = makeHashCode(sq, key); // check we don't have an external reference
329 seqsToIds.put(sq, key);
336 if (seqsToIds == null)
338 seqsToIds = new IdentityHashMap<>();
340 if (seqRefIds == null)
342 seqRefIds = new HashMap<>();
344 if (incompleteSeqs == null)
346 incompleteSeqs = new HashMap<>();
348 if (frefedSequence == null)
350 frefedSequence = new ArrayList<>();
358 public Jalview2XML(boolean raiseGUI)
360 this.raiseGUI = raiseGUI;
364 * base class for resolving forward references to sequences by their ID
369 abstract class SeqFref
375 public SeqFref(String _sref, String type)
381 public String getSref()
386 public SequenceI getSrefSeq()
388 return seqRefIds.get(sref);
391 public boolean isResolvable()
393 return seqRefIds.get(sref) != null;
396 public SequenceI getSrefDatasetSeq()
398 SequenceI sq = seqRefIds.get(sref);
401 while (sq.getDatasetSequence() != null)
403 sq = sq.getDatasetSequence();
410 * @return true if the forward reference was fully resolved
412 abstract boolean resolve();
415 public String toString()
417 return type + " reference to " + sref;
422 * create forward reference for a mapping
428 public SeqFref newMappingRef(final String sref,
429 final jalview.datamodel.Mapping _jmap)
431 SeqFref fref = new SeqFref(sref, "Mapping")
433 public jalview.datamodel.Mapping jmap = _jmap;
438 SequenceI seq = getSrefDatasetSeq();
450 public SeqFref newAlcodMapRef(final String sref,
451 final AlignedCodonFrame _cf,
452 final jalview.datamodel.Mapping _jmap)
455 SeqFref fref = new SeqFref(sref, "Codon Frame")
457 AlignedCodonFrame cf = _cf;
459 public jalview.datamodel.Mapping mp = _jmap;
462 public boolean isResolvable()
464 return super.isResolvable() && mp.getTo() != null;
470 SequenceI seq = getSrefDatasetSeq();
475 cf.addMap(seq, mp.getTo(), mp.getMap());
482 public void resolveFrefedSequences()
484 Iterator<SeqFref> nextFref = frefedSequence.iterator();
485 int toresolve = frefedSequence.size();
486 int unresolved = 0, failedtoresolve = 0;
487 while (nextFref.hasNext())
489 SeqFref ref = nextFref.next();
490 if (ref.isResolvable())
502 } catch (Exception x)
505 "IMPLEMENTATION ERROR: Failed to resolve forward reference for sequence "
518 System.err.println("Jalview Project Import: There were " + unresolved
519 + " forward references left unresolved on the stack.");
521 if (failedtoresolve > 0)
523 System.err.println("SERIOUS! " + failedtoresolve
524 + " resolvable forward references failed to resolve.");
526 if (incompleteSeqs != null && incompleteSeqs.size() > 0)
529 "Jalview Project Import: There are " + incompleteSeqs.size()
530 + " sequences which may have incomplete metadata.");
531 if (incompleteSeqs.size() < 10)
533 for (SequenceI s : incompleteSeqs.values())
535 System.err.println(s.toString());
541 "Too many to report. Skipping output of incomplete sequences.");
547 * This maintains a map of viewports, the key being the seqSetId. Important to
548 * set historyItem and redoList for multiple views
550 Map<String, AlignViewport> viewportsAdded = new HashMap<>();
552 Map<String, AlignmentAnnotation> annotationIds = new HashMap<>();
554 String uniqueSetSuffix = "";
557 * List of pdbfiles added to Jar
559 List<String> pdbfiles = null;
561 // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
562 public void saveState(File statefile)
564 FileOutputStream fos = null;
569 fos = new FileOutputStream(statefile);
571 JarOutputStream jout = new JarOutputStream(fos);
575 } catch (Exception e)
577 Cache.log.error("Couln't write Jalview state to " + statefile, e);
578 // TODO: inform user of the problem - they need to know if their data was
580 if (errorMessage == null)
582 errorMessage = "Did't write Jalview Archive to output file '"
583 + statefile + "' - See console error log for details";
587 errorMessage += "(Didn't write Jalview Archive to output file '"
598 } catch (IOException e)
608 * Writes a jalview project archive to the given Jar output stream.
612 public void saveState(JarOutputStream jout)
614 AlignFrame[] frames = Desktop.getAlignFrames();
620 saveAllFrames(Arrays.asList(frames), jout);
624 * core method for storing state for a set of AlignFrames.
627 * - frames involving all data to be exported (including containing
630 * - project output stream
632 private void saveAllFrames(List<AlignFrame> frames, JarOutputStream jout)
634 Hashtable<String, AlignFrame> dsses = new Hashtable<>();
637 * ensure cached data is clear before starting
639 // todo tidy up seqRefIds, seqsToIds initialisation / reset
641 splitFrameCandidates.clear();
646 // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
647 // //////////////////////////////////////////////////
649 List<String> shortNames = new ArrayList<>();
650 List<String> viewIds = new ArrayList<>();
653 for (int i = frames.size() - 1; i > -1; i--)
655 AlignFrame af = frames.get(i);
657 if (skipList != null && skipList
658 .containsKey(af.getViewport().getSequenceSetId()))
663 String shortName = makeFilename(af, shortNames);
665 int apSize = af.getAlignPanels().size();
667 for (int ap = 0; ap < apSize; ap++)
669 AlignmentPanel apanel = (AlignmentPanel) af.getAlignPanels()
671 String fileName = apSize == 1 ? shortName : ap + shortName;
672 if (!fileName.endsWith(".xml"))
674 fileName = fileName + ".xml";
677 saveState(apanel, fileName, jout, viewIds);
679 String dssid = getDatasetIdRef(
680 af.getViewport().getAlignment().getDataset());
681 if (!dsses.containsKey(dssid))
683 dsses.put(dssid, af);
688 writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix,
694 } catch (Exception foo)
698 } catch (Exception ex)
700 // TODO: inform user of the problem - they need to know if their data was
702 if (errorMessage == null)
704 errorMessage = "Couldn't write Jalview Archive - see error output for details";
706 ex.printStackTrace();
711 * Generates a distinct file name, based on the title of the AlignFrame, by
712 * appending _n for increasing n until an unused name is generated. The new
713 * name (without its extension) is added to the list.
717 * @return the generated name, with .xml extension
719 protected String makeFilename(AlignFrame af, List<String> namesUsed)
721 String shortName = af.getTitle();
723 if (shortName.indexOf(File.separatorChar) > -1)
725 shortName = shortName
726 .substring(shortName.lastIndexOf(File.separatorChar) + 1);
731 while (namesUsed.contains(shortName))
733 if (shortName.endsWith("_" + (count - 1)))
735 shortName = shortName.substring(0, shortName.lastIndexOf("_"));
738 shortName = shortName.concat("_" + count);
742 namesUsed.add(shortName);
744 if (!shortName.endsWith(".xml"))
746 shortName = shortName + ".xml";
751 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
752 public boolean saveAlignment(AlignFrame af, String jarFile,
757 // create backupfiles object and get new temp filename destination
758 boolean doBackup = BackupFiles.getEnabled();
759 BackupFiles backupfiles = doBackup ? new BackupFiles(jarFile) : null;
760 FileOutputStream fos = new FileOutputStream(doBackup ?
761 backupfiles.getTempFilePath() : jarFile);
763 JarOutputStream jout = new JarOutputStream(fos);
764 List<AlignFrame> frames = new ArrayList<>();
766 // resolve splitframes
767 if (af.getViewport().getCodingComplement() != null)
769 frames = ((SplitFrame) af.getSplitViewContainer()).getAlignFrames();
775 saveAllFrames(frames, jout);
779 } catch (Exception foo)
783 boolean success = true;
787 backupfiles.setWriteSuccess(success);
788 success = backupfiles.rollBackupsAndRenameTempFile();
792 } catch (Exception ex)
794 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
795 ex.printStackTrace();
800 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
801 String fileName, JarOutputStream jout)
804 for (String dssids : dsses.keySet())
806 AlignFrame _af = dsses.get(dssids);
807 String jfileName = fileName + " Dataset for " + _af.getTitle();
808 if (!jfileName.endsWith(".xml"))
810 jfileName = jfileName + ".xml";
812 saveState(_af.alignPanel, jfileName, true, jout, null);
817 * create a JalviewModel from an alignment view and marshall it to a
821 * panel to create jalview model for
823 * name of alignment panel written to output stream
830 public JalviewModel saveState(AlignmentPanel ap, String fileName,
831 JarOutputStream jout, List<String> viewIds)
833 return saveState(ap, fileName, false, jout, viewIds);
837 * create a JalviewModel from an alignment view and marshall it to a
841 * panel to create jalview model for
843 * name of alignment panel written to output stream
845 * when true, only write the dataset for the alignment, not the data
846 * associated with the view.
852 public JalviewModel saveState(AlignmentPanel ap, String fileName,
853 boolean storeDS, JarOutputStream jout, List<String> viewIds)
857 viewIds = new ArrayList<>();
862 List<UserColourScheme> userColours = new ArrayList<>();
864 AlignViewport av = ap.av;
865 ViewportRanges vpRanges = av.getRanges();
867 final ObjectFactory objectFactory = new ObjectFactory();
868 JalviewModel object = objectFactory.createJalviewModel();
869 object.setVamsasModel(new VAMSAS());
871 // object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
874 GregorianCalendar c = new GregorianCalendar();
875 DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
876 XMLGregorianCalendar now = datatypeFactory.newXMLGregorianCalendar(c);// gregorianCalendar);
877 object.setCreationDate(now);
878 } catch (DatatypeConfigurationException e)
880 System.err.println("error writing date: " + e.toString());
883 jalview.bin.Cache.getDefault("VERSION", "Development Build"));
886 * rjal is full height alignment, jal is actual alignment with full metadata
887 * but excludes hidden sequences.
889 jalview.datamodel.AlignmentI rjal = av.getAlignment(), jal = rjal;
891 if (av.hasHiddenRows())
893 rjal = jal.getHiddenSequences().getFullAlignment();
896 SequenceSet vamsasSet = new SequenceSet();
898 // JalviewModelSequence jms = new JalviewModelSequence();
900 vamsasSet.setGapChar(jal.getGapCharacter() + "");
902 if (jal.getDataset() != null)
904 // dataset id is the dataset's hashcode
905 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
908 // switch jal and the dataset
909 jal = jal.getDataset();
913 if (jal.getProperties() != null)
915 Enumeration en = jal.getProperties().keys();
916 while (en.hasMoreElements())
918 String key = en.nextElement().toString();
919 SequenceSetProperties ssp = new SequenceSetProperties();
921 ssp.setValue(jal.getProperties().get(key).toString());
922 // vamsasSet.addSequenceSetProperties(ssp);
923 vamsasSet.getSequenceSetProperties().add(ssp);
928 Set<String> calcIdSet = new HashSet<>();
929 // record the set of vamsas sequence XML POJO we create.
930 HashMap<String, Sequence> vamsasSetIds = new HashMap<>();
932 for (final SequenceI jds : rjal.getSequences())
934 final SequenceI jdatasq = jds.getDatasetSequence() == null ? jds
935 : jds.getDatasetSequence();
936 String id = seqHash(jds);
937 if (vamsasSetIds.get(id) == null)
939 if (seqRefIds.get(id) != null && !storeDS)
941 // This happens for two reasons: 1. multiple views are being
943 // 2. the hashCode has collided with another sequence's code. This
945 // HAPPEN! (PF00072.15.stk does this)
946 // JBPNote: Uncomment to debug writing out of files that do not read
947 // back in due to ArrayOutOfBoundExceptions.
948 // System.err.println("vamsasSeq backref: "+id+"");
949 // System.err.println(jds.getName()+"
950 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
951 // System.err.println("Hashcode: "+seqHash(jds));
952 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
953 // System.err.println(rsq.getName()+"
954 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
955 // System.err.println("Hashcode: "+seqHash(rsq));
959 vamsasSeq = createVamsasSequence(id, jds);
960 // vamsasSet.addSequence(vamsasSeq);
961 vamsasSet.getSequence().add(vamsasSeq);
962 vamsasSetIds.put(id, vamsasSeq);
963 seqRefIds.put(id, jds);
967 jseq.setStart(jds.getStart());
968 jseq.setEnd(jds.getEnd());
969 jseq.setColour(av.getSequenceColour(jds).getRGB());
971 jseq.setId(id); // jseq id should be a string not a number
974 // Store any sequences this sequence represents
975 if (av.hasHiddenRows())
977 // use rjal, contains the full height alignment
979 av.getAlignment().getHiddenSequences().isHidden(jds));
981 if (av.isHiddenRepSequence(jds))
983 jalview.datamodel.SequenceI[] reps = av
984 .getRepresentedSequences(jds).getSequencesInOrder(rjal);
986 for (int h = 0; h < reps.length; h++)
990 // jseq.addHiddenSequences(rjal.findIndex(reps[h]));
991 jseq.getHiddenSequences().add(rjal.findIndex(reps[h]));
996 // mark sequence as reference - if it is the reference for this view
999 jseq.setViewreference(jds == jal.getSeqrep());
1003 // TODO: omit sequence features from each alignment view's XML dump if we
1004 // are storing dataset
1005 List<SequenceFeature> sfs = jds.getSequenceFeatures();
1006 for (SequenceFeature sf : sfs)
1008 // Features features = new Features();
1009 Feature features = new Feature();
1011 features.setBegin(sf.getBegin());
1012 features.setEnd(sf.getEnd());
1013 features.setDescription(sf.getDescription());
1014 features.setType(sf.getType());
1015 features.setFeatureGroup(sf.getFeatureGroup());
1016 features.setScore(sf.getScore());
1017 if (sf.links != null)
1019 for (int l = 0; l < sf.links.size(); l++)
1021 OtherData keyValue = new OtherData();
1022 keyValue.setKey("LINK_" + l);
1023 keyValue.setValue(sf.links.elementAt(l).toString());
1024 // features.addOtherData(keyValue);
1025 features.getOtherData().add(keyValue);
1028 if (sf.otherDetails != null)
1031 * save feature attributes, which may be simple strings or
1032 * map valued (have sub-attributes)
1034 for (Entry<String, Object> entry : sf.otherDetails.entrySet())
1036 String key = entry.getKey();
1037 Object value = entry.getValue();
1038 if (value instanceof Map<?, ?>)
1040 for (Entry<String, Object> subAttribute : ((Map<String, Object>) value)
1043 OtherData otherData = new OtherData();
1044 otherData.setKey(key);
1045 otherData.setKey2(subAttribute.getKey());
1046 otherData.setValue(subAttribute.getValue().toString());
1047 // features.addOtherData(otherData);
1048 features.getOtherData().add(otherData);
1053 OtherData otherData = new OtherData();
1054 otherData.setKey(key);
1055 otherData.setValue(value.toString());
1056 // features.addOtherData(otherData);
1057 features.getOtherData().add(otherData);
1062 // jseq.addFeatures(features);
1063 jseq.getFeatures().add(features);
1066 if (jdatasq.getAllPDBEntries() != null)
1068 Enumeration<PDBEntry> en = jdatasq.getAllPDBEntries().elements();
1069 while (en.hasMoreElements())
1071 Pdbids pdb = new Pdbids();
1072 jalview.datamodel.PDBEntry entry = en.nextElement();
1074 String pdbId = entry.getId();
1076 pdb.setType(entry.getType());
1079 * Store any structure views associated with this sequence. This
1080 * section copes with duplicate entries in the project, so a dataset
1081 * only view *should* be coped with sensibly.
1083 // This must have been loaded, is it still visible?
1084 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1085 String matchedFile = null;
1086 for (int f = frames.length - 1; f > -1; f--)
1088 if (frames[f] instanceof StructureViewerBase)
1090 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
1091 matchedFile = saveStructureState(ap, jds, pdb, entry, viewIds,
1092 matchedFile, viewFrame);
1094 * Only store each structure viewer's state once in the project
1095 * jar. First time through only (storeDS==false)
1097 String viewId = viewFrame.getViewId();
1098 if (!storeDS && !viewIds.contains(viewId))
1100 viewIds.add(viewId);
1103 String viewerState = viewFrame.getStateInfo();
1104 writeJarEntry(jout, getViewerJarEntryName(viewId),
1105 viewerState.getBytes());
1106 } catch (IOException e)
1109 "Error saving viewer state: " + e.getMessage());
1115 if (matchedFile != null || entry.getFile() != null)
1117 if (entry.getFile() != null)
1120 matchedFile = entry.getFile();
1122 pdb.setFile(matchedFile); // entry.getFile());
1123 if (pdbfiles == null)
1125 pdbfiles = new ArrayList<>();
1128 if (!pdbfiles.contains(pdbId))
1130 pdbfiles.add(pdbId);
1131 copyFileToJar(jout, matchedFile, pdbId);
1135 Enumeration<String> props = entry.getProperties();
1136 if (props.hasMoreElements())
1138 // PdbentryItem item = new PdbentryItem();
1139 while (props.hasMoreElements())
1141 Property prop = new Property();
1142 String key = props.nextElement();
1144 prop.setValue(entry.getProperty(key).toString());
1145 // item.addProperty(prop);
1146 pdb.getProperty().add(prop);
1148 // pdb.addPdbentryItem(item);
1151 // jseq.addPdbids(pdb);
1152 jseq.getPdbids().add(pdb);
1156 saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
1158 // jms.addJSeq(jseq);
1159 object.getJSeq().add(jseq);
1162 if (!storeDS && av.hasHiddenRows())
1164 jal = av.getAlignment();
1168 if (storeDS && jal.getCodonFrames() != null)
1170 List<AlignedCodonFrame> jac = jal.getCodonFrames();
1171 for (AlignedCodonFrame acf : jac)
1173 AlcodonFrame alc = new AlcodonFrame();
1174 if (acf.getProtMappings() != null
1175 && acf.getProtMappings().length > 0)
1177 boolean hasMap = false;
1178 SequenceI[] dnas = acf.getdnaSeqs();
1179 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1180 for (int m = 0; m < pmaps.length; m++)
1182 AlcodMap alcmap = new AlcodMap();
1183 alcmap.setDnasq(seqHash(dnas[m]));
1185 createVamsasMapping(pmaps[m], dnas[m], null, false));
1186 // alc.addAlcodMap(alcmap);
1187 alc.getAlcodMap().add(alcmap);
1192 // vamsasSet.addAlcodonFrame(alc);
1193 vamsasSet.getAlcodonFrame().add(alc);
1196 // TODO: delete this ? dead code from 2.8.3->2.9 ?
1198 // AlcodonFrame alc = new AlcodonFrame();
1199 // vamsasSet.addAlcodonFrame(alc);
1200 // for (int p = 0; p < acf.aaWidth; p++)
1202 // Alcodon cmap = new Alcodon();
1203 // if (acf.codons[p] != null)
1205 // // Null codons indicate a gapped column in the translated peptide
1207 // cmap.setPos1(acf.codons[p][0]);
1208 // cmap.setPos2(acf.codons[p][1]);
1209 // cmap.setPos3(acf.codons[p][2]);
1211 // alc.addAlcodon(cmap);
1213 // if (acf.getProtMappings() != null
1214 // && acf.getProtMappings().length > 0)
1216 // SequenceI[] dnas = acf.getdnaSeqs();
1217 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1218 // for (int m = 0; m < pmaps.length; m++)
1220 // AlcodMap alcmap = new AlcodMap();
1221 // alcmap.setDnasq(seqHash(dnas[m]));
1222 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
1224 // alc.addAlcodMap(alcmap);
1231 // /////////////////////////////////
1232 if (!storeDS && av.getCurrentTree() != null)
1234 // FIND ANY ASSOCIATED TREES
1235 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
1236 if (Desktop.desktop != null)
1238 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1240 for (int t = 0; t < frames.length; t++)
1242 if (frames[t] instanceof TreePanel)
1244 TreePanel tp = (TreePanel) frames[t];
1246 if (tp.getTreeCanvas().getViewport().getAlignment() == jal)
1248 JalviewModel.Tree tree = new JalviewModel.Tree();
1249 tree.setTitle(tp.getTitle());
1250 tree.setCurrentTree((av.getCurrentTree() == tp.getTree()));
1251 tree.setNewick(tp.getTree().print());
1252 tree.setThreshold(tp.getTreeCanvas().getThreshold());
1254 tree.setFitToWindow(tp.fitToWindow.getState());
1255 tree.setFontName(tp.getTreeFont().getName());
1256 tree.setFontSize(tp.getTreeFont().getSize());
1257 tree.setFontStyle(tp.getTreeFont().getStyle());
1258 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
1260 tree.setShowBootstrap(tp.bootstrapMenu.getState());
1261 tree.setShowDistances(tp.distanceMenu.getState());
1263 tree.setHeight(tp.getHeight());
1264 tree.setWidth(tp.getWidth());
1265 tree.setXpos(tp.getX());
1266 tree.setYpos(tp.getY());
1267 tree.setId(makeHashCode(tp, null));
1268 tree.setLinkToAllViews(
1269 tp.getTreeCanvas().isApplyToAllViews());
1271 // jms.addTree(tree);
1272 object.getTree().add(tree);
1282 if (!storeDS && Desktop.desktop != null)
1284 for (JInternalFrame frame : Desktop.desktop.getAllFrames())
1286 if (frame instanceof PCAPanel)
1288 PCAPanel panel = (PCAPanel) frame;
1289 if (panel.getAlignViewport().getAlignment() == jal)
1291 savePCA(panel, object);
1299 * store forward refs from an annotationRow to any groups
1301 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<>();
1304 for (SequenceI sq : jal.getSequences())
1306 // Store annotation on dataset sequences only
1307 AlignmentAnnotation[] aa = sq.getAnnotation();
1308 if (aa != null && aa.length > 0)
1310 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1317 if (jal.getAlignmentAnnotation() != null)
1319 // Store the annotation shown on the alignment.
1320 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1321 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1326 if (jal.getGroups() != null)
1328 JGroup[] groups = new JGroup[jal.getGroups().size()];
1330 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1332 JGroup jGroup = new JGroup();
1333 groups[++i] = jGroup;
1335 jGroup.setStart(sg.getStartRes());
1336 jGroup.setEnd(sg.getEndRes());
1337 jGroup.setName(sg.getName());
1338 if (groupRefs.containsKey(sg))
1340 // group has references so set its ID field
1341 jGroup.setId(groupRefs.get(sg));
1343 ColourSchemeI colourScheme = sg.getColourScheme();
1344 if (colourScheme != null)
1346 ResidueShaderI groupColourScheme = sg.getGroupColourScheme();
1347 if (groupColourScheme.conservationApplied())
1349 jGroup.setConsThreshold(groupColourScheme.getConservationInc());
1351 if (colourScheme instanceof jalview.schemes.UserColourScheme)
1354 setUserColourScheme(colourScheme, userColours,
1359 jGroup.setColour(colourScheme.getSchemeName());
1362 else if (colourScheme instanceof jalview.schemes.AnnotationColourGradient)
1364 jGroup.setColour("AnnotationColourGradient");
1365 jGroup.setAnnotationColours(constructAnnotationColours(
1366 (jalview.schemes.AnnotationColourGradient) colourScheme,
1367 userColours, object));
1369 else if (colourScheme instanceof jalview.schemes.UserColourScheme)
1372 setUserColourScheme(colourScheme, userColours, object));
1376 jGroup.setColour(colourScheme.getSchemeName());
1379 jGroup.setPidThreshold(groupColourScheme.getThreshold());
1382 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1383 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1384 jGroup.setDisplayText(sg.getDisplayText());
1385 jGroup.setColourText(sg.getColourText());
1386 jGroup.setTextCol1(sg.textColour.getRGB());
1387 jGroup.setTextCol2(sg.textColour2.getRGB());
1388 jGroup.setTextColThreshold(sg.thresholdTextColour);
1389 jGroup.setShowUnconserved(sg.getShowNonconserved());
1390 jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1391 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1392 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1393 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1394 for (SequenceI seq : sg.getSequences())
1396 // jGroup.addSeq(seqHash(seq));
1397 jGroup.getSeq().add(seqHash(seq));
1401 //jms.setJGroup(groups);
1403 for (JGroup grp : groups)
1405 object.getJGroup().add(grp);
1410 // /////////SAVE VIEWPORT
1411 Viewport view = new Viewport();
1412 view.setTitle(ap.alignFrame.getTitle());
1413 view.setSequenceSetId(
1414 makeHashCode(av.getSequenceSetId(), av.getSequenceSetId()));
1415 view.setId(av.getViewId());
1416 if (av.getCodingComplement() != null)
1418 view.setComplementId(av.getCodingComplement().getViewId());
1420 view.setViewName(av.getViewName());
1421 view.setGatheredViews(av.isGatherViewsHere());
1423 Rectangle size = ap.av.getExplodedGeometry();
1424 Rectangle position = size;
1427 size = ap.alignFrame.getBounds();
1428 if (av.getCodingComplement() != null)
1430 position = ((SplitFrame) ap.alignFrame.getSplitViewContainer())
1438 view.setXpos(position.x);
1439 view.setYpos(position.y);
1441 view.setWidth(size.width);
1442 view.setHeight(size.height);
1444 view.setStartRes(vpRanges.getStartRes());
1445 view.setStartSeq(vpRanges.getStartSeq());
1447 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1449 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1450 userColours, object));
1453 .getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1455 AnnotationColourScheme ac = constructAnnotationColours(
1456 (jalview.schemes.AnnotationColourGradient) av
1457 .getGlobalColourScheme(),
1458 userColours, object);
1460 view.setAnnotationColours(ac);
1461 view.setBgColour("AnnotationColourGradient");
1465 view.setBgColour(ColourSchemeProperty
1466 .getColourName(av.getGlobalColourScheme()));
1469 ResidueShaderI vcs = av.getResidueShading();
1470 ColourSchemeI cs = av.getGlobalColourScheme();
1474 if (vcs.conservationApplied())
1476 view.setConsThreshold(vcs.getConservationInc());
1477 if (cs instanceof jalview.schemes.UserColourScheme)
1479 view.setBgColour(setUserColourScheme(cs, userColours, object));
1482 view.setPidThreshold(vcs.getThreshold());
1485 view.setConservationSelected(av.getConservationSelected());
1486 view.setPidSelected(av.getAbovePIDThreshold());
1487 final Font font = av.getFont();
1488 view.setFontName(font.getName());
1489 view.setFontSize(font.getSize());
1490 view.setFontStyle(font.getStyle());
1491 view.setScaleProteinAsCdna(av.getViewStyle().isScaleProteinAsCdna());
1492 view.setRenderGaps(av.isRenderGaps());
1493 view.setShowAnnotation(av.isShowAnnotation());
1494 view.setShowBoxes(av.getShowBoxes());
1495 view.setShowColourText(av.getColourText());
1496 view.setShowFullId(av.getShowJVSuffix());
1497 view.setRightAlignIds(av.isRightAlignIds());
1498 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1499 view.setShowText(av.getShowText());
1500 view.setShowUnconserved(av.getShowUnconserved());
1501 view.setWrapAlignment(av.getWrapAlignment());
1502 view.setTextCol1(av.getTextColour().getRGB());
1503 view.setTextCol2(av.getTextColour2().getRGB());
1504 view.setTextColThreshold(av.getThresholdTextColour());
1505 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1506 view.setShowSequenceLogo(av.isShowSequenceLogo());
1507 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1508 view.setShowGroupConsensus(av.isShowGroupConsensus());
1509 view.setShowGroupConservation(av.isShowGroupConservation());
1510 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1511 view.setShowDbRefTooltip(av.isShowDBRefs());
1512 view.setFollowHighlight(av.isFollowHighlight());
1513 view.setFollowSelection(av.followSelection);
1514 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1515 if (av.getFeaturesDisplayed() != null)
1517 FeatureSettings fs = new FeatureSettings();
1519 FeatureRenderer fr = ap.getSeqPanel().seqCanvas
1520 .getFeatureRenderer();
1521 String[] renderOrder = fr.getRenderOrder().toArray(new String[0]);
1523 Vector<String> settingsAdded = new Vector<>();
1524 if (renderOrder != null)
1526 for (String featureType : renderOrder)
1528 FeatureSettings.Setting setting = new FeatureSettings.Setting();
1529 setting.setType(featureType);
1532 * save any filter for the feature type
1534 FeatureMatcherSetI filter = fr.getFeatureFilter(featureType);
1535 if (filter != null) {
1536 Iterator<FeatureMatcherI> filters = filter.getMatchers().iterator();
1537 FeatureMatcherI firstFilter = filters.next();
1538 setting.setMatcherSet(Jalview2XML.marshalFilter(
1539 firstFilter, filters, filter.isAnded()));
1543 * save colour scheme for the feature type
1545 FeatureColourI fcol = fr.getFeatureStyle(featureType);
1546 if (!fcol.isSimpleColour())
1548 setting.setColour(fcol.getMaxColour().getRGB());
1549 setting.setMincolour(fcol.getMinColour().getRGB());
1550 setting.setMin(fcol.getMin());
1551 setting.setMax(fcol.getMax());
1552 setting.setColourByLabel(fcol.isColourByLabel());
1553 if (fcol.isColourByAttribute())
1555 String[] attName = fcol.getAttributeName();
1556 setting.getAttributeName().add(attName[0]);
1557 if (attName.length > 1)
1559 setting.getAttributeName().add(attName[1]);
1562 setting.setAutoScale(fcol.isAutoScaled());
1563 setting.setThreshold(fcol.getThreshold());
1564 Color noColour = fcol.getNoColour();
1565 if (noColour == null)
1567 setting.setNoValueColour(NoValueColour.NONE);
1569 else if (noColour.equals(fcol.getMaxColour()))
1571 setting.setNoValueColour(NoValueColour.MAX);
1575 setting.setNoValueColour(NoValueColour.MIN);
1577 // -1 = No threshold, 0 = Below, 1 = Above
1578 setting.setThreshstate(fcol.isAboveThreshold() ? 1
1579 : (fcol.isBelowThreshold() ? 0 : -1));
1583 setting.setColour(fcol.getColour().getRGB());
1587 av.getFeaturesDisplayed().isVisible(featureType));
1589 .getOrder(featureType);
1592 setting.setOrder(rorder);
1594 /// fs.addSetting(setting);
1595 fs.getSetting().add(setting);
1596 settingsAdded.addElement(featureType);
1600 // is groups actually supposed to be a map here ?
1601 Iterator<String> en = fr.getFeatureGroups().iterator();
1602 Vector<String> groupsAdded = new Vector<>();
1603 while (en.hasNext())
1605 String grp = en.next();
1606 if (groupsAdded.contains(grp))
1610 Group g = new Group();
1612 g.setDisplay(((Boolean) fr.checkGroupVisibility(grp, false))
1615 fs.getGroup().add(g);
1616 groupsAdded.addElement(grp);
1618 // jms.setFeatureSettings(fs);
1619 object.setFeatureSettings(fs);
1622 if (av.hasHiddenColumns())
1624 jalview.datamodel.HiddenColumns hidden = av.getAlignment()
1625 .getHiddenColumns();
1628 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1632 Iterator<int[]> hiddenRegions = hidden.iterator();
1633 while (hiddenRegions.hasNext())
1635 int[] region = hiddenRegions.next();
1636 HiddenColumns hc = new HiddenColumns();
1637 hc.setStart(region[0]);
1638 hc.setEnd(region[1]);
1639 // view.addHiddenColumns(hc);
1640 view.getHiddenColumns().add(hc);
1644 if (calcIdSet.size() > 0)
1646 for (String calcId : calcIdSet)
1648 if (calcId.trim().length() > 0)
1650 CalcIdParam cidp = createCalcIdParam(calcId, av);
1651 // Some calcIds have no parameters.
1654 // view.addCalcIdParam(cidp);
1655 view.getCalcIdParam().add(cidp);
1661 // jms.addViewport(view);
1662 object.getViewport().add(view);
1664 // object.setJalviewModelSequence(jms);
1665 // object.getVamsasModel().addSequenceSet(vamsasSet);
1666 object.getVamsasModel().getSequenceSet().add(vamsasSet);
1668 if (jout != null && fileName != null)
1670 // We may not want to write the object to disk,
1671 // eg we can copy the alignViewport to a new view object
1672 // using save and then load
1675 fileName = fileName.replace('\\', '/');
1676 System.out.println("Writing jar entry " + fileName);
1677 JarEntry entry = new JarEntry(fileName);
1678 jout.putNextEntry(entry);
1679 PrintWriter pout = new PrintWriter(
1680 new OutputStreamWriter(jout, UTF_8));
1681 JAXBContext jaxbContext = JAXBContext
1682 .newInstance(JalviewModel.class);
1683 Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
1685 // output pretty printed
1686 // jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
1687 jaxbMarshaller.marshal(
1688 new ObjectFactory().createJalviewModel(object), pout);
1690 // jaxbMarshaller.marshal(object, pout);
1691 // marshaller.marshal(object);
1694 } catch (Exception ex)
1696 // TODO: raise error in GUI if marshalling failed.
1697 System.err.println("Error writing Jalview project");
1698 ex.printStackTrace();
1705 * Writes PCA viewer attributes and computed values to an XML model object and
1706 * adds it to the JalviewModel. Any exceptions are reported by logging.
1708 protected void savePCA(PCAPanel panel, JalviewModel object)
1712 PcaViewer viewer = new PcaViewer();
1713 viewer.setHeight(panel.getHeight());
1714 viewer.setWidth(panel.getWidth());
1715 viewer.setXpos(panel.getX());
1716 viewer.setYpos(panel.getY());
1717 viewer.setTitle(panel.getTitle());
1718 PCAModel pcaModel = panel.getPcaModel();
1719 viewer.setScoreModelName(pcaModel.getScoreModelName());
1720 viewer.setXDim(panel.getSelectedDimensionIndex(X));
1721 viewer.setYDim(panel.getSelectedDimensionIndex(Y));
1722 viewer.setZDim(panel.getSelectedDimensionIndex(Z));
1724 panel.getRotatableCanvas().getBackgroundColour().getRGB());
1725 viewer.setScaleFactor(panel.getRotatableCanvas().getScaleFactor());
1726 float[] spMin = panel.getRotatableCanvas().getSeqMin();
1727 SeqPointMin spmin = new SeqPointMin();
1728 spmin.setXPos(spMin[0]);
1729 spmin.setYPos(spMin[1]);
1730 spmin.setZPos(spMin[2]);
1731 viewer.setSeqPointMin(spmin);
1732 float[] spMax = panel.getRotatableCanvas().getSeqMax();
1733 SeqPointMax spmax = new SeqPointMax();
1734 spmax.setXPos(spMax[0]);
1735 spmax.setYPos(spMax[1]);
1736 spmax.setZPos(spMax[2]);
1737 viewer.setSeqPointMax(spmax);
1738 viewer.setShowLabels(panel.getRotatableCanvas().isShowLabels());
1739 viewer.setLinkToAllViews(
1740 panel.getRotatableCanvas().isApplyToAllViews());
1741 SimilarityParamsI sp = pcaModel.getSimilarityParameters();
1742 viewer.setIncludeGaps(sp.includeGaps());
1743 viewer.setMatchGaps(sp.matchGaps());
1744 viewer.setIncludeGappedColumns(sp.includeGappedColumns());
1745 viewer.setDenominateByShortestLength(sp.denominateByShortestLength());
1748 * sequence points on display
1750 for (jalview.datamodel.SequencePoint spt : pcaModel
1751 .getSequencePoints())
1753 SequencePoint point = new SequencePoint();
1754 point.setSequenceRef(seqHash(spt.getSequence()));
1755 point.setXPos(spt.coord.x);
1756 point.setYPos(spt.coord.y);
1757 point.setZPos(spt.coord.z);
1758 viewer.getSequencePoint().add(point);
1762 * (end points of) axes on display
1764 for (Point p : panel.getRotatableCanvas().getAxisEndPoints())
1767 Axis axis = new Axis();
1771 viewer.getAxis().add(axis);
1775 * raw PCA data (note we are not restoring PCA inputs here -
1776 * alignment view, score model, similarity parameters)
1778 PcaDataType data = new PcaDataType();
1779 viewer.setPcaData(data);
1780 PCA pca = pcaModel.getPcaData();
1782 DoubleMatrix pm = new DoubleMatrix();
1783 saveDoubleMatrix(pca.getPairwiseScores(), pm);
1784 data.setPairwiseMatrix(pm);
1786 DoubleMatrix tm = new DoubleMatrix();
1787 saveDoubleMatrix(pca.getTridiagonal(), tm);
1788 data.setTridiagonalMatrix(tm);
1790 DoubleMatrix eigenMatrix = new DoubleMatrix();
1791 data.setEigenMatrix(eigenMatrix);
1792 saveDoubleMatrix(pca.getEigenmatrix(), eigenMatrix);
1794 object.getPcaViewer().add(viewer);
1795 } catch (Throwable t)
1797 Cache.log.error("Error saving PCA: " + t.getMessage());
1802 * Stores values from a matrix into an XML element, including (if present) the
1807 * @see #loadDoubleMatrix(DoubleMatrix)
1809 protected void saveDoubleMatrix(MatrixI m, DoubleMatrix xmlMatrix)
1811 xmlMatrix.setRows(m.height());
1812 xmlMatrix.setColumns(m.width());
1813 for (int i = 0; i < m.height(); i++)
1815 DoubleVector row = new DoubleVector();
1816 for (int j = 0; j < m.width(); j++)
1818 row.getV().add(m.getValue(i, j));
1820 xmlMatrix.getRow().add(row);
1822 if (m.getD() != null)
1824 DoubleVector dVector = new DoubleVector();
1825 for (double d : m.getD())
1827 dVector.getV().add(d);
1829 xmlMatrix.setD(dVector);
1831 if (m.getE() != null)
1833 DoubleVector eVector = new DoubleVector();
1834 for (double e : m.getE())
1836 eVector.getV().add(e);
1838 xmlMatrix.setE(eVector);
1843 * Loads XML matrix data into a new Matrix object, including the D and/or E
1844 * vectors (if present)
1848 * @see Jalview2XML#saveDoubleMatrix(MatrixI, DoubleMatrix)
1850 protected MatrixI loadDoubleMatrix(DoubleMatrix mData)
1852 int rows = mData.getRows();
1853 double[][] vals = new double[rows][];
1855 for (int i = 0; i < rows; i++)
1857 List<Double> dVector = mData.getRow().get(i).getV();
1858 vals[i] = new double[dVector.size()];
1860 for (Double d : dVector)
1866 MatrixI m = new Matrix(vals);
1868 if (mData.getD() != null)
1870 List<Double> dVector = mData.getD().getV();
1871 double[] vec = new double[dVector.size()];
1873 for (Double d : dVector)
1879 if (mData.getE() != null)
1881 List<Double> dVector = mData.getE().getV();
1882 double[] vec = new double[dVector.size()];
1884 for (Double d : dVector)
1895 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1896 * for each viewer, with
1898 * <li>viewer geometry (position, size, split pane divider location)</li>
1899 * <li>index of the selected structure in the viewer (currently shows gapped
1901 * <li>the id of the annotation holding RNA secondary structure</li>
1902 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1904 * Varna viewer state is also written out (in native Varna XML) to separate
1905 * project jar entries. A separate entry is written for each RNA structure
1906 * displayed, with the naming convention
1908 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
1916 * @param storeDataset
1918 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
1919 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
1920 boolean storeDataset)
1922 if (Desktop.desktop == null)
1926 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1927 for (int f = frames.length - 1; f > -1; f--)
1929 if (frames[f] instanceof AppVarna)
1931 AppVarna varna = (AppVarna) frames[f];
1933 * link the sequence to every viewer that is showing it and is linked to
1934 * its alignment panel
1936 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1938 String viewId = varna.getViewId();
1939 RnaViewer rna = new RnaViewer();
1940 rna.setViewId(viewId);
1941 rna.setTitle(varna.getTitle());
1942 rna.setXpos(varna.getX());
1943 rna.setYpos(varna.getY());
1944 rna.setWidth(varna.getWidth());
1945 rna.setHeight(varna.getHeight());
1946 rna.setDividerLocation(varna.getDividerLocation());
1947 rna.setSelectedRna(varna.getSelectedIndex());
1948 // jseq.addRnaViewer(rna);
1949 jseq.getRnaViewer().add(rna);
1952 * Store each Varna panel's state once in the project per sequence.
1953 * First time through only (storeDataset==false)
1955 // boolean storeSessions = false;
1956 // String sequenceViewId = viewId + seqsToIds.get(jds);
1957 // if (!storeDataset && !viewIds.contains(sequenceViewId))
1959 // viewIds.add(sequenceViewId);
1960 // storeSessions = true;
1962 for (RnaModel model : varna.getModels())
1964 if (model.seq == jds)
1967 * VARNA saves each view (sequence or alignment secondary
1968 * structure, gapped or trimmed) as a separate XML file
1970 String jarEntryName = rnaSessions.get(model);
1971 if (jarEntryName == null)
1974 String varnaStateFile = varna.getStateInfo(model.rna);
1975 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
1976 copyFileToJar(jout, varnaStateFile, jarEntryName);
1977 rnaSessions.put(model, jarEntryName);
1979 SecondaryStructure ss = new SecondaryStructure();
1980 String annotationId = varna.getAnnotation(jds).annotationId;
1981 ss.setAnnotationId(annotationId);
1982 ss.setViewerState(jarEntryName);
1983 ss.setGapped(model.gapped);
1984 ss.setTitle(model.title);
1985 // rna.addSecondaryStructure(ss);
1986 rna.getSecondaryStructure().add(ss);
1995 * Copy the contents of a file to a new entry added to the output jar
1999 * @param jarEntryName
2001 protected void copyFileToJar(JarOutputStream jout, String infilePath,
2002 String jarEntryName)
2004 DataInputStream dis = null;
2007 File file = new File(infilePath);
2008 if (file.exists() && jout != null)
2010 dis = new DataInputStream(new FileInputStream(file));
2011 byte[] data = new byte[(int) file.length()];
2012 dis.readFully(data);
2013 writeJarEntry(jout, jarEntryName, data);
2015 } catch (Exception ex)
2017 ex.printStackTrace();
2025 } catch (IOException e)
2034 * Write the data to a new entry of given name in the output jar file
2037 * @param jarEntryName
2039 * @throws IOException
2041 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
2042 byte[] data) throws IOException
2046 jarEntryName = jarEntryName.replace('\\','/');
2047 System.out.println("Writing jar entry " + jarEntryName);
2048 jout.putNextEntry(new JarEntry(jarEntryName));
2049 DataOutputStream dout = new DataOutputStream(jout);
2050 dout.write(data, 0, data.length);
2057 * Save the state of a structure viewer
2062 * the archive XML element under which to save the state
2065 * @param matchedFile
2069 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
2070 Pdbids pdb, PDBEntry entry, List<String> viewIds,
2071 String matchedFile, StructureViewerBase viewFrame)
2073 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
2076 * Look for any bindings for this viewer to the PDB file of interest
2077 * (including part matches excluding chain id)
2079 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
2081 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
2082 final String pdbId = pdbentry.getId();
2083 if (!pdbId.equals(entry.getId())
2084 && !(entry.getId().length() > 4 && entry.getId().toLowerCase()
2085 .startsWith(pdbId.toLowerCase())))
2088 * not interested in a binding to a different PDB entry here
2092 if (matchedFile == null)
2094 matchedFile = pdbentry.getFile();
2096 else if (!matchedFile.equals(pdbentry.getFile()))
2099 "Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
2100 + pdbentry.getFile());
2104 // can get at it if the ID
2105 // match is ambiguous (e.g.
2108 for (int smap = 0; smap < viewFrame.getBinding()
2109 .getSequence()[peid].length; smap++)
2111 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
2112 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
2114 StructureState state = new StructureState();
2115 state.setVisible(true);
2116 state.setXpos(viewFrame.getX());
2117 state.setYpos(viewFrame.getY());
2118 state.setWidth(viewFrame.getWidth());
2119 state.setHeight(viewFrame.getHeight());
2120 final String viewId = viewFrame.getViewId();
2121 state.setViewId(viewId);
2122 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
2123 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
2124 state.setColourByJmol(viewFrame.isColouredByViewer());
2125 state.setType(viewFrame.getViewerType().toString());
2126 // pdb.addStructureState(state);
2127 pdb.getStructureState().add(state);
2135 * Populates the AnnotationColourScheme xml for save. This captures the
2136 * settings of the options in the 'Colour by Annotation' dialog.
2139 * @param userColours
2143 private AnnotationColourScheme constructAnnotationColours(
2144 AnnotationColourGradient acg, List<UserColourScheme> userColours,
2147 AnnotationColourScheme ac = new AnnotationColourScheme();
2148 ac.setAboveThreshold(acg.getAboveThreshold());
2149 ac.setThreshold(acg.getAnnotationThreshold());
2150 // 2.10.2 save annotationId (unique) not annotation label
2151 ac.setAnnotation(acg.getAnnotation().annotationId);
2152 if (acg.getBaseColour() instanceof UserColourScheme)
2155 setUserColourScheme(acg.getBaseColour(), userColours, jm));
2160 ColourSchemeProperty.getColourName(acg.getBaseColour()));
2163 ac.setMaxColour(acg.getMaxColour().getRGB());
2164 ac.setMinColour(acg.getMinColour().getRGB());
2165 ac.setPerSequence(acg.isSeqAssociated());
2166 ac.setPredefinedColours(acg.isPredefinedColours());
2170 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
2171 IdentityHashMap<SequenceGroup, String> groupRefs,
2172 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
2173 SequenceSet vamsasSet)
2176 for (int i = 0; i < aa.length; i++)
2178 Annotation an = new Annotation();
2180 AlignmentAnnotation annotation = aa[i];
2181 if (annotation.annotationId != null)
2183 annotationIds.put(annotation.annotationId, annotation);
2186 an.setId(annotation.annotationId);
2188 an.setVisible(annotation.visible);
2190 an.setDescription(annotation.description);
2192 if (annotation.sequenceRef != null)
2194 // 2.9 JAL-1781 xref on sequence id rather than name
2195 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
2197 if (annotation.groupRef != null)
2199 String groupIdr = groupRefs.get(annotation.groupRef);
2200 if (groupIdr == null)
2202 // make a locally unique String
2203 groupRefs.put(annotation.groupRef,
2204 groupIdr = ("" + System.currentTimeMillis()
2205 + annotation.groupRef.getName()
2206 + groupRefs.size()));
2208 an.setGroupRef(groupIdr.toString());
2211 // store all visualization attributes for annotation
2212 an.setGraphHeight(annotation.graphHeight);
2213 an.setCentreColLabels(annotation.centreColLabels);
2214 an.setScaleColLabels(annotation.scaleColLabel);
2215 an.setShowAllColLabels(annotation.showAllColLabels);
2216 an.setBelowAlignment(annotation.belowAlignment);
2218 if (annotation.graph > 0)
2221 an.setGraphType(annotation.graph);
2222 an.setGraphGroup(annotation.graphGroup);
2223 if (annotation.getThreshold() != null)
2225 ThresholdLine line = new ThresholdLine();
2226 line.setLabel(annotation.getThreshold().label);
2227 line.setValue(annotation.getThreshold().value);
2228 line.setColour(annotation.getThreshold().colour.getRGB());
2229 an.setThresholdLine(line);
2237 an.setLabel(annotation.label);
2239 if (annotation == av.getAlignmentQualityAnnot()
2240 || annotation == av.getAlignmentConservationAnnotation()
2241 || annotation == av.getAlignmentConsensusAnnotation()
2242 || annotation.autoCalculated)
2244 // new way of indicating autocalculated annotation -
2245 an.setAutoCalculated(annotation.autoCalculated);
2247 if (annotation.hasScore())
2249 an.setScore(annotation.getScore());
2252 if (annotation.getCalcId() != null)
2254 calcIdSet.add(annotation.getCalcId());
2255 an.setCalcId(annotation.getCalcId());
2257 if (annotation.hasProperties())
2259 for (String pr : annotation.getProperties())
2261 jalview.xml.binding.jalview.Annotation.Property prop = new jalview.xml.binding.jalview.Annotation.Property();
2263 prop.setValue(annotation.getProperty(pr));
2264 // an.addProperty(prop);
2265 an.getProperty().add(prop);
2269 AnnotationElement ae;
2270 if (annotation.annotations != null)
2272 an.setScoreOnly(false);
2273 for (int a = 0; a < annotation.annotations.length; a++)
2275 if ((annotation == null) || (annotation.annotations[a] == null))
2280 ae = new AnnotationElement();
2281 if (annotation.annotations[a].description != null)
2283 ae.setDescription(annotation.annotations[a].description);
2285 if (annotation.annotations[a].displayCharacter != null)
2287 ae.setDisplayCharacter(
2288 annotation.annotations[a].displayCharacter);
2291 if (!Float.isNaN(annotation.annotations[a].value))
2293 ae.setValue(annotation.annotations[a].value);
2297 if (annotation.annotations[a].secondaryStructure > ' ')
2299 ae.setSecondaryStructure(
2300 annotation.annotations[a].secondaryStructure + "");
2303 if (annotation.annotations[a].colour != null
2304 && annotation.annotations[a].colour != java.awt.Color.black)
2306 ae.setColour(annotation.annotations[a].colour.getRGB());
2309 // an.addAnnotationElement(ae);
2310 an.getAnnotationElement().add(ae);
2311 if (annotation.autoCalculated)
2313 // only write one non-null entry into the annotation row -
2314 // sufficient to get the visualization attributes necessary to
2322 an.setScoreOnly(true);
2324 if (!storeDS || (storeDS && !annotation.autoCalculated))
2326 // skip autocalculated annotation - these are only provided for
2328 // vamsasSet.addAnnotation(an);
2329 vamsasSet.getAnnotation().add(an);
2335 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
2337 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
2338 if (settings != null)
2340 CalcIdParam vCalcIdParam = new CalcIdParam();
2341 vCalcIdParam.setCalcId(calcId);
2342 // vCalcIdParam.addServiceURL(settings.getServiceURI());
2343 vCalcIdParam.getServiceURL().add(settings.getServiceURI());
2344 // generic URI allowing a third party to resolve another instance of the
2345 // service used for this calculation
2346 for (String url : settings.getServiceURLs())
2348 // vCalcIdParam.addServiceURL(urls);
2349 vCalcIdParam.getServiceURL().add(url);
2351 vCalcIdParam.setVersion("1.0");
2352 if (settings.getPreset() != null)
2354 WsParamSetI setting = settings.getPreset();
2355 vCalcIdParam.setName(setting.getName());
2356 vCalcIdParam.setDescription(setting.getDescription());
2360 vCalcIdParam.setName("");
2361 vCalcIdParam.setDescription("Last used parameters");
2363 // need to be able to recover 1) settings 2) user-defined presets or
2364 // recreate settings from preset 3) predefined settings provided by
2365 // service - or settings that can be transferred (or discarded)
2366 vCalcIdParam.setParameters(
2367 settings.getWsParamFile().replace("\n", "|\\n|"));
2368 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
2369 // todo - decide if updateImmediately is needed for any projects.
2371 return vCalcIdParam;
2376 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
2379 if (calcIdParam.getVersion().equals("1.0"))
2381 final String[] calcIds = calcIdParam.getServiceURL().toArray(new String[0]);
2382 Jws2Instance service = Jws2Discoverer.getDiscoverer()
2383 .getPreferredServiceFor(calcIds);
2384 if (service != null)
2386 WsParamSetI parmSet = null;
2389 parmSet = service.getParamStore().parseServiceParameterFile(
2390 calcIdParam.getName(), calcIdParam.getDescription(),
2392 calcIdParam.getParameters().replace("|\\n|", "\n"));
2393 } catch (IOException x)
2395 warn("Couldn't parse parameter data for "
2396 + calcIdParam.getCalcId(), x);
2399 List<ArgumentI> argList = null;
2400 if (calcIdParam.getName().length() > 0)
2402 parmSet = service.getParamStore()
2403 .getPreset(calcIdParam.getName());
2404 if (parmSet != null)
2406 // TODO : check we have a good match with settings in AACon -
2407 // otherwise we'll need to create a new preset
2412 argList = parmSet.getArguments();
2415 AAConSettings settings = new AAConSettings(
2416 calcIdParam.isAutoUpdate(), service, parmSet, argList);
2417 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
2418 calcIdParam.isNeedsUpdate());
2423 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
2427 throw new Error(MessageManager.formatMessage(
2428 "error.unsupported_version_calcIdparam", new Object[]
2429 { calcIdParam.toString() }));
2433 * External mapping between jalview objects and objects yielding a valid and
2434 * unique object ID string. This is null for normal Jalview project IO, but
2435 * non-null when a jalview project is being read or written as part of a
2438 IdentityHashMap jv2vobj = null;
2441 * Construct a unique ID for jvobj using either existing bindings or if none
2442 * exist, the result of the hashcode call for the object.
2445 * jalview data object
2446 * @return unique ID for referring to jvobj
2448 private String makeHashCode(Object jvobj, String altCode)
2450 if (jv2vobj != null)
2452 Object id = jv2vobj.get(jvobj);
2455 return id.toString();
2457 // check string ID mappings
2458 if (jvids2vobj != null && jvobj instanceof String)
2460 id = jvids2vobj.get(jvobj);
2464 return id.toString();
2466 // give up and warn that something has gone wrong
2467 warn("Cannot find ID for object in external mapping : " + jvobj);
2473 * return local jalview object mapped to ID, if it exists
2477 * @return null or object bound to idcode
2479 private Object retrieveExistingObj(String idcode)
2481 if (idcode != null && vobj2jv != null)
2483 return vobj2jv.get(idcode);
2489 * binding from ID strings from external mapping table to jalview data model
2492 private Hashtable vobj2jv;
2494 private Sequence createVamsasSequence(String id, SequenceI jds)
2496 return createVamsasSequence(true, id, jds, null);
2499 private Sequence createVamsasSequence(boolean recurse, String id,
2500 SequenceI jds, SequenceI parentseq)
2502 Sequence vamsasSeq = new Sequence();
2503 vamsasSeq.setId(id);
2504 vamsasSeq.setName(jds.getName());
2505 vamsasSeq.setSequence(jds.getSequenceAsString());
2506 vamsasSeq.setDescription(jds.getDescription());
2507 List<DBRefEntry> dbrefs = null;
2508 if (jds.getDatasetSequence() != null)
2510 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
2514 // seqId==dsseqid so we can tell which sequences really are
2515 // dataset sequences only
2516 vamsasSeq.setDsseqid(id);
2517 dbrefs = jds.getDBRefs();
2518 if (parentseq == null)
2525 for (int d = 0, nd = dbrefs.size(); d < nd; d++)
2527 DBRef dbref = new DBRef();
2528 DBRefEntry ref = dbrefs.get(d);
2529 dbref.setSource(ref.getSource());
2530 dbref.setVersion(ref.getVersion());
2531 dbref.setAccessionId(ref.getAccessionId());
2534 Mapping mp = createVamsasMapping(ref.getMap(), parentseq,
2536 dbref.setMapping(mp);
2538 // vamsasSeq.addDBRef(dbref);
2539 vamsasSeq.getDBRef().add(dbref);
2545 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
2546 SequenceI parentseq, SequenceI jds, boolean recurse)
2549 if (jmp.getMap() != null)
2553 jalview.util.MapList mlst = jmp.getMap();
2554 List<int[]> r = mlst.getFromRanges();
2555 for (int[] range : r)
2557 MapListFrom mfrom = new MapListFrom();
2558 mfrom.setStart(range[0]);
2559 mfrom.setEnd(range[1]);
2560 // mp.addMapListFrom(mfrom);
2561 mp.getMapListFrom().add(mfrom);
2563 r = mlst.getToRanges();
2564 for (int[] range : r)
2566 MapListTo mto = new MapListTo();
2567 mto.setStart(range[0]);
2568 mto.setEnd(range[1]);
2569 // mp.addMapListTo(mto);
2570 mp.getMapListTo().add(mto);
2572 mp.setMapFromUnit(BigInteger.valueOf(mlst.getFromRatio()));
2573 mp.setMapToUnit(BigInteger.valueOf(mlst.getToRatio()));
2574 if (jmp.getTo() != null)
2576 // MappingChoice mpc = new MappingChoice();
2578 // check/create ID for the sequence referenced by getTo()
2581 SequenceI ps = null;
2582 if (parentseq != jmp.getTo()
2583 && parentseq.getDatasetSequence() != jmp.getTo())
2585 // chaining dbref rather than a handshaking one
2586 jmpid = seqHash(ps = jmp.getTo());
2590 jmpid = seqHash(ps = parentseq);
2592 // mpc.setDseqFor(jmpid);
2593 mp.setDseqFor(jmpid);
2594 if (!seqRefIds.containsKey(jmpid))
2596 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2597 seqRefIds.put(jmpid, ps);
2601 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2604 // mp.setMappingChoice(mpc);
2610 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2611 List<UserColourScheme> userColours, JalviewModel jm)
2614 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2615 boolean newucs = false;
2616 if (!userColours.contains(ucs))
2618 userColours.add(ucs);
2621 id = "ucs" + userColours.indexOf(ucs);
2624 // actually create the scheme's entry in the XML model
2625 java.awt.Color[] colours = ucs.getColours();
2626 UserColours uc = new UserColours();
2627 // UserColourScheme jbucs = new UserColourScheme();
2628 JalviewUserColours jbucs = new JalviewUserColours();
2630 for (int i = 0; i < colours.length; i++)
2632 Colour col = new Colour();
2633 col.setName(ResidueProperties.aa[i]);
2634 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2635 // jbucs.addColour(col);
2636 jbucs.getColour().add(col);
2638 if (ucs.getLowerCaseColours() != null)
2640 colours = ucs.getLowerCaseColours();
2641 for (int i = 0; i < colours.length; i++)
2643 Colour col = new Colour();
2644 col.setName(ResidueProperties.aa[i].toLowerCase());
2645 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2646 // jbucs.addColour(col);
2647 jbucs.getColour().add(col);
2652 uc.setUserColourScheme(jbucs);
2653 // jm.addUserColours(uc);
2654 jm.getUserColours().add(uc);
2660 jalview.schemes.UserColourScheme getUserColourScheme(
2661 JalviewModel jm, String id)
2663 List<UserColours> uc = jm.getUserColours();
2664 UserColours colours = null;
2666 for (int i = 0; i < uc.length; i++)
2668 if (uc[i].getId().equals(id))
2675 for (UserColours c : uc)
2677 if (c.getId().equals(id))
2684 java.awt.Color[] newColours = new java.awt.Color[24];
2686 for (int i = 0; i < 24; i++)
2688 newColours[i] = new java.awt.Color(Integer.parseInt(
2689 // colours.getUserColourScheme().getColour(i).getRGB(), 16));
2690 colours.getUserColourScheme().getColour().get(i).getRGB(),
2694 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2697 if (colours.getUserColourScheme().getColour().size()/*Count()*/ > 24)
2699 newColours = new java.awt.Color[23];
2700 for (int i = 0; i < 23; i++)
2702 newColours[i] = new java.awt.Color(Integer.parseInt(
2703 colours.getUserColourScheme().getColour().get(i + 24)
2707 ucs.setLowerCaseColours(newColours);
2714 * contains last error message (if any) encountered by XML loader.
2716 String errorMessage = null;
2719 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2720 * exceptions are raised during project XML parsing
2722 public boolean attemptversion1parse = false;
2725 * Load a jalview project archive from a jar file
2728 * - HTTP URL or filename
2730 public AlignFrame loadJalviewAlign(final Object file)
2733 jalview.gui.AlignFrame af = null;
2737 // create list to store references for any new Jmol viewers created
2738 newStructureViewers = new Vector<>();
2739 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2740 // Workaround is to make sure caller implements the JarInputStreamProvider
2742 // so we can re-open the jar input stream for each entry.
2744 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2745 af = loadJalviewAlign(jprovider);
2748 af.setMenusForViewport();
2750 } catch (MalformedURLException e)
2752 errorMessage = "Invalid URL format for '" + file + "'";
2758 SwingUtilities.invokeAndWait(new Runnable()
2763 setLoadingFinishedForNewStructureViewers();
2766 } catch (Exception x)
2768 System.err.println("Error loading alignment: " + x.getMessage());
2774 @SuppressWarnings("unused")
2775 private jarInputStreamProvider createjarInputStreamProvider(final Object ofile) throws MalformedURLException {
2777 // BH 2018 allow for bytes already attached to File object
2779 String file = (ofile instanceof File ? ((File) ofile).getCanonicalPath() : ofile.toString());
2780 byte[] bytes = Platform.isJS() ? Platform.getFileBytes((File) ofile)
2783 errorMessage = null;
2784 uniqueSetSuffix = null;
2786 viewportsAdded.clear();
2787 frefedSequence = null;
2789 if (file.startsWith("http://")) {
2790 url = new URL(file);
2792 final URL _url = url;
2793 return new jarInputStreamProvider() {
2796 public JarInputStream getJarInputStream() throws IOException {
2797 if (bytes != null) {
2798 // System.out.println("Jalview2XML: opening byte jarInputStream for bytes.length=" + bytes.length);
2799 return new JarInputStream(new ByteArrayInputStream(bytes));
2802 // System.out.println("Jalview2XML: opening url jarInputStream for " + _url);
2803 return new JarInputStream(_url.openStream());
2805 // System.out.println("Jalview2XML: opening file jarInputStream for " + file);
2806 return new JarInputStream(new FileInputStream(file));
2811 public String getFilename() {
2815 } catch (IOException e) {
2816 e.printStackTrace();
2822 * Recover jalview session from a jalview project archive. Caller may
2823 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2824 * themselves. Any null fields will be initialised with default values,
2825 * non-null fields are left alone.
2830 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2832 errorMessage = null;
2833 if (uniqueSetSuffix == null)
2835 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2837 if (seqRefIds == null)
2841 AlignFrame af = null, _af = null;
2842 IdentityHashMap<AlignmentI, AlignmentI> importedDatasets = new IdentityHashMap<>();
2843 Map<String, AlignFrame> gatherToThisFrame = new HashMap<>();
2844 final String file = jprovider.getFilename();
2847 JarInputStream jin = null;
2848 JarEntry jarentry = null;
2853 jin = jprovider.getJarInputStream();
2854 for (int i = 0; i < entryCount; i++)
2856 jarentry = jin.getNextJarEntry();
2859 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2861 JAXBContext jc = JAXBContext
2862 .newInstance("jalview.xml.binding.jalview");
2863 XMLStreamReader streamReader = XMLInputFactory.newInstance()
2864 .createXMLStreamReader(jin);
2865 javax.xml.bind.Unmarshaller um = jc.createUnmarshaller();
2866 JAXBElement<JalviewModel> jbe = um
2867 .unmarshal(streamReader, JalviewModel.class);
2868 JalviewModel object = jbe.getValue();
2870 if (true) // !skipViewport(object))
2872 _af = loadFromObject(object, file, true, jprovider);
2873 if (_af != null && object.getViewport().size() > 0)
2874 // getJalviewModelSequence().getViewportCount() > 0)
2878 // store a reference to the first view
2881 if (_af.getViewport().isGatherViewsHere())
2883 // if this is a gathered view, keep its reference since
2884 // after gathering views, only this frame will remain
2886 gatherToThisFrame.put(_af.getViewport().getSequenceSetId(),
2889 // Save dataset to register mappings once all resolved
2890 importedDatasets.put(
2891 af.getViewport().getAlignment().getDataset(),
2892 af.getViewport().getAlignment().getDataset());
2897 else if (jarentry != null)
2899 // Some other file here.
2902 } while (jarentry != null);
2903 resolveFrefedSequences();
2904 } catch (IOException ex)
2906 ex.printStackTrace();
2907 errorMessage = "Couldn't locate Jalview XML file : " + file;
2909 "Exception whilst loading jalview XML file : " + ex + "\n");
2910 } catch (Exception ex)
2912 System.err.println("Parsing as Jalview Version 2 file failed.");
2913 ex.printStackTrace(System.err);
2914 if (attemptversion1parse)
2916 // used to attempt to parse as V1 castor-generated xml
2918 if (Desktop.instance != null)
2920 Desktop.instance.stopLoading();
2924 System.out.println("Successfully loaded archive file");
2927 ex.printStackTrace();
2930 "Exception whilst loading jalview XML file : " + ex + "\n");
2931 } catch (OutOfMemoryError e)
2933 // Don't use the OOM Window here
2934 errorMessage = "Out of memory loading jalview XML file";
2935 System.err.println("Out of memory whilst loading jalview XML file");
2936 e.printStackTrace();
2940 * Regather multiple views (with the same sequence set id) to the frame (if
2941 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2942 * views instead of separate frames. Note this doesn't restore a state where
2943 * some expanded views in turn have tabbed views - the last "first tab" read
2944 * in will play the role of gatherer for all.
2946 for (AlignFrame fr : gatherToThisFrame.values())
2948 Desktop.instance.gatherViews(fr);
2951 restoreSplitFrames();
2952 for (AlignmentI ds : importedDatasets.keySet())
2954 if (ds.getCodonFrames() != null)
2956 StructureSelectionManager
2957 .getStructureSelectionManager(Desktop.instance)
2958 .registerMappings(ds.getCodonFrames());
2961 if (errorMessage != null)
2966 if (Desktop.instance != null)
2968 Desktop.instance.stopLoading();
2975 * Try to reconstruct and display SplitFrame windows, where each contains
2976 * complementary dna and protein alignments. Done by pairing up AlignFrame
2977 * objects (created earlier) which have complementary viewport ids associated.
2979 protected void restoreSplitFrames()
2981 List<SplitFrame> gatherTo = new ArrayList<>();
2982 List<AlignFrame> addedToSplitFrames = new ArrayList<>();
2983 Map<String, AlignFrame> dna = new HashMap<>();
2986 * Identify the DNA alignments
2988 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2991 AlignFrame af = candidate.getValue();
2992 if (af.getViewport().getAlignment().isNucleotide())
2994 dna.put(candidate.getKey().getId(), af);
2999 * Try to match up the protein complements
3001 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
3004 AlignFrame af = candidate.getValue();
3005 if (!af.getViewport().getAlignment().isNucleotide())
3007 String complementId = candidate.getKey().getComplementId();
3008 // only non-null complements should be in the Map
3009 if (complementId != null && dna.containsKey(complementId))
3011 final AlignFrame dnaFrame = dna.get(complementId);
3012 SplitFrame sf = createSplitFrame(dnaFrame, af);
3013 addedToSplitFrames.add(dnaFrame);
3014 addedToSplitFrames.add(af);
3015 dnaFrame.setMenusForViewport();
3016 af.setMenusForViewport();
3017 if (af.getViewport().isGatherViewsHere())
3026 * Open any that we failed to pair up (which shouldn't happen!) as
3027 * standalone AlignFrame's.
3029 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
3032 AlignFrame af = candidate.getValue();
3033 if (!addedToSplitFrames.contains(af))
3035 Viewport view = candidate.getKey();
3036 Desktop.addInternalFrame(af, view.getTitle(),
3037 safeInt(view.getWidth()), safeInt(view.getHeight()));
3038 af.setMenusForViewport();
3039 System.err.println("Failed to restore view " + view.getTitle()
3040 + " to split frame");
3045 * Gather back into tabbed views as flagged.
3047 for (SplitFrame sf : gatherTo)
3049 Desktop.instance.gatherViews(sf);
3052 splitFrameCandidates.clear();
3056 * Construct and display one SplitFrame holding DNA and protein alignments.
3059 * @param proteinFrame
3062 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
3063 AlignFrame proteinFrame)
3065 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
3066 String title = MessageManager.getString("label.linked_view_title");
3067 int width = (int) dnaFrame.getBounds().getWidth();
3068 int height = (int) (dnaFrame.getBounds().getHeight()
3069 + proteinFrame.getBounds().getHeight() + 50);
3072 * SplitFrame location is saved to both enclosed frames
3074 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
3075 Desktop.addInternalFrame(splitFrame, title, width, height);
3078 * And compute cDNA consensus (couldn't do earlier with consensus as
3079 * mappings were not yet present)
3081 proteinFrame.getViewport().alignmentChanged(proteinFrame.alignPanel);
3087 * check errorMessage for a valid error message and raise an error box in the
3088 * GUI or write the current errorMessage to stderr and then clear the error
3091 protected void reportErrors()
3093 reportErrors(false);
3096 protected void reportErrors(final boolean saving)
3098 if (errorMessage != null)
3100 final String finalErrorMessage = errorMessage;
3103 javax.swing.SwingUtilities.invokeLater(new Runnable()
3108 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
3110 "Error " + (saving ? "saving" : "loading")
3112 JvOptionPane.WARNING_MESSAGE);
3118 System.err.println("Problem loading Jalview file: " + errorMessage);
3121 errorMessage = null;
3124 Map<String, String> alreadyLoadedPDB = new HashMap<>();
3127 * when set, local views will be updated from view stored in JalviewXML
3128 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
3129 * sync if this is set to true.
3131 private final boolean updateLocalViews = false;
3134 * Returns the path to a temporary file holding the PDB file for the given PDB
3135 * id. The first time of asking, searches for a file of that name in the
3136 * Jalview project jar, and copies it to a new temporary file. Any repeat
3137 * requests just return the path to the file previously created.
3143 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId,
3146 if (alreadyLoadedPDB.containsKey(pdbId))
3148 return alreadyLoadedPDB.get(pdbId).toString();
3151 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb",
3153 if (tempFile != null)
3155 alreadyLoadedPDB.put(pdbId, tempFile);
3161 * Copies the jar entry of given name to a new temporary file and returns the
3162 * path to the file, or null if the entry is not found.
3165 * @param jarEntryName
3167 * a prefix for the temporary file name, must be at least three
3170 * null or original file - so new file can be given the same suffix
3174 protected String copyJarEntry(jarInputStreamProvider jprovider,
3175 String jarEntryName, String prefix, String origFile)
3177 BufferedReader in = null;
3178 PrintWriter out = null;
3179 String suffix = ".tmp";
3180 if (origFile == null)
3182 origFile = jarEntryName;
3184 int sfpos = origFile.lastIndexOf(".");
3185 if (sfpos > -1 && sfpos < (origFile.length() - 3))
3187 suffix = "." + origFile.substring(sfpos + 1);
3191 JarInputStream jin = jprovider.getJarInputStream();
3193 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
3194 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
3195 * FileInputStream(jprovider)); }
3198 JarEntry entry = null;
3201 entry = jin.getNextJarEntry();
3202 } while (entry != null && !entry.getName().equals(jarEntryName));
3205 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
3206 File outFile = File.createTempFile(prefix, suffix);
3207 outFile.deleteOnExit();
3208 out = new PrintWriter(new FileOutputStream(outFile));
3211 while ((data = in.readLine()) != null)
3216 String t = outFile.getAbsolutePath();
3221 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
3223 } catch (Exception ex)
3225 ex.printStackTrace();
3233 } catch (IOException e)
3247 private class JvAnnotRow
3249 public JvAnnotRow(int i, AlignmentAnnotation jaa)
3256 * persisted version of annotation row from which to take vis properties
3258 public jalview.datamodel.AlignmentAnnotation template;
3261 * original position of the annotation row in the alignment
3267 * Load alignment frame from jalview XML DOM object
3269 * @param jalviewModel
3272 * filename source string
3273 * @param loadTreesAndStructures
3274 * when false only create Viewport
3276 * data source provider
3277 * @return alignment frame created from view stored in DOM
3279 AlignFrame loadFromObject(JalviewModel jalviewModel, String file,
3280 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
3282 SequenceSet vamsasSet = jalviewModel.getVamsasModel().getSequenceSet().get(0);
3283 List<Sequence> vamsasSeqs = vamsasSet.getSequence();
3285 // JalviewModelSequence jms = object.getJalviewModelSequence();
3287 // Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
3289 Viewport view = (jalviewModel.getViewport().size() > 0)
3290 ? jalviewModel.getViewport().get(0)
3293 // ////////////////////////////////
3294 // INITIALISE ALIGNMENT SEQUENCESETID AND VIEWID
3297 // If we just load in the same jar file again, the sequenceSetId
3298 // will be the same, and we end up with multiple references
3299 // to the same sequenceSet. We must modify this id on load
3300 // so that each load of the file gives a unique id
3303 * used to resolve correct alignment dataset for alignments with multiple
3306 String uniqueSeqSetId = null;
3307 String viewId = null;
3310 uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3311 viewId = (view.getId() == null ? null
3312 : view.getId() + uniqueSetSuffix);
3315 // ////////////////////////////////
3318 List<SequenceI> hiddenSeqs = null;
3320 List<SequenceI> tmpseqs = new ArrayList<>();
3322 boolean multipleView = false;
3323 SequenceI referenceseqForView = null;
3324 // JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
3325 List<JSeq> jseqs = jalviewModel.getJSeq();
3326 int vi = 0; // counter in vamsasSeq array
3327 for (int i = 0; i < jseqs.size(); i++)
3329 JSeq jseq = jseqs.get(i);
3330 String seqId = jseq.getId();
3332 SequenceI tmpSeq = seqRefIds.get(seqId);
3335 if (!incompleteSeqs.containsKey(seqId))
3337 // may not need this check, but keep it for at least 2.9,1 release
3338 if (tmpSeq.getStart() != jseq.getStart()
3339 || tmpSeq.getEnd() != jseq.getEnd())
3342 "Warning JAL-2154 regression: updating start/end for sequence "
3343 + tmpSeq.toString() + " to " + jseq);
3348 incompleteSeqs.remove(seqId);
3350 if (vamsasSeqs.size() > vi
3351 && vamsasSeqs.get(vi).getId().equals(seqId))
3353 // most likely we are reading a dataset XML document so
3354 // update from vamsasSeq section of XML for this sequence
3355 tmpSeq.setName(vamsasSeqs.get(vi).getName());
3356 tmpSeq.setDescription(vamsasSeqs.get(vi).getDescription());
3357 tmpSeq.setSequence(vamsasSeqs.get(vi).getSequence());
3362 // reading multiple views, so vamsasSeq set is a subset of JSeq
3363 multipleView = true;
3365 tmpSeq.setStart(jseq.getStart());
3366 tmpSeq.setEnd(jseq.getEnd());
3367 tmpseqs.add(tmpSeq);
3371 Sequence vamsasSeq = vamsasSeqs.get(vi);
3372 tmpSeq = new jalview.datamodel.Sequence(vamsasSeq.getName(),
3373 vamsasSeq.getSequence());
3374 tmpSeq.setDescription(vamsasSeq.getDescription());
3375 tmpSeq.setStart(jseq.getStart());
3376 tmpSeq.setEnd(jseq.getEnd());
3377 tmpSeq.setVamsasId(uniqueSetSuffix + seqId);
3378 seqRefIds.put(vamsasSeq.getId(), tmpSeq);
3379 tmpseqs.add(tmpSeq);
3383 if (safeBoolean(jseq.isViewreference()))
3385 referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
3388 if (jseq.isHidden() != null && jseq.isHidden().booleanValue())
3390 if (hiddenSeqs == null)
3392 hiddenSeqs = new ArrayList<>();
3395 hiddenSeqs.add(tmpSeq);
3400 // Create the alignment object from the sequence set
3401 // ///////////////////////////////
3402 SequenceI[] orderedSeqs = tmpseqs
3403 .toArray(new SequenceI[tmpseqs.size()]);
3405 AlignmentI al = null;
3406 // so we must create or recover the dataset alignment before going further
3407 // ///////////////////////////////
3408 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
3410 // older jalview projects do not have a dataset - so creat alignment and
3412 al = new Alignment(orderedSeqs);
3413 al.setDataset(null);
3417 boolean isdsal = jalviewModel.getViewport().isEmpty();
3420 // we are importing a dataset record, so
3421 // recover reference to an alignment already materialsed as dataset
3422 al = getDatasetFor(vamsasSet.getDatasetId());
3426 // materialse the alignment
3427 al = new Alignment(orderedSeqs);
3431 addDatasetRef(vamsasSet.getDatasetId(), al);
3434 // finally, verify all data in vamsasSet is actually present in al
3435 // passing on flag indicating if it is actually a stored dataset
3436 recoverDatasetFor(vamsasSet, al, isdsal, uniqueSeqSetId);
3439 if (referenceseqForView != null)
3441 al.setSeqrep(referenceseqForView);
3443 // / Add the alignment properties
3444 for (int i = 0; i < vamsasSet.getSequenceSetProperties().size(); i++)
3446 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties()
3448 al.setProperty(ssp.getKey(), ssp.getValue());
3451 // ///////////////////////////////
3453 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
3456 // load sequence features, database references and any associated PDB
3457 // structures for the alignment
3459 // prior to 2.10, this part would only be executed the first time a
3460 // sequence was encountered, but not afterwards.
3461 // now, for 2.10 projects, this is also done if the xml doc includes
3462 // dataset sequences not actually present in any particular view.
3464 for (int i = 0; i < vamsasSeqs.size(); i++)
3466 JSeq jseq = jseqs.get(i);
3467 if (jseq.getFeatures().size() > 0)
3469 List<Feature> features = jseq.getFeatures();
3470 for (int f = 0; f < features.size(); f++)
3472 Feature feat = features.get(f);
3473 SequenceFeature sf = new SequenceFeature(feat.getType(),
3474 feat.getDescription(), feat.getBegin(), feat.getEnd(),
3475 safeFloat(feat.getScore()), feat.getFeatureGroup());
3476 sf.setStatus(feat.getStatus());
3479 * load any feature attributes - include map-valued attributes
3481 Map<String, Map<String, String>> mapAttributes = new HashMap<>();
3482 for (int od = 0; od < feat.getOtherData().size(); od++)
3484 OtherData keyValue = feat.getOtherData().get(od);
3485 String attributeName = keyValue.getKey();
3486 String attributeValue = keyValue.getValue();
3487 if (attributeName.startsWith("LINK"))
3489 sf.addLink(attributeValue);
3493 String subAttribute = keyValue.getKey2();
3494 if (subAttribute == null)
3496 // simple string-valued attribute
3497 sf.setValue(attributeName, attributeValue);
3501 // attribute 'key' has sub-attribute 'key2'
3502 if (!mapAttributes.containsKey(attributeName))
3504 mapAttributes.put(attributeName, new HashMap<>());
3506 mapAttributes.get(attributeName).put(subAttribute,
3511 for (Entry<String, Map<String, String>> mapAttribute : mapAttributes
3514 sf.setValue(mapAttribute.getKey(), mapAttribute.getValue());
3517 // adds feature to datasequence's feature set (since Jalview 2.10)
3518 al.getSequenceAt(i).addSequenceFeature(sf);
3521 if (vamsasSeqs.get(i).getDBRef().size() > 0)
3523 // adds dbrefs to datasequence's set (since Jalview 2.10)
3525 al.getSequenceAt(i).getDatasetSequence() == null
3526 ? al.getSequenceAt(i)
3527 : al.getSequenceAt(i).getDatasetSequence(),
3530 if (jseq.getPdbids().size() > 0)
3532 List<Pdbids> ids = jseq.getPdbids();
3533 for (int p = 0; p < ids.size(); p++)
3535 Pdbids pdbid = ids.get(p);
3536 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
3537 entry.setId(pdbid.getId());
3538 if (pdbid.getType() != null)
3540 if (PDBEntry.Type.getType(pdbid.getType()) != null)
3542 entry.setType(PDBEntry.Type.getType(pdbid.getType()));
3546 entry.setType(PDBEntry.Type.FILE);
3549 // jprovider is null when executing 'New View'
3550 if (pdbid.getFile() != null && jprovider != null)
3552 if (!pdbloaded.containsKey(pdbid.getFile()))
3554 entry.setFile(loadPDBFile(jprovider, pdbid.getId(),
3559 entry.setFile(pdbloaded.get(pdbid.getId()).toString());
3563 if (pdbid.getPdbentryItem() != null)
3565 for (PdbentryItem item : pdbid.getPdbentryItem())
3567 for (Property pr : item.getProperty())
3569 entry.setProperty(pr.getName(), pr.getValue());
3574 for (Property prop : pdbid.getProperty())
3576 entry.setProperty(prop.getName(), prop.getValue());
3578 StructureSelectionManager
3579 .getStructureSelectionManager(Desktop.instance)
3580 .registerPDBEntry(entry);
3581 // adds PDBEntry to datasequence's set (since Jalview 2.10)
3582 if (al.getSequenceAt(i).getDatasetSequence() != null)
3584 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
3588 al.getSequenceAt(i).addPDBId(entry);
3593 } // end !multipleview
3595 // ///////////////////////////////
3596 // LOAD SEQUENCE MAPPINGS
3598 if (vamsasSet.getAlcodonFrame().size() > 0)
3600 // TODO Potentially this should only be done once for all views of an
3602 List<AlcodonFrame> alc = vamsasSet.getAlcodonFrame();
3603 for (int i = 0; i < alc.size(); i++)
3605 AlignedCodonFrame cf = new AlignedCodonFrame();
3606 if (alc.get(i).getAlcodMap().size() > 0)
3608 List<AlcodMap> maps = alc.get(i).getAlcodMap();
3609 for (int m = 0; m < maps.size(); m++)
3611 AlcodMap map = maps.get(m);
3612 SequenceI dnaseq = seqRefIds.get(map.getDnasq());
3614 jalview.datamodel.Mapping mapping = null;
3615 // attach to dna sequence reference.
3616 if (map.getMapping() != null)
3618 mapping = addMapping(map.getMapping());
3619 if (dnaseq != null && mapping.getTo() != null)
3621 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
3627 newAlcodMapRef(map.getDnasq(), cf, mapping));
3631 al.addCodonFrame(cf);
3636 // ////////////////////////////////
3638 List<JvAnnotRow> autoAlan = new ArrayList<>();
3641 * store any annotations which forward reference a group's ID
3643 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<>();
3645 if (vamsasSet.getAnnotation().size()/*Count()*/ > 0)
3647 List<Annotation> an = vamsasSet.getAnnotation();
3649 for (int i = 0; i < an.size(); i++)
3651 Annotation annotation = an.get(i);
3654 * test if annotation is automatically calculated for this view only
3656 boolean autoForView = false;
3657 if (annotation.getLabel().equals("Quality")
3658 || annotation.getLabel().equals("Conservation")
3659 || annotation.getLabel().equals("Consensus"))
3661 // Kludge for pre 2.5 projects which lacked the autocalculated flag
3663 // JAXB has no has() test; schema defaults value to false
3664 // if (!annotation.hasAutoCalculated())
3666 // annotation.setAutoCalculated(true);
3669 if (autoForView || annotation.isAutoCalculated())
3671 // remove ID - we don't recover annotation from other views for
3672 // view-specific annotation
3673 annotation.setId(null);
3676 // set visibility for other annotation in this view
3677 String annotationId = annotation.getId();
3678 if (annotationId != null && annotationIds.containsKey(annotationId))
3680 AlignmentAnnotation jda = annotationIds.get(annotationId);
3681 // in principle Visible should always be true for annotation displayed
3682 // in multiple views
3683 if (annotation.isVisible() != null)
3685 jda.visible = annotation.isVisible();
3688 al.addAnnotation(jda);
3692 // Construct new annotation from model.
3693 List<AnnotationElement> ae = annotation.getAnnotationElement();
3694 jalview.datamodel.Annotation[] anot = null;
3695 java.awt.Color firstColour = null;
3697 if (!annotation.isScoreOnly())
3699 anot = new jalview.datamodel.Annotation[al.getWidth()];
3700 for (int aa = 0; aa < ae.size() && aa < anot.length; aa++)
3702 AnnotationElement annElement = ae.get(aa);
3703 anpos = annElement.getPosition();
3705 if (anpos >= anot.length)
3710 float value = safeFloat(annElement.getValue());
3711 anot[anpos] = new jalview.datamodel.Annotation(
3712 annElement.getDisplayCharacter(),
3713 annElement.getDescription(),
3714 (annElement.getSecondaryStructure() == null
3715 || annElement.getSecondaryStructure()
3719 .getSecondaryStructure()
3722 anot[anpos].colour = new Color(safeInt(annElement.getColour()));
3723 if (firstColour == null)
3725 firstColour = anot[anpos].colour;
3729 jalview.datamodel.AlignmentAnnotation jaa = null;
3731 if (annotation.isGraph())
3733 float llim = 0, hlim = 0;
3734 // if (autoForView || an[i].isAutoCalculated()) {
3737 jaa = new jalview.datamodel.AlignmentAnnotation(
3738 annotation.getLabel(), annotation.getDescription(), anot,
3739 llim, hlim, safeInt(annotation.getGraphType()));
3741 jaa.graphGroup = safeInt(annotation.getGraphGroup());
3742 jaa._linecolour = firstColour;
3743 if (annotation.getThresholdLine() != null)
3745 jaa.setThreshold(new jalview.datamodel.GraphLine(
3746 safeFloat(annotation.getThresholdLine().getValue()),
3747 annotation.getThresholdLine().getLabel(),
3748 new java.awt.Color(safeInt(
3749 annotation.getThresholdLine().getColour()))));
3751 if (autoForView || annotation.isAutoCalculated())
3753 // Hardwire the symbol display line to ensure that labels for
3754 // histograms are displayed
3760 jaa = new jalview.datamodel.AlignmentAnnotation(
3761 annotation.getLabel(), annotation.getDescription(), anot);
3762 jaa._linecolour = firstColour;
3764 // register new annotation
3765 if (annotation.getId() != null)
3767 annotationIds.put(annotation.getId(), jaa);
3768 jaa.annotationId = annotation.getId();
3770 // recover sequence association
3771 String sequenceRef = annotation.getSequenceRef();
3772 if (sequenceRef != null)
3774 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3775 SequenceI sequence = seqRefIds.get(sequenceRef);
3776 if (sequence == null)
3778 // in pre-2.9 projects sequence ref is to sequence name
3779 sequence = al.findName(sequenceRef);
3781 if (sequence != null)
3783 jaa.createSequenceMapping(sequence, 1, true);
3784 sequence.addAlignmentAnnotation(jaa);
3787 // and make a note of any group association
3788 if (annotation.getGroupRef() != null
3789 && annotation.getGroupRef().length() > 0)
3791 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3792 .get(annotation.getGroupRef());
3795 aal = new ArrayList<>();
3796 groupAnnotRefs.put(annotation.getGroupRef(), aal);
3801 if (annotation.getScore() != null)
3803 jaa.setScore(annotation.getScore().doubleValue());
3805 if (annotation.isVisible() != null)
3807 jaa.visible = annotation.isVisible().booleanValue();
3810 if (annotation.isCentreColLabels() != null)
3812 jaa.centreColLabels = annotation.isCentreColLabels()
3816 if (annotation.isScaleColLabels() != null)
3818 jaa.scaleColLabel = annotation.isScaleColLabels().booleanValue();
3820 if (annotation.isAutoCalculated())
3822 // newer files have an 'autoCalculated' flag and store calculation
3823 // state in viewport properties
3824 jaa.autoCalculated = true; // means annotation will be marked for
3825 // update at end of load.
3827 if (annotation.getGraphHeight() != null)
3829 jaa.graphHeight = annotation.getGraphHeight().intValue();
3831 jaa.belowAlignment = annotation.isBelowAlignment();
3832 jaa.setCalcId(annotation.getCalcId());
3833 if (annotation.getProperty().size() > 0)
3835 for (Annotation.Property prop : annotation
3838 jaa.setProperty(prop.getName(), prop.getValue());
3841 if (jaa.autoCalculated)
3843 autoAlan.add(new JvAnnotRow(i, jaa));
3846 // if (!autoForView)
3848 // add autocalculated group annotation and any user created annotation
3850 al.addAnnotation(jaa);
3854 // ///////////////////////
3856 // Create alignment markup and styles for this view
3857 if (jalviewModel.getJGroup().size() > 0)
3859 List<JGroup> groups = jalviewModel.getJGroup();
3860 boolean addAnnotSchemeGroup = false;
3861 for (int i = 0; i < groups.size(); i++)
3863 JGroup jGroup = groups.get(i);
3864 ColourSchemeI cs = null;
3865 if (jGroup.getColour() != null)
3867 if (jGroup.getColour().startsWith("ucs"))
3869 cs = getUserColourScheme(jalviewModel, jGroup.getColour());
3871 else if (jGroup.getColour().equals("AnnotationColourGradient")
3872 && jGroup.getAnnotationColours() != null)
3874 addAnnotSchemeGroup = true;
3878 cs = ColourSchemeProperty.getColourScheme(null, al,
3879 jGroup.getColour());
3882 int pidThreshold = safeInt(jGroup.getPidThreshold());
3884 Vector<SequenceI> seqs = new Vector<>();
3886 for (int s = 0; s < jGroup.getSeq().size(); s++)
3888 String seqId = jGroup.getSeq().get(s);
3889 SequenceI ts = seqRefIds.get(seqId);
3893 seqs.addElement(ts);
3897 if (seqs.size() < 1)
3902 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3903 safeBoolean(jGroup.isDisplayBoxes()),
3904 safeBoolean(jGroup.isDisplayText()),
3905 safeBoolean(jGroup.isColourText()),
3906 safeInt(jGroup.getStart()), safeInt(jGroup.getEnd()));
3907 sg.getGroupColourScheme().setThreshold(pidThreshold, true);
3908 sg.getGroupColourScheme()
3909 .setConservationInc(safeInt(jGroup.getConsThreshold()));
3910 sg.setOutlineColour(new Color(safeInt(jGroup.getOutlineColour())));
3912 sg.textColour = new Color(safeInt(jGroup.getTextCol1()));
3913 sg.textColour2 = new Color(safeInt(jGroup.getTextCol2()));
3914 sg.setShowNonconserved(safeBoolean(jGroup.isShowUnconserved()));
3915 sg.thresholdTextColour = safeInt(jGroup.getTextColThreshold());
3916 // attributes with a default in the schema are never null
3917 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3918 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3919 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3920 sg.setIgnoreGapsConsensus(jGroup.isIgnoreGapsinConsensus());
3921 if (jGroup.getConsThreshold() != null
3922 && jGroup.getConsThreshold().intValue() != 0)
3924 Conservation c = new Conservation("All", sg.getSequences(null), 0,
3927 c.verdict(false, 25);
3928 sg.cs.setConservation(c);
3931 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3933 // re-instate unique group/annotation row reference
3934 List<AlignmentAnnotation> jaal = groupAnnotRefs
3935 .get(jGroup.getId());
3938 for (AlignmentAnnotation jaa : jaal)
3941 if (jaa.autoCalculated)
3943 // match up and try to set group autocalc alignment row for this
3945 if (jaa.label.startsWith("Consensus for "))
3947 sg.setConsensus(jaa);
3949 // match up and try to set group autocalc alignment row for this
3951 if (jaa.label.startsWith("Conservation for "))
3953 sg.setConservationRow(jaa);
3960 if (addAnnotSchemeGroup)
3962 // reconstruct the annotation colourscheme
3963 sg.setColourScheme(constructAnnotationColour(
3964 jGroup.getAnnotationColours(), null, al, jalviewModel, false));
3970 // only dataset in this model, so just return.
3973 // ///////////////////////////////
3976 AlignFrame af = null;
3977 AlignViewport av = null;
3978 // now check to see if we really need to create a new viewport.
3979 if (multipleView && viewportsAdded.size() == 0)
3981 // We recovered an alignment for which a viewport already exists.
3982 // TODO: fix up any settings necessary for overlaying stored state onto
3983 // state recovered from another document. (may not be necessary).
3984 // we may need a binding from a viewport in memory to one recovered from
3986 // and then recover its containing af to allow the settings to be applied.
3987 // TODO: fix for vamsas demo
3989 "About to recover a viewport for existing alignment: Sequence set ID is "
3991 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3992 if (seqsetobj != null)
3994 if (seqsetobj instanceof String)
3996 uniqueSeqSetId = (String) seqsetobj;
3998 "Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
4004 "Warning : Collision between sequence set ID string and existing jalview object mapping.");
4010 * indicate that annotation colours are applied across all groups (pre
4011 * Jalview 2.8.1 behaviour)
4013 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan("2.8.1",
4014 jalviewModel.getVersion());
4016 AlignmentPanel ap = null;
4017 boolean isnewview = true;
4020 // Check to see if this alignment already has a view id == viewId
4021 jalview.gui.AlignmentPanel views[] = Desktop
4022 .getAlignmentPanels(uniqueSeqSetId);
4023 if (views != null && views.length > 0)
4025 for (int v = 0; v < views.length; v++)
4027 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
4029 // recover the existing alignpanel, alignframe, viewport
4030 af = views[v].alignFrame;
4033 // TODO: could even skip resetting view settings if we don't want to
4034 // change the local settings from other jalview processes
4043 af = loadViewport(file, jseqs, hiddenSeqs, al, jalviewModel, view,
4044 uniqueSeqSetId, viewId, autoAlan);
4045 av = af.getViewport();
4050 * Load any trees, PDB structures and viewers
4052 * Not done if flag is false (when this method is used for New View)
4054 if (loadTreesAndStructures)
4056 loadTrees(jalviewModel, view, af, av, ap);
4057 loadPCAViewers(jalviewModel, ap);
4058 loadPDBStructures(jprovider, jseqs, af, ap);
4059 loadRnaViewers(jprovider, jseqs, ap);
4061 // and finally return.
4066 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
4067 * panel is restored from separate jar entries, two (gapped and trimmed) per
4068 * sequence and secondary structure.
4070 * Currently each viewer shows just one sequence and structure (gapped and
4071 * trimmed), however this method is designed to support multiple sequences or
4072 * structures in viewers if wanted in future.
4078 private void loadRnaViewers(jarInputStreamProvider jprovider,
4079 List<JSeq> jseqs, AlignmentPanel ap)
4082 * scan the sequences for references to viewers; create each one the first
4083 * time it is referenced, add Rna models to existing viewers
4085 for (JSeq jseq : jseqs)
4087 for (int i = 0; i < jseq.getRnaViewer().size(); i++)
4089 RnaViewer viewer = jseq.getRnaViewer().get(i);
4090 AppVarna appVarna = findOrCreateVarnaViewer(viewer, uniqueSetSuffix,
4093 for (int j = 0; j < viewer.getSecondaryStructure().size(); j++)
4095 SecondaryStructure ss = viewer.getSecondaryStructure().get(j);
4096 SequenceI seq = seqRefIds.get(jseq.getId());
4097 AlignmentAnnotation ann = this.annotationIds
4098 .get(ss.getAnnotationId());
4101 * add the structure to the Varna display (with session state copied
4102 * from the jar to a temporary file)
4104 boolean gapped = safeBoolean(ss.isGapped());
4105 String rnaTitle = ss.getTitle();
4106 String sessionState = ss.getViewerState();
4107 String tempStateFile = copyJarEntry(jprovider, sessionState,
4109 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
4110 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
4112 appVarna.setInitialSelection(safeInt(viewer.getSelectedRna()));
4118 * Locate and return an already instantiated matching AppVarna, or create one
4122 * @param viewIdSuffix
4126 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
4127 String viewIdSuffix, AlignmentPanel ap)
4130 * on each load a suffix is appended to the saved viewId, to avoid conflicts
4131 * if load is repeated
4133 String postLoadId = viewer.getViewId() + viewIdSuffix;
4134 for (JInternalFrame frame : getAllFrames())
4136 if (frame instanceof AppVarna)
4138 AppVarna varna = (AppVarna) frame;
4139 if (postLoadId.equals(varna.getViewId()))
4141 // this viewer is already instantiated
4142 // could in future here add ap as another 'parent' of the
4143 // AppVarna window; currently just 1-to-many
4150 * viewer not found - make it
4152 RnaViewerModel model = new RnaViewerModel(postLoadId, viewer.getTitle(),
4153 safeInt(viewer.getXpos()), safeInt(viewer.getYpos()),
4154 safeInt(viewer.getWidth()), safeInt(viewer.getHeight()),
4155 safeInt(viewer.getDividerLocation()));
4156 AppVarna varna = new AppVarna(model, ap);
4162 * Load any saved trees
4170 protected void loadTrees(JalviewModel jm, Viewport view,
4171 AlignFrame af, AlignViewport av, AlignmentPanel ap)
4173 // TODO result of automated refactoring - are all these parameters needed?
4176 for (int t = 0; t < jm.getTree().size(); t++)
4179 Tree tree = jm.getTree().get(t);
4181 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
4184 tp = af.showNewickTree(new NewickFile(tree.getNewick()),
4185 tree.getTitle(), safeInt(tree.getWidth()),
4186 safeInt(tree.getHeight()), safeInt(tree.getXpos()),
4187 safeInt(tree.getYpos()));
4188 if (tree.getId() != null)
4190 // perhaps bind the tree id to something ?
4195 // update local tree attributes ?
4196 // TODO: should check if tp has been manipulated by user - if so its
4197 // settings shouldn't be modified
4198 tp.setTitle(tree.getTitle());
4199 tp.setBounds(new Rectangle(safeInt(tree.getXpos()),
4200 safeInt(tree.getYpos()), safeInt(tree.getWidth()),
4201 safeInt(tree.getHeight())));
4202 tp.setViewport(av); // af.viewport;
4203 // TODO: verify 'associate with all views' works still
4204 tp.getTreeCanvas().setViewport(av); // af.viewport;
4205 tp.getTreeCanvas().setAssociatedPanel(ap); // af.alignPanel;
4207 tp.getTreeCanvas().setApplyToAllViews(tree.isLinkToAllViews());
4210 warn("There was a problem recovering stored Newick tree: \n"
4211 + tree.getNewick());
4215 tp.fitToWindow.setState(safeBoolean(tree.isFitToWindow()));
4216 tp.fitToWindow_actionPerformed(null);
4218 if (tree.getFontName() != null)
4221 new Font(tree.getFontName(), safeInt(tree.getFontStyle()),
4222 safeInt(tree.getFontSize())));
4227 new Font(view.getFontName(), safeInt(view.getFontStyle()),
4228 safeInt(view.getFontSize())));
4231 tp.showPlaceholders(safeBoolean(tree.isMarkUnlinked()));
4232 tp.showBootstrap(safeBoolean(tree.isShowBootstrap()));
4233 tp.showDistances(safeBoolean(tree.isShowDistances()));
4235 tp.getTreeCanvas().setThreshold(safeFloat(tree.getThreshold()));
4237 if (safeBoolean(tree.isCurrentTree()))
4239 af.getViewport().setCurrentTree(tp.getTree());
4243 } catch (Exception ex)
4245 ex.printStackTrace();
4250 * Load and link any saved structure viewers.
4257 protected void loadPDBStructures(jarInputStreamProvider jprovider,
4258 List<JSeq> jseqs, AlignFrame af, AlignmentPanel ap)
4261 * Run through all PDB ids on the alignment, and collect mappings between
4262 * distinct view ids and all sequences referring to that view.
4264 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<>();
4266 for (int i = 0; i < jseqs.size(); i++)
4268 JSeq jseq = jseqs.get(i);
4269 if (jseq.getPdbids().size() > 0)
4271 List<Pdbids> ids = jseq.getPdbids();
4272 for (int p = 0; p < ids.size(); p++)
4274 Pdbids pdbid = ids.get(p);
4275 final int structureStateCount = pdbid.getStructureState().size();
4276 for (int s = 0; s < structureStateCount; s++)
4278 // check to see if we haven't already created this structure view
4279 final StructureState structureState = pdbid
4280 .getStructureState().get(s);
4281 String sviewid = (structureState.getViewId() == null) ? null
4282 : structureState.getViewId() + uniqueSetSuffix;
4283 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
4284 // Originally : pdbid.getFile()
4285 // : TODO: verify external PDB file recovery still works in normal
4286 // jalview project load
4288 loadPDBFile(jprovider, pdbid.getId(), pdbid.getFile()));
4289 jpdb.setId(pdbid.getId());
4291 int x = safeInt(structureState.getXpos());
4292 int y = safeInt(structureState.getYpos());
4293 int width = safeInt(structureState.getWidth());
4294 int height = safeInt(structureState.getHeight());
4296 // Probably don't need to do this anymore...
4297 // Desktop.desktop.getComponentAt(x, y);
4298 // TODO: NOW: check that this recovers the PDB file correctly.
4299 String pdbFile = loadPDBFile(jprovider, pdbid.getId(),
4301 jalview.datamodel.SequenceI seq = seqRefIds
4302 .get(jseq.getId() + "");
4303 if (sviewid == null)
4305 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width + ","
4308 if (!structureViewers.containsKey(sviewid))
4310 structureViewers.put(sviewid,
4311 new StructureViewerModel(x, y, width, height, false,
4312 false, true, structureState.getViewId(),
4313 structureState.getType()));
4314 // Legacy pre-2.7 conversion JAL-823 :
4315 // do not assume any view has to be linked for colour by
4319 // assemble String[] { pdb files }, String[] { id for each
4320 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
4321 // seqs_file 2}, boolean[] {
4322 // linkAlignPanel,superposeWithAlignpanel}} from hash
4323 StructureViewerModel jmoldat = structureViewers.get(sviewid);
4324 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
4325 || structureState.isAlignwithAlignPanel());
4328 * Default colour by linked panel to false if not specified (e.g.
4329 * for pre-2.7 projects)
4331 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
4332 colourWithAlignPanel |= structureState.isColourwithAlignPanel();
4333 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
4336 * Default colour by viewer to true if not specified (e.g. for
4339 boolean colourByViewer = jmoldat.isColourByViewer();
4340 colourByViewer &= structureState.isColourByJmol();
4341 jmoldat.setColourByViewer(colourByViewer);
4343 if (jmoldat.getStateData().length() < structureState
4344 .getValue()/*Content()*/.length())
4346 jmoldat.setStateData(structureState.getValue());// Content());
4348 if (pdbid.getFile() != null)
4350 File mapkey = new File(pdbid.getFile());
4351 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
4352 if (seqstrmaps == null)
4354 jmoldat.getFileData().put(mapkey,
4355 seqstrmaps = jmoldat.new StructureData(pdbFile,
4358 if (!seqstrmaps.getSeqList().contains(seq))
4360 seqstrmaps.getSeqList().add(seq);
4366 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");
4373 // Instantiate the associated structure views
4374 for (Entry<String, StructureViewerModel> entry : structureViewers
4379 createOrLinkStructureViewer(entry, af, ap, jprovider);
4380 } catch (Exception e)
4383 "Error loading structure viewer: " + e.getMessage());
4384 // failed - try the next one
4396 protected void createOrLinkStructureViewer(
4397 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4398 AlignmentPanel ap, jarInputStreamProvider jprovider)
4400 final StructureViewerModel stateData = viewerData.getValue();
4403 * Search for any viewer windows already open from other alignment views
4404 * that exactly match the stored structure state
4406 StructureViewerBase comp = findMatchingViewer(viewerData);
4410 linkStructureViewer(ap, comp, stateData);
4415 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
4416 * "viewer_"+stateData.viewId
4418 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
4420 createChimeraViewer(viewerData, af, jprovider);
4425 * else Jmol (if pre-2.9, stateData contains JMOL state string)
4427 createJmolViewer(viewerData, af, jprovider);
4432 * Create a new Chimera viewer.
4438 protected void createChimeraViewer(
4439 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4440 jarInputStreamProvider jprovider)
4442 StructureViewerModel data = viewerData.getValue();
4443 String chimeraSessionFile = data.getStateData();
4446 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
4448 * NB this is the 'saved' viewId as in the project file XML, _not_ the
4449 * 'uniquified' sviewid used to reconstruct the viewer here
4451 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
4452 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
4455 Set<Entry<File, StructureData>> fileData = data.getFileData()
4457 List<PDBEntry> pdbs = new ArrayList<>();
4458 List<SequenceI[]> allseqs = new ArrayList<>();
4459 for (Entry<File, StructureData> pdb : fileData)
4461 String filePath = pdb.getValue().getFilePath();
4462 String pdbId = pdb.getValue().getPdbId();
4463 // pdbs.add(new PDBEntry(filePath, pdbId));
4464 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
4465 final List<SequenceI> seqList = pdb.getValue().getSeqList();
4466 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
4470 boolean colourByChimera = data.isColourByViewer();
4471 boolean colourBySequence = data.isColourWithAlignPanel();
4473 // TODO use StructureViewer as a factory here, see JAL-1761
4474 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
4475 final SequenceI[][] seqsArray = allseqs
4476 .toArray(new SequenceI[allseqs.size()][]);
4477 String newViewId = viewerData.getKey();
4479 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
4480 af.alignPanel, pdbArray, seqsArray, colourByChimera,
4481 colourBySequence, newViewId);
4482 cvf.setSize(data.getWidth(), data.getHeight());
4483 cvf.setLocation(data.getX(), data.getY());
4487 * Create a new Jmol window. First parse the Jmol state to translate filenames
4488 * loaded into the view, and record the order in which files are shown in the
4489 * Jmol view, so we can add the sequence mappings in same order.
4495 protected void createJmolViewer(
4496 final Entry<String, StructureViewerModel> viewerData,
4497 AlignFrame af, jarInputStreamProvider jprovider)
4499 final StructureViewerModel svattrib = viewerData.getValue();
4500 String state = svattrib.getStateData();
4503 * Pre-2.9: state element value is the Jmol state string
4505 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
4508 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
4510 state = readJarEntry(jprovider,
4511 getViewerJarEntryName(svattrib.getViewId()));
4514 List<String> pdbfilenames = new ArrayList<>();
4515 List<SequenceI[]> seqmaps = new ArrayList<>();
4516 List<String> pdbids = new ArrayList<>();
4517 StringBuilder newFileLoc = new StringBuilder(64);
4518 int cp = 0, ncp, ecp;
4519 Map<File, StructureData> oldFiles = svattrib.getFileData();
4520 while ((ncp = state.indexOf("load ", cp)) > -1)
4524 // look for next filename in load statement
4525 newFileLoc.append(state.substring(cp,
4526 ncp = (state.indexOf("\"", ncp + 1) + 1)));
4527 String oldfilenam = state.substring(ncp,
4528 ecp = state.indexOf("\"", ncp));
4529 // recover the new mapping data for this old filename
4530 // have to normalize filename - since Jmol and jalview do
4532 // translation differently.
4533 StructureData filedat = oldFiles.get(new File(oldfilenam));
4534 if (filedat == null)
4536 String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\");
4537 filedat = oldFiles.get(new File(reformatedOldFilename));
4539 newFileLoc.append(Platform.escapeBackslashes(filedat.getFilePath()));
4540 pdbfilenames.add(filedat.getFilePath());
4541 pdbids.add(filedat.getPdbId());
4542 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4543 newFileLoc.append("\"");
4544 cp = ecp + 1; // advance beyond last \" and set cursor so we can
4545 // look for next file statement.
4546 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
4550 // just append rest of state
4551 newFileLoc.append(state.substring(cp));
4555 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
4556 newFileLoc = new StringBuilder(state);
4557 newFileLoc.append("; load append ");
4558 for (File id : oldFiles.keySet())
4560 // add this and any other pdb files that should be present in
4562 StructureData filedat = oldFiles.get(id);
4563 newFileLoc.append(filedat.getFilePath());
4564 pdbfilenames.add(filedat.getFilePath());
4565 pdbids.add(filedat.getPdbId());
4566 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4567 newFileLoc.append(" \"");
4568 newFileLoc.append(filedat.getFilePath());
4569 newFileLoc.append("\"");
4572 newFileLoc.append(";");
4575 if (newFileLoc.length() == 0)
4579 int histbug = newFileLoc.indexOf("history = ");
4583 * change "history = [true|false];" to "history = [1|0];"
4586 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
4587 String val = (diff == -1) ? null
4588 : newFileLoc.substring(histbug, diff);
4589 if (val != null && val.length() >= 4)
4591 if (val.contains("e")) // eh? what can it be?
4593 if (val.trim().equals("true"))
4601 newFileLoc.replace(histbug, diff, val);
4606 final String[] pdbf = pdbfilenames
4607 .toArray(new String[pdbfilenames.size()]);
4608 final String[] id = pdbids.toArray(new String[pdbids.size()]);
4609 final SequenceI[][] sq = seqmaps
4610 .toArray(new SequenceI[seqmaps.size()][]);
4611 final String fileloc = newFileLoc.toString();
4612 final String sviewid = viewerData.getKey();
4613 final AlignFrame alf = af;
4614 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
4615 svattrib.getWidth(), svattrib.getHeight());
4618 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
4623 JalviewStructureDisplayI sview = null;
4626 sview = new StructureViewer(
4627 alf.alignPanel.getStructureSelectionManager())
4628 .createView(StructureViewer.ViewerType.JMOL,
4629 pdbf, id, sq, alf.alignPanel, svattrib,
4630 fileloc, rect, sviewid);
4631 addNewStructureViewer(sview);
4632 } catch (OutOfMemoryError ex)
4634 new OOMWarning("restoring structure view for PDB id " + id,
4635 (OutOfMemoryError) ex.getCause());
4636 if (sview != null && sview.isVisible())
4638 sview.closeViewer(false);
4639 sview.setVisible(false);
4645 } catch (InvocationTargetException ex)
4647 warn("Unexpected error when opening Jmol view.", ex);
4649 } catch (InterruptedException e)
4651 // e.printStackTrace();
4657 * Generates a name for the entry in the project jar file to hold state
4658 * information for a structure viewer
4663 protected String getViewerJarEntryName(String viewId)
4665 return VIEWER_PREFIX + viewId;
4669 * Returns any open frame that matches given structure viewer data. The match
4670 * is based on the unique viewId, or (for older project versions) the frame's
4676 protected StructureViewerBase findMatchingViewer(
4677 Entry<String, StructureViewerModel> viewerData)
4679 final String sviewid = viewerData.getKey();
4680 final StructureViewerModel svattrib = viewerData.getValue();
4681 StructureViewerBase comp = null;
4682 JInternalFrame[] frames = getAllFrames();
4683 for (JInternalFrame frame : frames)
4685 if (frame instanceof StructureViewerBase)
4688 * Post jalview 2.4 schema includes structure view id
4690 if (sviewid != null && ((StructureViewerBase) frame).getViewId()
4693 comp = (StructureViewerBase) frame;
4694 break; // break added in 2.9
4697 * Otherwise test for matching position and size of viewer frame
4699 else if (frame.getX() == svattrib.getX()
4700 && frame.getY() == svattrib.getY()
4701 && frame.getHeight() == svattrib.getHeight()
4702 && frame.getWidth() == svattrib.getWidth())
4704 comp = (StructureViewerBase) frame;
4705 // no break in faint hope of an exact match on viewId
4713 * Link an AlignmentPanel to an existing structure viewer.
4718 * @param useinViewerSuperpos
4719 * @param usetoColourbyseq
4720 * @param viewerColouring
4722 protected void linkStructureViewer(AlignmentPanel ap,
4723 StructureViewerBase viewer, StructureViewerModel stateData)
4725 // NOTE: if the jalview project is part of a shared session then
4726 // view synchronization should/could be done here.
4728 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4729 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4730 final boolean viewerColouring = stateData.isColourByViewer();
4731 Map<File, StructureData> oldFiles = stateData.getFileData();
4734 * Add mapping for sequences in this view to an already open viewer
4736 final AAStructureBindingModel binding = viewer.getBinding();
4737 for (File id : oldFiles.keySet())
4739 // add this and any other pdb files that should be present in the
4741 StructureData filedat = oldFiles.get(id);
4742 String pdbFile = filedat.getFilePath();
4743 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4744 binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE,
4746 binding.addSequenceForStructFile(pdbFile, seq);
4748 // and add the AlignmentPanel's reference to the view panel
4749 viewer.addAlignmentPanel(ap);
4750 if (useinViewerSuperpos)
4752 viewer.useAlignmentPanelForSuperposition(ap);
4756 viewer.excludeAlignmentPanelForSuperposition(ap);
4758 if (usetoColourbyseq)
4760 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4764 viewer.excludeAlignmentPanelForColourbyseq(ap);
4769 * Get all frames within the Desktop.
4773 protected JInternalFrame[] getAllFrames()
4775 JInternalFrame[] frames = null;
4776 // TODO is this necessary - is it safe - risk of hanging?
4781 frames = Desktop.desktop.getAllFrames();
4782 } catch (ArrayIndexOutOfBoundsException e)
4784 // occasional No such child exceptions are thrown here...
4788 } catch (InterruptedException f)
4792 } while (frames == null);
4797 * Answers true if 'version' is equal to or later than 'supported', where each
4798 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4799 * changes. Development and test values for 'version' are leniently treated
4803 * - minimum version we are comparing against
4805 * - version of data being processsed
4808 public static boolean isVersionStringLaterThan(String supported,
4811 if (supported == null || version == null
4812 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4813 || version.equalsIgnoreCase("Test")
4814 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4816 System.err.println("Assuming project file with "
4817 + (version == null ? "null" : version)
4818 + " is compatible with Jalview version " + supported);
4823 return StringUtils.compareVersions(version, supported, "b") >= 0;
4827 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4829 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4831 if (newStructureViewers != null)
4833 sview.getBinding().setFinishedLoadingFromArchive(false);
4834 newStructureViewers.add(sview);
4838 protected void setLoadingFinishedForNewStructureViewers()
4840 if (newStructureViewers != null)
4842 for (JalviewStructureDisplayI sview : newStructureViewers)
4844 sview.getBinding().setFinishedLoadingFromArchive(true);
4846 newStructureViewers.clear();
4847 newStructureViewers = null;
4851 AlignFrame loadViewport(String file, List<JSeq> JSEQ,
4852 List<SequenceI> hiddenSeqs, AlignmentI al,
4853 JalviewModel jm, Viewport view, String uniqueSeqSetId,
4854 String viewId, List<JvAnnotRow> autoAlan)
4856 AlignFrame af = null;
4857 af = new AlignFrame(al, safeInt(view.getWidth()),
4858 safeInt(view.getHeight()), uniqueSeqSetId, viewId)
4862 // protected void processKeyEvent(java.awt.event.KeyEvent e) {
4863 // System.out.println("Jalview2XML AF " + e);
4864 // super.processKeyEvent(e);
4871 af.setFileName(file, FileFormat.Jalview);
4873 final AlignViewport viewport = af.getViewport();
4874 for (int i = 0; i < JSEQ.size(); i++)
4876 int colour = safeInt(JSEQ.get(i).getColour());
4877 viewport.setSequenceColour(viewport.getAlignment().getSequenceAt(i),
4883 viewport.setColourByReferenceSeq(true);
4884 viewport.setDisplayReferenceSeq(true);
4887 viewport.setGatherViewsHere(safeBoolean(view.isGatheredViews()));
4889 if (view.getSequenceSetId() != null)
4891 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4893 viewport.setSequenceSetId(uniqueSeqSetId);
4896 // propagate shared settings to this new view
4897 viewport.setHistoryList(av.getHistoryList());
4898 viewport.setRedoList(av.getRedoList());
4902 viewportsAdded.put(uniqueSeqSetId, viewport);
4904 // TODO: check if this method can be called repeatedly without
4905 // side-effects if alignpanel already registered.
4906 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4908 // apply Hidden regions to view.
4909 if (hiddenSeqs != null)
4911 for (int s = 0; s < JSEQ.size(); s++)
4913 SequenceGroup hidden = new SequenceGroup();
4914 boolean isRepresentative = false;
4915 for (int r = 0; r < JSEQ.get(s).getHiddenSequences().size(); r++)
4917 isRepresentative = true;
4918 SequenceI sequenceToHide = al
4919 .getSequenceAt(JSEQ.get(s).getHiddenSequences().get(r));
4920 hidden.addSequence(sequenceToHide, false);
4921 // remove from hiddenSeqs list so we don't try to hide it twice
4922 hiddenSeqs.remove(sequenceToHide);
4924 if (isRepresentative)
4926 SequenceI representativeSequence = al.getSequenceAt(s);
4927 hidden.addSequence(representativeSequence, false);
4928 viewport.hideRepSequences(representativeSequence, hidden);
4932 SequenceI[] hseqs = hiddenSeqs
4933 .toArray(new SequenceI[hiddenSeqs.size()]);
4934 viewport.hideSequence(hseqs);
4937 // recover view properties and display parameters
4939 viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
4940 viewport.setAbovePIDThreshold(safeBoolean(view.isPidSelected()));
4941 final int pidThreshold = safeInt(view.getPidThreshold());
4942 viewport.setThreshold(pidThreshold);
4944 viewport.setColourText(safeBoolean(view.isShowColourText()));
4947 .setConservationSelected(
4948 safeBoolean(view.isConservationSelected()));
4949 viewport.setIncrement(safeInt(view.getConsThreshold()));
4950 viewport.setShowJVSuffix(safeBoolean(view.isShowFullId()));
4951 viewport.setRightAlignIds(safeBoolean(view.isRightAlignIds()));
4952 viewport.setFont(new Font(view.getFontName(),
4953 safeInt(view.getFontStyle()), safeInt(view.getFontSize())),
4955 ViewStyleI vs = viewport.getViewStyle();
4956 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
4957 viewport.setViewStyle(vs);
4958 // TODO: allow custom charWidth/Heights to be restored by updating them
4959 // after setting font - which means set above to false
4960 viewport.setRenderGaps(safeBoolean(view.isRenderGaps()));
4961 viewport.setWrapAlignment(safeBoolean(view.isWrapAlignment()));
4962 viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
4964 viewport.setShowBoxes(safeBoolean(view.isShowBoxes()));
4966 viewport.setShowText(safeBoolean(view.isShowText()));
4968 viewport.setTextColour(new Color(safeInt(view.getTextCol1())));
4969 viewport.setTextColour2(new Color(safeInt(view.getTextCol2())));
4970 viewport.setThresholdTextColour(safeInt(view.getTextColThreshold()));
4971 viewport.setShowUnconserved(view.isShowUnconserved());
4972 viewport.getRanges().setStartRes(safeInt(view.getStartRes()));
4974 if (view.getViewName() != null)
4976 viewport.setViewName(view.getViewName());
4977 af.setInitialTabVisible();
4979 af.setBounds(safeInt(view.getXpos()), safeInt(view.getYpos()),
4980 safeInt(view.getWidth()), safeInt(view.getHeight()));
4981 // startSeq set in af.alignPanel.updateLayout below
4982 af.alignPanel.updateLayout();
4983 ColourSchemeI cs = null;
4984 // apply colourschemes
4985 if (view.getBgColour() != null)
4987 if (view.getBgColour().startsWith("ucs"))
4989 cs = getUserColourScheme(jm, view.getBgColour());
4991 else if (view.getBgColour().startsWith("Annotation"))
4993 AnnotationColourScheme viewAnnColour = view.getAnnotationColours();
4994 cs = constructAnnotationColour(viewAnnColour, af, al, jm, true);
5001 cs = ColourSchemeProperty.getColourScheme(af.getViewport(), al,
5002 view.getBgColour());
5007 * turn off 'alignment colour applies to all groups'
5008 * while restoring global colour scheme
5010 viewport.setColourAppliesToAllGroups(false);
5011 viewport.setGlobalColourScheme(cs);
5012 viewport.getResidueShading().setThreshold(pidThreshold,
5013 view.isIgnoreGapsinConsensus());
5014 viewport.getResidueShading()
5015 .setConsensus(viewport.getSequenceConsensusHash());
5016 if (safeBoolean(view.isConservationSelected()) && cs != null)
5018 viewport.getResidueShading()
5019 .setConservationInc(safeInt(view.getConsThreshold()));
5021 af.changeColour(cs);
5022 viewport.setColourAppliesToAllGroups(true);
5025 .setShowSequenceFeatures(
5026 safeBoolean(view.isShowSequenceFeatures()));
5028 viewport.setCentreColumnLabels(view.isCentreColumnLabels());
5029 viewport.setIgnoreGapsConsensus(view.isIgnoreGapsinConsensus(), null);
5030 viewport.setFollowHighlight(view.isFollowHighlight());
5031 viewport.followSelection = view.isFollowSelection();
5032 viewport.setShowConsensusHistogram(view.isShowConsensusHistogram());
5033 viewport.setShowSequenceLogo(view.isShowSequenceLogo());
5034 viewport.setNormaliseSequenceLogo(view.isNormaliseSequenceLogo());
5035 viewport.setShowDBRefs(safeBoolean(view.isShowDbRefTooltip()));
5036 viewport.setShowNPFeats(safeBoolean(view.isShowNPfeatureTooltip()));
5037 viewport.setShowGroupConsensus(view.isShowGroupConsensus());
5038 viewport.setShowGroupConservation(view.isShowGroupConservation());
5040 // recover feature settings
5041 if (jm.getFeatureSettings() != null)
5043 FeatureRenderer fr = af.alignPanel.getSeqPanel().seqCanvas
5044 .getFeatureRenderer();
5045 FeaturesDisplayed fdi;
5046 viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
5047 String[] renderOrder = new String[jm.getFeatureSettings()
5048 .getSetting().size()];
5049 Map<String, FeatureColourI> featureColours = new Hashtable<>();
5050 Map<String, Float> featureOrder = new Hashtable<>();
5052 for (int fs = 0; fs < jm.getFeatureSettings()
5053 .getSetting().size(); fs++)
5055 Setting setting = jm.getFeatureSettings().getSetting().get(fs);
5056 String featureType = setting.getType();
5059 * restore feature filters (if any)
5061 jalview.xml.binding.jalview.FeatureMatcherSet filters = setting
5063 if (filters != null)
5065 FeatureMatcherSetI filter = Jalview2XML
5066 .parseFilter(featureType, filters);
5067 if (!filter.isEmpty())
5069 fr.setFeatureFilter(featureType, filter);
5074 * restore feature colour scheme
5076 Color maxColour = new Color(setting.getColour());
5077 if (setting.getMincolour() != null)
5080 * minColour is always set unless a simple colour
5081 * (including for colour by label though it doesn't use it)
5083 Color minColour = new Color(setting.getMincolour().intValue());
5084 Color noValueColour = minColour;
5085 NoValueColour noColour = setting.getNoValueColour();
5086 if (noColour == NoValueColour.NONE)
5088 noValueColour = null;
5090 else if (noColour == NoValueColour.MAX)
5092 noValueColour = maxColour;
5094 float min = safeFloat(safeFloat(setting.getMin()));
5095 float max = setting.getMax() == null ? 1f
5096 : setting.getMax().floatValue();
5097 FeatureColourI gc = new FeatureColour(maxColour, minColour,
5099 noValueColour, min, max);
5100 if (setting.getAttributeName().size() > 0)
5102 gc.setAttributeName(setting.getAttributeName().toArray(
5103 new String[setting.getAttributeName().size()]));
5105 if (setting.getThreshold() != null)
5107 gc.setThreshold(setting.getThreshold().floatValue());
5108 int threshstate = safeInt(setting.getThreshstate());
5109 // -1 = None, 0 = Below, 1 = Above threshold
5110 if (threshstate == 0)
5112 gc.setBelowThreshold(true);
5114 else if (threshstate == 1)
5116 gc.setAboveThreshold(true);
5119 gc.setAutoScaled(true); // default
5120 if (setting.isAutoScale() != null)
5122 gc.setAutoScaled(setting.isAutoScale());
5124 if (setting.isColourByLabel() != null)
5126 gc.setColourByLabel(setting.isColourByLabel());
5128 // and put in the feature colour table.
5129 featureColours.put(featureType, gc);
5133 featureColours.put(featureType,
5134 new FeatureColour(maxColour));
5136 renderOrder[fs] = featureType;
5137 if (setting.getOrder() != null)
5139 featureOrder.put(featureType, setting.getOrder().floatValue());
5143 featureOrder.put(featureType, Float.valueOf(
5144 fs / jm.getFeatureSettings().getSetting().size()));
5146 if (safeBoolean(setting.isDisplay()))
5148 fdi.setVisible(featureType);
5151 Map<String, Boolean> fgtable = new Hashtable<>();
5152 for (int gs = 0; gs < jm.getFeatureSettings().getGroup().size(); gs++)
5154 Group grp = jm.getFeatureSettings().getGroup().get(gs);
5155 fgtable.put(grp.getName(), Boolean.valueOf(grp.isDisplay()));
5157 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
5158 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
5159 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
5160 FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
5161 fgtable, featureColours, 1.0f, featureOrder);
5162 fr.transferSettings(frs);
5165 if (view.getHiddenColumns().size() > 0)
5167 for (int c = 0; c < view.getHiddenColumns().size(); c++)
5169 final HiddenColumns hc = view.getHiddenColumns().get(c);
5170 viewport.hideColumns(safeInt(hc.getStart()),
5171 safeInt(hc.getEnd()) /* +1 */);
5174 if (view.getCalcIdParam() != null)
5176 for (CalcIdParam calcIdParam : view.getCalcIdParam())
5178 if (calcIdParam != null)
5180 if (recoverCalcIdParam(calcIdParam, viewport))
5185 warn("Couldn't recover parameters for "
5186 + calcIdParam.getCalcId());
5191 af.setMenusFromViewport(viewport);
5192 af.setTitle(view.getTitle());
5193 // TODO: we don't need to do this if the viewport is aready visible.
5195 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
5196 * has a 'cdna/protein complement' view, in which case save it in order to
5197 * populate a SplitFrame once all views have been read in.
5199 String complementaryViewId = view.getComplementId();
5200 if (complementaryViewId == null)
5202 Desktop.addInternalFrame(af, view.getTitle(),
5203 safeInt(view.getWidth()), safeInt(view.getHeight()));
5204 // recompute any autoannotation
5205 af.alignPanel.updateAnnotation(false, true);
5206 reorderAutoannotation(af, al, autoAlan);
5207 af.alignPanel.alignmentChanged();
5211 splitFrameCandidates.put(view, af);
5217 * Reads saved data to restore Colour by Annotation settings
5219 * @param viewAnnColour
5223 * @param checkGroupAnnColour
5226 private ColourSchemeI constructAnnotationColour(
5227 AnnotationColourScheme viewAnnColour, AlignFrame af,
5228 AlignmentI al, JalviewModel model, boolean checkGroupAnnColour)
5230 boolean propagateAnnColour = false;
5231 AlignmentI annAlignment = af != null ? af.getViewport().getAlignment()
5233 if (checkGroupAnnColour && al.getGroups() != null
5234 && al.getGroups().size() > 0)
5236 // pre 2.8.1 behaviour
5237 // check to see if we should transfer annotation colours
5238 propagateAnnColour = true;
5239 for (SequenceGroup sg : al.getGroups())
5241 if (sg.getColourScheme() instanceof AnnotationColourGradient)
5243 propagateAnnColour = false;
5249 * 2.10.2- : saved annotationId is AlignmentAnnotation.annotationId
5251 String annotationId = viewAnnColour.getAnnotation();
5252 AlignmentAnnotation matchedAnnotation = annotationIds.get(annotationId);
5255 * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
5257 if (matchedAnnotation == null
5258 && annAlignment.getAlignmentAnnotation() != null)
5260 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
5263 .equals(annAlignment.getAlignmentAnnotation()[i].label))
5265 matchedAnnotation = annAlignment.getAlignmentAnnotation()[i];
5270 if (matchedAnnotation == null)
5272 System.err.println("Failed to match annotation colour scheme for "
5276 if (matchedAnnotation.getThreshold() == null)
5278 matchedAnnotation.setThreshold(
5279 new GraphLine(safeFloat(viewAnnColour.getThreshold()),
5280 "Threshold", Color.black));
5283 AnnotationColourGradient cs = null;
5284 if (viewAnnColour.getColourScheme().equals("None"))
5286 cs = new AnnotationColourGradient(matchedAnnotation,
5287 new Color(safeInt(viewAnnColour.getMinColour())),
5288 new Color(safeInt(viewAnnColour.getMaxColour())),
5289 safeInt(viewAnnColour.getAboveThreshold()));
5291 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
5293 cs = new AnnotationColourGradient(matchedAnnotation,
5294 getUserColourScheme(model, viewAnnColour.getColourScheme()),
5295 safeInt(viewAnnColour.getAboveThreshold()));
5299 cs = new AnnotationColourGradient(matchedAnnotation,
5300 ColourSchemeProperty.getColourScheme(af.getViewport(), al,
5301 viewAnnColour.getColourScheme()),
5302 safeInt(viewAnnColour.getAboveThreshold()));
5305 boolean perSequenceOnly = safeBoolean(viewAnnColour.isPerSequence());
5306 boolean useOriginalColours = safeBoolean(
5307 viewAnnColour.isPredefinedColours());
5308 cs.setSeqAssociated(perSequenceOnly);
5309 cs.setPredefinedColours(useOriginalColours);
5311 if (propagateAnnColour && al.getGroups() != null)
5313 // Also use these settings for all the groups
5314 for (int g = 0; g < al.getGroups().size(); g++)
5316 SequenceGroup sg = al.getGroups().get(g);
5317 if (sg.getGroupColourScheme() == null)
5322 AnnotationColourGradient groupScheme = new AnnotationColourGradient(
5323 matchedAnnotation, sg.getColourScheme(),
5324 safeInt(viewAnnColour.getAboveThreshold()));
5325 sg.setColourScheme(groupScheme);
5326 groupScheme.setSeqAssociated(perSequenceOnly);
5327 groupScheme.setPredefinedColours(useOriginalColours);
5333 private void reorderAutoannotation(AlignFrame af, AlignmentI al,
5334 List<JvAnnotRow> autoAlan)
5336 // copy over visualization settings for autocalculated annotation in the
5338 if (al.getAlignmentAnnotation() != null)
5341 * Kludge for magic autoannotation names (see JAL-811)
5343 String[] magicNames = new String[] { "Consensus", "Quality",
5345 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
5346 Hashtable<String, JvAnnotRow> visan = new Hashtable<>();
5347 for (String nm : magicNames)
5349 visan.put(nm, nullAnnot);
5351 for (JvAnnotRow auan : autoAlan)
5353 visan.put(auan.template.label
5354 + (auan.template.getCalcId() == null ? ""
5355 : "\t" + auan.template.getCalcId()),
5358 int hSize = al.getAlignmentAnnotation().length;
5359 List<JvAnnotRow> reorder = new ArrayList<>();
5360 // work through any autoCalculated annotation already on the view
5361 // removing it if it should be placed in a different location on the
5362 // annotation panel.
5363 List<String> remains = new ArrayList<>(visan.keySet());
5364 for (int h = 0; h < hSize; h++)
5366 jalview.datamodel.AlignmentAnnotation jalan = al
5367 .getAlignmentAnnotation()[h];
5368 if (jalan.autoCalculated)
5371 JvAnnotRow valan = visan.get(k = jalan.label);
5372 if (jalan.getCalcId() != null)
5374 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
5379 // delete the auto calculated row from the alignment
5380 al.deleteAnnotation(jalan, false);
5384 if (valan != nullAnnot)
5386 if (jalan != valan.template)
5388 // newly created autoannotation row instance
5389 // so keep a reference to the visible annotation row
5390 // and copy over all relevant attributes
5391 if (valan.template.graphHeight >= 0)
5394 jalan.graphHeight = valan.template.graphHeight;
5396 jalan.visible = valan.template.visible;
5398 reorder.add(new JvAnnotRow(valan.order, jalan));
5403 // Add any (possibly stale) autocalculated rows that were not appended to
5404 // the view during construction
5405 for (String other : remains)
5407 JvAnnotRow othera = visan.get(other);
5408 if (othera != nullAnnot && othera.template.getCalcId() != null
5409 && othera.template.getCalcId().length() > 0)
5411 reorder.add(othera);
5414 // now put the automatic annotation in its correct place
5415 int s = 0, srt[] = new int[reorder.size()];
5416 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
5417 for (JvAnnotRow jvar : reorder)
5420 srt[s++] = jvar.order;
5423 jalview.util.QuickSort.sort(srt, rws);
5424 // and re-insert the annotation at its correct position
5425 for (JvAnnotRow jvar : rws)
5427 al.addAnnotation(jvar.template, jvar.order);
5429 af.alignPanel.adjustAnnotationHeight();
5433 Hashtable skipList = null;
5436 * TODO remove this method
5439 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
5440 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
5441 * throw new Error("Implementation Error. No skipList defined for this
5442 * Jalview2XML instance."); } return (AlignFrame)
5443 * skipList.get(view.getSequenceSetId()); }
5447 * Check if the Jalview view contained in object should be skipped or not.
5450 * @return true if view's sequenceSetId is a key in skipList
5452 private boolean skipViewport(JalviewModel object)
5454 if (skipList == null)
5458 String id = object.getViewport().get(0).getSequenceSetId();
5459 if (skipList.containsKey(id))
5461 if (Cache.log != null && Cache.log.isDebugEnabled())
5463 Cache.log.debug("Skipping seuqence set id " + id);
5470 public void addToSkipList(AlignFrame af)
5472 if (skipList == null)
5474 skipList = new Hashtable();
5476 skipList.put(af.getViewport().getSequenceSetId(), af);
5479 public void clearSkipList()
5481 if (skipList != null)
5488 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
5489 boolean ignoreUnrefed, String uniqueSeqSetId)
5491 jalview.datamodel.AlignmentI ds = getDatasetFor(
5492 vamsasSet.getDatasetId());
5493 AlignmentI xtant_ds = ds;
5494 if (xtant_ds == null)
5496 // good chance we are about to create a new dataset, but check if we've
5497 // seen some of the dataset sequence IDs before.
5498 // TODO: skip this check if we are working with project generated by
5499 // version 2.11 or later
5500 xtant_ds = checkIfHasDataset(vamsasSet.getSequence());
5501 if (xtant_ds != null)
5504 addDatasetRef(vamsasSet.getDatasetId(), ds);
5507 Vector dseqs = null;
5510 // recovering an alignment View
5511 AlignmentI seqSetDS = getDatasetFor(UNIQSEQSETID + uniqueSeqSetId);
5512 if (seqSetDS != null)
5514 if (ds != null && ds != seqSetDS)
5516 warn("JAL-3171 regression: Overwriting a dataset reference for an alignment"
5517 + " - CDS/Protein crossreference data may be lost");
5518 if (xtant_ds != null)
5520 // This can only happen if the unique sequence set ID was bound to a
5521 // dataset that did not contain any of the sequences in the view
5522 // currently being restored.
5523 warn("JAL-3171 SERIOUS! TOTAL CONFUSION - please consider contacting the Jalview Development team so they can investigate why your project caused this message to be displayed.");
5527 addDatasetRef(vamsasSet.getDatasetId(), ds);
5532 // try even harder to restore dataset
5533 AlignmentI xtantDS = checkIfHasDataset(vamsasSet.getSequence());
5534 // create a list of new dataset sequences
5535 dseqs = new Vector();
5537 for (int i = 0, iSize = vamsasSet.getSequence().size(); i < iSize; i++)
5539 Sequence vamsasSeq = vamsasSet.getSequence().get(i);
5540 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
5542 // create a new dataset
5545 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
5546 dseqs.copyInto(dsseqs);
5547 ds = new jalview.datamodel.Alignment(dsseqs);
5548 debug("Created new dataset " + vamsasSet.getDatasetId()
5549 + " for alignment " + System.identityHashCode(al));
5550 addDatasetRef(vamsasSet.getDatasetId(), ds);
5552 // set the dataset for the newly imported alignment.
5553 if (al.getDataset() == null && !ignoreUnrefed)
5556 // register dataset for the alignment's uniqueSeqSetId for legacy projects
5557 addDatasetRef(UNIQSEQSETID + uniqueSeqSetId, ds);
5559 updateSeqDatasetBinding(vamsasSet.getSequence(), ds);
5563 * XML dataset sequence ID to materialised dataset reference
5565 HashMap<String, AlignmentI> seqToDataset = new HashMap<>();
5568 * @return the first materialised dataset reference containing a dataset
5569 * sequence referenced in the given view
5571 * - sequences from the view
5573 AlignmentI checkIfHasDataset(List<Sequence> list)
5575 for (Sequence restoredSeq : list)
5577 AlignmentI datasetFor = seqToDataset.get(restoredSeq.getDsseqid());
5578 if (datasetFor != null)
5587 * Register ds as the containing dataset for the dataset sequences referenced
5588 * by sequences in list
5591 * - sequences in a view
5594 void updateSeqDatasetBinding(List<Sequence> list, AlignmentI ds)
5596 for (Sequence restoredSeq : list)
5598 AlignmentI prevDS = seqToDataset.put(restoredSeq.getDsseqid(), ds);
5599 if (prevDS != null && prevDS != ds)
5601 warn("Dataset sequence appears in many datasets: "
5602 + restoredSeq.getDsseqid());
5603 // TODO: try to merge!
5610 * sequence definition to create/merge dataset sequence for
5614 * vector to add new dataset sequence to
5615 * @param ignoreUnrefed
5616 * - when true, don't create new sequences from vamsasSeq if it's id
5617 * doesn't already have an asssociated Jalview sequence.
5619 * - used to reorder the sequence in the alignment according to the
5620 * vamsasSeq array ordering, to preserve ordering of dataset
5622 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
5623 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed, int vseqpos)
5625 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
5627 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
5628 boolean reorder = false;
5629 SequenceI dsq = null;
5630 if (sq != null && sq.getDatasetSequence() != null)
5632 dsq = sq.getDatasetSequence();
5638 if (sq == null && ignoreUnrefed)
5642 String sqid = vamsasSeq.getDsseqid();
5645 // need to create or add a new dataset sequence reference to this sequence
5648 dsq = seqRefIds.get(sqid);
5653 // make a new dataset sequence
5654 dsq = sq.createDatasetSequence();
5657 // make up a new dataset reference for this sequence
5658 sqid = seqHash(dsq);
5660 dsq.setVamsasId(uniqueSetSuffix + sqid);
5661 seqRefIds.put(sqid, dsq);
5666 dseqs.addElement(dsq);
5671 ds.addSequence(dsq);
5677 { // make this dataset sequence sq's dataset sequence
5678 sq.setDatasetSequence(dsq);
5679 // and update the current dataset alignment
5684 if (!dseqs.contains(dsq))
5691 if (ds.findIndex(dsq) < 0)
5693 ds.addSequence(dsq);
5700 // TODO: refactor this as a merge dataset sequence function
5701 // now check that sq (the dataset sequence) sequence really is the union of
5702 // all references to it
5703 // boolean pre = sq.getStart() < dsq.getStart();
5704 // boolean post = sq.getEnd() > dsq.getEnd();
5708 // StringBuffer sb = new StringBuffer();
5709 String newres = jalview.analysis.AlignSeq.extractGaps(
5710 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
5711 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
5712 && newres.length() > dsq.getLength())
5714 // Update with the longer sequence.
5718 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
5719 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
5720 * sb.append(newres.substring(newres.length() - sq.getEnd() -
5721 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
5723 dsq.setSequence(newres);
5725 // TODO: merges will never happen if we 'know' we have the real dataset
5726 // sequence - this should be detected when id==dssid
5728 "DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
5729 // + (pre ? "prepended" : "") + " "
5730 // + (post ? "appended" : ""));
5735 // sequence refs are identical. We may need to update the existing dataset
5736 // alignment with this one, though.
5737 if (ds != null && dseqs == null)
5739 int opos = ds.findIndex(dsq);
5740 SequenceI tseq = null;
5741 if (opos != -1 && vseqpos != opos)
5743 // remove from old position
5744 ds.deleteSequence(dsq);
5746 if (vseqpos < ds.getHeight())
5748 if (vseqpos != opos)
5750 // save sequence at destination position
5751 tseq = ds.getSequenceAt(vseqpos);
5752 ds.replaceSequenceAt(vseqpos, dsq);
5753 ds.addSequence(tseq);
5758 ds.addSequence(dsq);
5765 * TODO use AlignmentI here and in related methods - needs
5766 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
5768 Hashtable<String, AlignmentI> datasetIds = null;
5770 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
5772 private AlignmentI getDatasetFor(String datasetId)
5774 if (datasetIds == null)
5776 datasetIds = new Hashtable<>();
5779 if (datasetIds.containsKey(datasetId))
5781 return datasetIds.get(datasetId);
5786 private void addDatasetRef(String datasetId, AlignmentI dataset)
5788 if (datasetIds == null)
5790 datasetIds = new Hashtable<>();
5792 datasetIds.put(datasetId, dataset);
5796 * make a new dataset ID for this jalview dataset alignment
5801 private String getDatasetIdRef(AlignmentI dataset)
5803 if (dataset.getDataset() != null)
5805 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
5807 String datasetId = makeHashCode(dataset, null);
5808 if (datasetId == null)
5810 // make a new datasetId and record it
5811 if (dataset2Ids == null)
5813 dataset2Ids = new IdentityHashMap<>();
5817 datasetId = dataset2Ids.get(dataset);
5819 if (datasetId == null)
5821 datasetId = "ds" + dataset2Ids.size() + 1;
5822 dataset2Ids.put(dataset, datasetId);
5828 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5830 for (int d = 0; d < sequence.getDBRef().size(); d++)
5832 DBRef dr = sequence.getDBRef().get(d);
5833 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
5834 dr.getSource(), dr.getVersion(), dr.getAccessionId());
5835 if (dr.getMapping() != null)
5837 entry.setMap(addMapping(dr.getMapping()));
5839 datasetSequence.addDBRef(entry);
5843 private jalview.datamodel.Mapping addMapping(Mapping m)
5845 SequenceI dsto = null;
5846 // Mapping m = dr.getMapping();
5847 int fr[] = new int[m.getMapListFrom().size() * 2];
5848 Iterator<MapListFrom> from = m.getMapListFrom().iterator();// enumerateMapListFrom();
5849 for (int _i = 0; from.hasNext(); _i += 2)
5851 MapListFrom mf = from.next();
5852 fr[_i] = mf.getStart();
5853 fr[_i + 1] = mf.getEnd();
5855 int fto[] = new int[m.getMapListTo().size() * 2];
5856 Iterator<MapListTo> to = m.getMapListTo().iterator();// enumerateMapListTo();
5857 for (int _i = 0; to.hasNext(); _i += 2)
5859 MapListTo mf = to.next();
5860 fto[_i] = mf.getStart();
5861 fto[_i + 1] = mf.getEnd();
5863 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto, fr,
5864 fto, m.getMapFromUnit().intValue(),
5865 m.getMapToUnit().intValue());
5868 * (optional) choice of dseqFor or Sequence
5870 if (m.getDseqFor() != null)
5872 String dsfor = m.getDseqFor();
5873 if (seqRefIds.containsKey(dsfor))
5878 jmap.setTo(seqRefIds.get(dsfor));
5882 frefedSequence.add(newMappingRef(dsfor, jmap));
5885 else if (m.getSequence() != null)
5888 * local sequence definition
5890 Sequence ms = m.getSequence();
5891 SequenceI djs = null;
5892 String sqid = ms.getDsseqid();
5893 if (sqid != null && sqid.length() > 0)
5896 * recover dataset sequence
5898 djs = seqRefIds.get(sqid);
5903 "Warning - making up dataset sequence id for DbRef sequence map reference");
5904 sqid = ((Object) ms).toString(); // make up a new hascode for
5905 // undefined dataset sequence hash
5906 // (unlikely to happen)
5912 * make a new dataset sequence and add it to refIds hash
5914 djs = new jalview.datamodel.Sequence(ms.getName(),
5916 djs.setStart(jmap.getMap().getToLowest());
5917 djs.setEnd(jmap.getMap().getToHighest());
5918 djs.setVamsasId(uniqueSetSuffix + sqid);
5920 incompleteSeqs.put(sqid, djs);
5921 seqRefIds.put(sqid, djs);
5924 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5933 * Provides a 'copy' of an alignment view (on action New View) by 'saving' the
5934 * view as XML (but not to file), and then reloading it
5939 public AlignmentPanel copyAlignPanel(AlignmentPanel ap)
5942 JalviewModel jm = saveState(ap, null, null, null);
5945 jm.getVamsasModel().getSequenceSet().get(0).getDatasetId(),
5946 ap.getAlignment().getDataset());
5948 uniqueSetSuffix = "";
5949 // jm.getJalviewModelSequence().getViewport(0).setId(null);
5950 jm.getViewport().get(0).setId(null);
5951 // we don't overwrite the view we just copied
5953 if (this.frefedSequence == null)
5955 frefedSequence = new Vector<>();
5958 viewportsAdded.clear();
5960 AlignFrame af = loadFromObject(jm, null, false, null);
5961 af.getAlignPanels().clear();
5962 af.closeMenuItem_actionPerformed(true);
5965 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5966 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5967 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5968 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5969 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5972 return af.alignPanel;
5975 private Hashtable jvids2vobj;
5977 private void warn(String msg)
5982 private void warn(String msg, Exception e)
5984 if (Cache.log != null)
5988 Cache.log.warn(msg, e);
5992 Cache.log.warn(msg);
5997 System.err.println("Warning: " + msg);
6000 e.printStackTrace();
6005 private void debug(String string)
6007 debug(string, null);
6010 private void debug(String msg, Exception e)
6012 if (Cache.log != null)
6016 Cache.log.debug(msg, e);
6020 Cache.log.debug(msg);
6025 System.err.println("Warning: " + msg);
6028 e.printStackTrace();
6034 * set the object to ID mapping tables used to write/recover objects and XML
6035 * ID strings for the jalview project. If external tables are provided then
6036 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
6037 * object goes out of scope. - also populates the datasetIds hashtable with
6038 * alignment objects containing dataset sequences
6041 * Map from ID strings to jalview datamodel
6043 * Map from jalview datamodel to ID strings
6047 public void setObjectMappingTables(Hashtable vobj2jv,
6048 IdentityHashMap jv2vobj)
6050 this.jv2vobj = jv2vobj;
6051 this.vobj2jv = vobj2jv;
6052 Iterator ds = jv2vobj.keySet().iterator();
6054 while (ds.hasNext())
6056 Object jvobj = ds.next();
6057 id = jv2vobj.get(jvobj).toString();
6058 if (jvobj instanceof jalview.datamodel.Alignment)
6060 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
6062 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
6065 else if (jvobj instanceof jalview.datamodel.Sequence)
6067 // register sequence object so the XML parser can recover it.
6068 if (seqRefIds == null)
6070 seqRefIds = new HashMap<>();
6072 if (seqsToIds == null)
6074 seqsToIds = new IdentityHashMap<>();
6076 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
6077 seqsToIds.put((SequenceI) jvobj, id);
6079 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
6082 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
6083 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
6084 if (jvann.annotationId == null)
6086 jvann.annotationId = anid;
6088 if (!jvann.annotationId.equals(anid))
6090 // TODO verify that this is the correct behaviour
6091 this.warn("Overriding Annotation ID for " + anid
6092 + " from different id : " + jvann.annotationId);
6093 jvann.annotationId = anid;
6096 else if (jvobj instanceof String)
6098 if (jvids2vobj == null)
6100 jvids2vobj = new Hashtable();
6101 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
6106 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
6112 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
6113 * objects created from the project archive. If string is null (default for
6114 * construction) then suffix will be set automatically.
6118 public void setUniqueSetSuffix(String string)
6120 uniqueSetSuffix = string;
6125 * uses skipList2 as the skipList for skipping views on sequence sets
6126 * associated with keys in the skipList
6130 public void setSkipList(Hashtable skipList2)
6132 skipList = skipList2;
6136 * Reads the jar entry of given name and returns its contents, or null if the
6137 * entry is not found.
6140 * @param jarEntryName
6143 protected String readJarEntry(jarInputStreamProvider jprovider,
6144 String jarEntryName)
6146 String result = null;
6147 BufferedReader in = null;
6152 * Reopen the jar input stream and traverse its entries to find a matching
6155 JarInputStream jin = jprovider.getJarInputStream();
6156 JarEntry entry = null;
6159 entry = jin.getNextJarEntry();
6160 } while (entry != null && !entry.getName().equals(jarEntryName));
6164 StringBuilder out = new StringBuilder(256);
6165 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
6168 while ((data = in.readLine()) != null)
6172 result = out.toString();
6176 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
6178 } catch (Exception ex)
6180 ex.printStackTrace();
6188 } catch (IOException e)
6199 * Returns an incrementing counter (0, 1, 2...)
6203 private synchronized int nextCounter()
6209 * Loads any saved PCA viewers
6214 protected void loadPCAViewers(JalviewModel model, AlignmentPanel ap)
6218 List<PcaViewer> pcaviewers = model.getPcaViewer();
6219 for (PcaViewer viewer : pcaviewers)
6221 String modelName = viewer.getScoreModelName();
6222 SimilarityParamsI params = new SimilarityParams(
6223 viewer.isIncludeGappedColumns(), viewer.isMatchGaps(),
6224 viewer.isIncludeGaps(),
6225 viewer.isDenominateByShortestLength());
6228 * create the panel (without computing the PCA)
6230 PCAPanel panel = new PCAPanel(ap, modelName, params);
6232 panel.setTitle(viewer.getTitle());
6233 panel.setBounds(new Rectangle(viewer.getXpos(), viewer.getYpos(),
6234 viewer.getWidth(), viewer.getHeight()));
6236 boolean showLabels = viewer.isShowLabels();
6237 panel.setShowLabels(showLabels);
6238 panel.getRotatableCanvas().setShowLabels(showLabels);
6239 panel.getRotatableCanvas()
6240 .setBgColour(new Color(viewer.getBgColour()));
6241 panel.getRotatableCanvas()
6242 .setApplyToAllViews(viewer.isLinkToAllViews());
6245 * load PCA output data
6247 ScoreModelI scoreModel = ScoreModels.getInstance()
6248 .getScoreModel(modelName, ap);
6249 PCA pca = new PCA(null, scoreModel, params);
6250 PcaDataType pcaData = viewer.getPcaData();
6252 MatrixI pairwise = loadDoubleMatrix(pcaData.getPairwiseMatrix());
6253 pca.setPairwiseScores(pairwise);
6255 MatrixI triDiag = loadDoubleMatrix(pcaData.getTridiagonalMatrix());
6256 pca.setTridiagonal(triDiag);
6258 MatrixI result = loadDoubleMatrix(pcaData.getEigenMatrix());
6259 pca.setEigenmatrix(result);
6261 panel.getPcaModel().setPCA(pca);
6264 * we haven't saved the input data! (JAL-2647 to do)
6266 panel.setInputData(null);
6269 * add the sequence points for the PCA display
6271 List<jalview.datamodel.SequencePoint> seqPoints = new ArrayList<>();
6272 for (SequencePoint sp : viewer.getSequencePoint())
6274 String seqId = sp.getSequenceRef();
6275 SequenceI seq = seqRefIds.get(seqId);
6278 throw new IllegalStateException(
6279 "Unmatched seqref for PCA: " + seqId);
6281 Point pt = new Point(sp.getXPos(), sp.getYPos(), sp.getZPos());
6282 jalview.datamodel.SequencePoint seqPoint = new jalview.datamodel.SequencePoint(
6284 seqPoints.add(seqPoint);
6286 panel.getRotatableCanvas().setPoints(seqPoints, seqPoints.size());
6289 * set min-max ranges and scale after setPoints (which recomputes them)
6291 panel.getRotatableCanvas().setScaleFactor(viewer.getScaleFactor());
6292 SeqPointMin spMin = viewer.getSeqPointMin();
6293 float[] min = new float[] { spMin.getXPos(), spMin.getYPos(),
6295 SeqPointMax spMax = viewer.getSeqPointMax();
6296 float[] max = new float[] { spMax.getXPos(), spMax.getYPos(),
6298 panel.getRotatableCanvas().setSeqMinMax(min, max);
6300 // todo: hold points list in PCAModel only
6301 panel.getPcaModel().setSequencePoints(seqPoints);
6303 panel.setSelectedDimensionIndex(viewer.getXDim(), X);
6304 panel.setSelectedDimensionIndex(viewer.getYDim(), Y);
6305 panel.setSelectedDimensionIndex(viewer.getZDim(), Z);
6307 // is this duplication needed?
6308 panel.setTop(seqPoints.size() - 1);
6309 panel.getPcaModel().setTop(seqPoints.size() - 1);
6312 * add the axes' end points for the display
6314 for (int i = 0; i < 3; i++)
6316 Axis axis = viewer.getAxis().get(i);
6317 panel.getRotatableCanvas().getAxisEndPoints()[i] = new Point(
6318 axis.getXPos(), axis.getYPos(), axis.getZPos());
6321 Desktop.addInternalFrame(panel, MessageManager.formatMessage(
6322 "label.calc_title", "PCA", modelName), 475, 450);
6324 } catch (Exception ex)
6326 Cache.log.error("Error loading PCA: " + ex.toString());
6331 * Populates an XML model of the feature colour scheme for one feature type
6333 * @param featureType
6337 public static Colour marshalColour(
6338 String featureType, FeatureColourI fcol)
6340 Colour col = new Colour();
6341 if (fcol.isSimpleColour())
6343 col.setRGB(Format.getHexString(fcol.getColour()));
6347 col.setRGB(Format.getHexString(fcol.getMaxColour()));
6348 col.setMin(fcol.getMin());
6349 col.setMax(fcol.getMax());
6350 col.setMinRGB(jalview.util.Format.getHexString(fcol.getMinColour()));
6351 col.setAutoScale(fcol.isAutoScaled());
6352 col.setThreshold(fcol.getThreshold());
6353 col.setColourByLabel(fcol.isColourByLabel());
6354 col.setThreshType(fcol.isAboveThreshold() ? ThresholdType.ABOVE
6355 : (fcol.isBelowThreshold() ? ThresholdType.BELOW
6356 : ThresholdType.NONE));
6357 if (fcol.isColourByAttribute())
6359 final String[] attName = fcol.getAttributeName();
6360 col.getAttributeName().add(attName[0]);
6361 if (attName.length > 1)
6363 col.getAttributeName().add(attName[1]);
6366 Color noColour = fcol.getNoColour();
6367 if (noColour == null)
6369 col.setNoValueColour(NoValueColour.NONE);
6371 else if (noColour == fcol.getMaxColour())
6373 col.setNoValueColour(NoValueColour.MAX);
6377 col.setNoValueColour(NoValueColour.MIN);
6380 col.setName(featureType);
6385 * Populates an XML model of the feature filter(s) for one feature type
6387 * @param firstMatcher
6388 * the first (or only) match condition)
6390 * remaining match conditions (if any)
6392 * if true, conditions are and-ed, else or-ed
6394 public static jalview.xml.binding.jalview.FeatureMatcherSet marshalFilter(
6395 FeatureMatcherI firstMatcher, Iterator<FeatureMatcherI> filters,
6398 jalview.xml.binding.jalview.FeatureMatcherSet result = new jalview.xml.binding.jalview.FeatureMatcherSet();
6400 if (filters.hasNext())
6405 CompoundMatcher compound = new CompoundMatcher();
6406 compound.setAnd(and);
6407 jalview.xml.binding.jalview.FeatureMatcherSet matcher1 = marshalFilter(
6408 firstMatcher, Collections.emptyIterator(), and);
6409 // compound.addMatcherSet(matcher1);
6410 compound.getMatcherSet().add(matcher1);
6411 FeatureMatcherI nextMatcher = filters.next();
6412 jalview.xml.binding.jalview.FeatureMatcherSet matcher2 = marshalFilter(
6413 nextMatcher, filters, and);
6414 // compound.addMatcherSet(matcher2);
6415 compound.getMatcherSet().add(matcher2);
6416 result.setCompoundMatcher(compound);
6421 * single condition matcher
6423 // MatchCondition matcherModel = new MatchCondition();
6424 jalview.xml.binding.jalview.FeatureMatcher matcherModel = new jalview.xml.binding.jalview.FeatureMatcher();
6425 matcherModel.setCondition(
6426 firstMatcher.getMatcher().getCondition().getStableName());
6427 matcherModel.setValue(firstMatcher.getMatcher().getPattern());
6428 if (firstMatcher.isByAttribute())
6430 matcherModel.setBy(FilterBy.BY_ATTRIBUTE);
6431 // matcherModel.setAttributeName(firstMatcher.getAttribute());
6432 String[] attName = firstMatcher.getAttribute();
6433 matcherModel.getAttributeName().add(attName[0]); // attribute
6434 if (attName.length > 1)
6436 matcherModel.getAttributeName().add(attName[1]); // sub-attribute
6439 else if (firstMatcher.isByLabel())
6441 matcherModel.setBy(FilterBy.BY_LABEL);
6443 else if (firstMatcher.isByScore())
6445 matcherModel.setBy(FilterBy.BY_SCORE);
6447 result.setMatchCondition(matcherModel);
6454 * Loads one XML model of a feature filter to a Jalview object
6456 * @param featureType
6457 * @param matcherSetModel
6460 public static FeatureMatcherSetI parseFilter(
6462 jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel)
6464 FeatureMatcherSetI result = new FeatureMatcherSet();
6467 parseFilterConditions(result, matcherSetModel, true);
6468 } catch (IllegalStateException e)
6470 // mixing AND and OR conditions perhaps
6472 String.format("Error reading filter conditions for '%s': %s",
6473 featureType, e.getMessage()));
6474 // return as much as was parsed up to the error
6481 * Adds feature match conditions to matcherSet as unmarshalled from XML
6482 * (possibly recursively for compound conditions)
6485 * @param matcherSetModel
6487 * if true, multiple conditions are AND-ed, else they are OR-ed
6488 * @throws IllegalStateException
6489 * if AND and OR conditions are mixed
6491 protected static void parseFilterConditions(
6492 FeatureMatcherSetI matcherSet,
6493 jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel,
6496 jalview.xml.binding.jalview.FeatureMatcher mc = matcherSetModel
6497 .getMatchCondition();
6503 FilterBy filterBy = mc.getBy();
6504 Condition cond = Condition.fromString(mc.getCondition());
6505 String pattern = mc.getValue();
6506 FeatureMatcherI matchCondition = null;
6507 if (filterBy == FilterBy.BY_LABEL)
6509 matchCondition = FeatureMatcher.byLabel(cond, pattern);
6511 else if (filterBy == FilterBy.BY_SCORE)
6513 matchCondition = FeatureMatcher.byScore(cond, pattern);
6516 else if (filterBy == FilterBy.BY_ATTRIBUTE)
6518 final List<String> attributeName = mc.getAttributeName();
6519 String[] attNames = attributeName
6520 .toArray(new String[attributeName.size()]);
6521 matchCondition = FeatureMatcher.byAttribute(cond, pattern,
6526 * note this throws IllegalStateException if AND-ing to a
6527 * previously OR-ed compound condition, or vice versa
6531 matcherSet.and(matchCondition);
6535 matcherSet.or(matchCondition);
6541 * compound condition
6543 List<jalview.xml.binding.jalview.FeatureMatcherSet> matchers = matcherSetModel
6544 .getCompoundMatcher().getMatcherSet();
6545 boolean anded = matcherSetModel.getCompoundMatcher().isAnd();
6546 if (matchers.size() == 2)
6548 parseFilterConditions(matcherSet, matchers.get(0), anded);
6549 parseFilterConditions(matcherSet, matchers.get(1), anded);
6553 System.err.println("Malformed compound filter condition");
6559 * Loads one XML model of a feature colour to a Jalview object
6561 * @param colourModel
6564 public static FeatureColourI parseColour(Colour colourModel)
6566 FeatureColourI colour = null;
6568 if (colourModel.getMax() != null)
6570 Color mincol = null;
6571 Color maxcol = null;
6572 Color noValueColour = null;
6576 mincol = new Color(Integer.parseInt(colourModel.getMinRGB(), 16));
6577 maxcol = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6578 } catch (Exception e)
6580 Cache.log.warn("Couldn't parse out graduated feature color.", e);
6583 NoValueColour noCol = colourModel.getNoValueColour();
6584 if (noCol == NoValueColour.MIN)
6586 noValueColour = mincol;
6588 else if (noCol == NoValueColour.MAX)
6590 noValueColour = maxcol;
6593 colour = new FeatureColour(maxcol, mincol, maxcol, noValueColour,
6594 safeFloat(colourModel.getMin()),
6595 safeFloat(colourModel.getMax()));
6596 final List<String> attributeName = colourModel.getAttributeName();
6597 String[] attributes = attributeName
6598 .toArray(new String[attributeName.size()]);
6599 if (attributes != null && attributes.length > 0)
6601 colour.setAttributeName(attributes);
6603 if (colourModel.isAutoScale() != null)
6605 colour.setAutoScaled(colourModel.isAutoScale().booleanValue());
6607 if (colourModel.isColourByLabel() != null)
6609 colour.setColourByLabel(
6610 colourModel.isColourByLabel().booleanValue());
6612 if (colourModel.getThreshold() != null)
6614 colour.setThreshold(colourModel.getThreshold().floatValue());
6616 ThresholdType ttyp = colourModel.getThreshType();
6617 if (ttyp == ThresholdType.ABOVE)
6619 colour.setAboveThreshold(true);
6621 else if (ttyp == ThresholdType.BELOW)
6623 colour.setBelowThreshold(true);
6628 Color color = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6629 colour = new FeatureColour(color);