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.AnnotationSorter;
28 import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
29 import jalview.analysis.Conservation;
30 import jalview.analysis.PCA;
31 import jalview.analysis.scoremodels.ScoreModels;
32 import jalview.analysis.scoremodels.SimilarityParams;
33 import jalview.api.FeatureColourI;
34 import jalview.api.ViewStyleI;
35 import jalview.api.analysis.ScoreModelI;
36 import jalview.api.analysis.SimilarityParamsI;
37 import jalview.api.structures.JalviewStructureDisplayI;
38 import jalview.bin.Cache;
39 import jalview.datamodel.AlignedCodonFrame;
40 import jalview.datamodel.Alignment;
41 import jalview.datamodel.AlignmentAnnotation;
42 import jalview.datamodel.AlignmentI;
43 import jalview.datamodel.GraphLine;
44 import jalview.datamodel.PDBEntry;
45 import jalview.datamodel.Point;
46 import jalview.datamodel.RnaViewerModel;
47 import jalview.datamodel.SequenceFeature;
48 import jalview.datamodel.SequenceGroup;
49 import jalview.datamodel.SequenceI;
50 import jalview.datamodel.StructureViewerModel;
51 import jalview.datamodel.StructureViewerModel.StructureData;
52 import jalview.datamodel.features.FeatureMatcher;
53 import jalview.datamodel.features.FeatureMatcherI;
54 import jalview.datamodel.features.FeatureMatcherSet;
55 import jalview.datamodel.features.FeatureMatcherSetI;
56 import jalview.ext.varna.RnaModel;
57 import jalview.gui.AlignFrame;
58 import jalview.gui.AlignViewport;
59 import jalview.gui.AlignmentPanel;
60 import jalview.gui.AppVarna;
61 import jalview.gui.ChimeraViewFrame;
62 import jalview.gui.Desktop;
63 import jalview.gui.FeatureRenderer;
64 import jalview.gui.JvOptionPane;
65 import jalview.gui.OOMWarning;
66 import jalview.gui.PCAPanel;
67 import jalview.gui.PaintRefresher;
68 import jalview.gui.SplitFrame;
69 import jalview.gui.StructureViewer;
70 import jalview.gui.StructureViewer.ViewerType;
71 import jalview.gui.StructureViewerBase;
72 import jalview.gui.TreePanel;
73 import jalview.io.BackupFiles;
74 import jalview.io.DataSourceType;
75 import jalview.io.FileFormat;
76 import jalview.io.NewickFile;
77 import jalview.math.Matrix;
78 import jalview.math.MatrixI;
79 import jalview.renderer.ResidueShaderI;
80 import jalview.schemes.AnnotationColourGradient;
81 import jalview.schemes.ColourSchemeI;
82 import jalview.schemes.ColourSchemeProperty;
83 import jalview.schemes.FeatureColour;
84 import jalview.schemes.ResidueProperties;
85 import jalview.schemes.UserColourScheme;
86 import jalview.structure.StructureSelectionManager;
87 import jalview.structures.models.AAStructureBindingModel;
88 import jalview.util.Format;
89 import jalview.util.MessageManager;
90 import jalview.util.Platform;
91 import jalview.util.StringUtils;
92 import jalview.util.jarInputStreamProvider;
93 import jalview.util.matcher.Condition;
94 import jalview.viewmodel.AlignmentViewport;
95 import jalview.viewmodel.AlignmentViewport.AutoAnnotation;
96 import jalview.viewmodel.PCAModel;
97 import jalview.viewmodel.ViewportRanges;
98 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
99 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
100 import jalview.ws.jws2.Jws2Discoverer;
101 import jalview.ws.jws2.dm.AAConSettings;
102 import jalview.ws.jws2.jabaws2.Jws2Instance;
103 import jalview.ws.params.ArgumentI;
104 import jalview.ws.params.AutoCalcSetting;
105 import jalview.ws.params.WsParamSetI;
106 import jalview.xml.binding.jalview.AlcodonFrame;
107 import jalview.xml.binding.jalview.AlcodonFrame.AlcodMap;
108 import jalview.xml.binding.jalview.Annotation;
109 import jalview.xml.binding.jalview.Annotation.ThresholdLine;
110 import jalview.xml.binding.jalview.AnnotationColourScheme;
111 import jalview.xml.binding.jalview.AnnotationElement;
112 import jalview.xml.binding.jalview.DoubleMatrix;
113 import jalview.xml.binding.jalview.DoubleVector;
114 import jalview.xml.binding.jalview.Feature;
115 import jalview.xml.binding.jalview.Feature.OtherData;
116 import jalview.xml.binding.jalview.FeatureMatcherSet.CompoundMatcher;
117 import jalview.xml.binding.jalview.FilterBy;
118 import jalview.xml.binding.jalview.JalviewModel;
119 import jalview.xml.binding.jalview.JalviewModel.FeatureSettings;
120 import jalview.xml.binding.jalview.JalviewModel.FeatureSettings.Group;
121 import jalview.xml.binding.jalview.JalviewModel.FeatureSettings.Setting;
122 import jalview.xml.binding.jalview.JalviewModel.JGroup;
123 import jalview.xml.binding.jalview.JalviewModel.JSeq;
124 import jalview.xml.binding.jalview.JalviewModel.JSeq.Pdbids;
125 import jalview.xml.binding.jalview.JalviewModel.JSeq.Pdbids.StructureState;
126 import jalview.xml.binding.jalview.JalviewModel.JSeq.RnaViewer;
127 import jalview.xml.binding.jalview.JalviewModel.JSeq.RnaViewer.SecondaryStructure;
128 import jalview.xml.binding.jalview.JalviewModel.PcaViewer;
129 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.Axis;
130 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.SeqPointMax;
131 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.SeqPointMin;
132 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.SequencePoint;
133 import jalview.xml.binding.jalview.JalviewModel.Tree;
134 import jalview.xml.binding.jalview.JalviewModel.UserColours;
135 import jalview.xml.binding.jalview.JalviewModel.Viewport;
136 import jalview.xml.binding.jalview.JalviewModel.Viewport.CalcIdParam;
137 import jalview.xml.binding.jalview.JalviewModel.Viewport.HiddenColumns;
138 import jalview.xml.binding.jalview.JalviewUserColours;
139 import jalview.xml.binding.jalview.JalviewUserColours.Colour;
140 import jalview.xml.binding.jalview.MapListType.MapListFrom;
141 import jalview.xml.binding.jalview.MapListType.MapListTo;
142 import jalview.xml.binding.jalview.Mapping;
143 import jalview.xml.binding.jalview.NoValueColour;
144 import jalview.xml.binding.jalview.ObjectFactory;
145 import jalview.xml.binding.jalview.PcaDataType;
146 import jalview.xml.binding.jalview.Pdbentry.Property;
147 import jalview.xml.binding.jalview.Sequence;
148 import jalview.xml.binding.jalview.Sequence.DBRef;
149 import jalview.xml.binding.jalview.SequenceSet;
150 import jalview.xml.binding.jalview.SequenceSet.SequenceSetProperties;
151 import jalview.xml.binding.jalview.ThresholdType;
152 import jalview.xml.binding.jalview.VAMSAS;
154 import java.awt.Color;
155 import java.awt.Font;
156 import java.awt.Rectangle;
157 import java.io.BufferedReader;
158 import java.io.DataInputStream;
159 import java.io.DataOutputStream;
161 import java.io.FileInputStream;
162 import java.io.FileOutputStream;
163 import java.io.IOException;
164 import java.io.InputStreamReader;
165 import java.io.OutputStreamWriter;
166 import java.io.PrintWriter;
167 import java.lang.reflect.InvocationTargetException;
168 import java.math.BigInteger;
169 import java.net.MalformedURLException;
171 import java.util.ArrayList;
172 import java.util.Arrays;
173 import java.util.Collections;
174 import java.util.Enumeration;
175 import java.util.GregorianCalendar;
176 import java.util.HashMap;
177 import java.util.HashSet;
178 import java.util.Hashtable;
179 import java.util.IdentityHashMap;
180 import java.util.Iterator;
181 import java.util.LinkedHashMap;
182 import java.util.List;
183 import java.util.Map;
184 import java.util.Map.Entry;
185 import java.util.Set;
186 import java.util.Vector;
187 import java.util.jar.JarEntry;
188 import java.util.jar.JarInputStream;
189 import java.util.jar.JarOutputStream;
191 import javax.swing.JInternalFrame;
192 import javax.swing.SwingUtilities;
193 import javax.xml.bind.JAXBContext;
194 import javax.xml.bind.JAXBElement;
195 import javax.xml.bind.Marshaller;
196 import javax.xml.datatype.DatatypeConfigurationException;
197 import javax.xml.datatype.DatatypeFactory;
198 import javax.xml.datatype.XMLGregorianCalendar;
199 import javax.xml.stream.XMLInputFactory;
200 import javax.xml.stream.XMLStreamReader;
203 * Provides methods to read in or write out the Jalview desktop state as a
204 * Jalview XML model, as one or more entries in a .jar archive. The jar file may
205 * include additional data file entries, such as
207 * <li>PDB structure data files</li>
208 * <li>session state for one or more Jmol, Chimera or Varna structure
212 public class Jalview2XML
214 private static final String TRUE = "true";
216 private static final String FALSE = "false";
218 private static final String VIEWER_PREFIX = "viewer_";
220 private static final String RNA_PREFIX = "rna_";
222 private static final String UTF_8 = "UTF-8";
225 * prefix for recovering datasets for alignments with multiple views where
226 * non-existent dataset IDs were written for some views
228 private static final String UNIQSEQSETID = "uniqueSeqSetId.";
230 // use this with nextCounter() to make unique names for entities
231 private int counter = 0;
234 * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
235 * of sequence objects are created.
237 IdentityHashMap<SequenceI, String> seqsToIds = null;
240 * jalview XML Sequence ID to jalview sequence object reference (both dataset
241 * and alignment sequences. Populated as XML reps of sequence objects are
244 Map<String, SequenceI> seqRefIds = null;
246 Map<String, SequenceI> incompleteSeqs = null;
248 List<SeqFref> frefedSequence = null;
250 boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
253 * Map of reconstructed AlignFrame objects that appear to have come from
254 * SplitFrame objects (have a dna/protein complement view).
256 private Map<Viewport, AlignFrame> splitFrameCandidates = new HashMap<>();
259 * Map from displayed rna structure models to their saved session state jar
262 private Map<RnaModel, String> rnaSessions = new HashMap<>();
265 * A helper method for safely using the value of an optional attribute that
266 * may be null if not present in the XML. Answers the boolean value, or false
272 public static boolean safeBoolean(Boolean b)
274 return b == null ? false : b.booleanValue();
278 * A helper method for safely using the value of an optional attribute that
279 * may be null if not present in the XML. Answers the integer value, or zero
285 public static int safeInt(Integer i)
287 return i == null ? 0 : i.intValue();
291 * A helper method for safely using the value of an optional attribute that
292 * may be null if not present in the XML. Answers the float value, or zero if
298 public static float safeFloat(Float f)
300 return f == null ? 0f : f.floatValue();
304 * create/return unique hash string for sq
307 * @return new or existing unique string for sq
309 String seqHash(SequenceI sq)
311 if (seqsToIds == null)
315 if (seqsToIds.containsKey(sq))
317 return seqsToIds.get(sq);
321 // create sequential key
322 String key = "sq" + (seqsToIds.size() + 1);
323 key = makeHashCode(sq, key); // check we don't have an external reference
325 seqsToIds.put(sq, key);
332 if (seqsToIds == null)
334 seqsToIds = new IdentityHashMap<>();
336 if (seqRefIds == null)
338 seqRefIds = new HashMap<>();
340 if (incompleteSeqs == null)
342 incompleteSeqs = new HashMap<>();
344 if (frefedSequence == null)
346 frefedSequence = new ArrayList<>();
354 public Jalview2XML(boolean raiseGUI)
356 this.raiseGUI = raiseGUI;
360 * base class for resolving forward references to sequences by their ID
365 abstract class SeqFref
371 public SeqFref(String _sref, String type)
377 public String getSref()
382 public SequenceI getSrefSeq()
384 return seqRefIds.get(sref);
387 public boolean isResolvable()
389 return seqRefIds.get(sref) != null;
392 public SequenceI getSrefDatasetSeq()
394 SequenceI sq = seqRefIds.get(sref);
397 while (sq.getDatasetSequence() != null)
399 sq = sq.getDatasetSequence();
406 * @return true if the forward reference was fully resolved
408 abstract boolean resolve();
411 public String toString()
413 return type + " reference to " + sref;
418 * create forward reference for a mapping
424 public SeqFref newMappingRef(final String sref,
425 final jalview.datamodel.Mapping _jmap)
427 SeqFref fref = new SeqFref(sref, "Mapping")
429 public jalview.datamodel.Mapping jmap = _jmap;
434 SequenceI seq = getSrefDatasetSeq();
446 public SeqFref newAlcodMapRef(final String sref,
447 final AlignedCodonFrame _cf,
448 final jalview.datamodel.Mapping _jmap)
451 SeqFref fref = new SeqFref(sref, "Codon Frame")
453 AlignedCodonFrame cf = _cf;
455 public jalview.datamodel.Mapping mp = _jmap;
458 public boolean isResolvable()
460 return super.isResolvable() && mp.getTo() != null;
466 SequenceI seq = getSrefDatasetSeq();
471 cf.addMap(seq, mp.getTo(), mp.getMap());
478 public void resolveFrefedSequences()
480 Iterator<SeqFref> nextFref = frefedSequence.iterator();
481 int toresolve = frefedSequence.size();
482 int unresolved = 0, failedtoresolve = 0;
483 while (nextFref.hasNext())
485 SeqFref ref = nextFref.next();
486 if (ref.isResolvable())
498 } catch (Exception x)
501 "IMPLEMENTATION ERROR: Failed to resolve forward reference for sequence "
514 System.err.println("Jalview Project Import: There were " + unresolved
515 + " forward references left unresolved on the stack.");
517 if (failedtoresolve > 0)
519 System.err.println("SERIOUS! " + failedtoresolve
520 + " resolvable forward references failed to resolve.");
522 if (incompleteSeqs != null && incompleteSeqs.size() > 0)
525 "Jalview Project Import: There are " + incompleteSeqs.size()
526 + " sequences which may have incomplete metadata.");
527 if (incompleteSeqs.size() < 10)
529 for (SequenceI s : incompleteSeqs.values())
531 System.err.println(s.toString());
537 "Too many to report. Skipping output of incomplete sequences.");
543 * This maintains a map of viewports, the key being the seqSetId. Important to
544 * set historyItem and redoList for multiple views
546 Map<String, AlignViewport> viewportsAdded = new HashMap<>();
548 Map<String, AlignmentAnnotation> annotationIds = new HashMap<>();
550 String uniqueSetSuffix = "";
553 * List of pdbfiles added to Jar
555 List<String> pdbfiles = null;
557 // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
558 public void saveState(File statefile)
560 FileOutputStream fos = null;
565 fos = new FileOutputStream(statefile);
567 JarOutputStream jout = new JarOutputStream(fos);
571 } catch (Exception e)
573 Cache.log.error("Couln't write Jalview state to " + statefile, e);
574 // TODO: inform user of the problem - they need to know if their data was
576 if (errorMessage == null)
578 errorMessage = "Did't write Jalview Archive to output file '"
579 + statefile + "' - See console error log for details";
583 errorMessage += "(Didn't write Jalview Archive to output file '"
594 } catch (IOException e)
604 * Writes a jalview project archive to the given Jar output stream.
608 public void saveState(JarOutputStream jout)
610 AlignFrame[] frames = Desktop.getAlignFrames();
616 saveAllFrames(Arrays.asList(frames), jout);
620 * core method for storing state for a set of AlignFrames.
623 * - frames involving all data to be exported (including containing
626 * - project output stream
628 private void saveAllFrames(List<AlignFrame> frames, JarOutputStream jout)
630 Hashtable<String, AlignFrame> dsses = new Hashtable<>();
633 * ensure cached data is clear before starting
635 // todo tidy up seqRefIds, seqsToIds initialisation / reset
637 splitFrameCandidates.clear();
642 // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
643 // //////////////////////////////////////////////////
645 List<String> shortNames = new ArrayList<>();
646 List<String> viewIds = new ArrayList<>();
649 for (int i = frames.size() - 1; i > -1; i--)
651 AlignFrame af = frames.get(i);
653 if (skipList != null && skipList
654 .containsKey(af.getViewport().getSequenceSetId()))
659 String shortName = makeFilename(af, shortNames);
661 int apSize = af.getAlignPanels().size();
663 for (int ap = 0; ap < apSize; ap++)
665 AlignmentPanel apanel = (AlignmentPanel) af.getAlignPanels()
667 String fileName = apSize == 1 ? shortName : ap + shortName;
668 if (!fileName.endsWith(".xml"))
670 fileName = fileName + ".xml";
673 saveState(apanel, fileName, jout, viewIds);
675 String dssid = getDatasetIdRef(
676 af.getViewport().getAlignment().getDataset());
677 if (!dsses.containsKey(dssid))
679 dsses.put(dssid, af);
684 writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix,
690 } catch (Exception foo)
695 } catch (Exception ex)
697 // TODO: inform user of the problem - they need to know if their data was
699 if (errorMessage == null)
701 errorMessage = "Couldn't write Jalview Archive - see error output for details";
703 ex.printStackTrace();
708 * Generates a distinct file name, based on the title of the AlignFrame, by
709 * appending _n for increasing n until an unused name is generated. The new
710 * name (without its extension) is added to the list.
714 * @return the generated name, with .xml extension
716 protected String makeFilename(AlignFrame af, List<String> namesUsed)
718 String shortName = af.getTitle();
720 if (shortName.indexOf(File.separatorChar) > -1)
722 shortName = shortName
723 .substring(shortName.lastIndexOf(File.separatorChar) + 1);
728 while (namesUsed.contains(shortName))
730 if (shortName.endsWith("_" + (count - 1)))
732 shortName = shortName.substring(0, shortName.lastIndexOf("_"));
735 shortName = shortName.concat("_" + count);
739 namesUsed.add(shortName);
741 if (!shortName.endsWith(".xml"))
743 shortName = shortName + ".xml";
748 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
749 public boolean saveAlignment(AlignFrame af, String jarFile,
754 // create backupfiles object and get new temp filename destination
755 BackupFiles backupfiles = new BackupFiles(jarFile);
756 FileOutputStream fos = new FileOutputStream(
757 backupfiles.getTempFilePath());
759 JarOutputStream jout = new JarOutputStream(fos);
760 List<AlignFrame> frames = new ArrayList<>();
762 // resolve splitframes
763 if (af.getViewport().getCodingComplement() != null)
765 frames = ((SplitFrame) af.getSplitViewContainer()).getAlignFrames();
771 saveAllFrames(frames, jout);
775 } catch (Exception foo)
780 boolean success = true;
782 backupfiles.setWriteSuccess(success);
783 success = backupfiles.rollBackupsAndRenameTempFile();
786 } catch (Exception ex)
788 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
789 ex.printStackTrace();
794 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
795 String fileName, JarOutputStream jout)
798 for (String dssids : dsses.keySet())
800 AlignFrame _af = dsses.get(dssids);
801 String jfileName = fileName + " Dataset for " + _af.getTitle();
802 if (!jfileName.endsWith(".xml"))
804 jfileName = jfileName + ".xml";
806 saveState(_af.alignPanel, jfileName, true, jout, null);
811 * create a JalviewModel from an alignment view and marshall it to a
815 * panel to create jalview model for
817 * name of alignment panel written to output stream
824 public JalviewModel saveState(AlignmentPanel ap, String fileName,
825 JarOutputStream jout, List<String> viewIds)
827 return saveState(ap, fileName, false, jout, viewIds);
831 * create a JalviewModel from an alignment view and marshall it to a
835 * panel to create jalview model for
837 * name of alignment panel written to output stream
839 * when true, only write the dataset for the alignment, not the data
840 * associated with the view.
846 public JalviewModel saveState(AlignmentPanel ap, String fileName,
847 boolean storeDS, JarOutputStream jout, List<String> viewIds)
851 viewIds = new ArrayList<>();
856 List<UserColourScheme> userColours = new ArrayList<>();
858 AlignViewport av = ap.av;
859 ViewportRanges vpRanges = av.getRanges();
861 final ObjectFactory objectFactory = new ObjectFactory();
862 JalviewModel object = objectFactory.createJalviewModel();
863 object.setVamsasModel(new VAMSAS());
865 // object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
868 GregorianCalendar c = new GregorianCalendar();
869 DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
870 XMLGregorianCalendar now = datatypeFactory.newXMLGregorianCalendar(c);// gregorianCalendar);
871 object.setCreationDate(now);
872 } catch (DatatypeConfigurationException e)
874 System.err.println("error writing date: " + e.toString());
877 jalview.bin.Cache.getDefault("VERSION", "Development Build"));
880 * rjal is full height alignment, jal is actual alignment with full metadata
881 * but excludes hidden sequences.
883 jalview.datamodel.AlignmentI rjal = av.getAlignment(), jal = rjal;
885 if (av.hasHiddenRows())
887 rjal = jal.getHiddenSequences().getFullAlignment();
890 SequenceSet vamsasSet = new SequenceSet();
892 // JalviewModelSequence jms = new JalviewModelSequence();
894 vamsasSet.setGapChar(jal.getGapCharacter() + "");
896 if (jal.getDataset() != null)
898 // dataset id is the dataset's hashcode
899 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
902 // switch jal and the dataset
903 jal = jal.getDataset();
907 if (jal.getProperties() != null)
909 Enumeration en = jal.getProperties().keys();
910 while (en.hasMoreElements())
912 String key = en.nextElement().toString();
913 SequenceSetProperties ssp = new SequenceSetProperties();
915 ssp.setValue(jal.getProperties().get(key).toString());
916 // vamsasSet.addSequenceSetProperties(ssp);
917 vamsasSet.getSequenceSetProperties().add(ssp);
922 Set<String> calcIdSet = new HashSet<>();
923 // record the set of vamsas sequence XML POJO we create.
924 HashMap<String, Sequence> vamsasSetIds = new HashMap<>();
926 for (final SequenceI jds : rjal.getSequences())
928 final SequenceI jdatasq = jds.getDatasetSequence() == null ? jds
929 : jds.getDatasetSequence();
930 String id = seqHash(jds);
931 if (vamsasSetIds.get(id) == null)
933 if (seqRefIds.get(id) != null && !storeDS)
935 // This happens for two reasons: 1. multiple views are being
937 // 2. the hashCode has collided with another sequence's code. This
939 // HAPPEN! (PF00072.15.stk does this)
940 // JBPNote: Uncomment to debug writing out of files that do not read
941 // back in due to ArrayOutOfBoundExceptions.
942 // System.err.println("vamsasSeq backref: "+id+"");
943 // System.err.println(jds.getName()+"
944 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
945 // System.err.println("Hashcode: "+seqHash(jds));
946 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
947 // System.err.println(rsq.getName()+"
948 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
949 // System.err.println("Hashcode: "+seqHash(rsq));
953 vamsasSeq = createVamsasSequence(id, jds);
954 // vamsasSet.addSequence(vamsasSeq);
955 vamsasSet.getSequence().add(vamsasSeq);
956 vamsasSetIds.put(id, vamsasSeq);
957 seqRefIds.put(id, jds);
961 jseq.setStart(jds.getStart());
962 jseq.setEnd(jds.getEnd());
963 jseq.setColour(av.getSequenceColour(jds).getRGB());
965 jseq.setId(id); // jseq id should be a string not a number
968 // Store any sequences this sequence represents
969 if (av.hasHiddenRows())
971 // use rjal, contains the full height alignment
973 av.getAlignment().getHiddenSequences().isHidden(jds));
975 if (av.isHiddenRepSequence(jds))
977 jalview.datamodel.SequenceI[] reps = av
978 .getRepresentedSequences(jds).getSequencesInOrder(rjal);
980 for (int h = 0; h < reps.length; h++)
984 // jseq.addHiddenSequences(rjal.findIndex(reps[h]));
985 jseq.getHiddenSequences().add(rjal.findIndex(reps[h]));
990 // mark sequence as reference - if it is the reference for this view
993 jseq.setViewreference(jds == jal.getSeqrep());
997 // TODO: omit sequence features from each alignment view's XML dump if we
998 // are storing dataset
999 List<SequenceFeature> sfs = jds.getSequenceFeatures();
1000 for (SequenceFeature sf : sfs)
1002 // Features features = new Features();
1003 Feature features = new Feature();
1005 features.setBegin(sf.getBegin());
1006 features.setEnd(sf.getEnd());
1007 features.setDescription(sf.getDescription());
1008 features.setType(sf.getType());
1009 features.setFeatureGroup(sf.getFeatureGroup());
1010 features.setScore(sf.getScore());
1011 if (sf.links != null)
1013 for (int l = 0; l < sf.links.size(); l++)
1015 OtherData keyValue = new OtherData();
1016 keyValue.setKey("LINK_" + l);
1017 keyValue.setValue(sf.links.elementAt(l).toString());
1018 // features.addOtherData(keyValue);
1019 features.getOtherData().add(keyValue);
1022 if (sf.otherDetails != null)
1025 * save feature attributes, which may be simple strings or
1026 * map valued (have sub-attributes)
1028 for (Entry<String, Object> entry : sf.otherDetails.entrySet())
1030 String key = entry.getKey();
1031 Object value = entry.getValue();
1032 if (value instanceof Map<?, ?>)
1034 for (Entry<String, Object> subAttribute : ((Map<String, Object>) value)
1037 OtherData otherData = new OtherData();
1038 otherData.setKey(key);
1039 otherData.setKey2(subAttribute.getKey());
1040 otherData.setValue(subAttribute.getValue().toString());
1041 // features.addOtherData(otherData);
1042 features.getOtherData().add(otherData);
1047 OtherData otherData = new OtherData();
1048 otherData.setKey(key);
1049 otherData.setValue(value.toString());
1050 // features.addOtherData(otherData);
1051 features.getOtherData().add(otherData);
1056 // jseq.addFeatures(features);
1057 jseq.getFeatures().add(features);
1060 if (jdatasq.getAllPDBEntries() != null)
1062 Enumeration<PDBEntry> en = jdatasq.getAllPDBEntries().elements();
1063 while (en.hasMoreElements())
1065 Pdbids pdb = new Pdbids();
1066 jalview.datamodel.PDBEntry entry = en.nextElement();
1068 String pdbId = entry.getId();
1070 pdb.setType(entry.getType());
1073 * Store any structure views associated with this sequence. This
1074 * section copes with duplicate entries in the project, so a dataset
1075 * only view *should* be coped with sensibly.
1077 // This must have been loaded, is it still visible?
1078 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1079 String matchedFile = null;
1080 for (int f = frames.length - 1; f > -1; f--)
1082 if (frames[f] instanceof StructureViewerBase)
1084 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
1085 matchedFile = saveStructureState(ap, jds, pdb, entry, viewIds,
1086 matchedFile, viewFrame);
1088 * Only store each structure viewer's state once in the project
1089 * jar. First time through only (storeDS==false)
1091 String viewId = viewFrame.getViewId();
1092 if (!storeDS && !viewIds.contains(viewId))
1094 viewIds.add(viewId);
1097 String viewerState = viewFrame.getStateInfo();
1098 writeJarEntry(jout, getViewerJarEntryName(viewId),
1099 viewerState.getBytes());
1100 } catch (IOException e)
1103 "Error saving viewer state: " + e.getMessage());
1109 if (matchedFile != null || entry.getFile() != null)
1111 if (entry.getFile() != null)
1114 matchedFile = entry.getFile();
1116 pdb.setFile(matchedFile); // entry.getFile());
1117 if (pdbfiles == null)
1119 pdbfiles = new ArrayList<>();
1122 if (!pdbfiles.contains(pdbId))
1124 pdbfiles.add(pdbId);
1125 copyFileToJar(jout, matchedFile, pdbId);
1129 Enumeration<String> props = entry.getProperties();
1130 if (props.hasMoreElements())
1132 // PdbentryItem item = new PdbentryItem();
1133 while (props.hasMoreElements())
1135 Property prop = new Property();
1136 String key = props.nextElement();
1138 prop.setValue(entry.getProperty(key).toString());
1139 // item.addProperty(prop);
1140 pdb.getProperty().add(prop);
1142 // pdb.addPdbentryItem(item);
1145 // jseq.addPdbids(pdb);
1146 jseq.getPdbids().add(pdb);
1150 saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
1152 // jms.addJSeq(jseq);
1153 object.getJSeq().add(jseq);
1156 if (!storeDS && av.hasHiddenRows())
1158 jal = av.getAlignment();
1162 if (storeDS && jal.getCodonFrames() != null)
1164 List<AlignedCodonFrame> jac = jal.getCodonFrames();
1165 for (AlignedCodonFrame acf : jac)
1167 AlcodonFrame alc = new AlcodonFrame();
1168 if (acf.getProtMappings() != null
1169 && acf.getProtMappings().length > 0)
1171 boolean hasMap = false;
1172 SequenceI[] dnas = acf.getdnaSeqs();
1173 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1174 for (int m = 0; m < pmaps.length; m++)
1176 AlcodMap alcmap = new AlcodMap();
1177 alcmap.setDnasq(seqHash(dnas[m]));
1179 createVamsasMapping(pmaps[m], dnas[m], null, false));
1180 // alc.addAlcodMap(alcmap);
1181 alc.getAlcodMap().add(alcmap);
1186 // vamsasSet.addAlcodonFrame(alc);
1187 vamsasSet.getAlcodonFrame().add(alc);
1190 // TODO: delete this ? dead code from 2.8.3->2.9 ?
1192 // AlcodonFrame alc = new AlcodonFrame();
1193 // vamsasSet.addAlcodonFrame(alc);
1194 // for (int p = 0; p < acf.aaWidth; p++)
1196 // Alcodon cmap = new Alcodon();
1197 // if (acf.codons[p] != null)
1199 // // Null codons indicate a gapped column in the translated peptide
1201 // cmap.setPos1(acf.codons[p][0]);
1202 // cmap.setPos2(acf.codons[p][1]);
1203 // cmap.setPos3(acf.codons[p][2]);
1205 // alc.addAlcodon(cmap);
1207 // if (acf.getProtMappings() != null
1208 // && acf.getProtMappings().length > 0)
1210 // SequenceI[] dnas = acf.getdnaSeqs();
1211 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1212 // for (int m = 0; m < pmaps.length; m++)
1214 // AlcodMap alcmap = new AlcodMap();
1215 // alcmap.setDnasq(seqHash(dnas[m]));
1216 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
1218 // alc.addAlcodMap(alcmap);
1225 // /////////////////////////////////
1226 if (!storeDS && av.getCurrentTree() != null)
1228 // FIND ANY ASSOCIATED TREES
1229 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
1230 if (Desktop.desktop != null)
1232 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1234 for (int t = 0; t < frames.length; t++)
1236 if (frames[t] instanceof TreePanel)
1238 TreePanel tp = (TreePanel) frames[t];
1240 if (tp.getTreeCanvas().getViewport().getAlignment() == jal)
1242 JalviewModel.Tree tree = new JalviewModel.Tree();
1243 tree.setTitle(tp.getTitle());
1244 tree.setCurrentTree((av.getCurrentTree() == tp.getTree()));
1245 tree.setNewick(tp.getTree().print());
1246 tree.setThreshold(tp.getTreeCanvas().getThreshold());
1248 tree.setFitToWindow(tp.fitToWindow.getState());
1249 tree.setFontName(tp.getTreeFont().getName());
1250 tree.setFontSize(tp.getTreeFont().getSize());
1251 tree.setFontStyle(tp.getTreeFont().getStyle());
1252 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
1254 tree.setShowBootstrap(tp.bootstrapMenu.getState());
1255 tree.setShowDistances(tp.distanceMenu.getState());
1257 tree.setHeight(tp.getHeight());
1258 tree.setWidth(tp.getWidth());
1259 tree.setXpos(tp.getX());
1260 tree.setYpos(tp.getY());
1261 tree.setId(makeHashCode(tp, null));
1262 tree.setLinkToAllViews(
1263 tp.getTreeCanvas().isApplyToAllViews());
1265 // jms.addTree(tree);
1266 object.getTree().add(tree);
1276 if (!storeDS && Desktop.desktop != null)
1278 for (JInternalFrame frame : Desktop.desktop.getAllFrames())
1280 if (frame instanceof PCAPanel)
1282 PCAPanel panel = (PCAPanel) frame;
1283 if (panel.getAlignViewport().getAlignment() == jal)
1285 savePCA(panel, object);
1293 * store forward refs from an annotationRow to any groups
1295 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<>();
1298 for (SequenceI sq : jal.getSequences())
1300 // Store annotation on dataset sequences only
1301 AlignmentAnnotation[] aa = sq.getAnnotation();
1302 if (aa != null && aa.length > 0)
1304 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1311 if (jal.getAlignmentAnnotation() != null)
1313 // Store the annotation shown on the alignment.
1314 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1315 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1320 if (jal.getGroups() != null)
1322 JGroup[] groups = new JGroup[jal.getGroups().size()];
1324 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1326 JGroup jGroup = new JGroup();
1327 groups[++i] = jGroup;
1329 jGroup.setStart(sg.getStartRes());
1330 jGroup.setEnd(sg.getEndRes());
1331 jGroup.setName(sg.getName());
1332 if (groupRefs.containsKey(sg))
1334 // group has references so set its ID field
1335 jGroup.setId(groupRefs.get(sg));
1337 ColourSchemeI colourScheme = sg.getColourScheme();
1338 if (colourScheme != null)
1340 ResidueShaderI groupColourScheme = sg.getGroupColourScheme();
1341 if (groupColourScheme.conservationApplied())
1343 jGroup.setConsThreshold(groupColourScheme.getConservationInc());
1345 if (colourScheme instanceof jalview.schemes.UserColourScheme)
1348 setUserColourScheme(colourScheme, userColours,
1353 jGroup.setColour(colourScheme.getSchemeName());
1356 else if (colourScheme instanceof jalview.schemes.AnnotationColourGradient)
1358 jGroup.setColour("AnnotationColourGradient");
1359 jGroup.setAnnotationColours(constructAnnotationColours(
1360 (jalview.schemes.AnnotationColourGradient) colourScheme,
1361 userColours, object));
1363 else if (colourScheme instanceof jalview.schemes.UserColourScheme)
1366 setUserColourScheme(colourScheme, userColours, object));
1370 jGroup.setColour(colourScheme.getSchemeName());
1373 jGroup.setPidThreshold(groupColourScheme.getThreshold());
1376 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1377 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1378 jGroup.setDisplayText(sg.getDisplayText());
1379 jGroup.setColourText(sg.getColourText());
1380 jGroup.setTextCol1(sg.textColour.getRGB());
1381 jGroup.setTextCol2(sg.textColour2.getRGB());
1382 jGroup.setTextColThreshold(sg.thresholdTextColour);
1383 jGroup.setShowUnconserved(sg.getShowNonconserved());
1384 jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1385 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1386 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1387 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1388 for (SequenceI seq : sg.getSequences())
1390 // jGroup.addSeq(seqHash(seq));
1391 jGroup.getSeq().add(seqHash(seq));
1395 //jms.setJGroup(groups);
1397 for (JGroup grp : groups)
1399 object.getJGroup().add(grp);
1404 // /////////SAVE VIEWPORT
1405 Viewport view = new Viewport();
1406 view.setTitle(ap.alignFrame.getTitle());
1407 view.setSequenceSetId(
1408 makeHashCode(av.getSequenceSetId(), av.getSequenceSetId()));
1409 view.setId(av.getViewId());
1410 if (av.getCodingComplement() != null)
1412 view.setComplementId(av.getCodingComplement().getViewId());
1414 view.setViewName(av.getViewName());
1415 view.setGatheredViews(av.isGatherViewsHere());
1417 Rectangle size = ap.av.getExplodedGeometry();
1418 Rectangle position = size;
1421 size = ap.alignFrame.getBounds();
1422 if (av.getCodingComplement() != null)
1424 position = ((SplitFrame) ap.alignFrame.getSplitViewContainer())
1432 view.setXpos(position.x);
1433 view.setYpos(position.y);
1435 view.setWidth(size.width);
1436 view.setHeight(size.height);
1438 view.setStartRes(vpRanges.getStartRes());
1439 view.setStartSeq(vpRanges.getStartSeq());
1441 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1443 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1444 userColours, object));
1447 .getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1449 AnnotationColourScheme ac = constructAnnotationColours(
1450 (jalview.schemes.AnnotationColourGradient) av
1451 .getGlobalColourScheme(),
1452 userColours, object);
1454 view.setAnnotationColours(ac);
1455 view.setBgColour("AnnotationColourGradient");
1459 view.setBgColour(ColourSchemeProperty
1460 .getColourName(av.getGlobalColourScheme()));
1463 ResidueShaderI vcs = av.getResidueShading();
1464 ColourSchemeI cs = av.getGlobalColourScheme();
1468 if (vcs.conservationApplied())
1470 view.setConsThreshold(vcs.getConservationInc());
1471 if (cs instanceof jalview.schemes.UserColourScheme)
1473 view.setBgColour(setUserColourScheme(cs, userColours, object));
1476 view.setPidThreshold(vcs.getThreshold());
1479 view.setConservationSelected(av.getConservationSelected());
1480 view.setPidSelected(av.getAbovePIDThreshold());
1481 final Font font = av.getFont();
1482 view.setFontName(font.getName());
1483 view.setFontSize(font.getSize());
1484 view.setFontStyle(font.getStyle());
1485 view.setScaleProteinAsCdna(av.getViewStyle().isScaleProteinAsCdna());
1486 view.setRenderGaps(av.isRenderGaps());
1487 view.setShowAnnotation(av.isShowAnnotation());
1488 view.setShowBoxes(av.getShowBoxes());
1489 view.setShowAutocalcAbove(av.isShowAutocalculatedAbove());
1490 view.setSortAnnotationsBy(av.getSortAnnotationsBy().name());
1491 view.setShowColourText(av.getColourText());
1492 view.setShowFullId(av.getShowJVSuffix());
1493 view.setRightAlignIds(av.isRightAlignIds());
1494 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1495 view.setShowText(av.getShowText());
1496 view.setShowUnconserved(av.getShowUnconserved());
1497 view.setWrapAlignment(av.getWrapAlignment());
1498 view.setTextCol1(av.getTextColour().getRGB());
1499 view.setTextCol2(av.getTextColour2().getRGB());
1500 view.setTextColThreshold(av.getThresholdTextColour());
1501 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1502 view.setShowSequenceLogo(av.isShowSequenceLogo());
1503 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1504 view.setShowGroupConsensus(av.isShowGroupConsensus());
1505 view.setShowGroupConservation(av.isShowGroupConservation());
1506 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1507 view.setShowDbRefTooltip(av.isShowDBRefs());
1508 view.setFollowHighlight(av.isFollowHighlight());
1509 view.setFollowSelection(av.followSelection);
1510 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1511 if (av.getFeaturesDisplayed() != null)
1513 FeatureSettings fs = new FeatureSettings();
1515 FeatureRenderer fr = ap.getSeqPanel().seqCanvas
1516 .getFeatureRenderer();
1517 String[] renderOrder = fr.getRenderOrder().toArray(new String[0]);
1519 Vector<String> settingsAdded = new Vector<>();
1520 if (renderOrder != null)
1522 for (String featureType : renderOrder)
1524 FeatureSettings.Setting setting = new FeatureSettings.Setting();
1525 setting.setType(featureType);
1528 * save any filter for the feature type
1530 FeatureMatcherSetI filter = fr.getFeatureFilter(featureType);
1531 if (filter != null) {
1532 Iterator<FeatureMatcherI> filters = filter.getMatchers().iterator();
1533 FeatureMatcherI firstFilter = filters.next();
1534 setting.setMatcherSet(Jalview2XML.marshalFilter(
1535 firstFilter, filters, filter.isAnded()));
1539 * save colour scheme for the feature type
1541 FeatureColourI fcol = fr.getFeatureStyle(featureType);
1542 if (!fcol.isSimpleColour())
1544 setting.setColour(fcol.getMaxColour().getRGB());
1545 setting.setMincolour(fcol.getMinColour().getRGB());
1546 setting.setMin(fcol.getMin());
1547 setting.setMax(fcol.getMax());
1548 setting.setColourByLabel(fcol.isColourByLabel());
1549 if (fcol.isColourByAttribute())
1551 String[] attName = fcol.getAttributeName();
1552 setting.getAttributeName().add(attName[0]);
1553 if (attName.length > 1)
1555 setting.getAttributeName().add(attName[1]);
1558 setting.setAutoScale(fcol.isAutoScaled());
1559 setting.setThreshold(fcol.getThreshold());
1560 Color noColour = fcol.getNoColour();
1561 if (noColour == null)
1563 setting.setNoValueColour(NoValueColour.NONE);
1565 else if (noColour.equals(fcol.getMaxColour()))
1567 setting.setNoValueColour(NoValueColour.MAX);
1571 setting.setNoValueColour(NoValueColour.MIN);
1573 // -1 = No threshold, 0 = Below, 1 = Above
1574 setting.setThreshstate(fcol.isAboveThreshold() ? 1
1575 : (fcol.isBelowThreshold() ? 0 : -1));
1579 setting.setColour(fcol.getColour().getRGB());
1583 av.getFeaturesDisplayed().isVisible(featureType));
1585 .getOrder(featureType);
1588 setting.setOrder(rorder);
1590 /// fs.addSetting(setting);
1591 fs.getSetting().add(setting);
1592 settingsAdded.addElement(featureType);
1596 // is groups actually supposed to be a map here ?
1597 Iterator<String> en = fr.getFeatureGroups().iterator();
1598 Vector<String> groupsAdded = new Vector<>();
1599 while (en.hasNext())
1601 String grp = en.next();
1602 if (groupsAdded.contains(grp))
1606 Group g = new Group();
1608 g.setDisplay(((Boolean) fr.checkGroupVisibility(grp, false))
1611 fs.getGroup().add(g);
1612 groupsAdded.addElement(grp);
1614 // jms.setFeatureSettings(fs);
1615 object.setFeatureSettings(fs);
1618 if (av.hasHiddenColumns())
1620 jalview.datamodel.HiddenColumns hidden = av.getAlignment()
1621 .getHiddenColumns();
1624 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1628 Iterator<int[]> hiddenRegions = hidden.iterator();
1629 while (hiddenRegions.hasNext())
1631 int[] region = hiddenRegions.next();
1632 HiddenColumns hc = new HiddenColumns();
1633 hc.setStart(region[0]);
1634 hc.setEnd(region[1]);
1635 // view.addHiddenColumns(hc);
1636 view.getHiddenColumns().add(hc);
1640 if (calcIdSet.size() > 0)
1642 for (String calcId : calcIdSet)
1644 if (calcId.trim().length() > 0)
1646 CalcIdParam cidp = createCalcIdParam(calcId, av);
1647 // Some calcIds have no parameters.
1650 // view.addCalcIdParam(cidp);
1651 view.getCalcIdParam().add(cidp);
1657 // jms.addViewport(view);
1658 object.getViewport().add(view);
1660 // object.setJalviewModelSequence(jms);
1661 // object.getVamsasModel().addSequenceSet(vamsasSet);
1662 object.getVamsasModel().getSequenceSet().add(vamsasSet);
1664 if (jout != null && fileName != null)
1666 // We may not want to write the object to disk,
1667 // eg we can copy the alignViewport to a new view object
1668 // using save and then load
1671 System.out.println("Writing jar entry " + fileName);
1672 JarEntry entry = new JarEntry(fileName);
1673 jout.putNextEntry(entry);
1674 PrintWriter pout = new PrintWriter(
1675 new OutputStreamWriter(jout, UTF_8));
1676 JAXBContext jaxbContext = JAXBContext
1677 .newInstance(JalviewModel.class);
1678 Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
1680 // output pretty printed
1681 // jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
1682 jaxbMarshaller.marshal(
1683 new ObjectFactory().createJalviewModel(object), pout);
1685 // jaxbMarshaller.marshal(object, pout);
1686 // marshaller.marshal(object);
1689 } catch (Exception ex)
1691 // TODO: raise error in GUI if marshalling failed.
1692 System.err.println("Error writing Jalview project");
1693 ex.printStackTrace();
1700 * Writes PCA viewer attributes and computed values to an XML model object and
1701 * adds it to the JalviewModel. Any exceptions are reported by logging.
1703 protected void savePCA(PCAPanel panel, JalviewModel object)
1707 PcaViewer viewer = new PcaViewer();
1708 viewer.setHeight(panel.getHeight());
1709 viewer.setWidth(panel.getWidth());
1710 viewer.setXpos(panel.getX());
1711 viewer.setYpos(panel.getY());
1712 viewer.setTitle(panel.getTitle());
1713 PCAModel pcaModel = panel.getPcaModel();
1714 viewer.setScoreModelName(pcaModel.getScoreModelName());
1715 viewer.setXDim(panel.getSelectedDimensionIndex(X));
1716 viewer.setYDim(panel.getSelectedDimensionIndex(Y));
1717 viewer.setZDim(panel.getSelectedDimensionIndex(Z));
1719 panel.getRotatableCanvas().getBackgroundColour().getRGB());
1720 viewer.setScaleFactor(panel.getRotatableCanvas().getScaleFactor());
1721 float[] spMin = panel.getRotatableCanvas().getSeqMin();
1722 SeqPointMin spmin = new SeqPointMin();
1723 spmin.setXPos(spMin[0]);
1724 spmin.setYPos(spMin[1]);
1725 spmin.setZPos(spMin[2]);
1726 viewer.setSeqPointMin(spmin);
1727 float[] spMax = panel.getRotatableCanvas().getSeqMax();
1728 SeqPointMax spmax = new SeqPointMax();
1729 spmax.setXPos(spMax[0]);
1730 spmax.setYPos(spMax[1]);
1731 spmax.setZPos(spMax[2]);
1732 viewer.setSeqPointMax(spmax);
1733 viewer.setShowLabels(panel.getRotatableCanvas().isShowLabels());
1734 viewer.setLinkToAllViews(
1735 panel.getRotatableCanvas().isApplyToAllViews());
1736 SimilarityParamsI sp = pcaModel.getSimilarityParameters();
1737 viewer.setIncludeGaps(sp.includeGaps());
1738 viewer.setMatchGaps(sp.matchGaps());
1739 viewer.setIncludeGappedColumns(sp.includeGappedColumns());
1740 viewer.setDenominateByShortestLength(sp.denominateByShortestLength());
1743 * sequence points on display
1745 for (jalview.datamodel.SequencePoint spt : pcaModel
1746 .getSequencePoints())
1748 SequencePoint point = new SequencePoint();
1749 point.setSequenceRef(seqHash(spt.getSequence()));
1750 point.setXPos(spt.coord.x);
1751 point.setYPos(spt.coord.y);
1752 point.setZPos(spt.coord.z);
1753 viewer.getSequencePoint().add(point);
1757 * (end points of) axes on display
1759 for (Point p : panel.getRotatableCanvas().getAxisEndPoints())
1762 Axis axis = new Axis();
1766 viewer.getAxis().add(axis);
1770 * raw PCA data (note we are not restoring PCA inputs here -
1771 * alignment view, score model, similarity parameters)
1773 PcaDataType data = new PcaDataType();
1774 viewer.setPcaData(data);
1775 PCA pca = pcaModel.getPcaData();
1777 DoubleMatrix pm = new DoubleMatrix();
1778 saveDoubleMatrix(pca.getPairwiseScores(), pm);
1779 data.setPairwiseMatrix(pm);
1781 DoubleMatrix tm = new DoubleMatrix();
1782 saveDoubleMatrix(pca.getTridiagonal(), tm);
1783 data.setTridiagonalMatrix(tm);
1785 DoubleMatrix eigenMatrix = new DoubleMatrix();
1786 data.setEigenMatrix(eigenMatrix);
1787 saveDoubleMatrix(pca.getEigenmatrix(), eigenMatrix);
1789 object.getPcaViewer().add(viewer);
1790 } catch (Throwable t)
1792 Cache.log.error("Error saving PCA: " + t.getMessage());
1797 * Stores values from a matrix into an XML element, including (if present) the
1802 * @see #loadDoubleMatrix(DoubleMatrix)
1804 protected void saveDoubleMatrix(MatrixI m, DoubleMatrix xmlMatrix)
1806 xmlMatrix.setRows(m.height());
1807 xmlMatrix.setColumns(m.width());
1808 for (int i = 0; i < m.height(); i++)
1810 DoubleVector row = new DoubleVector();
1811 for (int j = 0; j < m.width(); j++)
1813 row.getV().add(m.getValue(i, j));
1815 xmlMatrix.getRow().add(row);
1817 if (m.getD() != null)
1819 DoubleVector dVector = new DoubleVector();
1820 for (double d : m.getD())
1822 dVector.getV().add(d);
1824 xmlMatrix.setD(dVector);
1826 if (m.getE() != null)
1828 DoubleVector eVector = new DoubleVector();
1829 for (double e : m.getE())
1831 eVector.getV().add(e);
1833 xmlMatrix.setE(eVector);
1838 * Loads XML matrix data into a new Matrix object, including the D and/or E
1839 * vectors (if present)
1843 * @see Jalview2XML#saveDoubleMatrix(MatrixI, DoubleMatrix)
1845 protected MatrixI loadDoubleMatrix(DoubleMatrix mData)
1847 int rows = mData.getRows();
1848 double[][] vals = new double[rows][];
1850 for (int i = 0; i < rows; i++)
1852 List<Double> dVector = mData.getRow().get(i).getV();
1853 vals[i] = new double[dVector.size()];
1855 for (Double d : dVector)
1861 MatrixI m = new Matrix(vals);
1863 if (mData.getD() != null)
1865 List<Double> dVector = mData.getD().getV();
1866 double[] vec = new double[dVector.size()];
1868 for (Double d : dVector)
1874 if (mData.getE() != null)
1876 List<Double> dVector = mData.getE().getV();
1877 double[] vec = new double[dVector.size()];
1879 for (Double d : dVector)
1890 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1891 * for each viewer, with
1893 * <li>viewer geometry (position, size, split pane divider location)</li>
1894 * <li>index of the selected structure in the viewer (currently shows gapped
1896 * <li>the id of the annotation holding RNA secondary structure</li>
1897 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1899 * Varna viewer state is also written out (in native Varna XML) to separate
1900 * project jar entries. A separate entry is written for each RNA structure
1901 * displayed, with the naming convention
1903 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
1911 * @param storeDataset
1913 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
1914 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
1915 boolean storeDataset)
1917 if (Desktop.desktop == null)
1921 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1922 for (int f = frames.length - 1; f > -1; f--)
1924 if (frames[f] instanceof AppVarna)
1926 AppVarna varna = (AppVarna) frames[f];
1928 * link the sequence to every viewer that is showing it and is linked to
1929 * its alignment panel
1931 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1933 String viewId = varna.getViewId();
1934 RnaViewer rna = new RnaViewer();
1935 rna.setViewId(viewId);
1936 rna.setTitle(varna.getTitle());
1937 rna.setXpos(varna.getX());
1938 rna.setYpos(varna.getY());
1939 rna.setWidth(varna.getWidth());
1940 rna.setHeight(varna.getHeight());
1941 rna.setDividerLocation(varna.getDividerLocation());
1942 rna.setSelectedRna(varna.getSelectedIndex());
1943 // jseq.addRnaViewer(rna);
1944 jseq.getRnaViewer().add(rna);
1947 * Store each Varna panel's state once in the project per sequence.
1948 * First time through only (storeDataset==false)
1950 // boolean storeSessions = false;
1951 // String sequenceViewId = viewId + seqsToIds.get(jds);
1952 // if (!storeDataset && !viewIds.contains(sequenceViewId))
1954 // viewIds.add(sequenceViewId);
1955 // storeSessions = true;
1957 for (RnaModel model : varna.getModels())
1959 if (model.seq == jds)
1962 * VARNA saves each view (sequence or alignment secondary
1963 * structure, gapped or trimmed) as a separate XML file
1965 String jarEntryName = rnaSessions.get(model);
1966 if (jarEntryName == null)
1969 String varnaStateFile = varna.getStateInfo(model.rna);
1970 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
1971 copyFileToJar(jout, varnaStateFile, jarEntryName);
1972 rnaSessions.put(model, jarEntryName);
1974 SecondaryStructure ss = new SecondaryStructure();
1975 String annotationId = varna.getAnnotation(jds).annotationId;
1976 ss.setAnnotationId(annotationId);
1977 ss.setViewerState(jarEntryName);
1978 ss.setGapped(model.gapped);
1979 ss.setTitle(model.title);
1980 // rna.addSecondaryStructure(ss);
1981 rna.getSecondaryStructure().add(ss);
1990 * Copy the contents of a file to a new entry added to the output jar
1994 * @param jarEntryName
1996 protected void copyFileToJar(JarOutputStream jout, String infilePath,
1997 String jarEntryName)
1999 DataInputStream dis = null;
2002 File file = new File(infilePath);
2003 if (file.exists() && jout != null)
2005 dis = new DataInputStream(new FileInputStream(file));
2006 byte[] data = new byte[(int) file.length()];
2007 dis.readFully(data);
2008 writeJarEntry(jout, jarEntryName, data);
2010 } catch (Exception ex)
2012 ex.printStackTrace();
2020 } catch (IOException e)
2029 * Write the data to a new entry of given name in the output jar file
2032 * @param jarEntryName
2034 * @throws IOException
2036 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
2037 byte[] data) throws IOException
2041 System.out.println("Writing jar entry " + jarEntryName);
2042 jout.putNextEntry(new JarEntry(jarEntryName));
2043 DataOutputStream dout = new DataOutputStream(jout);
2044 dout.write(data, 0, data.length);
2051 * Save the state of a structure viewer
2056 * the archive XML element under which to save the state
2059 * @param matchedFile
2063 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
2064 Pdbids pdb, PDBEntry entry, List<String> viewIds,
2065 String matchedFile, StructureViewerBase viewFrame)
2067 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
2070 * Look for any bindings for this viewer to the PDB file of interest
2071 * (including part matches excluding chain id)
2073 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
2075 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
2076 final String pdbId = pdbentry.getId();
2077 if (!pdbId.equals(entry.getId())
2078 && !(entry.getId().length() > 4 && entry.getId().toLowerCase()
2079 .startsWith(pdbId.toLowerCase())))
2082 * not interested in a binding to a different PDB entry here
2086 if (matchedFile == null)
2088 matchedFile = pdbentry.getFile();
2090 else if (!matchedFile.equals(pdbentry.getFile()))
2093 "Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
2094 + pdbentry.getFile());
2098 // can get at it if the ID
2099 // match is ambiguous (e.g.
2102 for (int smap = 0; smap < viewFrame.getBinding()
2103 .getSequence()[peid].length; smap++)
2105 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
2106 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
2108 StructureState state = new StructureState();
2109 state.setVisible(true);
2110 state.setXpos(viewFrame.getX());
2111 state.setYpos(viewFrame.getY());
2112 state.setWidth(viewFrame.getWidth());
2113 state.setHeight(viewFrame.getHeight());
2114 final String viewId = viewFrame.getViewId();
2115 state.setViewId(viewId);
2116 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
2117 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
2118 state.setColourByJmol(viewFrame.isColouredByViewer());
2119 state.setType(viewFrame.getViewerType().toString());
2120 // pdb.addStructureState(state);
2121 pdb.getStructureState().add(state);
2129 * Populates the AnnotationColourScheme xml for save. This captures the
2130 * settings of the options in the 'Colour by Annotation' dialog.
2133 * @param userColours
2137 private AnnotationColourScheme constructAnnotationColours(
2138 AnnotationColourGradient acg, List<UserColourScheme> userColours,
2141 AnnotationColourScheme ac = new AnnotationColourScheme();
2142 ac.setAboveThreshold(acg.getAboveThreshold());
2143 ac.setThreshold(acg.getAnnotationThreshold());
2144 // 2.10.2 save annotationId (unique) not annotation label
2145 ac.setAnnotation(acg.getAnnotation().annotationId);
2146 if (acg.getBaseColour() instanceof UserColourScheme)
2149 setUserColourScheme(acg.getBaseColour(), userColours, jm));
2154 ColourSchemeProperty.getColourName(acg.getBaseColour()));
2157 ac.setMaxColour(acg.getMaxColour().getRGB());
2158 ac.setMinColour(acg.getMinColour().getRGB());
2159 ac.setPerSequence(acg.isSeqAssociated());
2160 ac.setPredefinedColours(acg.isPredefinedColours());
2164 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
2165 IdentityHashMap<SequenceGroup, String> groupRefs,
2166 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
2167 SequenceSet vamsasSet)
2170 for (int i = 0; i < aa.length; i++)
2172 Annotation an = new Annotation();
2174 AlignmentAnnotation annotation = aa[i];
2175 if (annotation.annotationId != null)
2177 annotationIds.put(annotation.annotationId, annotation);
2180 an.setId(annotation.annotationId);
2182 an.setVisible(annotation.visible);
2184 an.setDescription(annotation.description);
2186 if (annotation.sequenceRef != null)
2188 // 2.9 JAL-1781 xref on sequence id rather than name
2189 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
2191 if (annotation.groupRef != null)
2193 String groupIdr = groupRefs.get(annotation.groupRef);
2194 if (groupIdr == null)
2196 // make a locally unique String
2197 groupRefs.put(annotation.groupRef,
2198 groupIdr = ("" + System.currentTimeMillis()
2199 + annotation.groupRef.getName()
2200 + groupRefs.size()));
2202 an.setGroupRef(groupIdr.toString());
2205 // store all visualization attributes for annotation
2206 an.setGraphHeight(annotation.graphHeight);
2207 an.setCentreColLabels(annotation.centreColLabels);
2208 an.setScaleColLabels(annotation.scaleColLabel);
2209 an.setShowAllColLabels(annotation.showAllColLabels);
2210 an.setBelowAlignment(annotation.belowAlignment);
2212 if (annotation.graph > 0)
2215 an.setGraphType(annotation.graph);
2216 an.setGraphGroup(annotation.graphGroup);
2217 if (annotation.getThreshold() != null)
2219 ThresholdLine line = new ThresholdLine();
2220 line.setLabel(annotation.getThreshold().label);
2221 line.setValue(annotation.getThreshold().value);
2222 line.setColour(annotation.getThreshold().colour.getRGB());
2223 an.setThresholdLine(line);
2231 an.setLabel(annotation.label);
2233 if (annotation == av.getAlignmentQualityAnnot()
2234 || annotation == av.getAlignmentConservationAnnotation()
2235 || annotation == av.getAlignmentConsensusAnnotation()
2236 || annotation.autoCalculated)
2238 // new way of indicating autocalculated annotation -
2239 an.setAutoCalculated(annotation.autoCalculated);
2241 if (annotation.hasScore())
2243 an.setScore(annotation.getScore());
2246 if (annotation.getCalcId() != null)
2248 calcIdSet.add(annotation.getCalcId());
2249 an.setCalcId(annotation.getCalcId());
2251 if (annotation.hasProperties())
2253 for (String pr : annotation.getProperties())
2255 jalview.xml.binding.jalview.Annotation.Property prop = new jalview.xml.binding.jalview.Annotation.Property();
2257 prop.setValue(annotation.getProperty(pr));
2258 // an.addProperty(prop);
2259 an.getProperty().add(prop);
2263 AnnotationElement ae;
2264 if (annotation.annotations != null)
2266 an.setScoreOnly(false);
2267 for (int a = 0; a < annotation.annotations.length; a++)
2269 if ((annotation == null) || (annotation.annotations[a] == null))
2274 ae = new AnnotationElement();
2275 if (annotation.annotations[a].description != null)
2277 ae.setDescription(annotation.annotations[a].description);
2279 if (annotation.annotations[a].displayCharacter != null)
2281 ae.setDisplayCharacter(
2282 annotation.annotations[a].displayCharacter);
2285 if (!Float.isNaN(annotation.annotations[a].value))
2287 ae.setValue(annotation.annotations[a].value);
2291 if (annotation.annotations[a].secondaryStructure > ' ')
2293 ae.setSecondaryStructure(
2294 annotation.annotations[a].secondaryStructure + "");
2297 if (annotation.annotations[a].colour != null
2298 && annotation.annotations[a].colour != java.awt.Color.black)
2300 ae.setColour(annotation.annotations[a].colour.getRGB());
2303 // an.addAnnotationElement(ae);
2304 an.getAnnotationElement().add(ae);
2305 if (annotation.autoCalculated)
2307 // only write one non-null entry into the annotation row -
2308 // sufficient to get the visualization attributes necessary to
2316 an.setScoreOnly(true);
2318 if (!storeDS || (storeDS && !annotation.autoCalculated))
2320 // skip autocalculated annotation - these are only provided for
2322 // vamsasSet.addAnnotation(an);
2323 vamsasSet.getAnnotation().add(an);
2329 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
2331 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
2332 if (settings != null)
2334 CalcIdParam vCalcIdParam = new CalcIdParam();
2335 vCalcIdParam.setCalcId(calcId);
2336 // vCalcIdParam.addServiceURL(settings.getServiceURI());
2337 vCalcIdParam.getServiceURL().add(settings.getServiceURI());
2338 // generic URI allowing a third party to resolve another instance of the
2339 // service used for this calculation
2340 for (String url : settings.getServiceURLs())
2342 // vCalcIdParam.addServiceURL(urls);
2343 vCalcIdParam.getServiceURL().add(url);
2345 vCalcIdParam.setVersion("1.0");
2346 if (settings.getPreset() != null)
2348 WsParamSetI setting = settings.getPreset();
2349 vCalcIdParam.setName(setting.getName());
2350 vCalcIdParam.setDescription(setting.getDescription());
2354 vCalcIdParam.setName("");
2355 vCalcIdParam.setDescription("Last used parameters");
2357 // need to be able to recover 1) settings 2) user-defined presets or
2358 // recreate settings from preset 3) predefined settings provided by
2359 // service - or settings that can be transferred (or discarded)
2360 vCalcIdParam.setParameters(
2361 settings.getWsParamFile().replace("\n", "|\\n|"));
2362 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
2363 // todo - decide if updateImmediately is needed for any projects.
2365 return vCalcIdParam;
2370 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
2373 if (calcIdParam.getVersion().equals("1.0"))
2375 final String[] calcIds = calcIdParam.getServiceURL().toArray(new String[0]);
2376 Jws2Instance service = Jws2Discoverer.getDiscoverer()
2377 .getPreferredServiceFor(calcIds);
2378 if (service != null)
2380 WsParamSetI parmSet = null;
2383 parmSet = service.getParamStore().parseServiceParameterFile(
2384 calcIdParam.getName(), calcIdParam.getDescription(),
2386 calcIdParam.getParameters().replace("|\\n|", "\n"));
2387 } catch (IOException x)
2389 warn("Couldn't parse parameter data for "
2390 + calcIdParam.getCalcId(), x);
2393 List<ArgumentI> argList = null;
2394 if (calcIdParam.getName().length() > 0)
2396 parmSet = service.getParamStore()
2397 .getPreset(calcIdParam.getName());
2398 if (parmSet != null)
2400 // TODO : check we have a good match with settings in AACon -
2401 // otherwise we'll need to create a new preset
2406 argList = parmSet.getArguments();
2409 AAConSettings settings = new AAConSettings(
2410 calcIdParam.isAutoUpdate(), service, parmSet, argList);
2411 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
2412 calcIdParam.isNeedsUpdate());
2417 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
2421 throw new Error(MessageManager.formatMessage(
2422 "error.unsupported_version_calcIdparam", new Object[]
2423 { calcIdParam.toString() }));
2427 * External mapping between jalview objects and objects yielding a valid and
2428 * unique object ID string. This is null for normal Jalview project IO, but
2429 * non-null when a jalview project is being read or written as part of a
2432 IdentityHashMap jv2vobj = null;
2435 * Construct a unique ID for jvobj using either existing bindings or if none
2436 * exist, the result of the hashcode call for the object.
2439 * jalview data object
2440 * @return unique ID for referring to jvobj
2442 private String makeHashCode(Object jvobj, String altCode)
2444 if (jv2vobj != null)
2446 Object id = jv2vobj.get(jvobj);
2449 return id.toString();
2451 // check string ID mappings
2452 if (jvids2vobj != null && jvobj instanceof String)
2454 id = jvids2vobj.get(jvobj);
2458 return id.toString();
2460 // give up and warn that something has gone wrong
2461 warn("Cannot find ID for object in external mapping : " + jvobj);
2467 * return local jalview object mapped to ID, if it exists
2471 * @return null or object bound to idcode
2473 private Object retrieveExistingObj(String idcode)
2475 if (idcode != null && vobj2jv != null)
2477 return vobj2jv.get(idcode);
2483 * binding from ID strings from external mapping table to jalview data model
2486 private Hashtable vobj2jv;
2488 private Sequence createVamsasSequence(String id, SequenceI jds)
2490 return createVamsasSequence(true, id, jds, null);
2493 private Sequence createVamsasSequence(boolean recurse, String id,
2494 SequenceI jds, SequenceI parentseq)
2496 Sequence vamsasSeq = new Sequence();
2497 vamsasSeq.setId(id);
2498 vamsasSeq.setName(jds.getName());
2499 vamsasSeq.setSequence(jds.getSequenceAsString());
2500 vamsasSeq.setDescription(jds.getDescription());
2501 jalview.datamodel.DBRefEntry[] dbrefs = null;
2502 if (jds.getDatasetSequence() != null)
2504 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
2508 // seqId==dsseqid so we can tell which sequences really are
2509 // dataset sequences only
2510 vamsasSeq.setDsseqid(id);
2511 dbrefs = jds.getDBRefs();
2512 if (parentseq == null)
2519 for (int d = 0; d < dbrefs.length; d++)
2521 DBRef dbref = new DBRef();
2522 dbref.setSource(dbrefs[d].getSource());
2523 dbref.setVersion(dbrefs[d].getVersion());
2524 dbref.setAccessionId(dbrefs[d].getAccessionId());
2525 if (dbrefs[d].hasMap())
2527 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
2529 dbref.setMapping(mp);
2531 // vamsasSeq.addDBRef(dbref);
2532 vamsasSeq.getDBRef().add(dbref);
2538 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
2539 SequenceI parentseq, SequenceI jds, boolean recurse)
2542 if (jmp.getMap() != null)
2546 jalview.util.MapList mlst = jmp.getMap();
2547 List<int[]> r = mlst.getFromRanges();
2548 for (int[] range : r)
2550 MapListFrom mfrom = new MapListFrom();
2551 mfrom.setStart(range[0]);
2552 mfrom.setEnd(range[1]);
2553 // mp.addMapListFrom(mfrom);
2554 mp.getMapListFrom().add(mfrom);
2556 r = mlst.getToRanges();
2557 for (int[] range : r)
2559 MapListTo mto = new MapListTo();
2560 mto.setStart(range[0]);
2561 mto.setEnd(range[1]);
2562 // mp.addMapListTo(mto);
2563 mp.getMapListTo().add(mto);
2565 mp.setMapFromUnit(BigInteger.valueOf(mlst.getFromRatio()));
2566 mp.setMapToUnit(BigInteger.valueOf(mlst.getToRatio()));
2567 if (jmp.getTo() != null)
2569 // MappingChoice mpc = new MappingChoice();
2571 // check/create ID for the sequence referenced by getTo()
2574 SequenceI ps = null;
2575 if (parentseq != jmp.getTo()
2576 && parentseq.getDatasetSequence() != jmp.getTo())
2578 // chaining dbref rather than a handshaking one
2579 jmpid = seqHash(ps = jmp.getTo());
2583 jmpid = seqHash(ps = parentseq);
2585 // mpc.setDseqFor(jmpid);
2586 mp.setDseqFor(jmpid);
2587 if (!seqRefIds.containsKey(jmpid))
2589 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2590 seqRefIds.put(jmpid, ps);
2594 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2597 // mp.setMappingChoice(mpc);
2603 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2604 List<UserColourScheme> userColours, JalviewModel jm)
2607 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2608 boolean newucs = false;
2609 if (!userColours.contains(ucs))
2611 userColours.add(ucs);
2614 id = "ucs" + userColours.indexOf(ucs);
2617 // actually create the scheme's entry in the XML model
2618 java.awt.Color[] colours = ucs.getColours();
2619 UserColours uc = new UserColours();
2620 // UserColourScheme jbucs = new UserColourScheme();
2621 JalviewUserColours jbucs = new JalviewUserColours();
2623 for (int i = 0; i < colours.length; i++)
2625 Colour col = new Colour();
2626 col.setName(ResidueProperties.aa[i]);
2627 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2628 // jbucs.addColour(col);
2629 jbucs.getColour().add(col);
2631 if (ucs.getLowerCaseColours() != null)
2633 colours = ucs.getLowerCaseColours();
2634 for (int i = 0; i < colours.length; i++)
2636 Colour col = new Colour();
2637 col.setName(ResidueProperties.aa[i].toLowerCase());
2638 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2639 // jbucs.addColour(col);
2640 jbucs.getColour().add(col);
2645 uc.setUserColourScheme(jbucs);
2646 // jm.addUserColours(uc);
2647 jm.getUserColours().add(uc);
2653 jalview.schemes.UserColourScheme getUserColourScheme(
2654 JalviewModel jm, String id)
2656 List<UserColours> uc = jm.getUserColours();
2657 UserColours colours = null;
2659 for (int i = 0; i < uc.length; i++)
2661 if (uc[i].getId().equals(id))
2668 for (UserColours c : uc)
2670 if (c.getId().equals(id))
2677 java.awt.Color[] newColours = new java.awt.Color[24];
2679 for (int i = 0; i < 24; i++)
2681 newColours[i] = new java.awt.Color(Integer.parseInt(
2682 // colours.getUserColourScheme().getColour(i).getRGB(), 16));
2683 colours.getUserColourScheme().getColour().get(i).getRGB(),
2687 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2690 if (colours.getUserColourScheme().getColour().size()/*Count()*/ > 24)
2692 newColours = new java.awt.Color[23];
2693 for (int i = 0; i < 23; i++)
2695 newColours[i] = new java.awt.Color(Integer.parseInt(
2696 colours.getUserColourScheme().getColour().get(i + 24)
2700 ucs.setLowerCaseColours(newColours);
2707 * contains last error message (if any) encountered by XML loader.
2709 String errorMessage = null;
2712 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2713 * exceptions are raised during project XML parsing
2715 public boolean attemptversion1parse = false;
2718 * Load a jalview project archive from a jar file
2721 * - HTTP URL or filename
2723 public AlignFrame loadJalviewAlign(final String file)
2726 jalview.gui.AlignFrame af = null;
2730 // create list to store references for any new Jmol viewers created
2731 newStructureViewers = new Vector<>();
2732 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2733 // Workaround is to make sure caller implements the JarInputStreamProvider
2735 // so we can re-open the jar input stream for each entry.
2737 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2738 af = loadJalviewAlign(jprovider);
2741 af.setMenusForViewport();
2743 } catch (MalformedURLException e)
2745 errorMessage = "Invalid URL format for '" + file + "'";
2751 SwingUtilities.invokeAndWait(new Runnable()
2756 setLoadingFinishedForNewStructureViewers();
2759 } catch (Exception x)
2761 System.err.println("Error loading alignment: " + x.getMessage());
2767 private jarInputStreamProvider createjarInputStreamProvider(
2768 final String file) throws MalformedURLException
2771 errorMessage = null;
2772 uniqueSetSuffix = null;
2774 viewportsAdded.clear();
2775 frefedSequence = null;
2777 if (file.startsWith("http://"))
2779 url = new URL(file);
2781 final URL _url = url;
2782 return new jarInputStreamProvider()
2786 public JarInputStream getJarInputStream() throws IOException
2790 return new JarInputStream(_url.openStream());
2794 return new JarInputStream(new FileInputStream(file));
2799 public String getFilename()
2807 * Recover jalview session from a jalview project archive. Caller may
2808 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2809 * themselves. Any null fields will be initialised with default values,
2810 * non-null fields are left alone.
2815 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2817 errorMessage = null;
2818 if (uniqueSetSuffix == null)
2820 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2822 if (seqRefIds == null)
2826 AlignFrame af = null, _af = null;
2827 IdentityHashMap<AlignmentI, AlignmentI> importedDatasets = new IdentityHashMap<>();
2828 Map<String, AlignFrame> gatherToThisFrame = new HashMap<>();
2829 final String file = jprovider.getFilename();
2832 JarInputStream jin = null;
2833 JarEntry jarentry = null;
2838 jin = jprovider.getJarInputStream();
2839 for (int i = 0; i < entryCount; i++)
2841 jarentry = jin.getNextJarEntry();
2844 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2846 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2847 // JalviewModel object = new JalviewModel();
2849 JAXBContext jc = JAXBContext
2850 .newInstance("jalview.xml.binding.jalview");
2851 XMLStreamReader streamReader = XMLInputFactory.newInstance()
2852 .createXMLStreamReader(jin);
2853 javax.xml.bind.Unmarshaller um = jc.createUnmarshaller();
2854 JAXBElement<JalviewModel> jbe = um
2855 .unmarshal(streamReader, JalviewModel.class);
2856 JalviewModel object = jbe.getValue();
2859 Unmarshaller unmar = new Unmarshaller(object);
2860 unmar.setValidation(false);
2861 object = (JalviewModel) unmar.unmarshal(in);
2863 if (true) // !skipViewport(object))
2865 _af = loadFromObject(object, file, true, jprovider);
2866 if (_af != null && object.getViewport().size() > 0)
2867 // getJalviewModelSequence().getViewportCount() > 0)
2871 // store a reference to the first view
2874 if (_af.getViewport().isGatherViewsHere())
2876 // if this is a gathered view, keep its reference since
2877 // after gathering views, only this frame will remain
2879 gatherToThisFrame.put(_af.getViewport().getSequenceSetId(),
2882 // Save dataset to register mappings once all resolved
2883 importedDatasets.put(
2884 af.getViewport().getAlignment().getDataset(),
2885 af.getViewport().getAlignment().getDataset());
2890 else if (jarentry != null)
2892 // Some other file here.
2895 } while (jarentry != null);
2896 resolveFrefedSequences();
2897 } catch (IOException ex)
2899 ex.printStackTrace();
2900 errorMessage = "Couldn't locate Jalview XML file : " + file;
2902 "Exception whilst loading jalview XML file : " + ex + "\n");
2903 } catch (Exception ex)
2905 System.err.println("Parsing as Jalview Version 2 file failed.");
2906 ex.printStackTrace(System.err);
2907 if (attemptversion1parse)
2909 // used to attempt to parse as V1 castor-generated xml
2911 if (Desktop.instance != null)
2913 Desktop.instance.stopLoading();
2917 System.out.println("Successfully loaded archive file");
2920 ex.printStackTrace();
2923 "Exception whilst loading jalview XML file : " + ex + "\n");
2924 } catch (OutOfMemoryError e)
2926 // Don't use the OOM Window here
2927 errorMessage = "Out of memory loading jalview XML file";
2928 System.err.println("Out of memory whilst loading jalview XML file");
2929 e.printStackTrace();
2933 * Regather multiple views (with the same sequence set id) to the frame (if
2934 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2935 * views instead of separate frames. Note this doesn't restore a state where
2936 * some expanded views in turn have tabbed views - the last "first tab" read
2937 * in will play the role of gatherer for all.
2939 for (AlignFrame fr : gatherToThisFrame.values())
2941 Desktop.instance.gatherViews(fr);
2944 restoreSplitFrames();
2945 for (AlignmentI ds : importedDatasets.keySet())
2947 if (ds.getCodonFrames() != null)
2949 StructureSelectionManager
2950 .getStructureSelectionManager(Desktop.instance)
2951 .registerMappings(ds.getCodonFrames());
2954 if (errorMessage != null)
2959 if (Desktop.instance != null)
2961 Desktop.instance.stopLoading();
2968 * Try to reconstruct and display SplitFrame windows, where each contains
2969 * complementary dna and protein alignments. Done by pairing up AlignFrame
2970 * objects (created earlier) which have complementary viewport ids associated.
2972 protected void restoreSplitFrames()
2974 List<SplitFrame> gatherTo = new ArrayList<>();
2975 List<AlignFrame> addedToSplitFrames = new ArrayList<>();
2976 Map<String, AlignFrame> dna = new HashMap<>();
2979 * Identify the DNA alignments
2981 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2984 AlignFrame af = candidate.getValue();
2985 if (af.getViewport().getAlignment().isNucleotide())
2987 dna.put(candidate.getKey().getId(), af);
2992 * Try to match up the protein complements
2994 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2997 AlignFrame af = candidate.getValue();
2998 if (!af.getViewport().getAlignment().isNucleotide())
3000 String complementId = candidate.getKey().getComplementId();
3001 // only non-null complements should be in the Map
3002 if (complementId != null && dna.containsKey(complementId))
3004 final AlignFrame dnaFrame = dna.get(complementId);
3005 SplitFrame sf = createSplitFrame(dnaFrame, af);
3006 addedToSplitFrames.add(dnaFrame);
3007 addedToSplitFrames.add(af);
3008 dnaFrame.setMenusForViewport();
3009 af.setMenusForViewport();
3010 if (af.getViewport().isGatherViewsHere())
3019 * Open any that we failed to pair up (which shouldn't happen!) as
3020 * standalone AlignFrame's.
3022 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
3025 AlignFrame af = candidate.getValue();
3026 if (!addedToSplitFrames.contains(af))
3028 Viewport view = candidate.getKey();
3029 Desktop.addInternalFrame(af, view.getTitle(),
3030 safeInt(view.getWidth()), safeInt(view.getHeight()));
3031 af.setMenusForViewport();
3032 System.err.println("Failed to restore view " + view.getTitle()
3033 + " to split frame");
3038 * Gather back into tabbed views as flagged.
3040 for (SplitFrame sf : gatherTo)
3042 Desktop.instance.gatherViews(sf);
3045 splitFrameCandidates.clear();
3049 * Construct and display one SplitFrame holding DNA and protein alignments.
3052 * @param proteinFrame
3055 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
3056 AlignFrame proteinFrame)
3058 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
3059 String title = MessageManager.getString("label.linked_view_title");
3060 int width = (int) dnaFrame.getBounds().getWidth();
3061 int height = (int) (dnaFrame.getBounds().getHeight()
3062 + proteinFrame.getBounds().getHeight() + 50);
3065 * SplitFrame location is saved to both enclosed frames
3067 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
3068 Desktop.addInternalFrame(splitFrame, title, width, height);
3071 * And compute cDNA consensus (couldn't do earlier with consensus as
3072 * mappings were not yet present)
3074 proteinFrame.getViewport().alignmentChanged(proteinFrame.alignPanel);
3080 * check errorMessage for a valid error message and raise an error box in the
3081 * GUI or write the current errorMessage to stderr and then clear the error
3084 protected void reportErrors()
3086 reportErrors(false);
3089 protected void reportErrors(final boolean saving)
3091 if (errorMessage != null)
3093 final String finalErrorMessage = errorMessage;
3096 javax.swing.SwingUtilities.invokeLater(new Runnable()
3101 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
3103 "Error " + (saving ? "saving" : "loading")
3105 JvOptionPane.WARNING_MESSAGE);
3111 System.err.println("Problem loading Jalview file: " + errorMessage);
3114 errorMessage = null;
3117 Map<String, String> alreadyLoadedPDB = new HashMap<>();
3120 * when set, local views will be updated from view stored in JalviewXML
3121 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
3122 * sync if this is set to true.
3124 private final boolean updateLocalViews = false;
3127 * Returns the path to a temporary file holding the PDB file for the given PDB
3128 * id. The first time of asking, searches for a file of that name in the
3129 * Jalview project jar, and copies it to a new temporary file. Any repeat
3130 * requests just return the path to the file previously created.
3136 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId,
3139 if (alreadyLoadedPDB.containsKey(pdbId))
3141 return alreadyLoadedPDB.get(pdbId).toString();
3144 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb",
3146 if (tempFile != null)
3148 alreadyLoadedPDB.put(pdbId, tempFile);
3154 * Copies the jar entry of given name to a new temporary file and returns the
3155 * path to the file, or null if the entry is not found.
3158 * @param jarEntryName
3160 * a prefix for the temporary file name, must be at least three
3163 * null or original file - so new file can be given the same suffix
3167 protected String copyJarEntry(jarInputStreamProvider jprovider,
3168 String jarEntryName, String prefix, String origFile)
3170 BufferedReader in = null;
3171 PrintWriter out = null;
3172 String suffix = ".tmp";
3173 if (origFile == null)
3175 origFile = jarEntryName;
3177 int sfpos = origFile.lastIndexOf(".");
3178 if (sfpos > -1 && sfpos < (origFile.length() - 3))
3180 suffix = "." + origFile.substring(sfpos + 1);
3184 JarInputStream jin = jprovider.getJarInputStream();
3186 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
3187 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
3188 * FileInputStream(jprovider)); }
3191 JarEntry entry = null;
3194 entry = jin.getNextJarEntry();
3195 } while (entry != null && !entry.getName().equals(jarEntryName));
3198 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
3199 File outFile = File.createTempFile(prefix, suffix);
3200 outFile.deleteOnExit();
3201 out = new PrintWriter(new FileOutputStream(outFile));
3204 while ((data = in.readLine()) != null)
3209 String t = outFile.getAbsolutePath();
3214 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
3216 } catch (Exception ex)
3218 ex.printStackTrace();
3226 } catch (IOException e)
3240 private class JvAnnotRow
3242 public JvAnnotRow(int i, AlignmentAnnotation jaa)
3249 * persisted version of annotation row from which to take vis properties
3251 public jalview.datamodel.AlignmentAnnotation template;
3254 * original position of the annotation row in the alignment
3260 * Load alignment frame from jalview XML DOM object
3262 * @param jalviewModel
3265 * filename source string
3266 * @param loadTreesAndStructures
3267 * when false only create Viewport
3269 * data source provider
3270 * @return alignment frame created from view stored in DOM
3272 AlignFrame loadFromObject(JalviewModel jalviewModel, String file,
3273 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
3275 SequenceSet vamsasSet = jalviewModel.getVamsasModel().getSequenceSet().get(0);
3276 List<Sequence> vamsasSeqs = vamsasSet.getSequence();
3278 // JalviewModelSequence jms = object.getJalviewModelSequence();
3280 // Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
3282 Viewport view = (jalviewModel.getViewport().size() > 0)
3283 ? jalviewModel.getViewport().get(0)
3286 // ////////////////////////////////
3287 // INITIALISE ALIGNMENT SEQUENCESETID AND VIEWID
3290 // If we just load in the same jar file again, the sequenceSetId
3291 // will be the same, and we end up with multiple references
3292 // to the same sequenceSet. We must modify this id on load
3293 // so that each load of the file gives a unique id
3296 * used to resolve correct alignment dataset for alignments with multiple
3299 String uniqueSeqSetId = null;
3300 String viewId = null;
3303 uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3304 viewId = (view.getId() == null ? null
3305 : view.getId() + uniqueSetSuffix);
3308 // ////////////////////////////////
3311 List<SequenceI> hiddenSeqs = null;
3313 List<SequenceI> tmpseqs = new ArrayList<>();
3315 boolean multipleView = false;
3316 SequenceI referenceseqForView = null;
3317 // JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
3318 List<JSeq> jseqs = jalviewModel.getJSeq();
3319 int vi = 0; // counter in vamsasSeq array
3320 for (int i = 0; i < jseqs.size(); i++)
3322 JSeq jseq = jseqs.get(i);
3323 String seqId = jseq.getId();
3325 SequenceI tmpSeq = seqRefIds.get(seqId);
3328 if (!incompleteSeqs.containsKey(seqId))
3330 // may not need this check, but keep it for at least 2.9,1 release
3331 if (tmpSeq.getStart() != jseq.getStart()
3332 || tmpSeq.getEnd() != jseq.getEnd())
3335 "Warning JAL-2154 regression: updating start/end for sequence "
3336 + tmpSeq.toString() + " to " + jseq);
3341 incompleteSeqs.remove(seqId);
3343 if (vamsasSeqs.size() > vi
3344 && vamsasSeqs.get(vi).getId().equals(seqId))
3346 // most likely we are reading a dataset XML document so
3347 // update from vamsasSeq section of XML for this sequence
3348 tmpSeq.setName(vamsasSeqs.get(vi).getName());
3349 tmpSeq.setDescription(vamsasSeqs.get(vi).getDescription());
3350 tmpSeq.setSequence(vamsasSeqs.get(vi).getSequence());
3355 // reading multiple views, so vamsasSeq set is a subset of JSeq
3356 multipleView = true;
3358 tmpSeq.setStart(jseq.getStart());
3359 tmpSeq.setEnd(jseq.getEnd());
3360 tmpseqs.add(tmpSeq);
3364 Sequence vamsasSeq = vamsasSeqs.get(vi);
3365 tmpSeq = new jalview.datamodel.Sequence(vamsasSeq.getName(),
3366 vamsasSeq.getSequence());
3367 tmpSeq.setDescription(vamsasSeq.getDescription());
3368 tmpSeq.setStart(jseq.getStart());
3369 tmpSeq.setEnd(jseq.getEnd());
3370 tmpSeq.setVamsasId(uniqueSetSuffix + seqId);
3371 seqRefIds.put(vamsasSeq.getId(), tmpSeq);
3372 tmpseqs.add(tmpSeq);
3376 if (safeBoolean(jseq.isViewreference()))
3378 referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
3381 if (jseq.isHidden() != null && jseq.isHidden().booleanValue())
3383 if (hiddenSeqs == null)
3385 hiddenSeqs = new ArrayList<>();
3388 hiddenSeqs.add(tmpSeq);
3393 // Create the alignment object from the sequence set
3394 // ///////////////////////////////
3395 SequenceI[] orderedSeqs = tmpseqs
3396 .toArray(new SequenceI[tmpseqs.size()]);
3398 AlignmentI al = null;
3399 // so we must create or recover the dataset alignment before going further
3400 // ///////////////////////////////
3401 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
3403 // older jalview projects do not have a dataset - so creat alignment and
3405 al = new Alignment(orderedSeqs);
3406 al.setDataset(null);
3410 boolean isdsal = jalviewModel.getViewport().isEmpty();
3413 // we are importing a dataset record, so
3414 // recover reference to an alignment already materialsed as dataset
3415 al = getDatasetFor(vamsasSet.getDatasetId());
3419 // materialse the alignment
3420 al = new Alignment(orderedSeqs);
3424 addDatasetRef(vamsasSet.getDatasetId(), al);
3427 // finally, verify all data in vamsasSet is actually present in al
3428 // passing on flag indicating if it is actually a stored dataset
3429 recoverDatasetFor(vamsasSet, al, isdsal, uniqueSeqSetId);
3432 if (referenceseqForView != null)
3434 al.setSeqrep(referenceseqForView);
3436 // / Add the alignment properties
3437 for (int i = 0; i < vamsasSet.getSequenceSetProperties().size(); i++)
3439 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties()
3441 al.setProperty(ssp.getKey(), ssp.getValue());
3444 // ///////////////////////////////
3446 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
3449 // load sequence features, database references and any associated PDB
3450 // structures for the alignment
3452 // prior to 2.10, this part would only be executed the first time a
3453 // sequence was encountered, but not afterwards.
3454 // now, for 2.10 projects, this is also done if the xml doc includes
3455 // dataset sequences not actually present in any particular view.
3457 for (int i = 0; i < vamsasSeqs.size(); i++)
3459 JSeq jseq = jseqs.get(i);
3460 if (jseq.getFeatures().size() > 0)
3462 List<Feature> features = jseq.getFeatures();
3463 for (int f = 0; f < features.size(); f++)
3465 Feature feat = features.get(f);
3466 SequenceFeature sf = new SequenceFeature(feat.getType(),
3467 feat.getDescription(), feat.getBegin(), feat.getEnd(),
3468 safeFloat(feat.getScore()), feat.getFeatureGroup());
3469 sf.setStatus(feat.getStatus());
3472 * load any feature attributes - include map-valued attributes
3474 Map<String, Map<String, String>> mapAttributes = new HashMap<>();
3475 for (int od = 0; od < feat.getOtherData().size(); od++)
3477 OtherData keyValue = feat.getOtherData().get(od);
3478 String attributeName = keyValue.getKey();
3479 String attributeValue = keyValue.getValue();
3480 if (attributeName.startsWith("LINK"))
3482 sf.addLink(attributeValue);
3486 String subAttribute = keyValue.getKey2();
3487 if (subAttribute == null)
3489 // simple string-valued attribute
3490 sf.setValue(attributeName, attributeValue);
3494 // attribute 'key' has sub-attribute 'key2'
3495 if (!mapAttributes.containsKey(attributeName))
3497 mapAttributes.put(attributeName, new HashMap<>());
3499 mapAttributes.get(attributeName).put(subAttribute,
3504 for (Entry<String, Map<String, String>> mapAttribute : mapAttributes
3507 sf.setValue(mapAttribute.getKey(), mapAttribute.getValue());
3510 // adds feature to datasequence's feature set (since Jalview 2.10)
3511 al.getSequenceAt(i).addSequenceFeature(sf);
3514 if (vamsasSeqs.get(i).getDBRef().size() > 0)
3516 // adds dbrefs to datasequence's set (since Jalview 2.10)
3518 al.getSequenceAt(i).getDatasetSequence() == null
3519 ? al.getSequenceAt(i)
3520 : al.getSequenceAt(i).getDatasetSequence(),
3523 if (jseq.getPdbids().size() > 0)
3525 List<Pdbids> ids = jseq.getPdbids();
3526 for (int p = 0; p < ids.size(); p++)
3528 Pdbids pdbid = ids.get(p);
3529 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
3530 entry.setId(pdbid.getId());
3531 if (pdbid.getType() != null)
3533 if (PDBEntry.Type.getType(pdbid.getType()) != null)
3535 entry.setType(PDBEntry.Type.getType(pdbid.getType()));
3539 entry.setType(PDBEntry.Type.FILE);
3542 // jprovider is null when executing 'New View'
3543 if (pdbid.getFile() != null && jprovider != null)
3545 if (!pdbloaded.containsKey(pdbid.getFile()))
3547 entry.setFile(loadPDBFile(jprovider, pdbid.getId(),
3552 entry.setFile(pdbloaded.get(pdbid.getId()).toString());
3556 if (pdbid.getPdbentryItem() != null)
3558 for (PdbentryItem item : pdbid.getPdbentryItem())
3560 for (Property pr : item.getProperty())
3562 entry.setProperty(pr.getName(), pr.getValue());
3567 for (Property prop : pdbid.getProperty())
3569 entry.setProperty(prop.getName(), prop.getValue());
3571 StructureSelectionManager
3572 .getStructureSelectionManager(Desktop.instance)
3573 .registerPDBEntry(entry);
3574 // adds PDBEntry to datasequence's set (since Jalview 2.10)
3575 if (al.getSequenceAt(i).getDatasetSequence() != null)
3577 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
3581 al.getSequenceAt(i).addPDBId(entry);
3586 } // end !multipleview
3588 // ///////////////////////////////
3589 // LOAD SEQUENCE MAPPINGS
3591 if (vamsasSet.getAlcodonFrame().size() > 0)
3593 // TODO Potentially this should only be done once for all views of an
3595 List<AlcodonFrame> alc = vamsasSet.getAlcodonFrame();
3596 for (int i = 0; i < alc.size(); i++)
3598 AlignedCodonFrame cf = new AlignedCodonFrame();
3599 if (alc.get(i).getAlcodMap().size() > 0)
3601 List<AlcodMap> maps = alc.get(i).getAlcodMap();
3602 for (int m = 0; m < maps.size(); m++)
3604 AlcodMap map = maps.get(m);
3605 SequenceI dnaseq = seqRefIds.get(map.getDnasq());
3607 jalview.datamodel.Mapping mapping = null;
3608 // attach to dna sequence reference.
3609 if (map.getMapping() != null)
3611 mapping = addMapping(map.getMapping());
3612 if (dnaseq != null && mapping.getTo() != null)
3614 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
3620 newAlcodMapRef(map.getDnasq(), cf, mapping));
3624 al.addCodonFrame(cf);
3629 // ////////////////////////////////
3631 List<AlignmentAnnotation> addedAnnotation = new ArrayList<>();
3634 * store any annotations which forward reference a group's ID
3636 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<>();
3638 if (vamsasSet.getAnnotation().size()/*Count()*/ > 0)
3640 List<Annotation> an = vamsasSet.getAnnotation();
3642 for (int i = 0; i < an.size(); i++)
3644 Annotation annotation = an.get(i);
3647 * test if annotation is automatically calculated for this view only
3649 boolean autoForView = false;
3650 if (annotation.getLabel().equals(AutoAnnotation.QUALITY.label)
3651 || annotation.getLabel()
3652 .equals(AutoAnnotation.CONSERVATION.label)
3653 || annotation.getLabel()
3654 .equals(AutoAnnotation.CONSENSUS.label))
3656 // Kludge for pre 2.5 projects which lacked the autocalculated flag
3659 if (autoForView || annotation.isAutoCalculated())
3661 // remove ID - we don't recover annotation from other views for
3662 // view-specific annotation
3663 annotation.setId(null);
3666 // set visibility for other annotation in this view
3667 String annotationId = annotation.getId();
3668 if (annotationId != null && annotationIds.containsKey(annotationId))
3670 AlignmentAnnotation jda = annotationIds.get(annotationId);
3671 // in principle Visible should always be true for annotation displayed
3672 // in multiple views
3673 if (annotation.isVisible() != null)
3675 jda.visible = annotation.isVisible();
3678 al.addAnnotation(jda);
3679 addedAnnotation.add(jda);
3682 // Construct new annotation from model.
3683 List<AnnotationElement> ae = annotation.getAnnotationElement();
3684 jalview.datamodel.Annotation[] anot = null;
3685 java.awt.Color firstColour = null;
3687 if (!annotation.isScoreOnly())
3689 anot = new jalview.datamodel.Annotation[al.getWidth()];
3690 for (int aa = 0; aa < ae.size() && aa < anot.length; aa++)
3692 AnnotationElement annElement = ae.get(aa);
3693 anpos = annElement.getPosition();
3695 if (anpos >= anot.length)
3700 float value = safeFloat(annElement.getValue());
3701 anot[anpos] = new jalview.datamodel.Annotation(
3702 annElement.getDisplayCharacter(),
3703 annElement.getDescription(),
3704 (annElement.getSecondaryStructure() == null
3705 || annElement.getSecondaryStructure()
3709 .getSecondaryStructure()
3712 anot[anpos].colour = new Color(safeInt(annElement.getColour()));
3713 if (firstColour == null)
3715 firstColour = anot[anpos].colour;
3721 * construct the Jalview AlignmentAnnotation, add to alignment
3723 AlignmentAnnotation jaa = null;
3725 if (annotation.isGraph())
3727 float llim = 0, hlim = 0;
3728 // if (autoForView || an[i].isAutoCalculated()) {
3731 jaa = new jalview.datamodel.AlignmentAnnotation(
3732 annotation.getLabel(), annotation.getDescription(), anot,
3733 llim, hlim, safeInt(annotation.getGraphType()));
3735 jaa.graphGroup = safeInt(annotation.getGraphGroup());
3736 jaa._linecolour = firstColour;
3737 if (annotation.getThresholdLine() != null)
3739 jaa.setThreshold(new jalview.datamodel.GraphLine(
3740 safeFloat(annotation.getThresholdLine().getValue()),
3741 annotation.getThresholdLine().getLabel(),
3742 new java.awt.Color(safeInt(
3743 annotation.getThresholdLine().getColour()))));
3745 if (autoForView || annotation.isAutoCalculated())
3747 // Hardwire the symbol display line to ensure that labels for
3748 // histograms are displayed
3754 jaa = new jalview.datamodel.AlignmentAnnotation(
3755 annotation.getLabel(), annotation.getDescription(), anot);
3756 jaa._linecolour = firstColour;
3758 // register new annotation
3759 if (annotation.getId() != null)
3761 annotationIds.put(annotation.getId(), jaa);
3762 jaa.annotationId = annotation.getId();
3764 // recover sequence association
3765 String sequenceRef = annotation.getSequenceRef();
3766 if (sequenceRef != null)
3768 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3769 SequenceI sequence = seqRefIds.get(sequenceRef);
3770 if (sequence == null)
3772 // in pre-2.9 projects sequence ref is to sequence name
3773 sequence = al.findName(sequenceRef);
3775 if (sequence != null)
3777 jaa.createSequenceMapping(sequence, 1, true);
3778 sequence.addAlignmentAnnotation(jaa);
3781 // and make a note of any group association
3782 if (annotation.getGroupRef() != null
3783 && annotation.getGroupRef().length() > 0)
3785 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3786 .get(annotation.getGroupRef());
3789 aal = new ArrayList<>();
3790 groupAnnotRefs.put(annotation.getGroupRef(), aal);
3795 if (annotation.getScore() != null)
3797 jaa.setScore(annotation.getScore().doubleValue());
3799 if (annotation.isVisible() != null)
3801 jaa.visible = annotation.isVisible().booleanValue();
3804 if (annotation.isCentreColLabels() != null)
3806 jaa.centreColLabels = annotation.isCentreColLabels()
3810 if (annotation.isScaleColLabels() != null)
3812 jaa.scaleColLabel = annotation.isScaleColLabels().booleanValue();
3814 if (annotation.isAutoCalculated())
3816 // newer files have an 'autoCalculated' flag and store calculation
3817 // state in viewport properties
3818 jaa.autoCalculated = true; // means annotation will be marked for
3819 // update at end of load.
3821 Integer graphHeight = annotation.getGraphHeight();
3822 if (graphHeight != null)
3824 jaa.graphHeight = graphHeight.intValue();
3826 jaa.belowAlignment = annotation.isBelowAlignment();
3827 jaa.setCalcId(annotation.getCalcId());
3828 if (annotation.getProperty().size() > 0)
3830 for (Annotation.Property prop : annotation
3833 jaa.setProperty(prop.getName(), prop.getValue());
3836 if (!jaa.autoCalculated)
3838 // TODO ensure Consensus etc is enabled if found in project?
3840 * add autocalculated group annotation and any user created annotation
3843 al.addAnnotation(jaa);
3845 addedAnnotation.add(jaa);
3848 // ///////////////////////
3850 // Create alignment markup and styles for this view
3851 if (jalviewModel.getJGroup().size() > 0)
3853 List<JGroup> groups = jalviewModel.getJGroup();
3854 boolean addAnnotSchemeGroup = false;
3855 for (int i = 0; i < groups.size(); i++)
3857 JGroup jGroup = groups.get(i);
3858 ColourSchemeI cs = null;
3859 if (jGroup.getColour() != null)
3861 if (jGroup.getColour().startsWith("ucs"))
3863 cs = getUserColourScheme(jalviewModel, jGroup.getColour());
3865 else if (jGroup.getColour().equals("AnnotationColourGradient")
3866 && jGroup.getAnnotationColours() != null)
3868 addAnnotSchemeGroup = true;
3872 cs = ColourSchemeProperty.getColourScheme(null, al,
3873 jGroup.getColour());
3876 int pidThreshold = safeInt(jGroup.getPidThreshold());
3878 Vector<SequenceI> seqs = new Vector<>();
3880 for (int s = 0; s < jGroup.getSeq().size(); s++)
3882 String seqId = jGroup.getSeq().get(s);
3883 SequenceI ts = seqRefIds.get(seqId);
3887 seqs.addElement(ts);
3891 if (seqs.size() < 1)
3896 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3897 safeBoolean(jGroup.isDisplayBoxes()),
3898 safeBoolean(jGroup.isDisplayText()),
3899 safeBoolean(jGroup.isColourText()),
3900 safeInt(jGroup.getStart()), safeInt(jGroup.getEnd()));
3901 sg.getGroupColourScheme().setThreshold(pidThreshold, true);
3902 sg.getGroupColourScheme()
3903 .setConservationInc(safeInt(jGroup.getConsThreshold()));
3904 sg.setOutlineColour(new Color(safeInt(jGroup.getOutlineColour())));
3906 sg.textColour = new Color(safeInt(jGroup.getTextCol1()));
3907 sg.textColour2 = new Color(safeInt(jGroup.getTextCol2()));
3908 sg.setShowNonconserved(safeBoolean(jGroup.isShowUnconserved()));
3909 sg.thresholdTextColour = safeInt(jGroup.getTextColThreshold());
3910 // attributes with a default in the schema are never null
3911 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3912 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3913 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3914 sg.setIgnoreGapsConsensus(jGroup.isIgnoreGapsinConsensus());
3915 if (jGroup.getConsThreshold() != null
3916 && jGroup.getConsThreshold().intValue() != 0)
3918 Conservation c = new Conservation("All", sg.getSequences(null), 0,
3921 c.verdict(false, 25);
3922 sg.cs.setConservation(c);
3925 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3927 // re-instate unique group/annotation row reference
3928 List<AlignmentAnnotation> jaal = groupAnnotRefs
3929 .get(jGroup.getId());
3932 for (AlignmentAnnotation jaa : jaal)
3935 if (jaa.autoCalculated)
3937 // match up and try to set group autocalc alignment row for this
3939 if (jaa.label.startsWith("Consensus for "))
3941 sg.setConsensus(jaa);
3943 // match up and try to set group autocalc alignment row for this
3945 if (jaa.label.startsWith("Conservation for "))
3947 sg.setConservationRow(jaa);
3954 if (addAnnotSchemeGroup)
3956 // reconstruct the annotation colourscheme
3957 sg.setColourScheme(constructAnnotationColour(
3958 jGroup.getAnnotationColours(), null, al, jalviewModel, false));
3964 // only dataset in this model, so just return.
3967 // ///////////////////////////////
3970 AlignFrame af = null;
3971 AlignViewport av = null;
3972 // now check to see if we really need to create a new viewport.
3973 if (multipleView && viewportsAdded.size() == 0)
3975 // We recovered an alignment for which a viewport already exists.
3976 // TODO: fix up any settings necessary for overlaying stored state onto
3977 // state recovered from another document. (may not be necessary).
3978 // we may need a binding from a viewport in memory to one recovered from
3980 // and then recover its containing af to allow the settings to be applied.
3981 // TODO: fix for vamsas demo
3983 "About to recover a viewport for existing alignment: Sequence set ID is "
3985 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3986 if (seqsetobj != null)
3988 if (seqsetobj instanceof String)
3990 uniqueSeqSetId = (String) seqsetobj;
3992 "Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
3998 "Warning : Collision between sequence set ID string and existing jalview object mapping.");
4004 * indicate that annotation colours are applied across all groups (pre
4005 * Jalview 2.8.1 behaviour)
4007 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan("2.8.1",
4008 jalviewModel.getVersion());
4010 AlignmentPanel ap = null;
4011 boolean isnewview = true;
4014 // Check to see if this alignment already has a view id == viewId
4015 jalview.gui.AlignmentPanel views[] = Desktop
4016 .getAlignmentPanels(uniqueSeqSetId);
4017 if (views != null && views.length > 0)
4019 for (int v = 0; v < views.length; v++)
4021 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
4023 // recover the existing alignpanel, alignframe, viewport
4024 af = views[v].alignFrame;
4027 // TODO: could even skip resetting view settings if we don't want to
4028 // change the local settings from other jalview processes
4037 Map<String, String> originalPreferences = null;
4040 originalPreferences = setAutocalcPreferences(jalviewModel);
4041 af = loadViewport(file, jseqs, hiddenSeqs, al, jalviewModel, view,
4042 uniqueSeqSetId, viewId);
4045 restoreAutocalcPreferences(originalPreferences);
4049 * resort annotations to their order in the project
4050 * (also sets height and visibility for autocalc'd annotation)
4052 av = af.getViewport();
4053 new AnnotationSorter(av).sort(addedAnnotation);
4055 ap.adjustAnnotationHeight();
4059 * Load any trees, PDB structures and viewers
4061 * Not done if flag is false (when this method is used for New View)
4063 if (loadTreesAndStructures)
4065 loadTrees(jalviewModel, view, af, av, ap);
4066 loadPCAViewers(jalviewModel, ap);
4067 loadPDBStructures(jprovider, jseqs, af, ap);
4068 loadRnaViewers(jprovider, jseqs, ap);
4070 // and finally return.
4075 * Restores previously captured preferences (or deletes the preference if the
4076 * map entry value is null)
4078 * @param originalPreferences
4080 private void restoreAutocalcPreferences(
4081 Map<String, String> originalPreferences)
4083 for (Entry<String, String> entry : originalPreferences.entrySet())
4085 String key = entry.getKey();
4086 String value = entry.getValue();
4089 Cache.removeProperty(key);
4093 Cache.setProperty(key, value);
4099 * Inspects saved annotations and temporarily sets preferences for whether
4100 * autocalculated annotations should be created for Conservation, Consensus,
4101 * Quality, Occupancy. Returns a map containing the original values (which may
4102 * be null if property is not set, or is set to null).
4104 * @param jalviewModel
4107 private Map<String, String> setAutocalcPreferences(
4108 JalviewModel jalviewModel)
4110 Map<String, String> original = Cache.getProperties(
4111 AutoAnnotation.OCCUPANCY.preferenceKey,
4112 AutoAnnotation.CONSERVATION.preferenceKey,
4113 AutoAnnotation.QUALITY.preferenceKey,
4114 AutoAnnotation.CONSENSUS.preferenceKey);
4116 Cache.setProperty(AutoAnnotation.OCCUPANCY.preferenceKey, FALSE);
4117 Cache.setProperty(AutoAnnotation.CONSERVATION.preferenceKey, FALSE);
4118 Cache.setProperty(AutoAnnotation.QUALITY.preferenceKey, FALSE);
4119 Cache.setProperty(AutoAnnotation.CONSENSUS.preferenceKey, FALSE);
4121 List<SequenceSet> sequenceSet = jalviewModel.getVamsasModel()
4125 * expect sequenceSet to have just one entry
4127 if (sequenceSet.size() != 1)
4130 "Unexpected sequenceSet size: " + sequenceSet.size());
4133 List<Annotation> anns = sequenceSet.get(0).getAnnotation();
4134 for (Annotation ann : anns)
4136 if (ann.isAutoCalculated())
4138 String label = ann.getLabel();
4139 if (AutoAnnotation.CONSERVATION.label.equals(label))
4141 Cache.setProperty(AutoAnnotation.CONSERVATION.preferenceKey,
4144 else if (AutoAnnotation.QUALITY.label.equals(label))
4146 Cache.setProperty(AutoAnnotation.QUALITY.preferenceKey, TRUE);
4148 else if (AutoAnnotation.CONSENSUS.label.equals(label))
4150 Cache.setProperty(AutoAnnotation.CONSENSUS.preferenceKey, TRUE);
4152 else if (AutoAnnotation.OCCUPANCY.label.equals(label))
4154 Cache.setProperty(AutoAnnotation.OCCUPANCY.preferenceKey, TRUE);
4162 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
4163 * panel is restored from separate jar entries, two (gapped and trimmed) per
4164 * sequence and secondary structure.
4166 * Currently each viewer shows just one sequence and structure (gapped and
4167 * trimmed), however this method is designed to support multiple sequences or
4168 * structures in viewers if wanted in future.
4174 private void loadRnaViewers(jarInputStreamProvider jprovider,
4175 List<JSeq> jseqs, AlignmentPanel ap)
4178 * scan the sequences for references to viewers; create each one the first
4179 * time it is referenced, add Rna models to existing viewers
4181 for (JSeq jseq : jseqs)
4183 for (int i = 0; i < jseq.getRnaViewer().size(); i++)
4185 RnaViewer viewer = jseq.getRnaViewer().get(i);
4186 AppVarna appVarna = findOrCreateVarnaViewer(viewer, uniqueSetSuffix,
4189 for (int j = 0; j < viewer.getSecondaryStructure().size(); j++)
4191 SecondaryStructure ss = viewer.getSecondaryStructure().get(j);
4192 SequenceI seq = seqRefIds.get(jseq.getId());
4193 AlignmentAnnotation ann = this.annotationIds
4194 .get(ss.getAnnotationId());
4197 * add the structure to the Varna display (with session state copied
4198 * from the jar to a temporary file)
4200 boolean gapped = safeBoolean(ss.isGapped());
4201 String rnaTitle = ss.getTitle();
4202 String sessionState = ss.getViewerState();
4203 String tempStateFile = copyJarEntry(jprovider, sessionState,
4205 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
4206 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
4208 appVarna.setInitialSelection(safeInt(viewer.getSelectedRna()));
4214 * Locate and return an already instantiated matching AppVarna, or create one
4218 * @param viewIdSuffix
4222 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
4223 String viewIdSuffix, AlignmentPanel ap)
4226 * on each load a suffix is appended to the saved viewId, to avoid conflicts
4227 * if load is repeated
4229 String postLoadId = viewer.getViewId() + viewIdSuffix;
4230 for (JInternalFrame frame : getAllFrames())
4232 if (frame instanceof AppVarna)
4234 AppVarna varna = (AppVarna) frame;
4235 if (postLoadId.equals(varna.getViewId()))
4237 // this viewer is already instantiated
4238 // could in future here add ap as another 'parent' of the
4239 // AppVarna window; currently just 1-to-many
4246 * viewer not found - make it
4248 RnaViewerModel model = new RnaViewerModel(postLoadId, viewer.getTitle(),
4249 safeInt(viewer.getXpos()), safeInt(viewer.getYpos()),
4250 safeInt(viewer.getWidth()), safeInt(viewer.getHeight()),
4251 safeInt(viewer.getDividerLocation()));
4252 AppVarna varna = new AppVarna(model, ap);
4258 * Load any saved trees
4266 protected void loadTrees(JalviewModel jm, Viewport view,
4267 AlignFrame af, AlignViewport av, AlignmentPanel ap)
4269 // TODO result of automated refactoring - are all these parameters needed?
4272 for (int t = 0; t < jm.getTree().size(); t++)
4275 Tree tree = jm.getTree().get(t);
4277 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
4280 tp = af.showNewickTree(new NewickFile(tree.getNewick()),
4281 tree.getTitle(), safeInt(tree.getWidth()),
4282 safeInt(tree.getHeight()), safeInt(tree.getXpos()),
4283 safeInt(tree.getYpos()));
4284 if (tree.getId() != null)
4286 // perhaps bind the tree id to something ?
4291 // update local tree attributes ?
4292 // TODO: should check if tp has been manipulated by user - if so its
4293 // settings shouldn't be modified
4294 tp.setTitle(tree.getTitle());
4295 tp.setBounds(new Rectangle(safeInt(tree.getXpos()),
4296 safeInt(tree.getYpos()), safeInt(tree.getWidth()),
4297 safeInt(tree.getHeight())));
4298 tp.setViewport(av); // af.viewport;
4299 // TODO: verify 'associate with all views' works still
4300 tp.getTreeCanvas().setViewport(av); // af.viewport;
4301 tp.getTreeCanvas().setAssociatedPanel(ap); // af.alignPanel;
4303 tp.getTreeCanvas().setApplyToAllViews(tree.isLinkToAllViews());
4306 warn("There was a problem recovering stored Newick tree: \n"
4307 + tree.getNewick());
4311 tp.fitToWindow.setState(safeBoolean(tree.isFitToWindow()));
4312 tp.fitToWindow_actionPerformed(null);
4314 if (tree.getFontName() != null)
4317 new Font(tree.getFontName(), safeInt(tree.getFontStyle()),
4318 safeInt(tree.getFontSize())));
4323 new Font(view.getFontName(), safeInt(view.getFontStyle()),
4324 safeInt(view.getFontSize())));
4327 tp.showPlaceholders(safeBoolean(tree.isMarkUnlinked()));
4328 tp.showBootstrap(safeBoolean(tree.isShowBootstrap()));
4329 tp.showDistances(safeBoolean(tree.isShowDistances()));
4331 tp.getTreeCanvas().setThreshold(safeFloat(tree.getThreshold()));
4333 if (safeBoolean(tree.isCurrentTree()))
4335 af.getViewport().setCurrentTree(tp.getTree());
4339 } catch (Exception ex)
4341 ex.printStackTrace();
4346 * Load and link any saved structure viewers.
4353 protected void loadPDBStructures(jarInputStreamProvider jprovider,
4354 List<JSeq> jseqs, AlignFrame af, AlignmentPanel ap)
4357 * Run through all PDB ids on the alignment, and collect mappings between
4358 * distinct view ids and all sequences referring to that view.
4360 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<>();
4362 for (int i = 0; i < jseqs.size(); i++)
4364 JSeq jseq = jseqs.get(i);
4365 if (jseq.getPdbids().size() > 0)
4367 List<Pdbids> ids = jseq.getPdbids();
4368 for (int p = 0; p < ids.size(); p++)
4370 Pdbids pdbid = ids.get(p);
4371 final int structureStateCount = pdbid.getStructureState().size();
4372 for (int s = 0; s < structureStateCount; s++)
4374 // check to see if we haven't already created this structure view
4375 final StructureState structureState = pdbid
4376 .getStructureState().get(s);
4377 String sviewid = (structureState.getViewId() == null) ? null
4378 : structureState.getViewId() + uniqueSetSuffix;
4379 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
4380 // Originally : pdbid.getFile()
4381 // : TODO: verify external PDB file recovery still works in normal
4382 // jalview project load
4384 loadPDBFile(jprovider, pdbid.getId(), pdbid.getFile()));
4385 jpdb.setId(pdbid.getId());
4387 int x = safeInt(structureState.getXpos());
4388 int y = safeInt(structureState.getYpos());
4389 int width = safeInt(structureState.getWidth());
4390 int height = safeInt(structureState.getHeight());
4392 // Probably don't need to do this anymore...
4393 // Desktop.desktop.getComponentAt(x, y);
4394 // TODO: NOW: check that this recovers the PDB file correctly.
4395 String pdbFile = loadPDBFile(jprovider, pdbid.getId(),
4397 jalview.datamodel.SequenceI seq = seqRefIds
4398 .get(jseq.getId() + "");
4399 if (sviewid == null)
4401 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width + ","
4404 if (!structureViewers.containsKey(sviewid))
4406 structureViewers.put(sviewid,
4407 new StructureViewerModel(x, y, width, height, false,
4408 false, true, structureState.getViewId(),
4409 structureState.getType()));
4410 // Legacy pre-2.7 conversion JAL-823 :
4411 // do not assume any view has to be linked for colour by
4415 // assemble String[] { pdb files }, String[] { id for each
4416 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
4417 // seqs_file 2}, boolean[] {
4418 // linkAlignPanel,superposeWithAlignpanel}} from hash
4419 StructureViewerModel jmoldat = structureViewers.get(sviewid);
4420 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
4421 || structureState.isAlignwithAlignPanel());
4424 * Default colour by linked panel to false if not specified (e.g.
4425 * for pre-2.7 projects)
4427 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
4428 colourWithAlignPanel |= structureState.isColourwithAlignPanel();
4429 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
4432 * Default colour by viewer to true if not specified (e.g. for
4435 boolean colourByViewer = jmoldat.isColourByViewer();
4436 colourByViewer &= structureState.isColourByJmol();
4437 jmoldat.setColourByViewer(colourByViewer);
4439 if (jmoldat.getStateData().length() < structureState
4440 .getValue()/*Content()*/.length())
4442 jmoldat.setStateData(structureState.getValue());// Content());
4444 if (pdbid.getFile() != null)
4446 File mapkey = new File(pdbid.getFile());
4447 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
4448 if (seqstrmaps == null)
4450 jmoldat.getFileData().put(mapkey,
4451 seqstrmaps = jmoldat.new StructureData(pdbFile,
4454 if (!seqstrmaps.getSeqList().contains(seq))
4456 seqstrmaps.getSeqList().add(seq);
4462 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");
4469 // Instantiate the associated structure views
4470 for (Entry<String, StructureViewerModel> entry : structureViewers
4475 createOrLinkStructureViewer(entry, af, ap, jprovider);
4476 } catch (Exception e)
4479 "Error loading structure viewer: " + e.getMessage());
4480 // failed - try the next one
4492 protected void createOrLinkStructureViewer(
4493 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4494 AlignmentPanel ap, jarInputStreamProvider jprovider)
4496 final StructureViewerModel stateData = viewerData.getValue();
4499 * Search for any viewer windows already open from other alignment views
4500 * that exactly match the stored structure state
4502 StructureViewerBase comp = findMatchingViewer(viewerData);
4506 linkStructureViewer(ap, comp, stateData);
4511 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
4512 * "viewer_"+stateData.viewId
4514 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
4516 createChimeraViewer(viewerData, af, jprovider);
4521 * else Jmol (if pre-2.9, stateData contains JMOL state string)
4523 createJmolViewer(viewerData, af, jprovider);
4528 * Create a new Chimera viewer.
4534 protected void createChimeraViewer(
4535 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4536 jarInputStreamProvider jprovider)
4538 StructureViewerModel data = viewerData.getValue();
4539 String chimeraSessionFile = data.getStateData();
4542 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
4544 * NB this is the 'saved' viewId as in the project file XML, _not_ the
4545 * 'uniquified' sviewid used to reconstruct the viewer here
4547 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
4548 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
4551 Set<Entry<File, StructureData>> fileData = data.getFileData()
4553 List<PDBEntry> pdbs = new ArrayList<>();
4554 List<SequenceI[]> allseqs = new ArrayList<>();
4555 for (Entry<File, StructureData> pdb : fileData)
4557 String filePath = pdb.getValue().getFilePath();
4558 String pdbId = pdb.getValue().getPdbId();
4559 // pdbs.add(new PDBEntry(filePath, pdbId));
4560 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
4561 final List<SequenceI> seqList = pdb.getValue().getSeqList();
4562 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
4566 boolean colourByChimera = data.isColourByViewer();
4567 boolean colourBySequence = data.isColourWithAlignPanel();
4569 // TODO use StructureViewer as a factory here, see JAL-1761
4570 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
4571 final SequenceI[][] seqsArray = allseqs
4572 .toArray(new SequenceI[allseqs.size()][]);
4573 String newViewId = viewerData.getKey();
4575 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
4576 af.alignPanel, pdbArray, seqsArray, colourByChimera,
4577 colourBySequence, newViewId);
4578 cvf.setSize(data.getWidth(), data.getHeight());
4579 cvf.setLocation(data.getX(), data.getY());
4583 * Create a new Jmol window. First parse the Jmol state to translate filenames
4584 * loaded into the view, and record the order in which files are shown in the
4585 * Jmol view, so we can add the sequence mappings in same order.
4591 protected void createJmolViewer(
4592 final Entry<String, StructureViewerModel> viewerData,
4593 AlignFrame af, jarInputStreamProvider jprovider)
4595 final StructureViewerModel svattrib = viewerData.getValue();
4596 String state = svattrib.getStateData();
4599 * Pre-2.9: state element value is the Jmol state string
4601 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
4604 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
4606 state = readJarEntry(jprovider,
4607 getViewerJarEntryName(svattrib.getViewId()));
4610 List<String> pdbfilenames = new ArrayList<>();
4611 List<SequenceI[]> seqmaps = new ArrayList<>();
4612 List<String> pdbids = new ArrayList<>();
4613 StringBuilder newFileLoc = new StringBuilder(64);
4614 int cp = 0, ncp, ecp;
4615 Map<File, StructureData> oldFiles = svattrib.getFileData();
4616 while ((ncp = state.indexOf("load ", cp)) > -1)
4620 // look for next filename in load statement
4621 newFileLoc.append(state.substring(cp,
4622 ncp = (state.indexOf("\"", ncp + 1) + 1)));
4623 String oldfilenam = state.substring(ncp,
4624 ecp = state.indexOf("\"", ncp));
4625 // recover the new mapping data for this old filename
4626 // have to normalize filename - since Jmol and jalview do
4628 // translation differently.
4629 StructureData filedat = oldFiles.get(new File(oldfilenam));
4630 if (filedat == null)
4632 String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\");
4633 filedat = oldFiles.get(new File(reformatedOldFilename));
4635 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
4636 pdbfilenames.add(filedat.getFilePath());
4637 pdbids.add(filedat.getPdbId());
4638 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4639 newFileLoc.append("\"");
4640 cp = ecp + 1; // advance beyond last \" and set cursor so we can
4641 // look for next file statement.
4642 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
4646 // just append rest of state
4647 newFileLoc.append(state.substring(cp));
4651 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
4652 newFileLoc = new StringBuilder(state);
4653 newFileLoc.append("; load append ");
4654 for (File id : oldFiles.keySet())
4656 // add this and any other pdb files that should be present in
4658 StructureData filedat = oldFiles.get(id);
4659 newFileLoc.append(filedat.getFilePath());
4660 pdbfilenames.add(filedat.getFilePath());
4661 pdbids.add(filedat.getPdbId());
4662 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4663 newFileLoc.append(" \"");
4664 newFileLoc.append(filedat.getFilePath());
4665 newFileLoc.append("\"");
4668 newFileLoc.append(";");
4671 if (newFileLoc.length() == 0)
4675 int histbug = newFileLoc.indexOf("history = ");
4679 * change "history = [true|false];" to "history = [1|0];"
4682 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
4683 String val = (diff == -1) ? null
4684 : newFileLoc.substring(histbug, diff);
4685 if (val != null && val.length() >= 4)
4687 if (val.contains("e")) // eh? what can it be?
4689 if (val.trim().equals(TRUE))
4697 newFileLoc.replace(histbug, diff, val);
4702 final String[] pdbf = pdbfilenames
4703 .toArray(new String[pdbfilenames.size()]);
4704 final String[] id = pdbids.toArray(new String[pdbids.size()]);
4705 final SequenceI[][] sq = seqmaps
4706 .toArray(new SequenceI[seqmaps.size()][]);
4707 final String fileloc = newFileLoc.toString();
4708 final String sviewid = viewerData.getKey();
4709 final AlignFrame alf = af;
4710 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
4711 svattrib.getWidth(), svattrib.getHeight());
4714 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
4719 JalviewStructureDisplayI sview = null;
4722 sview = new StructureViewer(
4723 alf.alignPanel.getStructureSelectionManager())
4724 .createView(StructureViewer.ViewerType.JMOL,
4725 pdbf, id, sq, alf.alignPanel, svattrib,
4726 fileloc, rect, sviewid);
4727 addNewStructureViewer(sview);
4728 } catch (OutOfMemoryError ex)
4730 new OOMWarning("restoring structure view for PDB id " + id,
4731 (OutOfMemoryError) ex.getCause());
4732 if (sview != null && sview.isVisible())
4734 sview.closeViewer(false);
4735 sview.setVisible(false);
4741 } catch (InvocationTargetException ex)
4743 warn("Unexpected error when opening Jmol view.", ex);
4745 } catch (InterruptedException e)
4747 // e.printStackTrace();
4753 * Generates a name for the entry in the project jar file to hold state
4754 * information for a structure viewer
4759 protected String getViewerJarEntryName(String viewId)
4761 return VIEWER_PREFIX + viewId;
4765 * Returns any open frame that matches given structure viewer data. The match
4766 * is based on the unique viewId, or (for older project versions) the frame's
4772 protected StructureViewerBase findMatchingViewer(
4773 Entry<String, StructureViewerModel> viewerData)
4775 final String sviewid = viewerData.getKey();
4776 final StructureViewerModel svattrib = viewerData.getValue();
4777 StructureViewerBase comp = null;
4778 JInternalFrame[] frames = getAllFrames();
4779 for (JInternalFrame frame : frames)
4781 if (frame instanceof StructureViewerBase)
4784 * Post jalview 2.4 schema includes structure view id
4786 if (sviewid != null && ((StructureViewerBase) frame).getViewId()
4789 comp = (StructureViewerBase) frame;
4790 break; // break added in 2.9
4793 * Otherwise test for matching position and size of viewer frame
4795 else if (frame.getX() == svattrib.getX()
4796 && frame.getY() == svattrib.getY()
4797 && frame.getHeight() == svattrib.getHeight()
4798 && frame.getWidth() == svattrib.getWidth())
4800 comp = (StructureViewerBase) frame;
4801 // no break in faint hope of an exact match on viewId
4809 * Link an AlignmentPanel to an existing structure viewer.
4814 * @param useinViewerSuperpos
4815 * @param usetoColourbyseq
4816 * @param viewerColouring
4818 protected void linkStructureViewer(AlignmentPanel ap,
4819 StructureViewerBase viewer, StructureViewerModel stateData)
4821 // NOTE: if the jalview project is part of a shared session then
4822 // view synchronization should/could be done here.
4824 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4825 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4826 final boolean viewerColouring = stateData.isColourByViewer();
4827 Map<File, StructureData> oldFiles = stateData.getFileData();
4830 * Add mapping for sequences in this view to an already open viewer
4832 final AAStructureBindingModel binding = viewer.getBinding();
4833 for (File id : oldFiles.keySet())
4835 // add this and any other pdb files that should be present in the
4837 StructureData filedat = oldFiles.get(id);
4838 String pdbFile = filedat.getFilePath();
4839 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4840 binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE,
4842 binding.addSequenceForStructFile(pdbFile, seq);
4844 // and add the AlignmentPanel's reference to the view panel
4845 viewer.addAlignmentPanel(ap);
4846 if (useinViewerSuperpos)
4848 viewer.useAlignmentPanelForSuperposition(ap);
4852 viewer.excludeAlignmentPanelForSuperposition(ap);
4854 if (usetoColourbyseq)
4856 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4860 viewer.excludeAlignmentPanelForColourbyseq(ap);
4865 * Get all frames within the Desktop.
4869 protected JInternalFrame[] getAllFrames()
4871 JInternalFrame[] frames = null;
4872 // TODO is this necessary - is it safe - risk of hanging?
4877 frames = Desktop.desktop.getAllFrames();
4878 } catch (ArrayIndexOutOfBoundsException e)
4880 // occasional No such child exceptions are thrown here...
4884 } catch (InterruptedException f)
4888 } while (frames == null);
4893 * Answers true if 'version' is equal to or later than 'supported', where each
4894 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4895 * changes. Development and test values for 'version' are leniently treated
4899 * - minimum version we are comparing against
4901 * - version of data being processsed
4904 public static boolean isVersionStringLaterThan(String supported,
4907 if (supported == null || version == null
4908 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4909 || version.equalsIgnoreCase("Test")
4910 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4912 System.err.println("Assuming project file with "
4913 + (version == null ? "null" : version)
4914 + " is compatible with Jalview version " + supported);
4919 return StringUtils.compareVersions(version, supported, "b") >= 0;
4923 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4925 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4927 if (newStructureViewers != null)
4929 sview.getBinding().setFinishedLoadingFromArchive(false);
4930 newStructureViewers.add(sview);
4934 protected void setLoadingFinishedForNewStructureViewers()
4936 if (newStructureViewers != null)
4938 for (JalviewStructureDisplayI sview : newStructureViewers)
4940 sview.getBinding().setFinishedLoadingFromArchive(true);
4942 newStructureViewers.clear();
4943 newStructureViewers = null;
4947 AlignFrame loadViewport(String file, List<JSeq> JSEQ,
4948 List<SequenceI> hiddenSeqs, AlignmentI al,
4949 JalviewModel jm, Viewport view, String uniqueSeqSetId,
4952 AlignFrame af = null;
4953 af = new AlignFrame(al, safeInt(view.getWidth()),
4954 safeInt(view.getHeight()), uniqueSeqSetId, viewId);
4956 af.setFileName(file, FileFormat.Jalview);
4958 final AlignViewport viewport = af.getViewport();
4959 for (int i = 0; i < JSEQ.size(); i++)
4961 int colour = safeInt(JSEQ.get(i).getColour());
4962 viewport.setSequenceColour(viewport.getAlignment().getSequenceAt(i),
4968 viewport.setColourByReferenceSeq(true);
4969 viewport.setDisplayReferenceSeq(true);
4972 viewport.setGatherViewsHere(safeBoolean(view.isGatheredViews()));
4974 if (view.getSequenceSetId() != null)
4976 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4978 viewport.setSequenceSetId(uniqueSeqSetId);
4981 // propagate shared settings to this new view
4982 viewport.setHistoryList(av.getHistoryList());
4983 viewport.setRedoList(av.getRedoList());
4987 viewportsAdded.put(uniqueSeqSetId, viewport);
4989 // TODO: check if this method can be called repeatedly without
4990 // side-effects if alignpanel already registered.
4991 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4993 // apply Hidden regions to view.
4994 if (hiddenSeqs != null)
4996 for (int s = 0; s < JSEQ.size(); s++)
4998 SequenceGroup hidden = new SequenceGroup();
4999 boolean isRepresentative = false;
5000 for (int r = 0; r < JSEQ.get(s).getHiddenSequences().size(); r++)
5002 isRepresentative = true;
5003 SequenceI sequenceToHide = al
5004 .getSequenceAt(JSEQ.get(s).getHiddenSequences().get(r));
5005 hidden.addSequence(sequenceToHide, false);
5006 // remove from hiddenSeqs list so we don't try to hide it twice
5007 hiddenSeqs.remove(sequenceToHide);
5009 if (isRepresentative)
5011 SequenceI representativeSequence = al.getSequenceAt(s);
5012 hidden.addSequence(representativeSequence, false);
5013 viewport.hideRepSequences(representativeSequence, hidden);
5017 SequenceI[] hseqs = hiddenSeqs
5018 .toArray(new SequenceI[hiddenSeqs.size()]);
5019 viewport.hideSequence(hseqs);
5022 // recover view properties and display parameters
5024 viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
5025 viewport.setAbovePIDThreshold(safeBoolean(view.isPidSelected()));
5026 final int pidThreshold = safeInt(view.getPidThreshold());
5027 viewport.setThreshold(pidThreshold);
5029 viewport.setColourText(safeBoolean(view.isShowColourText()));
5031 viewport.setConservationSelected(
5032 safeBoolean(view.isConservationSelected()));
5033 viewport.setIncrement(safeInt(view.getConsThreshold()));
5034 viewport.setShowJVSuffix(safeBoolean(view.isShowFullId()));
5035 viewport.setRightAlignIds(safeBoolean(view.isRightAlignIds()));
5036 viewport.setFont(new Font(view.getFontName(),
5037 safeInt(view.getFontStyle()), safeInt(view.getFontSize())),
5039 ViewStyleI vs = viewport.getViewStyle();
5040 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
5041 viewport.setViewStyle(vs);
5042 // TODO: allow custom charWidth/Heights to be restored by updating them
5043 // after setting font - which means set above to false
5044 viewport.setRenderGaps(safeBoolean(view.isRenderGaps()));
5045 viewport.setWrapAlignment(safeBoolean(view.isWrapAlignment()));
5046 viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
5048 Boolean autocalcFirst = view.isShowAutocalcAbove();
5049 if (autocalcFirst != null)
5051 af.setShowAutoCalculatedAbove(autocalcFirst.booleanValue());
5053 String sortBy = view.getSortAnnotationsBy();
5058 viewport.setSortAnnotationsBy(
5059 SequenceAnnotationOrder.valueOf(sortBy));
5060 } catch (IllegalArgumentException e)
5063 "Invalid annotation sort specifier in project: " + sortBy);
5067 viewport.setShowBoxes(safeBoolean(view.isShowBoxes()));
5068 viewport.setShowText(safeBoolean(view.isShowText()));
5069 viewport.setTextColour(new Color(safeInt(view.getTextCol1())));
5070 viewport.setTextColour2(new Color(safeInt(view.getTextCol2())));
5071 viewport.setThresholdTextColour(safeInt(view.getTextColThreshold()));
5072 viewport.setShowUnconserved(view.isShowUnconserved());
5073 viewport.getRanges().setStartRes(safeInt(view.getStartRes()));
5075 if (view.getViewName() != null)
5077 viewport.setViewName(view.getViewName());
5078 af.setInitialTabVisible();
5080 af.setBounds(safeInt(view.getXpos()), safeInt(view.getYpos()),
5081 safeInt(view.getWidth()), safeInt(view.getHeight()));
5082 // startSeq set in af.alignPanel.updateLayout below
5083 af.alignPanel.updateLayout();
5084 ColourSchemeI cs = null;
5085 // apply colourschemes
5086 if (view.getBgColour() != null)
5088 if (view.getBgColour().startsWith("ucs"))
5090 cs = getUserColourScheme(jm, view.getBgColour());
5092 else if (view.getBgColour().startsWith("Annotation"))
5094 AnnotationColourScheme viewAnnColour = view.getAnnotationColours();
5095 cs = constructAnnotationColour(viewAnnColour, af, al, jm, true);
5102 cs = ColourSchemeProperty.getColourScheme(af.getViewport(), al,
5103 view.getBgColour());
5108 * turn off 'alignment colour applies to all groups'
5109 * while restoring global colour scheme
5111 viewport.setColourAppliesToAllGroups(false);
5112 viewport.setGlobalColourScheme(cs);
5113 viewport.getResidueShading().setThreshold(pidThreshold,
5114 view.isIgnoreGapsinConsensus());
5115 viewport.getResidueShading()
5116 .setConsensus(viewport.getSequenceConsensusHash());
5117 if (safeBoolean(view.isConservationSelected()) && cs != null)
5119 viewport.getResidueShading()
5120 .setConservationInc(safeInt(view.getConsThreshold()));
5122 af.changeColour(cs);
5123 viewport.setColourAppliesToAllGroups(true);
5126 .setShowSequenceFeatures(
5127 safeBoolean(view.isShowSequenceFeatures()));
5129 viewport.setCentreColumnLabels(view.isCentreColumnLabels());
5130 viewport.setIgnoreGapsConsensus(view.isIgnoreGapsinConsensus(), null);
5131 viewport.setFollowHighlight(view.isFollowHighlight());
5132 viewport.followSelection = view.isFollowSelection();
5133 viewport.setShowConsensusHistogram(view.isShowConsensusHistogram());
5134 viewport.setShowSequenceLogo(view.isShowSequenceLogo());
5135 viewport.setNormaliseSequenceLogo(view.isNormaliseSequenceLogo());
5136 viewport.setShowDBRefs(safeBoolean(view.isShowDbRefTooltip()));
5137 viewport.setShowNPFeats(safeBoolean(view.isShowNPfeatureTooltip()));
5138 viewport.setShowGroupConsensus(view.isShowGroupConsensus());
5139 viewport.setShowGroupConservation(view.isShowGroupConservation());
5141 // recover feature settings
5142 if (jm.getFeatureSettings() != null)
5144 FeatureRenderer fr = af.alignPanel.getSeqPanel().seqCanvas
5145 .getFeatureRenderer();
5146 FeaturesDisplayed fdi;
5147 viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
5148 String[] renderOrder = new String[jm.getFeatureSettings()
5149 .getSetting().size()];
5150 Map<String, FeatureColourI> featureColours = new Hashtable<>();
5151 Map<String, Float> featureOrder = new Hashtable<>();
5153 for (int fs = 0; fs < jm.getFeatureSettings()
5154 .getSetting().size(); fs++)
5156 Setting setting = jm.getFeatureSettings().getSetting().get(fs);
5157 String featureType = setting.getType();
5160 * restore feature filters (if any)
5162 jalview.xml.binding.jalview.FeatureMatcherSet filters = setting
5164 if (filters != null)
5166 FeatureMatcherSetI filter = Jalview2XML
5167 .parseFilter(featureType, filters);
5168 if (!filter.isEmpty())
5170 fr.setFeatureFilter(featureType, filter);
5175 * restore feature colour scheme
5177 Color maxColour = new Color(setting.getColour());
5178 if (setting.getMincolour() != null)
5181 * minColour is always set unless a simple colour
5182 * (including for colour by label though it doesn't use it)
5184 Color minColour = new Color(setting.getMincolour().intValue());
5185 Color noValueColour = minColour;
5186 NoValueColour noColour = setting.getNoValueColour();
5187 if (noColour == NoValueColour.NONE)
5189 noValueColour = null;
5191 else if (noColour == NoValueColour.MAX)
5193 noValueColour = maxColour;
5195 float min = safeFloat(safeFloat(setting.getMin()));
5196 float max = setting.getMax() == null ? 1f
5197 : setting.getMax().floatValue();
5198 FeatureColourI gc = new FeatureColour(maxColour, minColour,
5200 noValueColour, min, max);
5201 if (setting.getAttributeName().size() > 0)
5203 gc.setAttributeName(setting.getAttributeName().toArray(
5204 new String[setting.getAttributeName().size()]));
5206 if (setting.getThreshold() != null)
5208 gc.setThreshold(setting.getThreshold().floatValue());
5209 int threshstate = safeInt(setting.getThreshstate());
5210 // -1 = None, 0 = Below, 1 = Above threshold
5211 if (threshstate == 0)
5213 gc.setBelowThreshold(true);
5215 else if (threshstate == 1)
5217 gc.setAboveThreshold(true);
5220 gc.setAutoScaled(true); // default
5221 if (setting.isAutoScale() != null)
5223 gc.setAutoScaled(setting.isAutoScale());
5225 if (setting.isColourByLabel() != null)
5227 gc.setColourByLabel(setting.isColourByLabel());
5229 // and put in the feature colour table.
5230 featureColours.put(featureType, gc);
5234 featureColours.put(featureType,
5235 new FeatureColour(maxColour));
5237 renderOrder[fs] = featureType;
5238 if (setting.getOrder() != null)
5240 featureOrder.put(featureType, setting.getOrder().floatValue());
5244 featureOrder.put(featureType, new Float(
5245 fs / jm.getFeatureSettings().getSetting().size()));
5247 if (safeBoolean(setting.isDisplay()))
5249 fdi.setVisible(featureType);
5252 Map<String, Boolean> fgtable = new Hashtable<>();
5253 for (int gs = 0; gs < jm.getFeatureSettings().getGroup().size(); gs++)
5255 Group grp = jm.getFeatureSettings().getGroup().get(gs);
5256 fgtable.put(grp.getName(), new Boolean(grp.isDisplay()));
5258 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
5259 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
5260 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
5261 FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
5262 fgtable, featureColours, 1.0f, featureOrder);
5263 fr.transferSettings(frs);
5266 if (view.getHiddenColumns().size() > 0)
5268 for (int c = 0; c < view.getHiddenColumns().size(); c++)
5270 final HiddenColumns hc = view.getHiddenColumns().get(c);
5271 viewport.hideColumns(safeInt(hc.getStart()),
5272 safeInt(hc.getEnd()) /* +1 */);
5275 if (view.getCalcIdParam() != null)
5277 for (CalcIdParam calcIdParam : view.getCalcIdParam())
5279 if (calcIdParam != null)
5281 if (recoverCalcIdParam(calcIdParam, viewport))
5286 warn("Couldn't recover parameters for "
5287 + calcIdParam.getCalcId());
5292 af.setMenusFromViewport(viewport);
5293 af.setTitle(view.getTitle());
5294 // TODO: we don't need to do this if the viewport is aready visible.
5296 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
5297 * has a 'cdna/protein complement' view, in which case save it in order to
5298 * populate a SplitFrame once all views have been read in.
5300 String complementaryViewId = view.getComplementId();
5301 if (complementaryViewId == null)
5303 Desktop.addInternalFrame(af, view.getTitle(),
5304 safeInt(view.getWidth()), safeInt(view.getHeight()));
5305 // recompute any autoannotation
5306 af.alignPanel.updateAnnotation(false, true);
5307 af.alignPanel.alignmentChanged();
5311 splitFrameCandidates.put(view, af);
5317 * Reads saved data to restore Colour by Annotation settings
5319 * @param viewAnnColour
5323 * @param checkGroupAnnColour
5326 private ColourSchemeI constructAnnotationColour(
5327 AnnotationColourScheme viewAnnColour, AlignFrame af,
5328 AlignmentI al, JalviewModel model, boolean checkGroupAnnColour)
5330 boolean propagateAnnColour = false;
5331 AlignmentI annAlignment = af != null ? af.getViewport().getAlignment()
5333 if (checkGroupAnnColour && al.getGroups() != null
5334 && al.getGroups().size() > 0)
5336 // pre 2.8.1 behaviour
5337 // check to see if we should transfer annotation colours
5338 propagateAnnColour = true;
5339 for (SequenceGroup sg : al.getGroups())
5341 if (sg.getColourScheme() instanceof AnnotationColourGradient)
5343 propagateAnnColour = false;
5349 * 2.10.2- : saved annotationId is AlignmentAnnotation.annotationId
5351 String annotationId = viewAnnColour.getAnnotation();
5352 AlignmentAnnotation matchedAnnotation = annotationIds.get(annotationId);
5355 * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
5357 if (matchedAnnotation == null
5358 && annAlignment.getAlignmentAnnotation() != null)
5360 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
5363 .equals(annAlignment.getAlignmentAnnotation()[i].label))
5365 matchedAnnotation = annAlignment.getAlignmentAnnotation()[i];
5370 if (matchedAnnotation == null)
5372 System.err.println("Failed to match annotation colour scheme for "
5376 if (matchedAnnotation.getThreshold() == null)
5378 matchedAnnotation.setThreshold(
5379 new GraphLine(safeFloat(viewAnnColour.getThreshold()),
5380 "Threshold", Color.black));
5383 AnnotationColourGradient cs = null;
5384 if (viewAnnColour.getColourScheme().equals("None"))
5386 cs = new AnnotationColourGradient(matchedAnnotation,
5387 new Color(safeInt(viewAnnColour.getMinColour())),
5388 new Color(safeInt(viewAnnColour.getMaxColour())),
5389 safeInt(viewAnnColour.getAboveThreshold()));
5391 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
5393 cs = new AnnotationColourGradient(matchedAnnotation,
5394 getUserColourScheme(model, viewAnnColour.getColourScheme()),
5395 safeInt(viewAnnColour.getAboveThreshold()));
5399 cs = new AnnotationColourGradient(matchedAnnotation,
5400 ColourSchemeProperty.getColourScheme(af.getViewport(), al,
5401 viewAnnColour.getColourScheme()),
5402 safeInt(viewAnnColour.getAboveThreshold()));
5405 boolean perSequenceOnly = safeBoolean(viewAnnColour.isPerSequence());
5406 boolean useOriginalColours = safeBoolean(
5407 viewAnnColour.isPredefinedColours());
5408 cs.setSeqAssociated(perSequenceOnly);
5409 cs.setPredefinedColours(useOriginalColours);
5411 if (propagateAnnColour && al.getGroups() != null)
5413 // Also use these settings for all the groups
5414 for (int g = 0; g < al.getGroups().size(); g++)
5416 SequenceGroup sg = al.getGroups().get(g);
5417 if (sg.getGroupColourScheme() == null)
5422 AnnotationColourGradient groupScheme = new AnnotationColourGradient(
5423 matchedAnnotation, sg.getColourScheme(),
5424 safeInt(viewAnnColour.getAboveThreshold()));
5425 sg.setColourScheme(groupScheme);
5426 groupScheme.setSeqAssociated(perSequenceOnly);
5427 groupScheme.setPredefinedColours(useOriginalColours);
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);