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 af = loadViewport(file, jseqs, hiddenSeqs, al, jalviewModel, view,
4038 uniqueSeqSetId, viewId);
4039 // TODO restore autocalc preferences if overridden earlier?
4041 * resort annotations to their order in the project
4042 * (also sets height and visibility for autocalc'd annotation)
4044 av = af.getViewport();
4045 new AnnotationSorter(av).sort(addedAnnotation);
4047 ap.adjustAnnotationHeight();
4051 * Load any trees, PDB structures and viewers
4053 * Not done if flag is false (when this method is used for New View)
4055 if (loadTreesAndStructures)
4057 loadTrees(jalviewModel, view, af, av, ap);
4058 loadPCAViewers(jalviewModel, ap);
4059 loadPDBStructures(jprovider, jseqs, af, ap);
4060 loadRnaViewers(jprovider, jseqs, ap);
4062 // and finally return.
4067 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
4068 * panel is restored from separate jar entries, two (gapped and trimmed) per
4069 * sequence and secondary structure.
4071 * Currently each viewer shows just one sequence and structure (gapped and
4072 * trimmed), however this method is designed to support multiple sequences or
4073 * structures in viewers if wanted in future.
4079 private void loadRnaViewers(jarInputStreamProvider jprovider,
4080 List<JSeq> jseqs, AlignmentPanel ap)
4083 * scan the sequences for references to viewers; create each one the first
4084 * time it is referenced, add Rna models to existing viewers
4086 for (JSeq jseq : jseqs)
4088 for (int i = 0; i < jseq.getRnaViewer().size(); i++)
4090 RnaViewer viewer = jseq.getRnaViewer().get(i);
4091 AppVarna appVarna = findOrCreateVarnaViewer(viewer, uniqueSetSuffix,
4094 for (int j = 0; j < viewer.getSecondaryStructure().size(); j++)
4096 SecondaryStructure ss = viewer.getSecondaryStructure().get(j);
4097 SequenceI seq = seqRefIds.get(jseq.getId());
4098 AlignmentAnnotation ann = this.annotationIds
4099 .get(ss.getAnnotationId());
4102 * add the structure to the Varna display (with session state copied
4103 * from the jar to a temporary file)
4105 boolean gapped = safeBoolean(ss.isGapped());
4106 String rnaTitle = ss.getTitle();
4107 String sessionState = ss.getViewerState();
4108 String tempStateFile = copyJarEntry(jprovider, sessionState,
4110 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
4111 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
4113 appVarna.setInitialSelection(safeInt(viewer.getSelectedRna()));
4119 * Locate and return an already instantiated matching AppVarna, or create one
4123 * @param viewIdSuffix
4127 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
4128 String viewIdSuffix, AlignmentPanel ap)
4131 * on each load a suffix is appended to the saved viewId, to avoid conflicts
4132 * if load is repeated
4134 String postLoadId = viewer.getViewId() + viewIdSuffix;
4135 for (JInternalFrame frame : getAllFrames())
4137 if (frame instanceof AppVarna)
4139 AppVarna varna = (AppVarna) frame;
4140 if (postLoadId.equals(varna.getViewId()))
4142 // this viewer is already instantiated
4143 // could in future here add ap as another 'parent' of the
4144 // AppVarna window; currently just 1-to-many
4151 * viewer not found - make it
4153 RnaViewerModel model = new RnaViewerModel(postLoadId, viewer.getTitle(),
4154 safeInt(viewer.getXpos()), safeInt(viewer.getYpos()),
4155 safeInt(viewer.getWidth()), safeInt(viewer.getHeight()),
4156 safeInt(viewer.getDividerLocation()));
4157 AppVarna varna = new AppVarna(model, ap);
4163 * Load any saved trees
4171 protected void loadTrees(JalviewModel jm, Viewport view,
4172 AlignFrame af, AlignViewport av, AlignmentPanel ap)
4174 // TODO result of automated refactoring - are all these parameters needed?
4177 for (int t = 0; t < jm.getTree().size(); t++)
4180 Tree tree = jm.getTree().get(t);
4182 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
4185 tp = af.showNewickTree(new NewickFile(tree.getNewick()),
4186 tree.getTitle(), safeInt(tree.getWidth()),
4187 safeInt(tree.getHeight()), safeInt(tree.getXpos()),
4188 safeInt(tree.getYpos()));
4189 if (tree.getId() != null)
4191 // perhaps bind the tree id to something ?
4196 // update local tree attributes ?
4197 // TODO: should check if tp has been manipulated by user - if so its
4198 // settings shouldn't be modified
4199 tp.setTitle(tree.getTitle());
4200 tp.setBounds(new Rectangle(safeInt(tree.getXpos()),
4201 safeInt(tree.getYpos()), safeInt(tree.getWidth()),
4202 safeInt(tree.getHeight())));
4203 tp.setViewport(av); // af.viewport;
4204 // TODO: verify 'associate with all views' works still
4205 tp.getTreeCanvas().setViewport(av); // af.viewport;
4206 tp.getTreeCanvas().setAssociatedPanel(ap); // af.alignPanel;
4208 tp.getTreeCanvas().setApplyToAllViews(tree.isLinkToAllViews());
4211 warn("There was a problem recovering stored Newick tree: \n"
4212 + tree.getNewick());
4216 tp.fitToWindow.setState(safeBoolean(tree.isFitToWindow()));
4217 tp.fitToWindow_actionPerformed(null);
4219 if (tree.getFontName() != null)
4222 new Font(tree.getFontName(), safeInt(tree.getFontStyle()),
4223 safeInt(tree.getFontSize())));
4228 new Font(view.getFontName(), safeInt(view.getFontStyle()),
4229 safeInt(view.getFontSize())));
4232 tp.showPlaceholders(safeBoolean(tree.isMarkUnlinked()));
4233 tp.showBootstrap(safeBoolean(tree.isShowBootstrap()));
4234 tp.showDistances(safeBoolean(tree.isShowDistances()));
4236 tp.getTreeCanvas().setThreshold(safeFloat(tree.getThreshold()));
4238 if (safeBoolean(tree.isCurrentTree()))
4240 af.getViewport().setCurrentTree(tp.getTree());
4244 } catch (Exception ex)
4246 ex.printStackTrace();
4251 * Load and link any saved structure viewers.
4258 protected void loadPDBStructures(jarInputStreamProvider jprovider,
4259 List<JSeq> jseqs, AlignFrame af, AlignmentPanel ap)
4262 * Run through all PDB ids on the alignment, and collect mappings between
4263 * distinct view ids and all sequences referring to that view.
4265 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<>();
4267 for (int i = 0; i < jseqs.size(); i++)
4269 JSeq jseq = jseqs.get(i);
4270 if (jseq.getPdbids().size() > 0)
4272 List<Pdbids> ids = jseq.getPdbids();
4273 for (int p = 0; p < ids.size(); p++)
4275 Pdbids pdbid = ids.get(p);
4276 final int structureStateCount = pdbid.getStructureState().size();
4277 for (int s = 0; s < structureStateCount; s++)
4279 // check to see if we haven't already created this structure view
4280 final StructureState structureState = pdbid
4281 .getStructureState().get(s);
4282 String sviewid = (structureState.getViewId() == null) ? null
4283 : structureState.getViewId() + uniqueSetSuffix;
4284 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
4285 // Originally : pdbid.getFile()
4286 // : TODO: verify external PDB file recovery still works in normal
4287 // jalview project load
4289 loadPDBFile(jprovider, pdbid.getId(), pdbid.getFile()));
4290 jpdb.setId(pdbid.getId());
4292 int x = safeInt(structureState.getXpos());
4293 int y = safeInt(structureState.getYpos());
4294 int width = safeInt(structureState.getWidth());
4295 int height = safeInt(structureState.getHeight());
4297 // Probably don't need to do this anymore...
4298 // Desktop.desktop.getComponentAt(x, y);
4299 // TODO: NOW: check that this recovers the PDB file correctly.
4300 String pdbFile = loadPDBFile(jprovider, pdbid.getId(),
4302 jalview.datamodel.SequenceI seq = seqRefIds
4303 .get(jseq.getId() + "");
4304 if (sviewid == null)
4306 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width + ","
4309 if (!structureViewers.containsKey(sviewid))
4311 structureViewers.put(sviewid,
4312 new StructureViewerModel(x, y, width, height, false,
4313 false, true, structureState.getViewId(),
4314 structureState.getType()));
4315 // Legacy pre-2.7 conversion JAL-823 :
4316 // do not assume any view has to be linked for colour by
4320 // assemble String[] { pdb files }, String[] { id for each
4321 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
4322 // seqs_file 2}, boolean[] {
4323 // linkAlignPanel,superposeWithAlignpanel}} from hash
4324 StructureViewerModel jmoldat = structureViewers.get(sviewid);
4325 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
4326 || structureState.isAlignwithAlignPanel());
4329 * Default colour by linked panel to false if not specified (e.g.
4330 * for pre-2.7 projects)
4332 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
4333 colourWithAlignPanel |= structureState.isColourwithAlignPanel();
4334 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
4337 * Default colour by viewer to true if not specified (e.g. for
4340 boolean colourByViewer = jmoldat.isColourByViewer();
4341 colourByViewer &= structureState.isColourByJmol();
4342 jmoldat.setColourByViewer(colourByViewer);
4344 if (jmoldat.getStateData().length() < structureState
4345 .getValue()/*Content()*/.length())
4347 jmoldat.setStateData(structureState.getValue());// Content());
4349 if (pdbid.getFile() != null)
4351 File mapkey = new File(pdbid.getFile());
4352 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
4353 if (seqstrmaps == null)
4355 jmoldat.getFileData().put(mapkey,
4356 seqstrmaps = jmoldat.new StructureData(pdbFile,
4359 if (!seqstrmaps.getSeqList().contains(seq))
4361 seqstrmaps.getSeqList().add(seq);
4367 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");
4374 // Instantiate the associated structure views
4375 for (Entry<String, StructureViewerModel> entry : structureViewers
4380 createOrLinkStructureViewer(entry, af, ap, jprovider);
4381 } catch (Exception e)
4384 "Error loading structure viewer: " + e.getMessage());
4385 // failed - try the next one
4397 protected void createOrLinkStructureViewer(
4398 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4399 AlignmentPanel ap, jarInputStreamProvider jprovider)
4401 final StructureViewerModel stateData = viewerData.getValue();
4404 * Search for any viewer windows already open from other alignment views
4405 * that exactly match the stored structure state
4407 StructureViewerBase comp = findMatchingViewer(viewerData);
4411 linkStructureViewer(ap, comp, stateData);
4416 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
4417 * "viewer_"+stateData.viewId
4419 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
4421 createChimeraViewer(viewerData, af, jprovider);
4426 * else Jmol (if pre-2.9, stateData contains JMOL state string)
4428 createJmolViewer(viewerData, af, jprovider);
4433 * Create a new Chimera viewer.
4439 protected void createChimeraViewer(
4440 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4441 jarInputStreamProvider jprovider)
4443 StructureViewerModel data = viewerData.getValue();
4444 String chimeraSessionFile = data.getStateData();
4447 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
4449 * NB this is the 'saved' viewId as in the project file XML, _not_ the
4450 * 'uniquified' sviewid used to reconstruct the viewer here
4452 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
4453 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
4456 Set<Entry<File, StructureData>> fileData = data.getFileData()
4458 List<PDBEntry> pdbs = new ArrayList<>();
4459 List<SequenceI[]> allseqs = new ArrayList<>();
4460 for (Entry<File, StructureData> pdb : fileData)
4462 String filePath = pdb.getValue().getFilePath();
4463 String pdbId = pdb.getValue().getPdbId();
4464 // pdbs.add(new PDBEntry(filePath, pdbId));
4465 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
4466 final List<SequenceI> seqList = pdb.getValue().getSeqList();
4467 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
4471 boolean colourByChimera = data.isColourByViewer();
4472 boolean colourBySequence = data.isColourWithAlignPanel();
4474 // TODO use StructureViewer as a factory here, see JAL-1761
4475 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
4476 final SequenceI[][] seqsArray = allseqs
4477 .toArray(new SequenceI[allseqs.size()][]);
4478 String newViewId = viewerData.getKey();
4480 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
4481 af.alignPanel, pdbArray, seqsArray, colourByChimera,
4482 colourBySequence, newViewId);
4483 cvf.setSize(data.getWidth(), data.getHeight());
4484 cvf.setLocation(data.getX(), data.getY());
4488 * Create a new Jmol window. First parse the Jmol state to translate filenames
4489 * loaded into the view, and record the order in which files are shown in the
4490 * Jmol view, so we can add the sequence mappings in same order.
4496 protected void createJmolViewer(
4497 final Entry<String, StructureViewerModel> viewerData,
4498 AlignFrame af, jarInputStreamProvider jprovider)
4500 final StructureViewerModel svattrib = viewerData.getValue();
4501 String state = svattrib.getStateData();
4504 * Pre-2.9: state element value is the Jmol state string
4506 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
4509 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
4511 state = readJarEntry(jprovider,
4512 getViewerJarEntryName(svattrib.getViewId()));
4515 List<String> pdbfilenames = new ArrayList<>();
4516 List<SequenceI[]> seqmaps = new ArrayList<>();
4517 List<String> pdbids = new ArrayList<>();
4518 StringBuilder newFileLoc = new StringBuilder(64);
4519 int cp = 0, ncp, ecp;
4520 Map<File, StructureData> oldFiles = svattrib.getFileData();
4521 while ((ncp = state.indexOf("load ", cp)) > -1)
4525 // look for next filename in load statement
4526 newFileLoc.append(state.substring(cp,
4527 ncp = (state.indexOf("\"", ncp + 1) + 1)));
4528 String oldfilenam = state.substring(ncp,
4529 ecp = state.indexOf("\"", ncp));
4530 // recover the new mapping data for this old filename
4531 // have to normalize filename - since Jmol and jalview do
4533 // translation differently.
4534 StructureData filedat = oldFiles.get(new File(oldfilenam));
4535 if (filedat == null)
4537 String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\");
4538 filedat = oldFiles.get(new File(reformatedOldFilename));
4540 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
4541 pdbfilenames.add(filedat.getFilePath());
4542 pdbids.add(filedat.getPdbId());
4543 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4544 newFileLoc.append("\"");
4545 cp = ecp + 1; // advance beyond last \" and set cursor so we can
4546 // look for next file statement.
4547 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
4551 // just append rest of state
4552 newFileLoc.append(state.substring(cp));
4556 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
4557 newFileLoc = new StringBuilder(state);
4558 newFileLoc.append("; load append ");
4559 for (File id : oldFiles.keySet())
4561 // add this and any other pdb files that should be present in
4563 StructureData filedat = oldFiles.get(id);
4564 newFileLoc.append(filedat.getFilePath());
4565 pdbfilenames.add(filedat.getFilePath());
4566 pdbids.add(filedat.getPdbId());
4567 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4568 newFileLoc.append(" \"");
4569 newFileLoc.append(filedat.getFilePath());
4570 newFileLoc.append("\"");
4573 newFileLoc.append(";");
4576 if (newFileLoc.length() == 0)
4580 int histbug = newFileLoc.indexOf("history = ");
4584 * change "history = [true|false];" to "history = [1|0];"
4587 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
4588 String val = (diff == -1) ? null
4589 : newFileLoc.substring(histbug, diff);
4590 if (val != null && val.length() >= 4)
4592 if (val.contains("e")) // eh? what can it be?
4594 if (val.trim().equals(TRUE))
4602 newFileLoc.replace(histbug, diff, val);
4607 final String[] pdbf = pdbfilenames
4608 .toArray(new String[pdbfilenames.size()]);
4609 final String[] id = pdbids.toArray(new String[pdbids.size()]);
4610 final SequenceI[][] sq = seqmaps
4611 .toArray(new SequenceI[seqmaps.size()][]);
4612 final String fileloc = newFileLoc.toString();
4613 final String sviewid = viewerData.getKey();
4614 final AlignFrame alf = af;
4615 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
4616 svattrib.getWidth(), svattrib.getHeight());
4619 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
4624 JalviewStructureDisplayI sview = null;
4627 sview = new StructureViewer(
4628 alf.alignPanel.getStructureSelectionManager())
4629 .createView(StructureViewer.ViewerType.JMOL,
4630 pdbf, id, sq, alf.alignPanel, svattrib,
4631 fileloc, rect, sviewid);
4632 addNewStructureViewer(sview);
4633 } catch (OutOfMemoryError ex)
4635 new OOMWarning("restoring structure view for PDB id " + id,
4636 (OutOfMemoryError) ex.getCause());
4637 if (sview != null && sview.isVisible())
4639 sview.closeViewer(false);
4640 sview.setVisible(false);
4646 } catch (InvocationTargetException ex)
4648 warn("Unexpected error when opening Jmol view.", ex);
4650 } catch (InterruptedException e)
4652 // e.printStackTrace();
4658 * Generates a name for the entry in the project jar file to hold state
4659 * information for a structure viewer
4664 protected String getViewerJarEntryName(String viewId)
4666 return VIEWER_PREFIX + viewId;
4670 * Returns any open frame that matches given structure viewer data. The match
4671 * is based on the unique viewId, or (for older project versions) the frame's
4677 protected StructureViewerBase findMatchingViewer(
4678 Entry<String, StructureViewerModel> viewerData)
4680 final String sviewid = viewerData.getKey();
4681 final StructureViewerModel svattrib = viewerData.getValue();
4682 StructureViewerBase comp = null;
4683 JInternalFrame[] frames = getAllFrames();
4684 for (JInternalFrame frame : frames)
4686 if (frame instanceof StructureViewerBase)
4689 * Post jalview 2.4 schema includes structure view id
4691 if (sviewid != null && ((StructureViewerBase) frame).getViewId()
4694 comp = (StructureViewerBase) frame;
4695 break; // break added in 2.9
4698 * Otherwise test for matching position and size of viewer frame
4700 else if (frame.getX() == svattrib.getX()
4701 && frame.getY() == svattrib.getY()
4702 && frame.getHeight() == svattrib.getHeight()
4703 && frame.getWidth() == svattrib.getWidth())
4705 comp = (StructureViewerBase) frame;
4706 // no break in faint hope of an exact match on viewId
4714 * Link an AlignmentPanel to an existing structure viewer.
4719 * @param useinViewerSuperpos
4720 * @param usetoColourbyseq
4721 * @param viewerColouring
4723 protected void linkStructureViewer(AlignmentPanel ap,
4724 StructureViewerBase viewer, StructureViewerModel stateData)
4726 // NOTE: if the jalview project is part of a shared session then
4727 // view synchronization should/could be done here.
4729 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4730 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4731 final boolean viewerColouring = stateData.isColourByViewer();
4732 Map<File, StructureData> oldFiles = stateData.getFileData();
4735 * Add mapping for sequences in this view to an already open viewer
4737 final AAStructureBindingModel binding = viewer.getBinding();
4738 for (File id : oldFiles.keySet())
4740 // add this and any other pdb files that should be present in the
4742 StructureData filedat = oldFiles.get(id);
4743 String pdbFile = filedat.getFilePath();
4744 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4745 binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE,
4747 binding.addSequenceForStructFile(pdbFile, seq);
4749 // and add the AlignmentPanel's reference to the view panel
4750 viewer.addAlignmentPanel(ap);
4751 if (useinViewerSuperpos)
4753 viewer.useAlignmentPanelForSuperposition(ap);
4757 viewer.excludeAlignmentPanelForSuperposition(ap);
4759 if (usetoColourbyseq)
4761 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4765 viewer.excludeAlignmentPanelForColourbyseq(ap);
4770 * Get all frames within the Desktop.
4774 protected JInternalFrame[] getAllFrames()
4776 JInternalFrame[] frames = null;
4777 // TODO is this necessary - is it safe - risk of hanging?
4782 frames = Desktop.desktop.getAllFrames();
4783 } catch (ArrayIndexOutOfBoundsException e)
4785 // occasional No such child exceptions are thrown here...
4789 } catch (InterruptedException f)
4793 } while (frames == null);
4798 * Answers true if 'version' is equal to or later than 'supported', where each
4799 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4800 * changes. Development and test values for 'version' are leniently treated
4804 * - minimum version we are comparing against
4806 * - version of data being processsed
4809 public static boolean isVersionStringLaterThan(String supported,
4812 if (supported == null || version == null
4813 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4814 || version.equalsIgnoreCase("Test")
4815 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4817 System.err.println("Assuming project file with "
4818 + (version == null ? "null" : version)
4819 + " is compatible with Jalview version " + supported);
4824 return StringUtils.compareVersions(version, supported, "b") >= 0;
4828 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4830 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4832 if (newStructureViewers != null)
4834 sview.getBinding().setFinishedLoadingFromArchive(false);
4835 newStructureViewers.add(sview);
4839 protected void setLoadingFinishedForNewStructureViewers()
4841 if (newStructureViewers != null)
4843 for (JalviewStructureDisplayI sview : newStructureViewers)
4845 sview.getBinding().setFinishedLoadingFromArchive(true);
4847 newStructureViewers.clear();
4848 newStructureViewers = null;
4852 AlignFrame loadViewport(String file, List<JSeq> JSEQ,
4853 List<SequenceI> hiddenSeqs, AlignmentI al,
4854 JalviewModel jm, Viewport view, String uniqueSeqSetId,
4857 AlignFrame af = null;
4858 af = new AlignFrame(al, safeInt(view.getWidth()),
4859 safeInt(view.getHeight()), uniqueSeqSetId, viewId);
4861 af.setFileName(file, FileFormat.Jalview);
4863 final AlignViewport viewport = af.getViewport();
4864 for (int i = 0; i < JSEQ.size(); i++)
4866 int colour = safeInt(JSEQ.get(i).getColour());
4867 viewport.setSequenceColour(viewport.getAlignment().getSequenceAt(i),
4873 viewport.setColourByReferenceSeq(true);
4874 viewport.setDisplayReferenceSeq(true);
4877 viewport.setGatherViewsHere(safeBoolean(view.isGatheredViews()));
4879 if (view.getSequenceSetId() != null)
4881 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4883 viewport.setSequenceSetId(uniqueSeqSetId);
4886 // propagate shared settings to this new view
4887 viewport.setHistoryList(av.getHistoryList());
4888 viewport.setRedoList(av.getRedoList());
4892 viewportsAdded.put(uniqueSeqSetId, viewport);
4894 // TODO: check if this method can be called repeatedly without
4895 // side-effects if alignpanel already registered.
4896 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4898 // apply Hidden regions to view.
4899 if (hiddenSeqs != null)
4901 for (int s = 0; s < JSEQ.size(); s++)
4903 SequenceGroup hidden = new SequenceGroup();
4904 boolean isRepresentative = false;
4905 for (int r = 0; r < JSEQ.get(s).getHiddenSequences().size(); r++)
4907 isRepresentative = true;
4908 SequenceI sequenceToHide = al
4909 .getSequenceAt(JSEQ.get(s).getHiddenSequences().get(r));
4910 hidden.addSequence(sequenceToHide, false);
4911 // remove from hiddenSeqs list so we don't try to hide it twice
4912 hiddenSeqs.remove(sequenceToHide);
4914 if (isRepresentative)
4916 SequenceI representativeSequence = al.getSequenceAt(s);
4917 hidden.addSequence(representativeSequence, false);
4918 viewport.hideRepSequences(representativeSequence, hidden);
4922 SequenceI[] hseqs = hiddenSeqs
4923 .toArray(new SequenceI[hiddenSeqs.size()]);
4924 viewport.hideSequence(hseqs);
4927 // recover view properties and display parameters
4929 viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
4930 viewport.setAbovePIDThreshold(safeBoolean(view.isPidSelected()));
4931 final int pidThreshold = safeInt(view.getPidThreshold());
4932 viewport.setThreshold(pidThreshold);
4934 viewport.setColourText(safeBoolean(view.isShowColourText()));
4936 viewport.setConservationSelected(
4937 safeBoolean(view.isConservationSelected()));
4938 viewport.setIncrement(safeInt(view.getConsThreshold()));
4939 viewport.setShowJVSuffix(safeBoolean(view.isShowFullId()));
4940 viewport.setRightAlignIds(safeBoolean(view.isRightAlignIds()));
4941 viewport.setFont(new Font(view.getFontName(),
4942 safeInt(view.getFontStyle()), safeInt(view.getFontSize())),
4944 ViewStyleI vs = viewport.getViewStyle();
4945 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
4946 viewport.setViewStyle(vs);
4947 // TODO: allow custom charWidth/Heights to be restored by updating them
4948 // after setting font - which means set above to false
4949 viewport.setRenderGaps(safeBoolean(view.isRenderGaps()));
4950 viewport.setWrapAlignment(safeBoolean(view.isWrapAlignment()));
4951 viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
4953 Boolean autocalcFirst = view.isShowAutocalcAbove();
4954 if (autocalcFirst != null)
4956 af.setShowAutoCalculatedAbove(autocalcFirst.booleanValue());
4958 String sortBy = view.getSortAnnotationsBy();
4963 viewport.setSortAnnotationsBy(
4964 SequenceAnnotationOrder.valueOf(sortBy));
4965 } catch (IllegalArgumentException e)
4968 "Invalid annotation sort specifier in project: " + sortBy);
4972 viewport.setShowBoxes(safeBoolean(view.isShowBoxes()));
4973 viewport.setShowText(safeBoolean(view.isShowText()));
4974 viewport.setTextColour(new Color(safeInt(view.getTextCol1())));
4975 viewport.setTextColour2(new Color(safeInt(view.getTextCol2())));
4976 viewport.setThresholdTextColour(safeInt(view.getTextColThreshold()));
4977 viewport.setShowUnconserved(view.isShowUnconserved());
4978 viewport.getRanges().setStartRes(safeInt(view.getStartRes()));
4980 if (view.getViewName() != null)
4982 viewport.setViewName(view.getViewName());
4983 af.setInitialTabVisible();
4985 af.setBounds(safeInt(view.getXpos()), safeInt(view.getYpos()),
4986 safeInt(view.getWidth()), safeInt(view.getHeight()));
4987 // startSeq set in af.alignPanel.updateLayout below
4988 af.alignPanel.updateLayout();
4989 ColourSchemeI cs = null;
4990 // apply colourschemes
4991 if (view.getBgColour() != null)
4993 if (view.getBgColour().startsWith("ucs"))
4995 cs = getUserColourScheme(jm, view.getBgColour());
4997 else if (view.getBgColour().startsWith("Annotation"))
4999 AnnotationColourScheme viewAnnColour = view.getAnnotationColours();
5000 cs = constructAnnotationColour(viewAnnColour, af, al, jm, true);
5007 cs = ColourSchemeProperty.getColourScheme(af.getViewport(), al,
5008 view.getBgColour());
5013 * turn off 'alignment colour applies to all groups'
5014 * while restoring global colour scheme
5016 viewport.setColourAppliesToAllGroups(false);
5017 viewport.setGlobalColourScheme(cs);
5018 viewport.getResidueShading().setThreshold(pidThreshold,
5019 view.isIgnoreGapsinConsensus());
5020 viewport.getResidueShading()
5021 .setConsensus(viewport.getSequenceConsensusHash());
5022 if (safeBoolean(view.isConservationSelected()) && cs != null)
5024 viewport.getResidueShading()
5025 .setConservationInc(safeInt(view.getConsThreshold()));
5027 af.changeColour(cs);
5028 viewport.setColourAppliesToAllGroups(true);
5031 .setShowSequenceFeatures(
5032 safeBoolean(view.isShowSequenceFeatures()));
5034 viewport.setCentreColumnLabels(view.isCentreColumnLabels());
5035 viewport.setIgnoreGapsConsensus(view.isIgnoreGapsinConsensus(), null);
5036 viewport.setFollowHighlight(view.isFollowHighlight());
5037 viewport.followSelection = view.isFollowSelection();
5038 viewport.setShowConsensusHistogram(view.isShowConsensusHistogram());
5039 viewport.setShowSequenceLogo(view.isShowSequenceLogo());
5040 viewport.setNormaliseSequenceLogo(view.isNormaliseSequenceLogo());
5041 viewport.setShowDBRefs(safeBoolean(view.isShowDbRefTooltip()));
5042 viewport.setShowNPFeats(safeBoolean(view.isShowNPfeatureTooltip()));
5043 viewport.setShowGroupConsensus(view.isShowGroupConsensus());
5044 viewport.setShowGroupConservation(view.isShowGroupConservation());
5046 // recover feature settings
5047 if (jm.getFeatureSettings() != null)
5049 FeatureRenderer fr = af.alignPanel.getSeqPanel().seqCanvas
5050 .getFeatureRenderer();
5051 FeaturesDisplayed fdi;
5052 viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
5053 String[] renderOrder = new String[jm.getFeatureSettings()
5054 .getSetting().size()];
5055 Map<String, FeatureColourI> featureColours = new Hashtable<>();
5056 Map<String, Float> featureOrder = new Hashtable<>();
5058 for (int fs = 0; fs < jm.getFeatureSettings()
5059 .getSetting().size(); fs++)
5061 Setting setting = jm.getFeatureSettings().getSetting().get(fs);
5062 String featureType = setting.getType();
5065 * restore feature filters (if any)
5067 jalview.xml.binding.jalview.FeatureMatcherSet filters = setting
5069 if (filters != null)
5071 FeatureMatcherSetI filter = Jalview2XML
5072 .parseFilter(featureType, filters);
5073 if (!filter.isEmpty())
5075 fr.setFeatureFilter(featureType, filter);
5080 * restore feature colour scheme
5082 Color maxColour = new Color(setting.getColour());
5083 if (setting.getMincolour() != null)
5086 * minColour is always set unless a simple colour
5087 * (including for colour by label though it doesn't use it)
5089 Color minColour = new Color(setting.getMincolour().intValue());
5090 Color noValueColour = minColour;
5091 NoValueColour noColour = setting.getNoValueColour();
5092 if (noColour == NoValueColour.NONE)
5094 noValueColour = null;
5096 else if (noColour == NoValueColour.MAX)
5098 noValueColour = maxColour;
5100 float min = safeFloat(safeFloat(setting.getMin()));
5101 float max = setting.getMax() == null ? 1f
5102 : setting.getMax().floatValue();
5103 FeatureColourI gc = new FeatureColour(maxColour, minColour,
5105 noValueColour, min, max);
5106 if (setting.getAttributeName().size() > 0)
5108 gc.setAttributeName(setting.getAttributeName().toArray(
5109 new String[setting.getAttributeName().size()]));
5111 if (setting.getThreshold() != null)
5113 gc.setThreshold(setting.getThreshold().floatValue());
5114 int threshstate = safeInt(setting.getThreshstate());
5115 // -1 = None, 0 = Below, 1 = Above threshold
5116 if (threshstate == 0)
5118 gc.setBelowThreshold(true);
5120 else if (threshstate == 1)
5122 gc.setAboveThreshold(true);
5125 gc.setAutoScaled(true); // default
5126 if (setting.isAutoScale() != null)
5128 gc.setAutoScaled(setting.isAutoScale());
5130 if (setting.isColourByLabel() != null)
5132 gc.setColourByLabel(setting.isColourByLabel());
5134 // and put in the feature colour table.
5135 featureColours.put(featureType, gc);
5139 featureColours.put(featureType,
5140 new FeatureColour(maxColour));
5142 renderOrder[fs] = featureType;
5143 if (setting.getOrder() != null)
5145 featureOrder.put(featureType, setting.getOrder().floatValue());
5149 featureOrder.put(featureType, new Float(
5150 fs / jm.getFeatureSettings().getSetting().size()));
5152 if (safeBoolean(setting.isDisplay()))
5154 fdi.setVisible(featureType);
5157 Map<String, Boolean> fgtable = new Hashtable<>();
5158 for (int gs = 0; gs < jm.getFeatureSettings().getGroup().size(); gs++)
5160 Group grp = jm.getFeatureSettings().getGroup().get(gs);
5161 fgtable.put(grp.getName(), new Boolean(grp.isDisplay()));
5163 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
5164 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
5165 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
5166 FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
5167 fgtable, featureColours, 1.0f, featureOrder);
5168 fr.transferSettings(frs);
5171 if (view.getHiddenColumns().size() > 0)
5173 for (int c = 0; c < view.getHiddenColumns().size(); c++)
5175 final HiddenColumns hc = view.getHiddenColumns().get(c);
5176 viewport.hideColumns(safeInt(hc.getStart()),
5177 safeInt(hc.getEnd()) /* +1 */);
5180 if (view.getCalcIdParam() != null)
5182 for (CalcIdParam calcIdParam : view.getCalcIdParam())
5184 if (calcIdParam != null)
5186 if (recoverCalcIdParam(calcIdParam, viewport))
5191 warn("Couldn't recover parameters for "
5192 + calcIdParam.getCalcId());
5197 af.setMenusFromViewport(viewport);
5198 af.setTitle(view.getTitle());
5199 // TODO: we don't need to do this if the viewport is aready visible.
5201 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
5202 * has a 'cdna/protein complement' view, in which case save it in order to
5203 * populate a SplitFrame once all views have been read in.
5205 String complementaryViewId = view.getComplementId();
5206 if (complementaryViewId == null)
5208 Desktop.addInternalFrame(af, view.getTitle(),
5209 safeInt(view.getWidth()), safeInt(view.getHeight()));
5210 // recompute any autoannotation
5211 af.alignPanel.updateAnnotation(false, true);
5212 af.alignPanel.alignmentChanged();
5216 splitFrameCandidates.put(view, af);
5222 * Reads saved data to restore Colour by Annotation settings
5224 * @param viewAnnColour
5228 * @param checkGroupAnnColour
5231 private ColourSchemeI constructAnnotationColour(
5232 AnnotationColourScheme viewAnnColour, AlignFrame af,
5233 AlignmentI al, JalviewModel model, boolean checkGroupAnnColour)
5235 boolean propagateAnnColour = false;
5236 AlignmentI annAlignment = af != null ? af.getViewport().getAlignment()
5238 if (checkGroupAnnColour && al.getGroups() != null
5239 && al.getGroups().size() > 0)
5241 // pre 2.8.1 behaviour
5242 // check to see if we should transfer annotation colours
5243 propagateAnnColour = true;
5244 for (SequenceGroup sg : al.getGroups())
5246 if (sg.getColourScheme() instanceof AnnotationColourGradient)
5248 propagateAnnColour = false;
5254 * 2.10.2- : saved annotationId is AlignmentAnnotation.annotationId
5256 String annotationId = viewAnnColour.getAnnotation();
5257 AlignmentAnnotation matchedAnnotation = annotationIds.get(annotationId);
5260 * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
5262 if (matchedAnnotation == null
5263 && annAlignment.getAlignmentAnnotation() != null)
5265 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
5268 .equals(annAlignment.getAlignmentAnnotation()[i].label))
5270 matchedAnnotation = annAlignment.getAlignmentAnnotation()[i];
5275 if (matchedAnnotation == null)
5277 System.err.println("Failed to match annotation colour scheme for "
5281 if (matchedAnnotation.getThreshold() == null)
5283 matchedAnnotation.setThreshold(
5284 new GraphLine(safeFloat(viewAnnColour.getThreshold()),
5285 "Threshold", Color.black));
5288 AnnotationColourGradient cs = null;
5289 if (viewAnnColour.getColourScheme().equals("None"))
5291 cs = new AnnotationColourGradient(matchedAnnotation,
5292 new Color(safeInt(viewAnnColour.getMinColour())),
5293 new Color(safeInt(viewAnnColour.getMaxColour())),
5294 safeInt(viewAnnColour.getAboveThreshold()));
5296 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
5298 cs = new AnnotationColourGradient(matchedAnnotation,
5299 getUserColourScheme(model, viewAnnColour.getColourScheme()),
5300 safeInt(viewAnnColour.getAboveThreshold()));
5304 cs = new AnnotationColourGradient(matchedAnnotation,
5305 ColourSchemeProperty.getColourScheme(af.getViewport(), al,
5306 viewAnnColour.getColourScheme()),
5307 safeInt(viewAnnColour.getAboveThreshold()));
5310 boolean perSequenceOnly = safeBoolean(viewAnnColour.isPerSequence());
5311 boolean useOriginalColours = safeBoolean(
5312 viewAnnColour.isPredefinedColours());
5313 cs.setSeqAssociated(perSequenceOnly);
5314 cs.setPredefinedColours(useOriginalColours);
5316 if (propagateAnnColour && al.getGroups() != null)
5318 // Also use these settings for all the groups
5319 for (int g = 0; g < al.getGroups().size(); g++)
5321 SequenceGroup sg = al.getGroups().get(g);
5322 if (sg.getGroupColourScheme() == null)
5327 AnnotationColourGradient groupScheme = new AnnotationColourGradient(
5328 matchedAnnotation, sg.getColourScheme(),
5329 safeInt(viewAnnColour.getAboveThreshold()));
5330 sg.setColourScheme(groupScheme);
5331 groupScheme.setSeqAssociated(perSequenceOnly);
5332 groupScheme.setPredefinedColours(useOriginalColours);
5338 Hashtable skipList = null;
5341 * TODO remove this method
5344 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
5345 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
5346 * throw new Error("Implementation Error. No skipList defined for this
5347 * Jalview2XML instance."); } return (AlignFrame)
5348 * skipList.get(view.getSequenceSetId()); }
5352 * Check if the Jalview view contained in object should be skipped or not.
5355 * @return true if view's sequenceSetId is a key in skipList
5357 private boolean skipViewport(JalviewModel object)
5359 if (skipList == null)
5363 String id = object.getViewport().get(0).getSequenceSetId();
5364 if (skipList.containsKey(id))
5366 if (Cache.log != null && Cache.log.isDebugEnabled())
5368 Cache.log.debug("Skipping seuqence set id " + id);
5375 public void addToSkipList(AlignFrame af)
5377 if (skipList == null)
5379 skipList = new Hashtable();
5381 skipList.put(af.getViewport().getSequenceSetId(), af);
5384 public void clearSkipList()
5386 if (skipList != null)
5393 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
5394 boolean ignoreUnrefed, String uniqueSeqSetId)
5396 jalview.datamodel.AlignmentI ds = getDatasetFor(
5397 vamsasSet.getDatasetId());
5398 AlignmentI xtant_ds = ds;
5399 if (xtant_ds == null)
5401 // good chance we are about to create a new dataset, but check if we've
5402 // seen some of the dataset sequence IDs before.
5403 // TODO: skip this check if we are working with project generated by
5404 // version 2.11 or later
5405 xtant_ds = checkIfHasDataset(vamsasSet.getSequence());
5406 if (xtant_ds != null)
5409 addDatasetRef(vamsasSet.getDatasetId(), ds);
5412 Vector dseqs = null;
5415 // recovering an alignment View
5416 AlignmentI seqSetDS = getDatasetFor(UNIQSEQSETID + uniqueSeqSetId);
5417 if (seqSetDS != null)
5419 if (ds != null && ds != seqSetDS)
5421 warn("JAL-3171 regression: Overwriting a dataset reference for an alignment"
5422 + " - CDS/Protein crossreference data may be lost");
5423 if (xtant_ds != null)
5425 // This can only happen if the unique sequence set ID was bound to a
5426 // dataset that did not contain any of the sequences in the view
5427 // currently being restored.
5428 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.");
5432 addDatasetRef(vamsasSet.getDatasetId(), ds);
5437 // try even harder to restore dataset
5438 AlignmentI xtantDS = checkIfHasDataset(vamsasSet.getSequence());
5439 // create a list of new dataset sequences
5440 dseqs = new Vector();
5442 for (int i = 0, iSize = vamsasSet.getSequence().size(); i < iSize; i++)
5444 Sequence vamsasSeq = vamsasSet.getSequence().get(i);
5445 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
5447 // create a new dataset
5450 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
5451 dseqs.copyInto(dsseqs);
5452 ds = new jalview.datamodel.Alignment(dsseqs);
5453 debug("Created new dataset " + vamsasSet.getDatasetId()
5454 + " for alignment " + System.identityHashCode(al));
5455 addDatasetRef(vamsasSet.getDatasetId(), ds);
5457 // set the dataset for the newly imported alignment.
5458 if (al.getDataset() == null && !ignoreUnrefed)
5461 // register dataset for the alignment's uniqueSeqSetId for legacy projects
5462 addDatasetRef(UNIQSEQSETID + uniqueSeqSetId, ds);
5464 updateSeqDatasetBinding(vamsasSet.getSequence(), ds);
5468 * XML dataset sequence ID to materialised dataset reference
5470 HashMap<String, AlignmentI> seqToDataset = new HashMap<>();
5473 * @return the first materialised dataset reference containing a dataset
5474 * sequence referenced in the given view
5476 * - sequences from the view
5478 AlignmentI checkIfHasDataset(List<Sequence> list)
5480 for (Sequence restoredSeq : list)
5482 AlignmentI datasetFor = seqToDataset.get(restoredSeq.getDsseqid());
5483 if (datasetFor != null)
5492 * Register ds as the containing dataset for the dataset sequences referenced
5493 * by sequences in list
5496 * - sequences in a view
5499 void updateSeqDatasetBinding(List<Sequence> list, AlignmentI ds)
5501 for (Sequence restoredSeq : list)
5503 AlignmentI prevDS = seqToDataset.put(restoredSeq.getDsseqid(), ds);
5504 if (prevDS != null && prevDS != ds)
5506 warn("Dataset sequence appears in many datasets: "
5507 + restoredSeq.getDsseqid());
5508 // TODO: try to merge!
5515 * sequence definition to create/merge dataset sequence for
5519 * vector to add new dataset sequence to
5520 * @param ignoreUnrefed
5521 * - when true, don't create new sequences from vamsasSeq if it's id
5522 * doesn't already have an asssociated Jalview sequence.
5524 * - used to reorder the sequence in the alignment according to the
5525 * vamsasSeq array ordering, to preserve ordering of dataset
5527 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
5528 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed, int vseqpos)
5530 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
5532 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
5533 boolean reorder = false;
5534 SequenceI dsq = null;
5535 if (sq != null && sq.getDatasetSequence() != null)
5537 dsq = sq.getDatasetSequence();
5543 if (sq == null && ignoreUnrefed)
5547 String sqid = vamsasSeq.getDsseqid();
5550 // need to create or add a new dataset sequence reference to this sequence
5553 dsq = seqRefIds.get(sqid);
5558 // make a new dataset sequence
5559 dsq = sq.createDatasetSequence();
5562 // make up a new dataset reference for this sequence
5563 sqid = seqHash(dsq);
5565 dsq.setVamsasId(uniqueSetSuffix + sqid);
5566 seqRefIds.put(sqid, dsq);
5571 dseqs.addElement(dsq);
5576 ds.addSequence(dsq);
5582 { // make this dataset sequence sq's dataset sequence
5583 sq.setDatasetSequence(dsq);
5584 // and update the current dataset alignment
5589 if (!dseqs.contains(dsq))
5596 if (ds.findIndex(dsq) < 0)
5598 ds.addSequence(dsq);
5605 // TODO: refactor this as a merge dataset sequence function
5606 // now check that sq (the dataset sequence) sequence really is the union of
5607 // all references to it
5608 // boolean pre = sq.getStart() < dsq.getStart();
5609 // boolean post = sq.getEnd() > dsq.getEnd();
5613 // StringBuffer sb = new StringBuffer();
5614 String newres = jalview.analysis.AlignSeq.extractGaps(
5615 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
5616 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
5617 && newres.length() > dsq.getLength())
5619 // Update with the longer sequence.
5623 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
5624 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
5625 * sb.append(newres.substring(newres.length() - sq.getEnd() -
5626 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
5628 dsq.setSequence(newres);
5630 // TODO: merges will never happen if we 'know' we have the real dataset
5631 // sequence - this should be detected when id==dssid
5633 "DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
5634 // + (pre ? "prepended" : "") + " "
5635 // + (post ? "appended" : ""));
5640 // sequence refs are identical. We may need to update the existing dataset
5641 // alignment with this one, though.
5642 if (ds != null && dseqs == null)
5644 int opos = ds.findIndex(dsq);
5645 SequenceI tseq = null;
5646 if (opos != -1 && vseqpos != opos)
5648 // remove from old position
5649 ds.deleteSequence(dsq);
5651 if (vseqpos < ds.getHeight())
5653 if (vseqpos != opos)
5655 // save sequence at destination position
5656 tseq = ds.getSequenceAt(vseqpos);
5657 ds.replaceSequenceAt(vseqpos, dsq);
5658 ds.addSequence(tseq);
5663 ds.addSequence(dsq);
5670 * TODO use AlignmentI here and in related methods - needs
5671 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
5673 Hashtable<String, AlignmentI> datasetIds = null;
5675 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
5677 private AlignmentI getDatasetFor(String datasetId)
5679 if (datasetIds == null)
5681 datasetIds = new Hashtable<>();
5684 if (datasetIds.containsKey(datasetId))
5686 return datasetIds.get(datasetId);
5691 private void addDatasetRef(String datasetId, AlignmentI dataset)
5693 if (datasetIds == null)
5695 datasetIds = new Hashtable<>();
5697 datasetIds.put(datasetId, dataset);
5701 * make a new dataset ID for this jalview dataset alignment
5706 private String getDatasetIdRef(AlignmentI dataset)
5708 if (dataset.getDataset() != null)
5710 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
5712 String datasetId = makeHashCode(dataset, null);
5713 if (datasetId == null)
5715 // make a new datasetId and record it
5716 if (dataset2Ids == null)
5718 dataset2Ids = new IdentityHashMap<>();
5722 datasetId = dataset2Ids.get(dataset);
5724 if (datasetId == null)
5726 datasetId = "ds" + dataset2Ids.size() + 1;
5727 dataset2Ids.put(dataset, datasetId);
5733 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5735 for (int d = 0; d < sequence.getDBRef().size(); d++)
5737 DBRef dr = sequence.getDBRef().get(d);
5738 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
5739 dr.getSource(), dr.getVersion(), dr.getAccessionId());
5740 if (dr.getMapping() != null)
5742 entry.setMap(addMapping(dr.getMapping()));
5744 datasetSequence.addDBRef(entry);
5748 private jalview.datamodel.Mapping addMapping(Mapping m)
5750 SequenceI dsto = null;
5751 // Mapping m = dr.getMapping();
5752 int fr[] = new int[m.getMapListFrom().size() * 2];
5753 Iterator<MapListFrom> from = m.getMapListFrom().iterator();// enumerateMapListFrom();
5754 for (int _i = 0; from.hasNext(); _i += 2)
5756 MapListFrom mf = from.next();
5757 fr[_i] = mf.getStart();
5758 fr[_i + 1] = mf.getEnd();
5760 int fto[] = new int[m.getMapListTo().size() * 2];
5761 Iterator<MapListTo> to = m.getMapListTo().iterator();// enumerateMapListTo();
5762 for (int _i = 0; to.hasNext(); _i += 2)
5764 MapListTo mf = to.next();
5765 fto[_i] = mf.getStart();
5766 fto[_i + 1] = mf.getEnd();
5768 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto, fr,
5769 fto, m.getMapFromUnit().intValue(),
5770 m.getMapToUnit().intValue());
5773 * (optional) choice of dseqFor or Sequence
5775 if (m.getDseqFor() != null)
5777 String dsfor = m.getDseqFor();
5778 if (seqRefIds.containsKey(dsfor))
5783 jmap.setTo(seqRefIds.get(dsfor));
5787 frefedSequence.add(newMappingRef(dsfor, jmap));
5790 else if (m.getSequence() != null)
5793 * local sequence definition
5795 Sequence ms = m.getSequence();
5796 SequenceI djs = null;
5797 String sqid = ms.getDsseqid();
5798 if (sqid != null && sqid.length() > 0)
5801 * recover dataset sequence
5803 djs = seqRefIds.get(sqid);
5808 "Warning - making up dataset sequence id for DbRef sequence map reference");
5809 sqid = ((Object) ms).toString(); // make up a new hascode for
5810 // undefined dataset sequence hash
5811 // (unlikely to happen)
5817 * make a new dataset sequence and add it to refIds hash
5819 djs = new jalview.datamodel.Sequence(ms.getName(),
5821 djs.setStart(jmap.getMap().getToLowest());
5822 djs.setEnd(jmap.getMap().getToHighest());
5823 djs.setVamsasId(uniqueSetSuffix + sqid);
5825 incompleteSeqs.put(sqid, djs);
5826 seqRefIds.put(sqid, djs);
5829 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5838 * Provides a 'copy' of an alignment view (on action New View) by 'saving' the
5839 * view as XML (but not to file), and then reloading it
5844 public AlignmentPanel copyAlignPanel(AlignmentPanel ap)
5847 JalviewModel jm = saveState(ap, null, null, null);
5850 jm.getVamsasModel().getSequenceSet().get(0).getDatasetId(),
5851 ap.getAlignment().getDataset());
5853 uniqueSetSuffix = "";
5854 // jm.getJalviewModelSequence().getViewport(0).setId(null);
5855 jm.getViewport().get(0).setId(null);
5856 // we don't overwrite the view we just copied
5858 if (this.frefedSequence == null)
5860 frefedSequence = new Vector<>();
5863 viewportsAdded.clear();
5865 AlignFrame af = loadFromObject(jm, null, false, null);
5866 af.getAlignPanels().clear();
5867 af.closeMenuItem_actionPerformed(true);
5870 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5871 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5872 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5873 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5874 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5877 return af.alignPanel;
5880 private Hashtable jvids2vobj;
5882 private void warn(String msg)
5887 private void warn(String msg, Exception e)
5889 if (Cache.log != null)
5893 Cache.log.warn(msg, e);
5897 Cache.log.warn(msg);
5902 System.err.println("Warning: " + msg);
5905 e.printStackTrace();
5910 private void debug(String string)
5912 debug(string, null);
5915 private void debug(String msg, Exception e)
5917 if (Cache.log != null)
5921 Cache.log.debug(msg, e);
5925 Cache.log.debug(msg);
5930 System.err.println("Warning: " + msg);
5933 e.printStackTrace();
5939 * set the object to ID mapping tables used to write/recover objects and XML
5940 * ID strings for the jalview project. If external tables are provided then
5941 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
5942 * object goes out of scope. - also populates the datasetIds hashtable with
5943 * alignment objects containing dataset sequences
5946 * Map from ID strings to jalview datamodel
5948 * Map from jalview datamodel to ID strings
5952 public void setObjectMappingTables(Hashtable vobj2jv,
5953 IdentityHashMap jv2vobj)
5955 this.jv2vobj = jv2vobj;
5956 this.vobj2jv = vobj2jv;
5957 Iterator ds = jv2vobj.keySet().iterator();
5959 while (ds.hasNext())
5961 Object jvobj = ds.next();
5962 id = jv2vobj.get(jvobj).toString();
5963 if (jvobj instanceof jalview.datamodel.Alignment)
5965 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
5967 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
5970 else if (jvobj instanceof jalview.datamodel.Sequence)
5972 // register sequence object so the XML parser can recover it.
5973 if (seqRefIds == null)
5975 seqRefIds = new HashMap<>();
5977 if (seqsToIds == null)
5979 seqsToIds = new IdentityHashMap<>();
5981 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
5982 seqsToIds.put((SequenceI) jvobj, id);
5984 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
5987 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
5988 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
5989 if (jvann.annotationId == null)
5991 jvann.annotationId = anid;
5993 if (!jvann.annotationId.equals(anid))
5995 // TODO verify that this is the correct behaviour
5996 this.warn("Overriding Annotation ID for " + anid
5997 + " from different id : " + jvann.annotationId);
5998 jvann.annotationId = anid;
6001 else if (jvobj instanceof String)
6003 if (jvids2vobj == null)
6005 jvids2vobj = new Hashtable();
6006 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
6011 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
6017 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
6018 * objects created from the project archive. If string is null (default for
6019 * construction) then suffix will be set automatically.
6023 public void setUniqueSetSuffix(String string)
6025 uniqueSetSuffix = string;
6030 * uses skipList2 as the skipList for skipping views on sequence sets
6031 * associated with keys in the skipList
6035 public void setSkipList(Hashtable skipList2)
6037 skipList = skipList2;
6041 * Reads the jar entry of given name and returns its contents, or null if the
6042 * entry is not found.
6045 * @param jarEntryName
6048 protected String readJarEntry(jarInputStreamProvider jprovider,
6049 String jarEntryName)
6051 String result = null;
6052 BufferedReader in = null;
6057 * Reopen the jar input stream and traverse its entries to find a matching
6060 JarInputStream jin = jprovider.getJarInputStream();
6061 JarEntry entry = null;
6064 entry = jin.getNextJarEntry();
6065 } while (entry != null && !entry.getName().equals(jarEntryName));
6069 StringBuilder out = new StringBuilder(256);
6070 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
6073 while ((data = in.readLine()) != null)
6077 result = out.toString();
6081 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
6083 } catch (Exception ex)
6085 ex.printStackTrace();
6093 } catch (IOException e)
6104 * Returns an incrementing counter (0, 1, 2...)
6108 private synchronized int nextCounter()
6114 * Loads any saved PCA viewers
6119 protected void loadPCAViewers(JalviewModel model, AlignmentPanel ap)
6123 List<PcaViewer> pcaviewers = model.getPcaViewer();
6124 for (PcaViewer viewer : pcaviewers)
6126 String modelName = viewer.getScoreModelName();
6127 SimilarityParamsI params = new SimilarityParams(
6128 viewer.isIncludeGappedColumns(), viewer.isMatchGaps(),
6129 viewer.isIncludeGaps(),
6130 viewer.isDenominateByShortestLength());
6133 * create the panel (without computing the PCA)
6135 PCAPanel panel = new PCAPanel(ap, modelName, params);
6137 panel.setTitle(viewer.getTitle());
6138 panel.setBounds(new Rectangle(viewer.getXpos(), viewer.getYpos(),
6139 viewer.getWidth(), viewer.getHeight()));
6141 boolean showLabels = viewer.isShowLabels();
6142 panel.setShowLabels(showLabels);
6143 panel.getRotatableCanvas().setShowLabels(showLabels);
6144 panel.getRotatableCanvas()
6145 .setBgColour(new Color(viewer.getBgColour()));
6146 panel.getRotatableCanvas()
6147 .setApplyToAllViews(viewer.isLinkToAllViews());
6150 * load PCA output data
6152 ScoreModelI scoreModel = ScoreModels.getInstance()
6153 .getScoreModel(modelName, ap);
6154 PCA pca = new PCA(null, scoreModel, params);
6155 PcaDataType pcaData = viewer.getPcaData();
6157 MatrixI pairwise = loadDoubleMatrix(pcaData.getPairwiseMatrix());
6158 pca.setPairwiseScores(pairwise);
6160 MatrixI triDiag = loadDoubleMatrix(pcaData.getTridiagonalMatrix());
6161 pca.setTridiagonal(triDiag);
6163 MatrixI result = loadDoubleMatrix(pcaData.getEigenMatrix());
6164 pca.setEigenmatrix(result);
6166 panel.getPcaModel().setPCA(pca);
6169 * we haven't saved the input data! (JAL-2647 to do)
6171 panel.setInputData(null);
6174 * add the sequence points for the PCA display
6176 List<jalview.datamodel.SequencePoint> seqPoints = new ArrayList<>();
6177 for (SequencePoint sp : viewer.getSequencePoint())
6179 String seqId = sp.getSequenceRef();
6180 SequenceI seq = seqRefIds.get(seqId);
6183 throw new IllegalStateException(
6184 "Unmatched seqref for PCA: " + seqId);
6186 Point pt = new Point(sp.getXPos(), sp.getYPos(), sp.getZPos());
6187 jalview.datamodel.SequencePoint seqPoint = new jalview.datamodel.SequencePoint(
6189 seqPoints.add(seqPoint);
6191 panel.getRotatableCanvas().setPoints(seqPoints, seqPoints.size());
6194 * set min-max ranges and scale after setPoints (which recomputes them)
6196 panel.getRotatableCanvas().setScaleFactor(viewer.getScaleFactor());
6197 SeqPointMin spMin = viewer.getSeqPointMin();
6198 float[] min = new float[] { spMin.getXPos(), spMin.getYPos(),
6200 SeqPointMax spMax = viewer.getSeqPointMax();
6201 float[] max = new float[] { spMax.getXPos(), spMax.getYPos(),
6203 panel.getRotatableCanvas().setSeqMinMax(min, max);
6205 // todo: hold points list in PCAModel only
6206 panel.getPcaModel().setSequencePoints(seqPoints);
6208 panel.setSelectedDimensionIndex(viewer.getXDim(), X);
6209 panel.setSelectedDimensionIndex(viewer.getYDim(), Y);
6210 panel.setSelectedDimensionIndex(viewer.getZDim(), Z);
6212 // is this duplication needed?
6213 panel.setTop(seqPoints.size() - 1);
6214 panel.getPcaModel().setTop(seqPoints.size() - 1);
6217 * add the axes' end points for the display
6219 for (int i = 0; i < 3; i++)
6221 Axis axis = viewer.getAxis().get(i);
6222 panel.getRotatableCanvas().getAxisEndPoints()[i] = new Point(
6223 axis.getXPos(), axis.getYPos(), axis.getZPos());
6226 Desktop.addInternalFrame(panel, MessageManager.formatMessage(
6227 "label.calc_title", "PCA", modelName), 475, 450);
6229 } catch (Exception ex)
6231 Cache.log.error("Error loading PCA: " + ex.toString());
6236 * Populates an XML model of the feature colour scheme for one feature type
6238 * @param featureType
6242 public static Colour marshalColour(
6243 String featureType, FeatureColourI fcol)
6245 Colour col = new Colour();
6246 if (fcol.isSimpleColour())
6248 col.setRGB(Format.getHexString(fcol.getColour()));
6252 col.setRGB(Format.getHexString(fcol.getMaxColour()));
6253 col.setMin(fcol.getMin());
6254 col.setMax(fcol.getMax());
6255 col.setMinRGB(jalview.util.Format.getHexString(fcol.getMinColour()));
6256 col.setAutoScale(fcol.isAutoScaled());
6257 col.setThreshold(fcol.getThreshold());
6258 col.setColourByLabel(fcol.isColourByLabel());
6259 col.setThreshType(fcol.isAboveThreshold() ? ThresholdType.ABOVE
6260 : (fcol.isBelowThreshold() ? ThresholdType.BELOW
6261 : ThresholdType.NONE));
6262 if (fcol.isColourByAttribute())
6264 final String[] attName = fcol.getAttributeName();
6265 col.getAttributeName().add(attName[0]);
6266 if (attName.length > 1)
6268 col.getAttributeName().add(attName[1]);
6271 Color noColour = fcol.getNoColour();
6272 if (noColour == null)
6274 col.setNoValueColour(NoValueColour.NONE);
6276 else if (noColour == fcol.getMaxColour())
6278 col.setNoValueColour(NoValueColour.MAX);
6282 col.setNoValueColour(NoValueColour.MIN);
6285 col.setName(featureType);
6290 * Populates an XML model of the feature filter(s) for one feature type
6292 * @param firstMatcher
6293 * the first (or only) match condition)
6295 * remaining match conditions (if any)
6297 * if true, conditions are and-ed, else or-ed
6299 public static jalview.xml.binding.jalview.FeatureMatcherSet marshalFilter(
6300 FeatureMatcherI firstMatcher, Iterator<FeatureMatcherI> filters,
6303 jalview.xml.binding.jalview.FeatureMatcherSet result = new jalview.xml.binding.jalview.FeatureMatcherSet();
6305 if (filters.hasNext())
6310 CompoundMatcher compound = new CompoundMatcher();
6311 compound.setAnd(and);
6312 jalview.xml.binding.jalview.FeatureMatcherSet matcher1 = marshalFilter(
6313 firstMatcher, Collections.emptyIterator(), and);
6314 // compound.addMatcherSet(matcher1);
6315 compound.getMatcherSet().add(matcher1);
6316 FeatureMatcherI nextMatcher = filters.next();
6317 jalview.xml.binding.jalview.FeatureMatcherSet matcher2 = marshalFilter(
6318 nextMatcher, filters, and);
6319 // compound.addMatcherSet(matcher2);
6320 compound.getMatcherSet().add(matcher2);
6321 result.setCompoundMatcher(compound);
6326 * single condition matcher
6328 // MatchCondition matcherModel = new MatchCondition();
6329 jalview.xml.binding.jalview.FeatureMatcher matcherModel = new jalview.xml.binding.jalview.FeatureMatcher();
6330 matcherModel.setCondition(
6331 firstMatcher.getMatcher().getCondition().getStableName());
6332 matcherModel.setValue(firstMatcher.getMatcher().getPattern());
6333 if (firstMatcher.isByAttribute())
6335 matcherModel.setBy(FilterBy.BY_ATTRIBUTE);
6336 // matcherModel.setAttributeName(firstMatcher.getAttribute());
6337 String[] attName = firstMatcher.getAttribute();
6338 matcherModel.getAttributeName().add(attName[0]); // attribute
6339 if (attName.length > 1)
6341 matcherModel.getAttributeName().add(attName[1]); // sub-attribute
6344 else if (firstMatcher.isByLabel())
6346 matcherModel.setBy(FilterBy.BY_LABEL);
6348 else if (firstMatcher.isByScore())
6350 matcherModel.setBy(FilterBy.BY_SCORE);
6352 result.setMatchCondition(matcherModel);
6359 * Loads one XML model of a feature filter to a Jalview object
6361 * @param featureType
6362 * @param matcherSetModel
6365 public static FeatureMatcherSetI parseFilter(
6367 jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel)
6369 FeatureMatcherSetI result = new FeatureMatcherSet();
6372 parseFilterConditions(result, matcherSetModel, true);
6373 } catch (IllegalStateException e)
6375 // mixing AND and OR conditions perhaps
6377 String.format("Error reading filter conditions for '%s': %s",
6378 featureType, e.getMessage()));
6379 // return as much as was parsed up to the error
6386 * Adds feature match conditions to matcherSet as unmarshalled from XML
6387 * (possibly recursively for compound conditions)
6390 * @param matcherSetModel
6392 * if true, multiple conditions are AND-ed, else they are OR-ed
6393 * @throws IllegalStateException
6394 * if AND and OR conditions are mixed
6396 protected static void parseFilterConditions(
6397 FeatureMatcherSetI matcherSet,
6398 jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel,
6401 jalview.xml.binding.jalview.FeatureMatcher mc = matcherSetModel
6402 .getMatchCondition();
6408 FilterBy filterBy = mc.getBy();
6409 Condition cond = Condition.fromString(mc.getCondition());
6410 String pattern = mc.getValue();
6411 FeatureMatcherI matchCondition = null;
6412 if (filterBy == FilterBy.BY_LABEL)
6414 matchCondition = FeatureMatcher.byLabel(cond, pattern);
6416 else if (filterBy == FilterBy.BY_SCORE)
6418 matchCondition = FeatureMatcher.byScore(cond, pattern);
6421 else if (filterBy == FilterBy.BY_ATTRIBUTE)
6423 final List<String> attributeName = mc.getAttributeName();
6424 String[] attNames = attributeName
6425 .toArray(new String[attributeName.size()]);
6426 matchCondition = FeatureMatcher.byAttribute(cond, pattern,
6431 * note this throws IllegalStateException if AND-ing to a
6432 * previously OR-ed compound condition, or vice versa
6436 matcherSet.and(matchCondition);
6440 matcherSet.or(matchCondition);
6446 * compound condition
6448 List<jalview.xml.binding.jalview.FeatureMatcherSet> matchers = matcherSetModel
6449 .getCompoundMatcher().getMatcherSet();
6450 boolean anded = matcherSetModel.getCompoundMatcher().isAnd();
6451 if (matchers.size() == 2)
6453 parseFilterConditions(matcherSet, matchers.get(0), anded);
6454 parseFilterConditions(matcherSet, matchers.get(1), anded);
6458 System.err.println("Malformed compound filter condition");
6464 * Loads one XML model of a feature colour to a Jalview object
6466 * @param colourModel
6469 public static FeatureColourI parseColour(Colour colourModel)
6471 FeatureColourI colour = null;
6473 if (colourModel.getMax() != null)
6475 Color mincol = null;
6476 Color maxcol = null;
6477 Color noValueColour = null;
6481 mincol = new Color(Integer.parseInt(colourModel.getMinRGB(), 16));
6482 maxcol = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6483 } catch (Exception e)
6485 Cache.log.warn("Couldn't parse out graduated feature color.", e);
6488 NoValueColour noCol = colourModel.getNoValueColour();
6489 if (noCol == NoValueColour.MIN)
6491 noValueColour = mincol;
6493 else if (noCol == NoValueColour.MAX)
6495 noValueColour = maxcol;
6498 colour = new FeatureColour(maxcol, mincol, maxcol, noValueColour,
6499 safeFloat(colourModel.getMin()),
6500 safeFloat(colourModel.getMax()));
6501 final List<String> attributeName = colourModel.getAttributeName();
6502 String[] attributes = attributeName
6503 .toArray(new String[attributeName.size()]);
6504 if (attributes != null && attributes.length > 0)
6506 colour.setAttributeName(attributes);
6508 if (colourModel.isAutoScale() != null)
6510 colour.setAutoScaled(colourModel.isAutoScale().booleanValue());
6512 if (colourModel.isColourByLabel() != null)
6514 colour.setColourByLabel(
6515 colourModel.isColourByLabel().booleanValue());
6517 if (colourModel.getThreshold() != null)
6519 colour.setThreshold(colourModel.getThreshold().floatValue());
6521 ThresholdType ttyp = colourModel.getThreshType();
6522 if (ttyp == ThresholdType.ABOVE)
6524 colour.setAboveThreshold(true);
6526 else if (ttyp == ThresholdType.BELOW)
6528 colour.setBelowThreshold(true);
6533 Color color = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6534 colour = new FeatureColour(color);