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.SequenceAnnotationOrder;
28 import jalview.analysis.Conservation;
29 import jalview.analysis.PCA;
30 import jalview.analysis.scoremodels.ScoreModels;
31 import jalview.analysis.scoremodels.SimilarityParams;
32 import jalview.api.FeatureColourI;
33 import jalview.api.ViewStyleI;
34 import jalview.api.analysis.ScoreModelI;
35 import jalview.api.analysis.SimilarityParamsI;
36 import jalview.api.structures.JalviewStructureDisplayI;
37 import jalview.bin.Cache;
38 import jalview.datamodel.AlignedCodonFrame;
39 import jalview.datamodel.Alignment;
40 import jalview.datamodel.AlignmentAnnotation;
41 import jalview.datamodel.AlignmentI;
42 import jalview.datamodel.GraphLine;
43 import jalview.datamodel.PDBEntry;
44 import jalview.datamodel.Point;
45 import jalview.datamodel.RnaViewerModel;
46 import jalview.datamodel.SequenceFeature;
47 import jalview.datamodel.SequenceGroup;
48 import jalview.datamodel.SequenceI;
49 import jalview.datamodel.StructureViewerModel;
50 import jalview.datamodel.StructureViewerModel.StructureData;
51 import jalview.datamodel.features.FeatureMatcher;
52 import jalview.datamodel.features.FeatureMatcherI;
53 import jalview.datamodel.features.FeatureMatcherSet;
54 import jalview.datamodel.features.FeatureMatcherSetI;
55 import jalview.ext.varna.RnaModel;
56 import jalview.gui.AlignFrame;
57 import jalview.gui.AlignViewport;
58 import jalview.gui.AlignmentPanel;
59 import jalview.gui.AppVarna;
60 import jalview.gui.ChimeraViewFrame;
61 import jalview.gui.Desktop;
62 import jalview.gui.FeatureRenderer;
63 import jalview.gui.JvOptionPane;
64 import jalview.gui.OOMWarning;
65 import jalview.gui.PCAPanel;
66 import jalview.gui.PaintRefresher;
67 import jalview.gui.SplitFrame;
68 import jalview.gui.StructureViewer;
69 import jalview.gui.StructureViewer.ViewerType;
70 import jalview.gui.StructureViewerBase;
71 import jalview.gui.TreePanel;
72 import jalview.io.BackupFiles;
73 import jalview.io.DataSourceType;
74 import jalview.io.FileFormat;
75 import jalview.io.NewickFile;
76 import jalview.math.Matrix;
77 import jalview.math.MatrixI;
78 import jalview.renderer.ResidueShaderI;
79 import jalview.schemes.AnnotationColourGradient;
80 import jalview.schemes.ColourSchemeI;
81 import jalview.schemes.ColourSchemeProperty;
82 import jalview.schemes.FeatureColour;
83 import jalview.schemes.ResidueProperties;
84 import jalview.schemes.UserColourScheme;
85 import jalview.structure.StructureSelectionManager;
86 import jalview.structures.models.AAStructureBindingModel;
87 import jalview.util.Format;
88 import jalview.util.MessageManager;
89 import jalview.util.Platform;
90 import jalview.util.StringUtils;
91 import jalview.util.jarInputStreamProvider;
92 import jalview.util.matcher.Condition;
93 import jalview.viewmodel.AlignmentViewport;
94 import jalview.viewmodel.PCAModel;
95 import jalview.viewmodel.ViewportRanges;
96 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
97 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
98 import jalview.ws.jws2.Jws2Discoverer;
99 import jalview.ws.jws2.dm.AAConSettings;
100 import jalview.ws.jws2.jabaws2.Jws2Instance;
101 import jalview.ws.params.ArgumentI;
102 import jalview.ws.params.AutoCalcSetting;
103 import jalview.ws.params.WsParamSetI;
104 import jalview.xml.binding.jalview.AlcodonFrame;
105 import jalview.xml.binding.jalview.AlcodonFrame.AlcodMap;
106 import jalview.xml.binding.jalview.Annotation;
107 import jalview.xml.binding.jalview.Annotation.ThresholdLine;
108 import jalview.xml.binding.jalview.AnnotationColourScheme;
109 import jalview.xml.binding.jalview.AnnotationElement;
110 import jalview.xml.binding.jalview.DoubleMatrix;
111 import jalview.xml.binding.jalview.DoubleVector;
112 import jalview.xml.binding.jalview.Feature;
113 import jalview.xml.binding.jalview.Feature.OtherData;
114 import jalview.xml.binding.jalview.FeatureMatcherSet.CompoundMatcher;
115 import jalview.xml.binding.jalview.FilterBy;
116 import jalview.xml.binding.jalview.JalviewModel;
117 import jalview.xml.binding.jalview.JalviewModel.FeatureSettings;
118 import jalview.xml.binding.jalview.JalviewModel.FeatureSettings.Group;
119 import jalview.xml.binding.jalview.JalviewModel.FeatureSettings.Setting;
120 import jalview.xml.binding.jalview.JalviewModel.JGroup;
121 import jalview.xml.binding.jalview.JalviewModel.JSeq;
122 import jalview.xml.binding.jalview.JalviewModel.JSeq.Pdbids;
123 import jalview.xml.binding.jalview.JalviewModel.JSeq.Pdbids.StructureState;
124 import jalview.xml.binding.jalview.JalviewModel.JSeq.RnaViewer;
125 import jalview.xml.binding.jalview.JalviewModel.JSeq.RnaViewer.SecondaryStructure;
126 import jalview.xml.binding.jalview.JalviewModel.PcaViewer;
127 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.Axis;
128 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.SeqPointMax;
129 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.SeqPointMin;
130 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.SequencePoint;
131 import jalview.xml.binding.jalview.JalviewModel.Tree;
132 import jalview.xml.binding.jalview.JalviewModel.UserColours;
133 import jalview.xml.binding.jalview.JalviewModel.Viewport;
134 import jalview.xml.binding.jalview.JalviewModel.Viewport.CalcIdParam;
135 import jalview.xml.binding.jalview.JalviewModel.Viewport.HiddenColumns;
136 import jalview.xml.binding.jalview.JalviewUserColours;
137 import jalview.xml.binding.jalview.JalviewUserColours.Colour;
138 import jalview.xml.binding.jalview.MapListType.MapListFrom;
139 import jalview.xml.binding.jalview.MapListType.MapListTo;
140 import jalview.xml.binding.jalview.Mapping;
141 import jalview.xml.binding.jalview.NoValueColour;
142 import jalview.xml.binding.jalview.ObjectFactory;
143 import jalview.xml.binding.jalview.PcaDataType;
144 import jalview.xml.binding.jalview.Pdbentry.Property;
145 import jalview.xml.binding.jalview.Sequence;
146 import jalview.xml.binding.jalview.Sequence.DBRef;
147 import jalview.xml.binding.jalview.SequenceSet;
148 import jalview.xml.binding.jalview.SequenceSet.SequenceSetProperties;
149 import jalview.xml.binding.jalview.ThresholdType;
150 import jalview.xml.binding.jalview.VAMSAS;
152 import java.awt.Color;
153 import java.awt.Font;
154 import java.awt.Rectangle;
155 import java.io.BufferedReader;
156 import java.io.DataInputStream;
157 import java.io.DataOutputStream;
159 import java.io.FileInputStream;
160 import java.io.FileOutputStream;
161 import java.io.IOException;
162 import java.io.InputStreamReader;
163 import java.io.OutputStreamWriter;
164 import java.io.PrintWriter;
165 import java.lang.reflect.InvocationTargetException;
166 import java.math.BigInteger;
167 import java.net.MalformedURLException;
169 import java.util.ArrayList;
170 import java.util.Arrays;
171 import java.util.Collections;
172 import java.util.Enumeration;
173 import java.util.GregorianCalendar;
174 import java.util.HashMap;
175 import java.util.HashSet;
176 import java.util.Hashtable;
177 import java.util.IdentityHashMap;
178 import java.util.Iterator;
179 import java.util.LinkedHashMap;
180 import java.util.List;
181 import java.util.Map;
182 import java.util.Map.Entry;
183 import java.util.Set;
184 import java.util.Vector;
185 import java.util.jar.JarEntry;
186 import java.util.jar.JarInputStream;
187 import java.util.jar.JarOutputStream;
189 import javax.swing.JInternalFrame;
190 import javax.swing.SwingUtilities;
191 import javax.xml.bind.JAXBContext;
192 import javax.xml.bind.JAXBElement;
193 import javax.xml.bind.Marshaller;
194 import javax.xml.datatype.DatatypeConfigurationException;
195 import javax.xml.datatype.DatatypeFactory;
196 import javax.xml.datatype.XMLGregorianCalendar;
197 import javax.xml.stream.XMLInputFactory;
198 import javax.xml.stream.XMLStreamReader;
201 * Write out the current jalview desktop state as a Jalview XML stream.
203 * Note: the vamsas objects referred to here are primitive versions of the
204 * VAMSAS project schema elements - they are not the same and most likely never
208 * @version $Revision: 1.134 $
210 public class Jalview2XML
212 private static final String VIEWER_PREFIX = "viewer_";
214 private static final String RNA_PREFIX = "rna_";
216 private static final String UTF_8 = "UTF-8";
219 * prefix for recovering datasets for alignments with multiple views where
220 * non-existent dataset IDs were written for some views
222 private static final String UNIQSEQSETID = "uniqueSeqSetId.";
224 // use this with nextCounter() to make unique names for entities
225 private int counter = 0;
228 * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
229 * of sequence objects are created.
231 IdentityHashMap<SequenceI, String> seqsToIds = null;
234 * jalview XML Sequence ID to jalview sequence object reference (both dataset
235 * and alignment sequences. Populated as XML reps of sequence objects are
238 Map<String, SequenceI> seqRefIds = null;
240 Map<String, SequenceI> incompleteSeqs = null;
242 List<SeqFref> frefedSequence = null;
244 boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
247 * Map of reconstructed AlignFrame objects that appear to have come from
248 * SplitFrame objects (have a dna/protein complement view).
250 private Map<Viewport, AlignFrame> splitFrameCandidates = new HashMap<>();
253 * Map from displayed rna structure models to their saved session state jar
256 private Map<RnaModel, String> rnaSessions = new HashMap<>();
259 * A helper method for safely using the value of an optional attribute that
260 * may be null if not present in the XML. Answers the boolean value, or false
266 public static boolean safeBoolean(Boolean b)
268 return b == null ? false : b.booleanValue();
272 * A helper method for safely using the value of an optional attribute that
273 * may be null if not present in the XML. Answers the integer value, or zero
279 public static int safeInt(Integer i)
281 return i == null ? 0 : i.intValue();
285 * A helper method for safely using the value of an optional attribute that
286 * may be null if not present in the XML. Answers the float value, or zero if
292 public static float safeFloat(Float f)
294 return f == null ? 0f : f.floatValue();
298 * create/return unique hash string for sq
301 * @return new or existing unique string for sq
303 String seqHash(SequenceI sq)
305 if (seqsToIds == null)
309 if (seqsToIds.containsKey(sq))
311 return seqsToIds.get(sq);
315 // create sequential key
316 String key = "sq" + (seqsToIds.size() + 1);
317 key = makeHashCode(sq, key); // check we don't have an external reference
319 seqsToIds.put(sq, key);
326 if (seqsToIds == null)
328 seqsToIds = new IdentityHashMap<>();
330 if (seqRefIds == null)
332 seqRefIds = new HashMap<>();
334 if (incompleteSeqs == null)
336 incompleteSeqs = new HashMap<>();
338 if (frefedSequence == null)
340 frefedSequence = new ArrayList<>();
348 public Jalview2XML(boolean raiseGUI)
350 this.raiseGUI = raiseGUI;
354 * base class for resolving forward references to sequences by their ID
359 abstract class SeqFref
365 public SeqFref(String _sref, String type)
371 public String getSref()
376 public SequenceI getSrefSeq()
378 return seqRefIds.get(sref);
381 public boolean isResolvable()
383 return seqRefIds.get(sref) != null;
386 public SequenceI getSrefDatasetSeq()
388 SequenceI sq = seqRefIds.get(sref);
391 while (sq.getDatasetSequence() != null)
393 sq = sq.getDatasetSequence();
400 * @return true if the forward reference was fully resolved
402 abstract boolean resolve();
405 public String toString()
407 return type + " reference to " + sref;
412 * create forward reference for a mapping
418 public SeqFref newMappingRef(final String sref,
419 final jalview.datamodel.Mapping _jmap)
421 SeqFref fref = new SeqFref(sref, "Mapping")
423 public jalview.datamodel.Mapping jmap = _jmap;
428 SequenceI seq = getSrefDatasetSeq();
440 public SeqFref newAlcodMapRef(final String sref,
441 final AlignedCodonFrame _cf,
442 final jalview.datamodel.Mapping _jmap)
445 SeqFref fref = new SeqFref(sref, "Codon Frame")
447 AlignedCodonFrame cf = _cf;
449 public jalview.datamodel.Mapping mp = _jmap;
452 public boolean isResolvable()
454 return super.isResolvable() && mp.getTo() != null;
460 SequenceI seq = getSrefDatasetSeq();
465 cf.addMap(seq, mp.getTo(), mp.getMap());
472 public void resolveFrefedSequences()
474 Iterator<SeqFref> nextFref = frefedSequence.iterator();
475 int toresolve = frefedSequence.size();
476 int unresolved = 0, failedtoresolve = 0;
477 while (nextFref.hasNext())
479 SeqFref ref = nextFref.next();
480 if (ref.isResolvable())
492 } catch (Exception x)
495 "IMPLEMENTATION ERROR: Failed to resolve forward reference for sequence "
508 System.err.println("Jalview Project Import: There were " + unresolved
509 + " forward references left unresolved on the stack.");
511 if (failedtoresolve > 0)
513 System.err.println("SERIOUS! " + failedtoresolve
514 + " resolvable forward references failed to resolve.");
516 if (incompleteSeqs != null && incompleteSeqs.size() > 0)
519 "Jalview Project Import: There are " + incompleteSeqs.size()
520 + " sequences which may have incomplete metadata.");
521 if (incompleteSeqs.size() < 10)
523 for (SequenceI s : incompleteSeqs.values())
525 System.err.println(s.toString());
531 "Too many to report. Skipping output of incomplete sequences.");
537 * This maintains a map of viewports, the key being the seqSetId. Important to
538 * set historyItem and redoList for multiple views
540 Map<String, AlignViewport> viewportsAdded = new HashMap<>();
542 Map<String, AlignmentAnnotation> annotationIds = new HashMap<>();
544 String uniqueSetSuffix = "";
547 * List of pdbfiles added to Jar
549 List<String> pdbfiles = null;
551 // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
552 public void saveState(File statefile)
554 FileOutputStream fos = null;
559 fos = new FileOutputStream(statefile);
561 JarOutputStream jout = new JarOutputStream(fos);
565 } catch (Exception e)
567 Cache.log.error("Couln't write Jalview state to " + statefile, e);
568 // TODO: inform user of the problem - they need to know if their data was
570 if (errorMessage == null)
572 errorMessage = "Did't write Jalview Archive to output file '"
573 + statefile + "' - See console error log for details";
577 errorMessage += "(Didn't write Jalview Archive to output file '"
588 } catch (IOException e)
598 * Writes a jalview project archive to the given Jar output stream.
602 public void saveState(JarOutputStream jout)
604 AlignFrame[] frames = Desktop.getAlignFrames();
610 saveAllFrames(Arrays.asList(frames), jout);
614 * core method for storing state for a set of AlignFrames.
617 * - frames involving all data to be exported (including containing
620 * - project output stream
622 private void saveAllFrames(List<AlignFrame> frames, JarOutputStream jout)
624 Hashtable<String, AlignFrame> dsses = new Hashtable<>();
627 * ensure cached data is clear before starting
629 // todo tidy up seqRefIds, seqsToIds initialisation / reset
631 splitFrameCandidates.clear();
636 // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
637 // //////////////////////////////////////////////////
639 List<String> shortNames = new ArrayList<>();
640 List<String> viewIds = new ArrayList<>();
643 for (int i = frames.size() - 1; i > -1; i--)
645 AlignFrame af = frames.get(i);
647 if (skipList != null && skipList
648 .containsKey(af.getViewport().getSequenceSetId()))
653 String shortName = makeFilename(af, shortNames);
655 int apSize = af.getAlignPanels().size();
657 for (int ap = 0; ap < apSize; ap++)
659 AlignmentPanel apanel = (AlignmentPanel) af.getAlignPanels()
661 String fileName = apSize == 1 ? shortName : ap + shortName;
662 if (!fileName.endsWith(".xml"))
664 fileName = fileName + ".xml";
667 saveState(apanel, fileName, jout, viewIds);
669 String dssid = getDatasetIdRef(
670 af.getViewport().getAlignment().getDataset());
671 if (!dsses.containsKey(dssid))
673 dsses.put(dssid, af);
678 writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix,
684 } catch (Exception foo)
689 } catch (Exception ex)
691 // TODO: inform user of the problem - they need to know if their data was
693 if (errorMessage == null)
695 errorMessage = "Couldn't write Jalview Archive - see error output for details";
697 ex.printStackTrace();
702 * Generates a distinct file name, based on the title of the AlignFrame, by
703 * appending _n for increasing n until an unused name is generated. The new
704 * name (without its extension) is added to the list.
708 * @return the generated name, with .xml extension
710 protected String makeFilename(AlignFrame af, List<String> namesUsed)
712 String shortName = af.getTitle();
714 if (shortName.indexOf(File.separatorChar) > -1)
716 shortName = shortName
717 .substring(shortName.lastIndexOf(File.separatorChar) + 1);
722 while (namesUsed.contains(shortName))
724 if (shortName.endsWith("_" + (count - 1)))
726 shortName = shortName.substring(0, shortName.lastIndexOf("_"));
729 shortName = shortName.concat("_" + count);
733 namesUsed.add(shortName);
735 if (!shortName.endsWith(".xml"))
737 shortName = shortName + ".xml";
742 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
743 public boolean saveAlignment(AlignFrame af, String jarFile,
748 // create backupfiles object and get new temp filename destination
749 BackupFiles backupfiles = new BackupFiles(jarFile);
750 FileOutputStream fos = new FileOutputStream(
751 backupfiles.getTempFilePath());
753 JarOutputStream jout = new JarOutputStream(fos);
754 List<AlignFrame> frames = new ArrayList<>();
756 // resolve splitframes
757 if (af.getViewport().getCodingComplement() != null)
759 frames = ((SplitFrame) af.getSplitViewContainer()).getAlignFrames();
765 saveAllFrames(frames, jout);
769 } catch (Exception foo)
774 boolean success = true;
776 backupfiles.setWriteSuccess(success);
777 success = backupfiles.rollBackupsAndRenameTempFile();
780 } catch (Exception ex)
782 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
783 ex.printStackTrace();
788 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
789 String fileName, JarOutputStream jout)
792 for (String dssids : dsses.keySet())
794 AlignFrame _af = dsses.get(dssids);
795 String jfileName = fileName + " Dataset for " + _af.getTitle();
796 if (!jfileName.endsWith(".xml"))
798 jfileName = jfileName + ".xml";
800 saveState(_af.alignPanel, jfileName, true, jout, null);
805 * create a JalviewModel from an alignment view and marshall it to a
809 * panel to create jalview model for
811 * name of alignment panel written to output stream
818 public JalviewModel saveState(AlignmentPanel ap, String fileName,
819 JarOutputStream jout, List<String> viewIds)
821 return saveState(ap, fileName, false, jout, viewIds);
825 * create a JalviewModel from an alignment view and marshall it to a
829 * panel to create jalview model for
831 * name of alignment panel written to output stream
833 * when true, only write the dataset for the alignment, not the data
834 * associated with the view.
840 public JalviewModel saveState(AlignmentPanel ap, String fileName,
841 boolean storeDS, JarOutputStream jout, List<String> viewIds)
845 viewIds = new ArrayList<>();
850 List<UserColourScheme> userColours = new ArrayList<>();
852 AlignViewport av = ap.av;
853 ViewportRanges vpRanges = av.getRanges();
855 final ObjectFactory objectFactory = new ObjectFactory();
856 JalviewModel object = objectFactory.createJalviewModel();
857 object.setVamsasModel(new VAMSAS());
859 // object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
862 GregorianCalendar c = new GregorianCalendar();
863 DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
864 XMLGregorianCalendar now = datatypeFactory.newXMLGregorianCalendar(c);// gregorianCalendar);
865 object.setCreationDate(now);
866 } catch (DatatypeConfigurationException e)
868 System.err.println("error writing date: " + e.toString());
871 jalview.bin.Cache.getDefault("VERSION", "Development Build"));
874 * rjal is full height alignment, jal is actual alignment with full metadata
875 * but excludes hidden sequences.
877 jalview.datamodel.AlignmentI rjal = av.getAlignment(), jal = rjal;
879 if (av.hasHiddenRows())
881 rjal = jal.getHiddenSequences().getFullAlignment();
884 SequenceSet vamsasSet = new SequenceSet();
886 // JalviewModelSequence jms = new JalviewModelSequence();
888 vamsasSet.setGapChar(jal.getGapCharacter() + "");
890 if (jal.getDataset() != null)
892 // dataset id is the dataset's hashcode
893 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
896 // switch jal and the dataset
897 jal = jal.getDataset();
901 if (jal.getProperties() != null)
903 Enumeration en = jal.getProperties().keys();
904 while (en.hasMoreElements())
906 String key = en.nextElement().toString();
907 SequenceSetProperties ssp = new SequenceSetProperties();
909 ssp.setValue(jal.getProperties().get(key).toString());
910 // vamsasSet.addSequenceSetProperties(ssp);
911 vamsasSet.getSequenceSetProperties().add(ssp);
916 Set<String> calcIdSet = new HashSet<>();
917 // record the set of vamsas sequence XML POJO we create.
918 HashMap<String, Sequence> vamsasSetIds = new HashMap<>();
920 for (final SequenceI jds : rjal.getSequences())
922 final SequenceI jdatasq = jds.getDatasetSequence() == null ? jds
923 : jds.getDatasetSequence();
924 String id = seqHash(jds);
925 if (vamsasSetIds.get(id) == null)
927 if (seqRefIds.get(id) != null && !storeDS)
929 // This happens for two reasons: 1. multiple views are being
931 // 2. the hashCode has collided with another sequence's code. This
933 // HAPPEN! (PF00072.15.stk does this)
934 // JBPNote: Uncomment to debug writing out of files that do not read
935 // back in due to ArrayOutOfBoundExceptions.
936 // System.err.println("vamsasSeq backref: "+id+"");
937 // System.err.println(jds.getName()+"
938 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
939 // System.err.println("Hashcode: "+seqHash(jds));
940 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
941 // System.err.println(rsq.getName()+"
942 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
943 // System.err.println("Hashcode: "+seqHash(rsq));
947 vamsasSeq = createVamsasSequence(id, jds);
948 // vamsasSet.addSequence(vamsasSeq);
949 vamsasSet.getSequence().add(vamsasSeq);
950 vamsasSetIds.put(id, vamsasSeq);
951 seqRefIds.put(id, jds);
955 jseq.setStart(jds.getStart());
956 jseq.setEnd(jds.getEnd());
957 jseq.setColour(av.getSequenceColour(jds).getRGB());
959 jseq.setId(id); // jseq id should be a string not a number
962 // Store any sequences this sequence represents
963 if (av.hasHiddenRows())
965 // use rjal, contains the full height alignment
967 av.getAlignment().getHiddenSequences().isHidden(jds));
969 if (av.isHiddenRepSequence(jds))
971 jalview.datamodel.SequenceI[] reps = av
972 .getRepresentedSequences(jds).getSequencesInOrder(rjal);
974 for (int h = 0; h < reps.length; h++)
978 // jseq.addHiddenSequences(rjal.findIndex(reps[h]));
979 jseq.getHiddenSequences().add(rjal.findIndex(reps[h]));
984 // mark sequence as reference - if it is the reference for this view
987 jseq.setViewreference(jds == jal.getSeqrep());
991 // TODO: omit sequence features from each alignment view's XML dump if we
992 // are storing dataset
993 List<SequenceFeature> sfs = jds.getSequenceFeatures();
994 for (SequenceFeature sf : sfs)
996 // Features features = new Features();
997 Feature features = new Feature();
999 features.setBegin(sf.getBegin());
1000 features.setEnd(sf.getEnd());
1001 features.setDescription(sf.getDescription());
1002 features.setType(sf.getType());
1003 features.setFeatureGroup(sf.getFeatureGroup());
1004 features.setScore(sf.getScore());
1005 if (sf.links != null)
1007 for (int l = 0; l < sf.links.size(); l++)
1009 OtherData keyValue = new OtherData();
1010 keyValue.setKey("LINK_" + l);
1011 keyValue.setValue(sf.links.elementAt(l).toString());
1012 // features.addOtherData(keyValue);
1013 features.getOtherData().add(keyValue);
1016 if (sf.otherDetails != null)
1019 * save feature attributes, which may be simple strings or
1020 * map valued (have sub-attributes)
1022 for (Entry<String, Object> entry : sf.otherDetails.entrySet())
1024 String key = entry.getKey();
1025 Object value = entry.getValue();
1026 if (value instanceof Map<?, ?>)
1028 for (Entry<String, Object> subAttribute : ((Map<String, Object>) value)
1031 OtherData otherData = new OtherData();
1032 otherData.setKey(key);
1033 otherData.setKey2(subAttribute.getKey());
1034 otherData.setValue(subAttribute.getValue().toString());
1035 // features.addOtherData(otherData);
1036 features.getOtherData().add(otherData);
1041 OtherData otherData = new OtherData();
1042 otherData.setKey(key);
1043 otherData.setValue(value.toString());
1044 // features.addOtherData(otherData);
1045 features.getOtherData().add(otherData);
1050 // jseq.addFeatures(features);
1051 jseq.getFeatures().add(features);
1054 if (jdatasq.getAllPDBEntries() != null)
1056 Enumeration<PDBEntry> en = jdatasq.getAllPDBEntries().elements();
1057 while (en.hasMoreElements())
1059 Pdbids pdb = new Pdbids();
1060 jalview.datamodel.PDBEntry entry = en.nextElement();
1062 String pdbId = entry.getId();
1064 pdb.setType(entry.getType());
1067 * Store any structure views associated with this sequence. This
1068 * section copes with duplicate entries in the project, so a dataset
1069 * only view *should* be coped with sensibly.
1071 // This must have been loaded, is it still visible?
1072 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1073 String matchedFile = null;
1074 for (int f = frames.length - 1; f > -1; f--)
1076 if (frames[f] instanceof StructureViewerBase)
1078 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
1079 matchedFile = saveStructureState(ap, jds, pdb, entry, viewIds,
1080 matchedFile, viewFrame);
1082 * Only store each structure viewer's state once in the project
1083 * jar. First time through only (storeDS==false)
1085 String viewId = viewFrame.getViewId();
1086 if (!storeDS && !viewIds.contains(viewId))
1088 viewIds.add(viewId);
1091 String viewerState = viewFrame.getStateInfo();
1092 writeJarEntry(jout, getViewerJarEntryName(viewId),
1093 viewerState.getBytes());
1094 } catch (IOException e)
1097 "Error saving viewer state: " + e.getMessage());
1103 if (matchedFile != null || entry.getFile() != null)
1105 if (entry.getFile() != null)
1108 matchedFile = entry.getFile();
1110 pdb.setFile(matchedFile); // entry.getFile());
1111 if (pdbfiles == null)
1113 pdbfiles = new ArrayList<>();
1116 if (!pdbfiles.contains(pdbId))
1118 pdbfiles.add(pdbId);
1119 copyFileToJar(jout, matchedFile, pdbId);
1123 Enumeration<String> props = entry.getProperties();
1124 if (props.hasMoreElements())
1126 // PdbentryItem item = new PdbentryItem();
1127 while (props.hasMoreElements())
1129 Property prop = new Property();
1130 String key = props.nextElement();
1132 prop.setValue(entry.getProperty(key).toString());
1133 // item.addProperty(prop);
1134 pdb.getProperty().add(prop);
1136 // pdb.addPdbentryItem(item);
1139 // jseq.addPdbids(pdb);
1140 jseq.getPdbids().add(pdb);
1144 saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
1146 // jms.addJSeq(jseq);
1147 object.getJSeq().add(jseq);
1150 if (!storeDS && av.hasHiddenRows())
1152 jal = av.getAlignment();
1156 if (storeDS && jal.getCodonFrames() != null)
1158 List<AlignedCodonFrame> jac = jal.getCodonFrames();
1159 for (AlignedCodonFrame acf : jac)
1161 AlcodonFrame alc = new AlcodonFrame();
1162 if (acf.getProtMappings() != null
1163 && acf.getProtMappings().length > 0)
1165 boolean hasMap = false;
1166 SequenceI[] dnas = acf.getdnaSeqs();
1167 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1168 for (int m = 0; m < pmaps.length; m++)
1170 AlcodMap alcmap = new AlcodMap();
1171 alcmap.setDnasq(seqHash(dnas[m]));
1173 createVamsasMapping(pmaps[m], dnas[m], null, false));
1174 // alc.addAlcodMap(alcmap);
1175 alc.getAlcodMap().add(alcmap);
1180 // vamsasSet.addAlcodonFrame(alc);
1181 vamsasSet.getAlcodonFrame().add(alc);
1184 // TODO: delete this ? dead code from 2.8.3->2.9 ?
1186 // AlcodonFrame alc = new AlcodonFrame();
1187 // vamsasSet.addAlcodonFrame(alc);
1188 // for (int p = 0; p < acf.aaWidth; p++)
1190 // Alcodon cmap = new Alcodon();
1191 // if (acf.codons[p] != null)
1193 // // Null codons indicate a gapped column in the translated peptide
1195 // cmap.setPos1(acf.codons[p][0]);
1196 // cmap.setPos2(acf.codons[p][1]);
1197 // cmap.setPos3(acf.codons[p][2]);
1199 // alc.addAlcodon(cmap);
1201 // if (acf.getProtMappings() != null
1202 // && acf.getProtMappings().length > 0)
1204 // SequenceI[] dnas = acf.getdnaSeqs();
1205 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1206 // for (int m = 0; m < pmaps.length; m++)
1208 // AlcodMap alcmap = new AlcodMap();
1209 // alcmap.setDnasq(seqHash(dnas[m]));
1210 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
1212 // alc.addAlcodMap(alcmap);
1219 // /////////////////////////////////
1220 if (!storeDS && av.getCurrentTree() != null)
1222 // FIND ANY ASSOCIATED TREES
1223 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
1224 if (Desktop.desktop != null)
1226 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1228 for (int t = 0; t < frames.length; t++)
1230 if (frames[t] instanceof TreePanel)
1232 TreePanel tp = (TreePanel) frames[t];
1234 if (tp.getTreeCanvas().getViewport().getAlignment() == jal)
1236 JalviewModel.Tree tree = new JalviewModel.Tree();
1237 tree.setTitle(tp.getTitle());
1238 tree.setCurrentTree((av.getCurrentTree() == tp.getTree()));
1239 tree.setNewick(tp.getTree().print());
1240 tree.setThreshold(tp.getTreeCanvas().getThreshold());
1242 tree.setFitToWindow(tp.fitToWindow.getState());
1243 tree.setFontName(tp.getTreeFont().getName());
1244 tree.setFontSize(tp.getTreeFont().getSize());
1245 tree.setFontStyle(tp.getTreeFont().getStyle());
1246 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
1248 tree.setShowBootstrap(tp.bootstrapMenu.getState());
1249 tree.setShowDistances(tp.distanceMenu.getState());
1251 tree.setHeight(tp.getHeight());
1252 tree.setWidth(tp.getWidth());
1253 tree.setXpos(tp.getX());
1254 tree.setYpos(tp.getY());
1255 tree.setId(makeHashCode(tp, null));
1256 tree.setLinkToAllViews(
1257 tp.getTreeCanvas().isApplyToAllViews());
1259 // jms.addTree(tree);
1260 object.getTree().add(tree);
1270 if (!storeDS && Desktop.desktop != null)
1272 for (JInternalFrame frame : Desktop.desktop.getAllFrames())
1274 if (frame instanceof PCAPanel)
1276 PCAPanel panel = (PCAPanel) frame;
1277 if (panel.getAlignViewport().getAlignment() == jal)
1279 savePCA(panel, object);
1287 * store forward refs from an annotationRow to any groups
1289 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<>();
1292 for (SequenceI sq : jal.getSequences())
1294 // Store annotation on dataset sequences only
1295 AlignmentAnnotation[] aa = sq.getAnnotation();
1296 if (aa != null && aa.length > 0)
1298 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1305 if (jal.getAlignmentAnnotation() != null)
1307 // Store the annotation shown on the alignment.
1308 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1309 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1314 if (jal.getGroups() != null)
1316 JGroup[] groups = new JGroup[jal.getGroups().size()];
1318 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1320 JGroup jGroup = new JGroup();
1321 groups[++i] = jGroup;
1323 jGroup.setStart(sg.getStartRes());
1324 jGroup.setEnd(sg.getEndRes());
1325 jGroup.setName(sg.getName());
1326 if (groupRefs.containsKey(sg))
1328 // group has references so set its ID field
1329 jGroup.setId(groupRefs.get(sg));
1331 ColourSchemeI colourScheme = sg.getColourScheme();
1332 if (colourScheme != null)
1334 ResidueShaderI groupColourScheme = sg.getGroupColourScheme();
1335 if (groupColourScheme.conservationApplied())
1337 jGroup.setConsThreshold(groupColourScheme.getConservationInc());
1339 if (colourScheme instanceof jalview.schemes.UserColourScheme)
1342 setUserColourScheme(colourScheme, userColours,
1347 jGroup.setColour(colourScheme.getSchemeName());
1350 else if (colourScheme instanceof jalview.schemes.AnnotationColourGradient)
1352 jGroup.setColour("AnnotationColourGradient");
1353 jGroup.setAnnotationColours(constructAnnotationColours(
1354 (jalview.schemes.AnnotationColourGradient) colourScheme,
1355 userColours, object));
1357 else if (colourScheme instanceof jalview.schemes.UserColourScheme)
1360 setUserColourScheme(colourScheme, userColours, object));
1364 jGroup.setColour(colourScheme.getSchemeName());
1367 jGroup.setPidThreshold(groupColourScheme.getThreshold());
1370 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1371 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1372 jGroup.setDisplayText(sg.getDisplayText());
1373 jGroup.setColourText(sg.getColourText());
1374 jGroup.setTextCol1(sg.textColour.getRGB());
1375 jGroup.setTextCol2(sg.textColour2.getRGB());
1376 jGroup.setTextColThreshold(sg.thresholdTextColour);
1377 jGroup.setShowUnconserved(sg.getShowNonconserved());
1378 jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1379 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1380 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1381 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1382 for (SequenceI seq : sg.getSequences())
1384 // jGroup.addSeq(seqHash(seq));
1385 jGroup.getSeq().add(seqHash(seq));
1389 //jms.setJGroup(groups);
1391 for (JGroup grp : groups)
1393 object.getJGroup().add(grp);
1398 // /////////SAVE VIEWPORT
1399 Viewport view = new Viewport();
1400 view.setTitle(ap.alignFrame.getTitle());
1401 view.setSequenceSetId(
1402 makeHashCode(av.getSequenceSetId(), av.getSequenceSetId()));
1403 view.setId(av.getViewId());
1404 if (av.getCodingComplement() != null)
1406 view.setComplementId(av.getCodingComplement().getViewId());
1408 view.setViewName(av.getViewName());
1409 view.setGatheredViews(av.isGatherViewsHere());
1411 Rectangle size = ap.av.getExplodedGeometry();
1412 Rectangle position = size;
1415 size = ap.alignFrame.getBounds();
1416 if (av.getCodingComplement() != null)
1418 position = ((SplitFrame) ap.alignFrame.getSplitViewContainer())
1426 view.setXpos(position.x);
1427 view.setYpos(position.y);
1429 view.setWidth(size.width);
1430 view.setHeight(size.height);
1432 view.setStartRes(vpRanges.getStartRes());
1433 view.setStartSeq(vpRanges.getStartSeq());
1435 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1437 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1438 userColours, object));
1441 .getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1443 AnnotationColourScheme ac = constructAnnotationColours(
1444 (jalview.schemes.AnnotationColourGradient) av
1445 .getGlobalColourScheme(),
1446 userColours, object);
1448 view.setAnnotationColours(ac);
1449 view.setBgColour("AnnotationColourGradient");
1453 view.setBgColour(ColourSchemeProperty
1454 .getColourName(av.getGlobalColourScheme()));
1457 ResidueShaderI vcs = av.getResidueShading();
1458 ColourSchemeI cs = av.getGlobalColourScheme();
1462 if (vcs.conservationApplied())
1464 view.setConsThreshold(vcs.getConservationInc());
1465 if (cs instanceof jalview.schemes.UserColourScheme)
1467 view.setBgColour(setUserColourScheme(cs, userColours, object));
1470 view.setPidThreshold(vcs.getThreshold());
1473 view.setConservationSelected(av.getConservationSelected());
1474 view.setPidSelected(av.getAbovePIDThreshold());
1475 final Font font = av.getFont();
1476 view.setFontName(font.getName());
1477 view.setFontSize(font.getSize());
1478 view.setFontStyle(font.getStyle());
1479 view.setScaleProteinAsCdna(av.getViewStyle().isScaleProteinAsCdna());
1480 view.setRenderGaps(av.isRenderGaps());
1481 view.setShowAnnotation(av.isShowAnnotation());
1482 view.setShowBoxes(av.getShowBoxes());
1483 view.setShowAutocalcAbove(av.isShowAutocalculatedAbove());
1484 view.setSortAnnotationsBy(av.getSortAnnotationsBy().name());
1485 view.setShowColourText(av.getColourText());
1486 view.setShowFullId(av.getShowJVSuffix());
1487 view.setRightAlignIds(av.isRightAlignIds());
1488 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1489 view.setShowText(av.getShowText());
1490 view.setShowUnconserved(av.getShowUnconserved());
1491 view.setWrapAlignment(av.getWrapAlignment());
1492 view.setTextCol1(av.getTextColour().getRGB());
1493 view.setTextCol2(av.getTextColour2().getRGB());
1494 view.setTextColThreshold(av.getThresholdTextColour());
1495 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1496 view.setShowSequenceLogo(av.isShowSequenceLogo());
1497 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1498 view.setShowGroupConsensus(av.isShowGroupConsensus());
1499 view.setShowGroupConservation(av.isShowGroupConservation());
1500 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1501 view.setShowDbRefTooltip(av.isShowDBRefs());
1502 view.setFollowHighlight(av.isFollowHighlight());
1503 view.setFollowSelection(av.followSelection);
1504 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1505 if (av.getFeaturesDisplayed() != null)
1507 FeatureSettings fs = new FeatureSettings();
1509 FeatureRenderer fr = ap.getSeqPanel().seqCanvas
1510 .getFeatureRenderer();
1511 String[] renderOrder = fr.getRenderOrder().toArray(new String[0]);
1513 Vector<String> settingsAdded = new Vector<>();
1514 if (renderOrder != null)
1516 for (String featureType : renderOrder)
1518 FeatureSettings.Setting setting = new FeatureSettings.Setting();
1519 setting.setType(featureType);
1522 * save any filter for the feature type
1524 FeatureMatcherSetI filter = fr.getFeatureFilter(featureType);
1525 if (filter != null) {
1526 Iterator<FeatureMatcherI> filters = filter.getMatchers().iterator();
1527 FeatureMatcherI firstFilter = filters.next();
1528 setting.setMatcherSet(Jalview2XML.marshalFilter(
1529 firstFilter, filters, filter.isAnded()));
1533 * save colour scheme for the feature type
1535 FeatureColourI fcol = fr.getFeatureStyle(featureType);
1536 if (!fcol.isSimpleColour())
1538 setting.setColour(fcol.getMaxColour().getRGB());
1539 setting.setMincolour(fcol.getMinColour().getRGB());
1540 setting.setMin(fcol.getMin());
1541 setting.setMax(fcol.getMax());
1542 setting.setColourByLabel(fcol.isColourByLabel());
1543 if (fcol.isColourByAttribute())
1545 String[] attName = fcol.getAttributeName();
1546 setting.getAttributeName().add(attName[0]);
1547 if (attName.length > 1)
1549 setting.getAttributeName().add(attName[1]);
1552 setting.setAutoScale(fcol.isAutoScaled());
1553 setting.setThreshold(fcol.getThreshold());
1554 Color noColour = fcol.getNoColour();
1555 if (noColour == null)
1557 setting.setNoValueColour(NoValueColour.NONE);
1559 else if (noColour.equals(fcol.getMaxColour()))
1561 setting.setNoValueColour(NoValueColour.MAX);
1565 setting.setNoValueColour(NoValueColour.MIN);
1567 // -1 = No threshold, 0 = Below, 1 = Above
1568 setting.setThreshstate(fcol.isAboveThreshold() ? 1
1569 : (fcol.isBelowThreshold() ? 0 : -1));
1573 setting.setColour(fcol.getColour().getRGB());
1577 av.getFeaturesDisplayed().isVisible(featureType));
1579 .getOrder(featureType);
1582 setting.setOrder(rorder);
1584 /// fs.addSetting(setting);
1585 fs.getSetting().add(setting);
1586 settingsAdded.addElement(featureType);
1590 // is groups actually supposed to be a map here ?
1591 Iterator<String> en = fr.getFeatureGroups().iterator();
1592 Vector<String> groupsAdded = new Vector<>();
1593 while (en.hasNext())
1595 String grp = en.next();
1596 if (groupsAdded.contains(grp))
1600 Group g = new Group();
1602 g.setDisplay(((Boolean) fr.checkGroupVisibility(grp, false))
1605 fs.getGroup().add(g);
1606 groupsAdded.addElement(grp);
1608 // jms.setFeatureSettings(fs);
1609 object.setFeatureSettings(fs);
1612 if (av.hasHiddenColumns())
1614 jalview.datamodel.HiddenColumns hidden = av.getAlignment()
1615 .getHiddenColumns();
1618 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1622 Iterator<int[]> hiddenRegions = hidden.iterator();
1623 while (hiddenRegions.hasNext())
1625 int[] region = hiddenRegions.next();
1626 HiddenColumns hc = new HiddenColumns();
1627 hc.setStart(region[0]);
1628 hc.setEnd(region[1]);
1629 // view.addHiddenColumns(hc);
1630 view.getHiddenColumns().add(hc);
1634 if (calcIdSet.size() > 0)
1636 for (String calcId : calcIdSet)
1638 if (calcId.trim().length() > 0)
1640 CalcIdParam cidp = createCalcIdParam(calcId, av);
1641 // Some calcIds have no parameters.
1644 // view.addCalcIdParam(cidp);
1645 view.getCalcIdParam().add(cidp);
1651 // jms.addViewport(view);
1652 object.getViewport().add(view);
1654 // object.setJalviewModelSequence(jms);
1655 // object.getVamsasModel().addSequenceSet(vamsasSet);
1656 object.getVamsasModel().getSequenceSet().add(vamsasSet);
1658 if (jout != null && fileName != null)
1660 // We may not want to write the object to disk,
1661 // eg we can copy the alignViewport to a new view object
1662 // using save and then load
1665 System.out.println("Writing jar entry " + fileName);
1666 JarEntry entry = new JarEntry(fileName);
1667 jout.putNextEntry(entry);
1668 PrintWriter pout = new PrintWriter(
1669 new OutputStreamWriter(jout, UTF_8));
1670 JAXBContext jaxbContext = JAXBContext
1671 .newInstance(JalviewModel.class);
1672 Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
1674 // output pretty printed
1675 // jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
1676 jaxbMarshaller.marshal(
1677 new ObjectFactory().createJalviewModel(object), pout);
1679 // jaxbMarshaller.marshal(object, pout);
1680 // marshaller.marshal(object);
1683 } catch (Exception ex)
1685 // TODO: raise error in GUI if marshalling failed.
1686 System.err.println("Error writing Jalview project");
1687 ex.printStackTrace();
1694 * Writes PCA viewer attributes and computed values to an XML model object and
1695 * adds it to the JalviewModel. Any exceptions are reported by logging.
1697 protected void savePCA(PCAPanel panel, JalviewModel object)
1701 PcaViewer viewer = new PcaViewer();
1702 viewer.setHeight(panel.getHeight());
1703 viewer.setWidth(panel.getWidth());
1704 viewer.setXpos(panel.getX());
1705 viewer.setYpos(panel.getY());
1706 viewer.setTitle(panel.getTitle());
1707 PCAModel pcaModel = panel.getPcaModel();
1708 viewer.setScoreModelName(pcaModel.getScoreModelName());
1709 viewer.setXDim(panel.getSelectedDimensionIndex(X));
1710 viewer.setYDim(panel.getSelectedDimensionIndex(Y));
1711 viewer.setZDim(panel.getSelectedDimensionIndex(Z));
1713 panel.getRotatableCanvas().getBackgroundColour().getRGB());
1714 viewer.setScaleFactor(panel.getRotatableCanvas().getScaleFactor());
1715 float[] spMin = panel.getRotatableCanvas().getSeqMin();
1716 SeqPointMin spmin = new SeqPointMin();
1717 spmin.setXPos(spMin[0]);
1718 spmin.setYPos(spMin[1]);
1719 spmin.setZPos(spMin[2]);
1720 viewer.setSeqPointMin(spmin);
1721 float[] spMax = panel.getRotatableCanvas().getSeqMax();
1722 SeqPointMax spmax = new SeqPointMax();
1723 spmax.setXPos(spMax[0]);
1724 spmax.setYPos(spMax[1]);
1725 spmax.setZPos(spMax[2]);
1726 viewer.setSeqPointMax(spmax);
1727 viewer.setShowLabels(panel.getRotatableCanvas().isShowLabels());
1728 viewer.setLinkToAllViews(
1729 panel.getRotatableCanvas().isApplyToAllViews());
1730 SimilarityParamsI sp = pcaModel.getSimilarityParameters();
1731 viewer.setIncludeGaps(sp.includeGaps());
1732 viewer.setMatchGaps(sp.matchGaps());
1733 viewer.setIncludeGappedColumns(sp.includeGappedColumns());
1734 viewer.setDenominateByShortestLength(sp.denominateByShortestLength());
1737 * sequence points on display
1739 for (jalview.datamodel.SequencePoint spt : pcaModel
1740 .getSequencePoints())
1742 SequencePoint point = new SequencePoint();
1743 point.setSequenceRef(seqHash(spt.getSequence()));
1744 point.setXPos(spt.coord.x);
1745 point.setYPos(spt.coord.y);
1746 point.setZPos(spt.coord.z);
1747 viewer.getSequencePoint().add(point);
1751 * (end points of) axes on display
1753 for (Point p : panel.getRotatableCanvas().getAxisEndPoints())
1756 Axis axis = new Axis();
1760 viewer.getAxis().add(axis);
1764 * raw PCA data (note we are not restoring PCA inputs here -
1765 * alignment view, score model, similarity parameters)
1767 PcaDataType data = new PcaDataType();
1768 viewer.setPcaData(data);
1769 PCA pca = pcaModel.getPcaData();
1771 DoubleMatrix pm = new DoubleMatrix();
1772 saveDoubleMatrix(pca.getPairwiseScores(), pm);
1773 data.setPairwiseMatrix(pm);
1775 DoubleMatrix tm = new DoubleMatrix();
1776 saveDoubleMatrix(pca.getTridiagonal(), tm);
1777 data.setTridiagonalMatrix(tm);
1779 DoubleMatrix eigenMatrix = new DoubleMatrix();
1780 data.setEigenMatrix(eigenMatrix);
1781 saveDoubleMatrix(pca.getEigenmatrix(), eigenMatrix);
1783 object.getPcaViewer().add(viewer);
1784 } catch (Throwable t)
1786 Cache.log.error("Error saving PCA: " + t.getMessage());
1791 * Stores values from a matrix into an XML element, including (if present) the
1796 * @see #loadDoubleMatrix(DoubleMatrix)
1798 protected void saveDoubleMatrix(MatrixI m, DoubleMatrix xmlMatrix)
1800 xmlMatrix.setRows(m.height());
1801 xmlMatrix.setColumns(m.width());
1802 for (int i = 0; i < m.height(); i++)
1804 DoubleVector row = new DoubleVector();
1805 for (int j = 0; j < m.width(); j++)
1807 row.getV().add(m.getValue(i, j));
1809 xmlMatrix.getRow().add(row);
1811 if (m.getD() != null)
1813 DoubleVector dVector = new DoubleVector();
1814 for (double d : m.getD())
1816 dVector.getV().add(d);
1818 xmlMatrix.setD(dVector);
1820 if (m.getE() != null)
1822 DoubleVector eVector = new DoubleVector();
1823 for (double e : m.getE())
1825 eVector.getV().add(e);
1827 xmlMatrix.setE(eVector);
1832 * Loads XML matrix data into a new Matrix object, including the D and/or E
1833 * vectors (if present)
1837 * @see Jalview2XML#saveDoubleMatrix(MatrixI, DoubleMatrix)
1839 protected MatrixI loadDoubleMatrix(DoubleMatrix mData)
1841 int rows = mData.getRows();
1842 double[][] vals = new double[rows][];
1844 for (int i = 0; i < rows; i++)
1846 List<Double> dVector = mData.getRow().get(i).getV();
1847 vals[i] = new double[dVector.size()];
1849 for (Double d : dVector)
1855 MatrixI m = new Matrix(vals);
1857 if (mData.getD() != null)
1859 List<Double> dVector = mData.getD().getV();
1860 double[] vec = new double[dVector.size()];
1862 for (Double d : dVector)
1868 if (mData.getE() != null)
1870 List<Double> dVector = mData.getE().getV();
1871 double[] vec = new double[dVector.size()];
1873 for (Double d : dVector)
1884 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1885 * for each viewer, with
1887 * <li>viewer geometry (position, size, split pane divider location)</li>
1888 * <li>index of the selected structure in the viewer (currently shows gapped
1890 * <li>the id of the annotation holding RNA secondary structure</li>
1891 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1893 * Varna viewer state is also written out (in native Varna XML) to separate
1894 * project jar entries. A separate entry is written for each RNA structure
1895 * displayed, with the naming convention
1897 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
1905 * @param storeDataset
1907 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
1908 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
1909 boolean storeDataset)
1911 if (Desktop.desktop == null)
1915 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1916 for (int f = frames.length - 1; f > -1; f--)
1918 if (frames[f] instanceof AppVarna)
1920 AppVarna varna = (AppVarna) frames[f];
1922 * link the sequence to every viewer that is showing it and is linked to
1923 * its alignment panel
1925 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1927 String viewId = varna.getViewId();
1928 RnaViewer rna = new RnaViewer();
1929 rna.setViewId(viewId);
1930 rna.setTitle(varna.getTitle());
1931 rna.setXpos(varna.getX());
1932 rna.setYpos(varna.getY());
1933 rna.setWidth(varna.getWidth());
1934 rna.setHeight(varna.getHeight());
1935 rna.setDividerLocation(varna.getDividerLocation());
1936 rna.setSelectedRna(varna.getSelectedIndex());
1937 // jseq.addRnaViewer(rna);
1938 jseq.getRnaViewer().add(rna);
1941 * Store each Varna panel's state once in the project per sequence.
1942 * First time through only (storeDataset==false)
1944 // boolean storeSessions = false;
1945 // String sequenceViewId = viewId + seqsToIds.get(jds);
1946 // if (!storeDataset && !viewIds.contains(sequenceViewId))
1948 // viewIds.add(sequenceViewId);
1949 // storeSessions = true;
1951 for (RnaModel model : varna.getModels())
1953 if (model.seq == jds)
1956 * VARNA saves each view (sequence or alignment secondary
1957 * structure, gapped or trimmed) as a separate XML file
1959 String jarEntryName = rnaSessions.get(model);
1960 if (jarEntryName == null)
1963 String varnaStateFile = varna.getStateInfo(model.rna);
1964 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
1965 copyFileToJar(jout, varnaStateFile, jarEntryName);
1966 rnaSessions.put(model, jarEntryName);
1968 SecondaryStructure ss = new SecondaryStructure();
1969 String annotationId = varna.getAnnotation(jds).annotationId;
1970 ss.setAnnotationId(annotationId);
1971 ss.setViewerState(jarEntryName);
1972 ss.setGapped(model.gapped);
1973 ss.setTitle(model.title);
1974 // rna.addSecondaryStructure(ss);
1975 rna.getSecondaryStructure().add(ss);
1984 * Copy the contents of a file to a new entry added to the output jar
1988 * @param jarEntryName
1990 protected void copyFileToJar(JarOutputStream jout, String infilePath,
1991 String jarEntryName)
1993 DataInputStream dis = null;
1996 File file = new File(infilePath);
1997 if (file.exists() && jout != null)
1999 dis = new DataInputStream(new FileInputStream(file));
2000 byte[] data = new byte[(int) file.length()];
2001 dis.readFully(data);
2002 writeJarEntry(jout, jarEntryName, data);
2004 } catch (Exception ex)
2006 ex.printStackTrace();
2014 } catch (IOException e)
2023 * Write the data to a new entry of given name in the output jar file
2026 * @param jarEntryName
2028 * @throws IOException
2030 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
2031 byte[] data) throws IOException
2035 System.out.println("Writing jar entry " + jarEntryName);
2036 jout.putNextEntry(new JarEntry(jarEntryName));
2037 DataOutputStream dout = new DataOutputStream(jout);
2038 dout.write(data, 0, data.length);
2045 * Save the state of a structure viewer
2050 * the archive XML element under which to save the state
2053 * @param matchedFile
2057 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
2058 Pdbids pdb, PDBEntry entry, List<String> viewIds,
2059 String matchedFile, StructureViewerBase viewFrame)
2061 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
2064 * Look for any bindings for this viewer to the PDB file of interest
2065 * (including part matches excluding chain id)
2067 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
2069 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
2070 final String pdbId = pdbentry.getId();
2071 if (!pdbId.equals(entry.getId())
2072 && !(entry.getId().length() > 4 && entry.getId().toLowerCase()
2073 .startsWith(pdbId.toLowerCase())))
2076 * not interested in a binding to a different PDB entry here
2080 if (matchedFile == null)
2082 matchedFile = pdbentry.getFile();
2084 else if (!matchedFile.equals(pdbentry.getFile()))
2087 "Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
2088 + pdbentry.getFile());
2092 // can get at it if the ID
2093 // match is ambiguous (e.g.
2096 for (int smap = 0; smap < viewFrame.getBinding()
2097 .getSequence()[peid].length; smap++)
2099 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
2100 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
2102 StructureState state = new StructureState();
2103 state.setVisible(true);
2104 state.setXpos(viewFrame.getX());
2105 state.setYpos(viewFrame.getY());
2106 state.setWidth(viewFrame.getWidth());
2107 state.setHeight(viewFrame.getHeight());
2108 final String viewId = viewFrame.getViewId();
2109 state.setViewId(viewId);
2110 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
2111 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
2112 state.setColourByJmol(viewFrame.isColouredByViewer());
2113 state.setType(viewFrame.getViewerType().toString());
2114 // pdb.addStructureState(state);
2115 pdb.getStructureState().add(state);
2123 * Populates the AnnotationColourScheme xml for save. This captures the
2124 * settings of the options in the 'Colour by Annotation' dialog.
2127 * @param userColours
2131 private AnnotationColourScheme constructAnnotationColours(
2132 AnnotationColourGradient acg, List<UserColourScheme> userColours,
2135 AnnotationColourScheme ac = new AnnotationColourScheme();
2136 ac.setAboveThreshold(acg.getAboveThreshold());
2137 ac.setThreshold(acg.getAnnotationThreshold());
2138 // 2.10.2 save annotationId (unique) not annotation label
2139 ac.setAnnotation(acg.getAnnotation().annotationId);
2140 if (acg.getBaseColour() instanceof UserColourScheme)
2143 setUserColourScheme(acg.getBaseColour(), userColours, jm));
2148 ColourSchemeProperty.getColourName(acg.getBaseColour()));
2151 ac.setMaxColour(acg.getMaxColour().getRGB());
2152 ac.setMinColour(acg.getMinColour().getRGB());
2153 ac.setPerSequence(acg.isSeqAssociated());
2154 ac.setPredefinedColours(acg.isPredefinedColours());
2158 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
2159 IdentityHashMap<SequenceGroup, String> groupRefs,
2160 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
2161 SequenceSet vamsasSet)
2164 for (int i = 0; i < aa.length; i++)
2166 Annotation an = new Annotation();
2168 AlignmentAnnotation annotation = aa[i];
2169 if (annotation.annotationId != null)
2171 annotationIds.put(annotation.annotationId, annotation);
2174 an.setId(annotation.annotationId);
2176 an.setVisible(annotation.visible);
2178 an.setDescription(annotation.description);
2180 if (annotation.sequenceRef != null)
2182 // 2.9 JAL-1781 xref on sequence id rather than name
2183 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
2185 if (annotation.groupRef != null)
2187 String groupIdr = groupRefs.get(annotation.groupRef);
2188 if (groupIdr == null)
2190 // make a locally unique String
2191 groupRefs.put(annotation.groupRef,
2192 groupIdr = ("" + System.currentTimeMillis()
2193 + annotation.groupRef.getName()
2194 + groupRefs.size()));
2196 an.setGroupRef(groupIdr.toString());
2199 // store all visualization attributes for annotation
2200 an.setGraphHeight(annotation.graphHeight);
2201 an.setCentreColLabels(annotation.centreColLabels);
2202 an.setScaleColLabels(annotation.scaleColLabel);
2203 an.setShowAllColLabels(annotation.showAllColLabels);
2204 an.setBelowAlignment(annotation.belowAlignment);
2206 if (annotation.graph > 0)
2209 an.setGraphType(annotation.graph);
2210 an.setGraphGroup(annotation.graphGroup);
2211 if (annotation.getThreshold() != null)
2213 ThresholdLine line = new ThresholdLine();
2214 line.setLabel(annotation.getThreshold().label);
2215 line.setValue(annotation.getThreshold().value);
2216 line.setColour(annotation.getThreshold().colour.getRGB());
2217 an.setThresholdLine(line);
2225 an.setLabel(annotation.label);
2227 if (annotation == av.getAlignmentQualityAnnot()
2228 || annotation == av.getAlignmentConservationAnnotation()
2229 || annotation == av.getAlignmentConsensusAnnotation()
2230 || annotation.autoCalculated)
2232 // new way of indicating autocalculated annotation -
2233 an.setAutoCalculated(annotation.autoCalculated);
2235 if (annotation.hasScore())
2237 an.setScore(annotation.getScore());
2240 if (annotation.getCalcId() != null)
2242 calcIdSet.add(annotation.getCalcId());
2243 an.setCalcId(annotation.getCalcId());
2245 if (annotation.hasProperties())
2247 for (String pr : annotation.getProperties())
2249 jalview.xml.binding.jalview.Annotation.Property prop = new jalview.xml.binding.jalview.Annotation.Property();
2251 prop.setValue(annotation.getProperty(pr));
2252 // an.addProperty(prop);
2253 an.getProperty().add(prop);
2257 AnnotationElement ae;
2258 if (annotation.annotations != null)
2260 an.setScoreOnly(false);
2261 for (int a = 0; a < annotation.annotations.length; a++)
2263 if ((annotation == null) || (annotation.annotations[a] == null))
2268 ae = new AnnotationElement();
2269 if (annotation.annotations[a].description != null)
2271 ae.setDescription(annotation.annotations[a].description);
2273 if (annotation.annotations[a].displayCharacter != null)
2275 ae.setDisplayCharacter(
2276 annotation.annotations[a].displayCharacter);
2279 if (!Float.isNaN(annotation.annotations[a].value))
2281 ae.setValue(annotation.annotations[a].value);
2285 if (annotation.annotations[a].secondaryStructure > ' ')
2287 ae.setSecondaryStructure(
2288 annotation.annotations[a].secondaryStructure + "");
2291 if (annotation.annotations[a].colour != null
2292 && annotation.annotations[a].colour != java.awt.Color.black)
2294 ae.setColour(annotation.annotations[a].colour.getRGB());
2297 // an.addAnnotationElement(ae);
2298 an.getAnnotationElement().add(ae);
2299 if (annotation.autoCalculated)
2301 // only write one non-null entry into the annotation row -
2302 // sufficient to get the visualization attributes necessary to
2310 an.setScoreOnly(true);
2312 if (!storeDS || (storeDS && !annotation.autoCalculated))
2314 // skip autocalculated annotation - these are only provided for
2316 // vamsasSet.addAnnotation(an);
2317 vamsasSet.getAnnotation().add(an);
2323 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
2325 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
2326 if (settings != null)
2328 CalcIdParam vCalcIdParam = new CalcIdParam();
2329 vCalcIdParam.setCalcId(calcId);
2330 // vCalcIdParam.addServiceURL(settings.getServiceURI());
2331 vCalcIdParam.getServiceURL().add(settings.getServiceURI());
2332 // generic URI allowing a third party to resolve another instance of the
2333 // service used for this calculation
2334 for (String url : settings.getServiceURLs())
2336 // vCalcIdParam.addServiceURL(urls);
2337 vCalcIdParam.getServiceURL().add(url);
2339 vCalcIdParam.setVersion("1.0");
2340 if (settings.getPreset() != null)
2342 WsParamSetI setting = settings.getPreset();
2343 vCalcIdParam.setName(setting.getName());
2344 vCalcIdParam.setDescription(setting.getDescription());
2348 vCalcIdParam.setName("");
2349 vCalcIdParam.setDescription("Last used parameters");
2351 // need to be able to recover 1) settings 2) user-defined presets or
2352 // recreate settings from preset 3) predefined settings provided by
2353 // service - or settings that can be transferred (or discarded)
2354 vCalcIdParam.setParameters(
2355 settings.getWsParamFile().replace("\n", "|\\n|"));
2356 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
2357 // todo - decide if updateImmediately is needed for any projects.
2359 return vCalcIdParam;
2364 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
2367 if (calcIdParam.getVersion().equals("1.0"))
2369 final String[] calcIds = calcIdParam.getServiceURL().toArray(new String[0]);
2370 Jws2Instance service = Jws2Discoverer.getDiscoverer()
2371 .getPreferredServiceFor(calcIds);
2372 if (service != null)
2374 WsParamSetI parmSet = null;
2377 parmSet = service.getParamStore().parseServiceParameterFile(
2378 calcIdParam.getName(), calcIdParam.getDescription(),
2380 calcIdParam.getParameters().replace("|\\n|", "\n"));
2381 } catch (IOException x)
2383 warn("Couldn't parse parameter data for "
2384 + calcIdParam.getCalcId(), x);
2387 List<ArgumentI> argList = null;
2388 if (calcIdParam.getName().length() > 0)
2390 parmSet = service.getParamStore()
2391 .getPreset(calcIdParam.getName());
2392 if (parmSet != null)
2394 // TODO : check we have a good match with settings in AACon -
2395 // otherwise we'll need to create a new preset
2400 argList = parmSet.getArguments();
2403 AAConSettings settings = new AAConSettings(
2404 calcIdParam.isAutoUpdate(), service, parmSet, argList);
2405 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
2406 calcIdParam.isNeedsUpdate());
2411 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
2415 throw new Error(MessageManager.formatMessage(
2416 "error.unsupported_version_calcIdparam", new Object[]
2417 { calcIdParam.toString() }));
2421 * External mapping between jalview objects and objects yielding a valid and
2422 * unique object ID string. This is null for normal Jalview project IO, but
2423 * non-null when a jalview project is being read or written as part of a
2426 IdentityHashMap jv2vobj = null;
2429 * Construct a unique ID for jvobj using either existing bindings or if none
2430 * exist, the result of the hashcode call for the object.
2433 * jalview data object
2434 * @return unique ID for referring to jvobj
2436 private String makeHashCode(Object jvobj, String altCode)
2438 if (jv2vobj != null)
2440 Object id = jv2vobj.get(jvobj);
2443 return id.toString();
2445 // check string ID mappings
2446 if (jvids2vobj != null && jvobj instanceof String)
2448 id = jvids2vobj.get(jvobj);
2452 return id.toString();
2454 // give up and warn that something has gone wrong
2455 warn("Cannot find ID for object in external mapping : " + jvobj);
2461 * return local jalview object mapped to ID, if it exists
2465 * @return null or object bound to idcode
2467 private Object retrieveExistingObj(String idcode)
2469 if (idcode != null && vobj2jv != null)
2471 return vobj2jv.get(idcode);
2477 * binding from ID strings from external mapping table to jalview data model
2480 private Hashtable vobj2jv;
2482 private Sequence createVamsasSequence(String id, SequenceI jds)
2484 return createVamsasSequence(true, id, jds, null);
2487 private Sequence createVamsasSequence(boolean recurse, String id,
2488 SequenceI jds, SequenceI parentseq)
2490 Sequence vamsasSeq = new Sequence();
2491 vamsasSeq.setId(id);
2492 vamsasSeq.setName(jds.getName());
2493 vamsasSeq.setSequence(jds.getSequenceAsString());
2494 vamsasSeq.setDescription(jds.getDescription());
2495 jalview.datamodel.DBRefEntry[] dbrefs = null;
2496 if (jds.getDatasetSequence() != null)
2498 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
2502 // seqId==dsseqid so we can tell which sequences really are
2503 // dataset sequences only
2504 vamsasSeq.setDsseqid(id);
2505 dbrefs = jds.getDBRefs();
2506 if (parentseq == null)
2513 for (int d = 0; d < dbrefs.length; d++)
2515 DBRef dbref = new DBRef();
2516 dbref.setSource(dbrefs[d].getSource());
2517 dbref.setVersion(dbrefs[d].getVersion());
2518 dbref.setAccessionId(dbrefs[d].getAccessionId());
2519 if (dbrefs[d].hasMap())
2521 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
2523 dbref.setMapping(mp);
2525 // vamsasSeq.addDBRef(dbref);
2526 vamsasSeq.getDBRef().add(dbref);
2532 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
2533 SequenceI parentseq, SequenceI jds, boolean recurse)
2536 if (jmp.getMap() != null)
2540 jalview.util.MapList mlst = jmp.getMap();
2541 List<int[]> r = mlst.getFromRanges();
2542 for (int[] range : r)
2544 MapListFrom mfrom = new MapListFrom();
2545 mfrom.setStart(range[0]);
2546 mfrom.setEnd(range[1]);
2547 // mp.addMapListFrom(mfrom);
2548 mp.getMapListFrom().add(mfrom);
2550 r = mlst.getToRanges();
2551 for (int[] range : r)
2553 MapListTo mto = new MapListTo();
2554 mto.setStart(range[0]);
2555 mto.setEnd(range[1]);
2556 // mp.addMapListTo(mto);
2557 mp.getMapListTo().add(mto);
2559 mp.setMapFromUnit(BigInteger.valueOf(mlst.getFromRatio()));
2560 mp.setMapToUnit(BigInteger.valueOf(mlst.getToRatio()));
2561 if (jmp.getTo() != null)
2563 // MappingChoice mpc = new MappingChoice();
2565 // check/create ID for the sequence referenced by getTo()
2568 SequenceI ps = null;
2569 if (parentseq != jmp.getTo()
2570 && parentseq.getDatasetSequence() != jmp.getTo())
2572 // chaining dbref rather than a handshaking one
2573 jmpid = seqHash(ps = jmp.getTo());
2577 jmpid = seqHash(ps = parentseq);
2579 // mpc.setDseqFor(jmpid);
2580 mp.setDseqFor(jmpid);
2581 if (!seqRefIds.containsKey(jmpid))
2583 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2584 seqRefIds.put(jmpid, ps);
2588 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2591 // mp.setMappingChoice(mpc);
2597 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2598 List<UserColourScheme> userColours, JalviewModel jm)
2601 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2602 boolean newucs = false;
2603 if (!userColours.contains(ucs))
2605 userColours.add(ucs);
2608 id = "ucs" + userColours.indexOf(ucs);
2611 // actually create the scheme's entry in the XML model
2612 java.awt.Color[] colours = ucs.getColours();
2613 UserColours uc = new UserColours();
2614 // UserColourScheme jbucs = new UserColourScheme();
2615 JalviewUserColours jbucs = new JalviewUserColours();
2617 for (int i = 0; i < colours.length; i++)
2619 Colour col = new Colour();
2620 col.setName(ResidueProperties.aa[i]);
2621 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2622 // jbucs.addColour(col);
2623 jbucs.getColour().add(col);
2625 if (ucs.getLowerCaseColours() != null)
2627 colours = ucs.getLowerCaseColours();
2628 for (int i = 0; i < colours.length; i++)
2630 Colour col = new Colour();
2631 col.setName(ResidueProperties.aa[i].toLowerCase());
2632 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2633 // jbucs.addColour(col);
2634 jbucs.getColour().add(col);
2639 uc.setUserColourScheme(jbucs);
2640 // jm.addUserColours(uc);
2641 jm.getUserColours().add(uc);
2647 jalview.schemes.UserColourScheme getUserColourScheme(
2648 JalviewModel jm, String id)
2650 List<UserColours> uc = jm.getUserColours();
2651 UserColours colours = null;
2653 for (int i = 0; i < uc.length; i++)
2655 if (uc[i].getId().equals(id))
2662 for (UserColours c : uc)
2664 if (c.getId().equals(id))
2671 java.awt.Color[] newColours = new java.awt.Color[24];
2673 for (int i = 0; i < 24; i++)
2675 newColours[i] = new java.awt.Color(Integer.parseInt(
2676 // colours.getUserColourScheme().getColour(i).getRGB(), 16));
2677 colours.getUserColourScheme().getColour().get(i).getRGB(),
2681 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2684 if (colours.getUserColourScheme().getColour().size()/*Count()*/ > 24)
2686 newColours = new java.awt.Color[23];
2687 for (int i = 0; i < 23; i++)
2689 newColours[i] = new java.awt.Color(Integer.parseInt(
2690 colours.getUserColourScheme().getColour().get(i + 24)
2694 ucs.setLowerCaseColours(newColours);
2701 * contains last error message (if any) encountered by XML loader.
2703 String errorMessage = null;
2706 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2707 * exceptions are raised during project XML parsing
2709 public boolean attemptversion1parse = false;
2712 * Load a jalview project archive from a jar file
2715 * - HTTP URL or filename
2717 public AlignFrame loadJalviewAlign(final String file)
2720 jalview.gui.AlignFrame af = null;
2724 // create list to store references for any new Jmol viewers created
2725 newStructureViewers = new Vector<>();
2726 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2727 // Workaround is to make sure caller implements the JarInputStreamProvider
2729 // so we can re-open the jar input stream for each entry.
2731 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2732 af = loadJalviewAlign(jprovider);
2735 af.setMenusForViewport();
2737 } catch (MalformedURLException e)
2739 errorMessage = "Invalid URL format for '" + file + "'";
2745 SwingUtilities.invokeAndWait(new Runnable()
2750 setLoadingFinishedForNewStructureViewers();
2753 } catch (Exception x)
2755 System.err.println("Error loading alignment: " + x.getMessage());
2761 private jarInputStreamProvider createjarInputStreamProvider(
2762 final String file) throws MalformedURLException
2765 errorMessage = null;
2766 uniqueSetSuffix = null;
2768 viewportsAdded.clear();
2769 frefedSequence = null;
2771 if (file.startsWith("http://"))
2773 url = new URL(file);
2775 final URL _url = url;
2776 return new jarInputStreamProvider()
2780 public JarInputStream getJarInputStream() throws IOException
2784 return new JarInputStream(_url.openStream());
2788 return new JarInputStream(new FileInputStream(file));
2793 public String getFilename()
2801 * Recover jalview session from a jalview project archive. Caller may
2802 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2803 * themselves. Any null fields will be initialised with default values,
2804 * non-null fields are left alone.
2809 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2811 errorMessage = null;
2812 if (uniqueSetSuffix == null)
2814 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2816 if (seqRefIds == null)
2820 AlignFrame af = null, _af = null;
2821 IdentityHashMap<AlignmentI, AlignmentI> importedDatasets = new IdentityHashMap<>();
2822 Map<String, AlignFrame> gatherToThisFrame = new HashMap<>();
2823 final String file = jprovider.getFilename();
2826 JarInputStream jin = null;
2827 JarEntry jarentry = null;
2832 jin = jprovider.getJarInputStream();
2833 for (int i = 0; i < entryCount; i++)
2835 jarentry = jin.getNextJarEntry();
2838 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2840 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2841 // JalviewModel object = new JalviewModel();
2843 JAXBContext jc = JAXBContext
2844 .newInstance("jalview.xml.binding.jalview");
2845 XMLStreamReader streamReader = XMLInputFactory.newInstance()
2846 .createXMLStreamReader(jin);
2847 javax.xml.bind.Unmarshaller um = jc.createUnmarshaller();
2848 JAXBElement<JalviewModel> jbe = um
2849 .unmarshal(streamReader, JalviewModel.class);
2850 JalviewModel object = jbe.getValue();
2853 Unmarshaller unmar = new Unmarshaller(object);
2854 unmar.setValidation(false);
2855 object = (JalviewModel) unmar.unmarshal(in);
2857 if (true) // !skipViewport(object))
2859 _af = loadFromObject(object, file, true, jprovider);
2860 if (_af != null && object.getViewport().size() > 0)
2861 // getJalviewModelSequence().getViewportCount() > 0)
2865 // store a reference to the first view
2868 if (_af.getViewport().isGatherViewsHere())
2870 // if this is a gathered view, keep its reference since
2871 // after gathering views, only this frame will remain
2873 gatherToThisFrame.put(_af.getViewport().getSequenceSetId(),
2876 // Save dataset to register mappings once all resolved
2877 importedDatasets.put(
2878 af.getViewport().getAlignment().getDataset(),
2879 af.getViewport().getAlignment().getDataset());
2884 else if (jarentry != null)
2886 // Some other file here.
2889 } while (jarentry != null);
2890 resolveFrefedSequences();
2891 } catch (IOException ex)
2893 ex.printStackTrace();
2894 errorMessage = "Couldn't locate Jalview XML file : " + file;
2896 "Exception whilst loading jalview XML file : " + ex + "\n");
2897 } catch (Exception ex)
2899 System.err.println("Parsing as Jalview Version 2 file failed.");
2900 ex.printStackTrace(System.err);
2901 if (attemptversion1parse)
2903 // used to attempt to parse as V1 castor-generated xml
2905 if (Desktop.instance != null)
2907 Desktop.instance.stopLoading();
2911 System.out.println("Successfully loaded archive file");
2914 ex.printStackTrace();
2917 "Exception whilst loading jalview XML file : " + ex + "\n");
2918 } catch (OutOfMemoryError e)
2920 // Don't use the OOM Window here
2921 errorMessage = "Out of memory loading jalview XML file";
2922 System.err.println("Out of memory whilst loading jalview XML file");
2923 e.printStackTrace();
2927 * Regather multiple views (with the same sequence set id) to the frame (if
2928 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2929 * views instead of separate frames. Note this doesn't restore a state where
2930 * some expanded views in turn have tabbed views - the last "first tab" read
2931 * in will play the role of gatherer for all.
2933 for (AlignFrame fr : gatherToThisFrame.values())
2935 Desktop.instance.gatherViews(fr);
2938 restoreSplitFrames();
2939 for (AlignmentI ds : importedDatasets.keySet())
2941 if (ds.getCodonFrames() != null)
2943 StructureSelectionManager
2944 .getStructureSelectionManager(Desktop.instance)
2945 .registerMappings(ds.getCodonFrames());
2948 if (errorMessage != null)
2953 if (Desktop.instance != null)
2955 Desktop.instance.stopLoading();
2962 * Try to reconstruct and display SplitFrame windows, where each contains
2963 * complementary dna and protein alignments. Done by pairing up AlignFrame
2964 * objects (created earlier) which have complementary viewport ids associated.
2966 protected void restoreSplitFrames()
2968 List<SplitFrame> gatherTo = new ArrayList<>();
2969 List<AlignFrame> addedToSplitFrames = new ArrayList<>();
2970 Map<String, AlignFrame> dna = new HashMap<>();
2973 * Identify the DNA alignments
2975 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2978 AlignFrame af = candidate.getValue();
2979 if (af.getViewport().getAlignment().isNucleotide())
2981 dna.put(candidate.getKey().getId(), af);
2986 * Try to match up the protein complements
2988 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2991 AlignFrame af = candidate.getValue();
2992 if (!af.getViewport().getAlignment().isNucleotide())
2994 String complementId = candidate.getKey().getComplementId();
2995 // only non-null complements should be in the Map
2996 if (complementId != null && dna.containsKey(complementId))
2998 final AlignFrame dnaFrame = dna.get(complementId);
2999 SplitFrame sf = createSplitFrame(dnaFrame, af);
3000 addedToSplitFrames.add(dnaFrame);
3001 addedToSplitFrames.add(af);
3002 dnaFrame.setMenusForViewport();
3003 af.setMenusForViewport();
3004 if (af.getViewport().isGatherViewsHere())
3013 * Open any that we failed to pair up (which shouldn't happen!) as
3014 * standalone AlignFrame's.
3016 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
3019 AlignFrame af = candidate.getValue();
3020 if (!addedToSplitFrames.contains(af))
3022 Viewport view = candidate.getKey();
3023 Desktop.addInternalFrame(af, view.getTitle(),
3024 safeInt(view.getWidth()), safeInt(view.getHeight()));
3025 af.setMenusForViewport();
3026 System.err.println("Failed to restore view " + view.getTitle()
3027 + " to split frame");
3032 * Gather back into tabbed views as flagged.
3034 for (SplitFrame sf : gatherTo)
3036 Desktop.instance.gatherViews(sf);
3039 splitFrameCandidates.clear();
3043 * Construct and display one SplitFrame holding DNA and protein alignments.
3046 * @param proteinFrame
3049 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
3050 AlignFrame proteinFrame)
3052 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
3053 String title = MessageManager.getString("label.linked_view_title");
3054 int width = (int) dnaFrame.getBounds().getWidth();
3055 int height = (int) (dnaFrame.getBounds().getHeight()
3056 + proteinFrame.getBounds().getHeight() + 50);
3059 * SplitFrame location is saved to both enclosed frames
3061 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
3062 Desktop.addInternalFrame(splitFrame, title, width, height);
3065 * And compute cDNA consensus (couldn't do earlier with consensus as
3066 * mappings were not yet present)
3068 proteinFrame.getViewport().alignmentChanged(proteinFrame.alignPanel);
3074 * check errorMessage for a valid error message and raise an error box in the
3075 * GUI or write the current errorMessage to stderr and then clear the error
3078 protected void reportErrors()
3080 reportErrors(false);
3083 protected void reportErrors(final boolean saving)
3085 if (errorMessage != null)
3087 final String finalErrorMessage = errorMessage;
3090 javax.swing.SwingUtilities.invokeLater(new Runnable()
3095 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
3097 "Error " + (saving ? "saving" : "loading")
3099 JvOptionPane.WARNING_MESSAGE);
3105 System.err.println("Problem loading Jalview file: " + errorMessage);
3108 errorMessage = null;
3111 Map<String, String> alreadyLoadedPDB = new HashMap<>();
3114 * when set, local views will be updated from view stored in JalviewXML
3115 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
3116 * sync if this is set to true.
3118 private final boolean updateLocalViews = false;
3121 * Returns the path to a temporary file holding the PDB file for the given PDB
3122 * id. The first time of asking, searches for a file of that name in the
3123 * Jalview project jar, and copies it to a new temporary file. Any repeat
3124 * requests just return the path to the file previously created.
3130 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId,
3133 if (alreadyLoadedPDB.containsKey(pdbId))
3135 return alreadyLoadedPDB.get(pdbId).toString();
3138 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb",
3140 if (tempFile != null)
3142 alreadyLoadedPDB.put(pdbId, tempFile);
3148 * Copies the jar entry of given name to a new temporary file and returns the
3149 * path to the file, or null if the entry is not found.
3152 * @param jarEntryName
3154 * a prefix for the temporary file name, must be at least three
3157 * null or original file - so new file can be given the same suffix
3161 protected String copyJarEntry(jarInputStreamProvider jprovider,
3162 String jarEntryName, String prefix, String origFile)
3164 BufferedReader in = null;
3165 PrintWriter out = null;
3166 String suffix = ".tmp";
3167 if (origFile == null)
3169 origFile = jarEntryName;
3171 int sfpos = origFile.lastIndexOf(".");
3172 if (sfpos > -1 && sfpos < (origFile.length() - 3))
3174 suffix = "." + origFile.substring(sfpos + 1);
3178 JarInputStream jin = jprovider.getJarInputStream();
3180 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
3181 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
3182 * FileInputStream(jprovider)); }
3185 JarEntry entry = null;
3188 entry = jin.getNextJarEntry();
3189 } while (entry != null && !entry.getName().equals(jarEntryName));
3192 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
3193 File outFile = File.createTempFile(prefix, suffix);
3194 outFile.deleteOnExit();
3195 out = new PrintWriter(new FileOutputStream(outFile));
3198 while ((data = in.readLine()) != null)
3203 String t = outFile.getAbsolutePath();
3208 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
3210 } catch (Exception ex)
3212 ex.printStackTrace();
3220 } catch (IOException e)
3234 private class JvAnnotRow
3236 public JvAnnotRow(int i, AlignmentAnnotation jaa)
3243 * persisted version of annotation row from which to take vis properties
3245 public jalview.datamodel.AlignmentAnnotation template;
3248 * original position of the annotation row in the alignment
3254 * Load alignment frame from jalview XML DOM object
3256 * @param jalviewModel
3259 * filename source string
3260 * @param loadTreesAndStructures
3261 * when false only create Viewport
3263 * data source provider
3264 * @return alignment frame created from view stored in DOM
3266 AlignFrame loadFromObject(JalviewModel jalviewModel, String file,
3267 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
3269 SequenceSet vamsasSet = jalviewModel.getVamsasModel().getSequenceSet().get(0);
3270 List<Sequence> vamsasSeqs = vamsasSet.getSequence();
3272 // JalviewModelSequence jms = object.getJalviewModelSequence();
3274 // Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
3276 Viewport view = (jalviewModel.getViewport().size() > 0)
3277 ? jalviewModel.getViewport().get(0)
3280 // ////////////////////////////////
3281 // INITIALISE ALIGNMENT SEQUENCESETID AND VIEWID
3284 // If we just load in the same jar file again, the sequenceSetId
3285 // will be the same, and we end up with multiple references
3286 // to the same sequenceSet. We must modify this id on load
3287 // so that each load of the file gives a unique id
3290 * used to resolve correct alignment dataset for alignments with multiple
3293 String uniqueSeqSetId = null;
3294 String viewId = null;
3297 uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3298 viewId = (view.getId() == null ? null
3299 : view.getId() + uniqueSetSuffix);
3302 // ////////////////////////////////
3305 List<SequenceI> hiddenSeqs = null;
3307 List<SequenceI> tmpseqs = new ArrayList<>();
3309 boolean multipleView = false;
3310 SequenceI referenceseqForView = null;
3311 // JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
3312 List<JSeq> jseqs = jalviewModel.getJSeq();
3313 int vi = 0; // counter in vamsasSeq array
3314 for (int i = 0; i < jseqs.size(); i++)
3316 JSeq jseq = jseqs.get(i);
3317 String seqId = jseq.getId();
3319 SequenceI tmpSeq = seqRefIds.get(seqId);
3322 if (!incompleteSeqs.containsKey(seqId))
3324 // may not need this check, but keep it for at least 2.9,1 release
3325 if (tmpSeq.getStart() != jseq.getStart()
3326 || tmpSeq.getEnd() != jseq.getEnd())
3329 "Warning JAL-2154 regression: updating start/end for sequence "
3330 + tmpSeq.toString() + " to " + jseq);
3335 incompleteSeqs.remove(seqId);
3337 if (vamsasSeqs.size() > vi
3338 && vamsasSeqs.get(vi).getId().equals(seqId))
3340 // most likely we are reading a dataset XML document so
3341 // update from vamsasSeq section of XML for this sequence
3342 tmpSeq.setName(vamsasSeqs.get(vi).getName());
3343 tmpSeq.setDescription(vamsasSeqs.get(vi).getDescription());
3344 tmpSeq.setSequence(vamsasSeqs.get(vi).getSequence());
3349 // reading multiple views, so vamsasSeq set is a subset of JSeq
3350 multipleView = true;
3352 tmpSeq.setStart(jseq.getStart());
3353 tmpSeq.setEnd(jseq.getEnd());
3354 tmpseqs.add(tmpSeq);
3358 Sequence vamsasSeq = vamsasSeqs.get(vi);
3359 tmpSeq = new jalview.datamodel.Sequence(vamsasSeq.getName(),
3360 vamsasSeq.getSequence());
3361 tmpSeq.setDescription(vamsasSeq.getDescription());
3362 tmpSeq.setStart(jseq.getStart());
3363 tmpSeq.setEnd(jseq.getEnd());
3364 tmpSeq.setVamsasId(uniqueSetSuffix + seqId);
3365 seqRefIds.put(vamsasSeq.getId(), tmpSeq);
3366 tmpseqs.add(tmpSeq);
3370 if (safeBoolean(jseq.isViewreference()))
3372 referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
3375 if (jseq.isHidden() != null && jseq.isHidden().booleanValue())
3377 if (hiddenSeqs == null)
3379 hiddenSeqs = new ArrayList<>();
3382 hiddenSeqs.add(tmpSeq);
3387 // Create the alignment object from the sequence set
3388 // ///////////////////////////////
3389 SequenceI[] orderedSeqs = tmpseqs
3390 .toArray(new SequenceI[tmpseqs.size()]);
3392 AlignmentI al = null;
3393 // so we must create or recover the dataset alignment before going further
3394 // ///////////////////////////////
3395 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
3397 // older jalview projects do not have a dataset - so creat alignment and
3399 al = new Alignment(orderedSeqs);
3400 al.setDataset(null);
3404 boolean isdsal = jalviewModel.getViewport().isEmpty();
3407 // we are importing a dataset record, so
3408 // recover reference to an alignment already materialsed as dataset
3409 al = getDatasetFor(vamsasSet.getDatasetId());
3413 // materialse the alignment
3414 al = new Alignment(orderedSeqs);
3418 addDatasetRef(vamsasSet.getDatasetId(), al);
3421 // finally, verify all data in vamsasSet is actually present in al
3422 // passing on flag indicating if it is actually a stored dataset
3423 recoverDatasetFor(vamsasSet, al, isdsal, uniqueSeqSetId);
3426 if (referenceseqForView != null)
3428 al.setSeqrep(referenceseqForView);
3430 // / Add the alignment properties
3431 for (int i = 0; i < vamsasSet.getSequenceSetProperties().size(); i++)
3433 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties()
3435 al.setProperty(ssp.getKey(), ssp.getValue());
3438 // ///////////////////////////////
3440 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
3443 // load sequence features, database references and any associated PDB
3444 // structures for the alignment
3446 // prior to 2.10, this part would only be executed the first time a
3447 // sequence was encountered, but not afterwards.
3448 // now, for 2.10 projects, this is also done if the xml doc includes
3449 // dataset sequences not actually present in any particular view.
3451 for (int i = 0; i < vamsasSeqs.size(); i++)
3453 JSeq jseq = jseqs.get(i);
3454 if (jseq.getFeatures().size() > 0)
3456 List<Feature> features = jseq.getFeatures();
3457 for (int f = 0; f < features.size(); f++)
3459 Feature feat = features.get(f);
3460 SequenceFeature sf = new SequenceFeature(feat.getType(),
3461 feat.getDescription(), feat.getBegin(), feat.getEnd(),
3462 safeFloat(feat.getScore()), feat.getFeatureGroup());
3463 sf.setStatus(feat.getStatus());
3466 * load any feature attributes - include map-valued attributes
3468 Map<String, Map<String, String>> mapAttributes = new HashMap<>();
3469 for (int od = 0; od < feat.getOtherData().size(); od++)
3471 OtherData keyValue = feat.getOtherData().get(od);
3472 String attributeName = keyValue.getKey();
3473 String attributeValue = keyValue.getValue();
3474 if (attributeName.startsWith("LINK"))
3476 sf.addLink(attributeValue);
3480 String subAttribute = keyValue.getKey2();
3481 if (subAttribute == null)
3483 // simple string-valued attribute
3484 sf.setValue(attributeName, attributeValue);
3488 // attribute 'key' has sub-attribute 'key2'
3489 if (!mapAttributes.containsKey(attributeName))
3491 mapAttributes.put(attributeName, new HashMap<>());
3493 mapAttributes.get(attributeName).put(subAttribute,
3498 for (Entry<String, Map<String, String>> mapAttribute : mapAttributes
3501 sf.setValue(mapAttribute.getKey(), mapAttribute.getValue());
3504 // adds feature to datasequence's feature set (since Jalview 2.10)
3505 al.getSequenceAt(i).addSequenceFeature(sf);
3508 if (vamsasSeqs.get(i).getDBRef().size() > 0)
3510 // adds dbrefs to datasequence's set (since Jalview 2.10)
3512 al.getSequenceAt(i).getDatasetSequence() == null
3513 ? al.getSequenceAt(i)
3514 : al.getSequenceAt(i).getDatasetSequence(),
3517 if (jseq.getPdbids().size() > 0)
3519 List<Pdbids> ids = jseq.getPdbids();
3520 for (int p = 0; p < ids.size(); p++)
3522 Pdbids pdbid = ids.get(p);
3523 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
3524 entry.setId(pdbid.getId());
3525 if (pdbid.getType() != null)
3527 if (PDBEntry.Type.getType(pdbid.getType()) != null)
3529 entry.setType(PDBEntry.Type.getType(pdbid.getType()));
3533 entry.setType(PDBEntry.Type.FILE);
3536 // jprovider is null when executing 'New View'
3537 if (pdbid.getFile() != null && jprovider != null)
3539 if (!pdbloaded.containsKey(pdbid.getFile()))
3541 entry.setFile(loadPDBFile(jprovider, pdbid.getId(),
3546 entry.setFile(pdbloaded.get(pdbid.getId()).toString());
3550 if (pdbid.getPdbentryItem() != null)
3552 for (PdbentryItem item : pdbid.getPdbentryItem())
3554 for (Property pr : item.getProperty())
3556 entry.setProperty(pr.getName(), pr.getValue());
3561 for (Property prop : pdbid.getProperty())
3563 entry.setProperty(prop.getName(), prop.getValue());
3565 StructureSelectionManager
3566 .getStructureSelectionManager(Desktop.instance)
3567 .registerPDBEntry(entry);
3568 // adds PDBEntry to datasequence's set (since Jalview 2.10)
3569 if (al.getSequenceAt(i).getDatasetSequence() != null)
3571 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
3575 al.getSequenceAt(i).addPDBId(entry);
3580 } // end !multipleview
3582 // ///////////////////////////////
3583 // LOAD SEQUENCE MAPPINGS
3585 if (vamsasSet.getAlcodonFrame().size() > 0)
3587 // TODO Potentially this should only be done once for all views of an
3589 List<AlcodonFrame> alc = vamsasSet.getAlcodonFrame();
3590 for (int i = 0; i < alc.size(); i++)
3592 AlignedCodonFrame cf = new AlignedCodonFrame();
3593 if (alc.get(i).getAlcodMap().size() > 0)
3595 List<AlcodMap> maps = alc.get(i).getAlcodMap();
3596 for (int m = 0; m < maps.size(); m++)
3598 AlcodMap map = maps.get(m);
3599 SequenceI dnaseq = seqRefIds.get(map.getDnasq());
3601 jalview.datamodel.Mapping mapping = null;
3602 // attach to dna sequence reference.
3603 if (map.getMapping() != null)
3605 mapping = addMapping(map.getMapping());
3606 if (dnaseq != null && mapping.getTo() != null)
3608 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
3614 newAlcodMapRef(map.getDnasq(), cf, mapping));
3618 al.addCodonFrame(cf);
3623 // ////////////////////////////////
3625 List<JvAnnotRow> autoAlan = new ArrayList<>();
3628 * store any annotations which forward reference a group's ID
3630 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<>();
3632 if (vamsasSet.getAnnotation().size()/*Count()*/ > 0)
3634 List<Annotation> an = vamsasSet.getAnnotation();
3636 for (int i = 0; i < an.size(); i++)
3638 Annotation annotation = an.get(i);
3641 * test if annotation is automatically calculated for this view only
3643 boolean autoForView = false;
3644 if (annotation.getLabel().equals("Quality")
3645 || annotation.getLabel().equals("Conservation")
3646 || annotation.getLabel().equals("Consensus"))
3648 // Kludge for pre 2.5 projects which lacked the autocalculated flag
3650 // JAXB has no has() test; schema defaults value to false
3651 // if (!annotation.hasAutoCalculated())
3653 // annotation.setAutoCalculated(true);
3656 if (autoForView || annotation.isAutoCalculated())
3658 // remove ID - we don't recover annotation from other views for
3659 // view-specific annotation
3660 annotation.setId(null);
3663 // set visibility for other annotation in this view
3664 String annotationId = annotation.getId();
3665 if (annotationId != null && annotationIds.containsKey(annotationId))
3667 AlignmentAnnotation jda = annotationIds.get(annotationId);
3668 // in principle Visible should always be true for annotation displayed
3669 // in multiple views
3670 if (annotation.isVisible() != null)
3672 jda.visible = annotation.isVisible();
3675 al.addAnnotation(jda);
3679 // Construct new annotation from model.
3680 List<AnnotationElement> ae = annotation.getAnnotationElement();
3681 jalview.datamodel.Annotation[] anot = null;
3682 java.awt.Color firstColour = null;
3684 if (!annotation.isScoreOnly())
3686 anot = new jalview.datamodel.Annotation[al.getWidth()];
3687 for (int aa = 0; aa < ae.size() && aa < anot.length; aa++)
3689 AnnotationElement annElement = ae.get(aa);
3690 anpos = annElement.getPosition();
3692 if (anpos >= anot.length)
3697 float value = safeFloat(annElement.getValue());
3698 anot[anpos] = new jalview.datamodel.Annotation(
3699 annElement.getDisplayCharacter(),
3700 annElement.getDescription(),
3701 (annElement.getSecondaryStructure() == null
3702 || annElement.getSecondaryStructure()
3706 .getSecondaryStructure()
3709 anot[anpos].colour = new Color(safeInt(annElement.getColour()));
3710 if (firstColour == null)
3712 firstColour = anot[anpos].colour;
3716 jalview.datamodel.AlignmentAnnotation jaa = null;
3718 if (annotation.isGraph())
3720 float llim = 0, hlim = 0;
3721 // if (autoForView || an[i].isAutoCalculated()) {
3724 jaa = new jalview.datamodel.AlignmentAnnotation(
3725 annotation.getLabel(), annotation.getDescription(), anot,
3726 llim, hlim, safeInt(annotation.getGraphType()));
3728 jaa.graphGroup = safeInt(annotation.getGraphGroup());
3729 jaa._linecolour = firstColour;
3730 if (annotation.getThresholdLine() != null)
3732 jaa.setThreshold(new jalview.datamodel.GraphLine(
3733 safeFloat(annotation.getThresholdLine().getValue()),
3734 annotation.getThresholdLine().getLabel(),
3735 new java.awt.Color(safeInt(
3736 annotation.getThresholdLine().getColour()))));
3738 if (autoForView || annotation.isAutoCalculated())
3740 // Hardwire the symbol display line to ensure that labels for
3741 // histograms are displayed
3747 jaa = new jalview.datamodel.AlignmentAnnotation(
3748 annotation.getLabel(), annotation.getDescription(), anot);
3749 jaa._linecolour = firstColour;
3751 // register new annotation
3752 if (annotation.getId() != null)
3754 annotationIds.put(annotation.getId(), jaa);
3755 jaa.annotationId = annotation.getId();
3757 // recover sequence association
3758 String sequenceRef = annotation.getSequenceRef();
3759 if (sequenceRef != null)
3761 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3762 SequenceI sequence = seqRefIds.get(sequenceRef);
3763 if (sequence == null)
3765 // in pre-2.9 projects sequence ref is to sequence name
3766 sequence = al.findName(sequenceRef);
3768 if (sequence != null)
3770 jaa.createSequenceMapping(sequence, 1, true);
3771 sequence.addAlignmentAnnotation(jaa);
3774 // and make a note of any group association
3775 if (annotation.getGroupRef() != null
3776 && annotation.getGroupRef().length() > 0)
3778 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3779 .get(annotation.getGroupRef());
3782 aal = new ArrayList<>();
3783 groupAnnotRefs.put(annotation.getGroupRef(), aal);
3788 if (annotation.getScore() != null)
3790 jaa.setScore(annotation.getScore().doubleValue());
3792 if (annotation.isVisible() != null)
3794 jaa.visible = annotation.isVisible().booleanValue();
3797 if (annotation.isCentreColLabels() != null)
3799 jaa.centreColLabels = annotation.isCentreColLabels()
3803 if (annotation.isScaleColLabels() != null)
3805 jaa.scaleColLabel = annotation.isScaleColLabels().booleanValue();
3807 if (annotation.isAutoCalculated())
3809 // newer files have an 'autoCalculated' flag and store calculation
3810 // state in viewport properties
3811 jaa.autoCalculated = true; // means annotation will be marked for
3812 // update at end of load.
3814 if (annotation.getGraphHeight() != null)
3816 jaa.graphHeight = annotation.getGraphHeight().intValue();
3818 jaa.belowAlignment = annotation.isBelowAlignment();
3819 jaa.setCalcId(annotation.getCalcId());
3820 if (annotation.getProperty().size() > 0)
3822 for (Annotation.Property prop : annotation
3825 jaa.setProperty(prop.getName(), prop.getValue());
3828 if (jaa.autoCalculated)
3830 autoAlan.add(new JvAnnotRow(i, jaa));
3833 // if (!autoForView)
3835 // add autocalculated group annotation and any user created annotation
3837 al.addAnnotation(jaa);
3841 // ///////////////////////
3843 // Create alignment markup and styles for this view
3844 if (jalviewModel.getJGroup().size() > 0)
3846 List<JGroup> groups = jalviewModel.getJGroup();
3847 boolean addAnnotSchemeGroup = false;
3848 for (int i = 0; i < groups.size(); i++)
3850 JGroup jGroup = groups.get(i);
3851 ColourSchemeI cs = null;
3852 if (jGroup.getColour() != null)
3854 if (jGroup.getColour().startsWith("ucs"))
3856 cs = getUserColourScheme(jalviewModel, jGroup.getColour());
3858 else if (jGroup.getColour().equals("AnnotationColourGradient")
3859 && jGroup.getAnnotationColours() != null)
3861 addAnnotSchemeGroup = true;
3865 cs = ColourSchemeProperty.getColourScheme(null, al,
3866 jGroup.getColour());
3869 int pidThreshold = safeInt(jGroup.getPidThreshold());
3871 Vector<SequenceI> seqs = new Vector<>();
3873 for (int s = 0; s < jGroup.getSeq().size(); s++)
3875 String seqId = jGroup.getSeq().get(s);
3876 SequenceI ts = seqRefIds.get(seqId);
3880 seqs.addElement(ts);
3884 if (seqs.size() < 1)
3889 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3890 safeBoolean(jGroup.isDisplayBoxes()),
3891 safeBoolean(jGroup.isDisplayText()),
3892 safeBoolean(jGroup.isColourText()),
3893 safeInt(jGroup.getStart()), safeInt(jGroup.getEnd()));
3894 sg.getGroupColourScheme().setThreshold(pidThreshold, true);
3895 sg.getGroupColourScheme()
3896 .setConservationInc(safeInt(jGroup.getConsThreshold()));
3897 sg.setOutlineColour(new Color(safeInt(jGroup.getOutlineColour())));
3899 sg.textColour = new Color(safeInt(jGroup.getTextCol1()));
3900 sg.textColour2 = new Color(safeInt(jGroup.getTextCol2()));
3901 sg.setShowNonconserved(safeBoolean(jGroup.isShowUnconserved()));
3902 sg.thresholdTextColour = safeInt(jGroup.getTextColThreshold());
3903 // attributes with a default in the schema are never null
3904 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3905 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3906 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3907 sg.setIgnoreGapsConsensus(jGroup.isIgnoreGapsinConsensus());
3908 if (jGroup.getConsThreshold() != null
3909 && jGroup.getConsThreshold().intValue() != 0)
3911 Conservation c = new Conservation("All", sg.getSequences(null), 0,
3914 c.verdict(false, 25);
3915 sg.cs.setConservation(c);
3918 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3920 // re-instate unique group/annotation row reference
3921 List<AlignmentAnnotation> jaal = groupAnnotRefs
3922 .get(jGroup.getId());
3925 for (AlignmentAnnotation jaa : jaal)
3928 if (jaa.autoCalculated)
3930 // match up and try to set group autocalc alignment row for this
3932 if (jaa.label.startsWith("Consensus for "))
3934 sg.setConsensus(jaa);
3936 // match up and try to set group autocalc alignment row for this
3938 if (jaa.label.startsWith("Conservation for "))
3940 sg.setConservationRow(jaa);
3947 if (addAnnotSchemeGroup)
3949 // reconstruct the annotation colourscheme
3950 sg.setColourScheme(constructAnnotationColour(
3951 jGroup.getAnnotationColours(), null, al, jalviewModel, false));
3957 // only dataset in this model, so just return.
3960 // ///////////////////////////////
3963 AlignFrame af = null;
3964 AlignViewport av = null;
3965 // now check to see if we really need to create a new viewport.
3966 if (multipleView && viewportsAdded.size() == 0)
3968 // We recovered an alignment for which a viewport already exists.
3969 // TODO: fix up any settings necessary for overlaying stored state onto
3970 // state recovered from another document. (may not be necessary).
3971 // we may need a binding from a viewport in memory to one recovered from
3973 // and then recover its containing af to allow the settings to be applied.
3974 // TODO: fix for vamsas demo
3976 "About to recover a viewport for existing alignment: Sequence set ID is "
3978 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3979 if (seqsetobj != null)
3981 if (seqsetobj instanceof String)
3983 uniqueSeqSetId = (String) seqsetobj;
3985 "Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
3991 "Warning : Collision between sequence set ID string and existing jalview object mapping.");
3997 * indicate that annotation colours are applied across all groups (pre
3998 * Jalview 2.8.1 behaviour)
4000 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan("2.8.1",
4001 jalviewModel.getVersion());
4003 AlignmentPanel ap = null;
4004 boolean isnewview = true;
4007 // Check to see if this alignment already has a view id == viewId
4008 jalview.gui.AlignmentPanel views[] = Desktop
4009 .getAlignmentPanels(uniqueSeqSetId);
4010 if (views != null && views.length > 0)
4012 for (int v = 0; v < views.length; v++)
4014 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
4016 // recover the existing alignpanel, alignframe, viewport
4017 af = views[v].alignFrame;
4020 // TODO: could even skip resetting view settings if we don't want to
4021 // change the local settings from other jalview processes
4030 af = loadViewport(file, jseqs, hiddenSeqs, al, jalviewModel, view,
4031 uniqueSeqSetId, viewId, autoAlan);
4032 av = af.getViewport();
4037 * Load any trees, PDB structures and viewers
4039 * Not done if flag is false (when this method is used for New View)
4041 if (loadTreesAndStructures)
4043 loadTrees(jalviewModel, view, af, av, ap);
4044 loadPCAViewers(jalviewModel, ap);
4045 loadPDBStructures(jprovider, jseqs, af, ap);
4046 loadRnaViewers(jprovider, jseqs, ap);
4048 // and finally return.
4053 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
4054 * panel is restored from separate jar entries, two (gapped and trimmed) per
4055 * sequence and secondary structure.
4057 * Currently each viewer shows just one sequence and structure (gapped and
4058 * trimmed), however this method is designed to support multiple sequences or
4059 * structures in viewers if wanted in future.
4065 private void loadRnaViewers(jarInputStreamProvider jprovider,
4066 List<JSeq> jseqs, AlignmentPanel ap)
4069 * scan the sequences for references to viewers; create each one the first
4070 * time it is referenced, add Rna models to existing viewers
4072 for (JSeq jseq : jseqs)
4074 for (int i = 0; i < jseq.getRnaViewer().size(); i++)
4076 RnaViewer viewer = jseq.getRnaViewer().get(i);
4077 AppVarna appVarna = findOrCreateVarnaViewer(viewer, uniqueSetSuffix,
4080 for (int j = 0; j < viewer.getSecondaryStructure().size(); j++)
4082 SecondaryStructure ss = viewer.getSecondaryStructure().get(j);
4083 SequenceI seq = seqRefIds.get(jseq.getId());
4084 AlignmentAnnotation ann = this.annotationIds
4085 .get(ss.getAnnotationId());
4088 * add the structure to the Varna display (with session state copied
4089 * from the jar to a temporary file)
4091 boolean gapped = safeBoolean(ss.isGapped());
4092 String rnaTitle = ss.getTitle();
4093 String sessionState = ss.getViewerState();
4094 String tempStateFile = copyJarEntry(jprovider, sessionState,
4096 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
4097 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
4099 appVarna.setInitialSelection(safeInt(viewer.getSelectedRna()));
4105 * Locate and return an already instantiated matching AppVarna, or create one
4109 * @param viewIdSuffix
4113 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
4114 String viewIdSuffix, AlignmentPanel ap)
4117 * on each load a suffix is appended to the saved viewId, to avoid conflicts
4118 * if load is repeated
4120 String postLoadId = viewer.getViewId() + viewIdSuffix;
4121 for (JInternalFrame frame : getAllFrames())
4123 if (frame instanceof AppVarna)
4125 AppVarna varna = (AppVarna) frame;
4126 if (postLoadId.equals(varna.getViewId()))
4128 // this viewer is already instantiated
4129 // could in future here add ap as another 'parent' of the
4130 // AppVarna window; currently just 1-to-many
4137 * viewer not found - make it
4139 RnaViewerModel model = new RnaViewerModel(postLoadId, viewer.getTitle(),
4140 safeInt(viewer.getXpos()), safeInt(viewer.getYpos()),
4141 safeInt(viewer.getWidth()), safeInt(viewer.getHeight()),
4142 safeInt(viewer.getDividerLocation()));
4143 AppVarna varna = new AppVarna(model, ap);
4149 * Load any saved trees
4157 protected void loadTrees(JalviewModel jm, Viewport view,
4158 AlignFrame af, AlignViewport av, AlignmentPanel ap)
4160 // TODO result of automated refactoring - are all these parameters needed?
4163 for (int t = 0; t < jm.getTree().size(); t++)
4166 Tree tree = jm.getTree().get(t);
4168 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
4171 tp = af.showNewickTree(new NewickFile(tree.getNewick()),
4172 tree.getTitle(), safeInt(tree.getWidth()),
4173 safeInt(tree.getHeight()), safeInt(tree.getXpos()),
4174 safeInt(tree.getYpos()));
4175 if (tree.getId() != null)
4177 // perhaps bind the tree id to something ?
4182 // update local tree attributes ?
4183 // TODO: should check if tp has been manipulated by user - if so its
4184 // settings shouldn't be modified
4185 tp.setTitle(tree.getTitle());
4186 tp.setBounds(new Rectangle(safeInt(tree.getXpos()),
4187 safeInt(tree.getYpos()), safeInt(tree.getWidth()),
4188 safeInt(tree.getHeight())));
4189 tp.setViewport(av); // af.viewport;
4190 // TODO: verify 'associate with all views' works still
4191 tp.getTreeCanvas().setViewport(av); // af.viewport;
4192 tp.getTreeCanvas().setAssociatedPanel(ap); // af.alignPanel;
4194 tp.getTreeCanvas().setApplyToAllViews(tree.isLinkToAllViews());
4197 warn("There was a problem recovering stored Newick tree: \n"
4198 + tree.getNewick());
4202 tp.fitToWindow.setState(safeBoolean(tree.isFitToWindow()));
4203 tp.fitToWindow_actionPerformed(null);
4205 if (tree.getFontName() != null)
4208 new Font(tree.getFontName(), safeInt(tree.getFontStyle()),
4209 safeInt(tree.getFontSize())));
4214 new Font(view.getFontName(), safeInt(view.getFontStyle()),
4215 safeInt(view.getFontSize())));
4218 tp.showPlaceholders(safeBoolean(tree.isMarkUnlinked()));
4219 tp.showBootstrap(safeBoolean(tree.isShowBootstrap()));
4220 tp.showDistances(safeBoolean(tree.isShowDistances()));
4222 tp.getTreeCanvas().setThreshold(safeFloat(tree.getThreshold()));
4224 if (safeBoolean(tree.isCurrentTree()))
4226 af.getViewport().setCurrentTree(tp.getTree());
4230 } catch (Exception ex)
4232 ex.printStackTrace();
4237 * Load and link any saved structure viewers.
4244 protected void loadPDBStructures(jarInputStreamProvider jprovider,
4245 List<JSeq> jseqs, AlignFrame af, AlignmentPanel ap)
4248 * Run through all PDB ids on the alignment, and collect mappings between
4249 * distinct view ids and all sequences referring to that view.
4251 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<>();
4253 for (int i = 0; i < jseqs.size(); i++)
4255 JSeq jseq = jseqs.get(i);
4256 if (jseq.getPdbids().size() > 0)
4258 List<Pdbids> ids = jseq.getPdbids();
4259 for (int p = 0; p < ids.size(); p++)
4261 Pdbids pdbid = ids.get(p);
4262 final int structureStateCount = pdbid.getStructureState().size();
4263 for (int s = 0; s < structureStateCount; s++)
4265 // check to see if we haven't already created this structure view
4266 final StructureState structureState = pdbid
4267 .getStructureState().get(s);
4268 String sviewid = (structureState.getViewId() == null) ? null
4269 : structureState.getViewId() + uniqueSetSuffix;
4270 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
4271 // Originally : pdbid.getFile()
4272 // : TODO: verify external PDB file recovery still works in normal
4273 // jalview project load
4275 loadPDBFile(jprovider, pdbid.getId(), pdbid.getFile()));
4276 jpdb.setId(pdbid.getId());
4278 int x = safeInt(structureState.getXpos());
4279 int y = safeInt(structureState.getYpos());
4280 int width = safeInt(structureState.getWidth());
4281 int height = safeInt(structureState.getHeight());
4283 // Probably don't need to do this anymore...
4284 // Desktop.desktop.getComponentAt(x, y);
4285 // TODO: NOW: check that this recovers the PDB file correctly.
4286 String pdbFile = loadPDBFile(jprovider, pdbid.getId(),
4288 jalview.datamodel.SequenceI seq = seqRefIds
4289 .get(jseq.getId() + "");
4290 if (sviewid == null)
4292 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width + ","
4295 if (!structureViewers.containsKey(sviewid))
4297 structureViewers.put(sviewid,
4298 new StructureViewerModel(x, y, width, height, false,
4299 false, true, structureState.getViewId(),
4300 structureState.getType()));
4301 // Legacy pre-2.7 conversion JAL-823 :
4302 // do not assume any view has to be linked for colour by
4306 // assemble String[] { pdb files }, String[] { id for each
4307 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
4308 // seqs_file 2}, boolean[] {
4309 // linkAlignPanel,superposeWithAlignpanel}} from hash
4310 StructureViewerModel jmoldat = structureViewers.get(sviewid);
4311 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
4312 || structureState.isAlignwithAlignPanel());
4315 * Default colour by linked panel to false if not specified (e.g.
4316 * for pre-2.7 projects)
4318 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
4319 colourWithAlignPanel |= structureState.isColourwithAlignPanel();
4320 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
4323 * Default colour by viewer to true if not specified (e.g. for
4326 boolean colourByViewer = jmoldat.isColourByViewer();
4327 colourByViewer &= structureState.isColourByJmol();
4328 jmoldat.setColourByViewer(colourByViewer);
4330 if (jmoldat.getStateData().length() < structureState
4331 .getValue()/*Content()*/.length())
4333 jmoldat.setStateData(structureState.getValue());// Content());
4335 if (pdbid.getFile() != null)
4337 File mapkey = new File(pdbid.getFile());
4338 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
4339 if (seqstrmaps == null)
4341 jmoldat.getFileData().put(mapkey,
4342 seqstrmaps = jmoldat.new StructureData(pdbFile,
4345 if (!seqstrmaps.getSeqList().contains(seq))
4347 seqstrmaps.getSeqList().add(seq);
4353 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");
4360 // Instantiate the associated structure views
4361 for (Entry<String, StructureViewerModel> entry : structureViewers
4366 createOrLinkStructureViewer(entry, af, ap, jprovider);
4367 } catch (Exception e)
4370 "Error loading structure viewer: " + e.getMessage());
4371 // failed - try the next one
4383 protected void createOrLinkStructureViewer(
4384 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4385 AlignmentPanel ap, jarInputStreamProvider jprovider)
4387 final StructureViewerModel stateData = viewerData.getValue();
4390 * Search for any viewer windows already open from other alignment views
4391 * that exactly match the stored structure state
4393 StructureViewerBase comp = findMatchingViewer(viewerData);
4397 linkStructureViewer(ap, comp, stateData);
4402 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
4403 * "viewer_"+stateData.viewId
4405 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
4407 createChimeraViewer(viewerData, af, jprovider);
4412 * else Jmol (if pre-2.9, stateData contains JMOL state string)
4414 createJmolViewer(viewerData, af, jprovider);
4419 * Create a new Chimera viewer.
4425 protected void createChimeraViewer(
4426 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4427 jarInputStreamProvider jprovider)
4429 StructureViewerModel data = viewerData.getValue();
4430 String chimeraSessionFile = data.getStateData();
4433 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
4435 * NB this is the 'saved' viewId as in the project file XML, _not_ the
4436 * 'uniquified' sviewid used to reconstruct the viewer here
4438 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
4439 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
4442 Set<Entry<File, StructureData>> fileData = data.getFileData()
4444 List<PDBEntry> pdbs = new ArrayList<>();
4445 List<SequenceI[]> allseqs = new ArrayList<>();
4446 for (Entry<File, StructureData> pdb : fileData)
4448 String filePath = pdb.getValue().getFilePath();
4449 String pdbId = pdb.getValue().getPdbId();
4450 // pdbs.add(new PDBEntry(filePath, pdbId));
4451 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
4452 final List<SequenceI> seqList = pdb.getValue().getSeqList();
4453 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
4457 boolean colourByChimera = data.isColourByViewer();
4458 boolean colourBySequence = data.isColourWithAlignPanel();
4460 // TODO use StructureViewer as a factory here, see JAL-1761
4461 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
4462 final SequenceI[][] seqsArray = allseqs
4463 .toArray(new SequenceI[allseqs.size()][]);
4464 String newViewId = viewerData.getKey();
4466 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
4467 af.alignPanel, pdbArray, seqsArray, colourByChimera,
4468 colourBySequence, newViewId);
4469 cvf.setSize(data.getWidth(), data.getHeight());
4470 cvf.setLocation(data.getX(), data.getY());
4474 * Create a new Jmol window. First parse the Jmol state to translate filenames
4475 * loaded into the view, and record the order in which files are shown in the
4476 * Jmol view, so we can add the sequence mappings in same order.
4482 protected void createJmolViewer(
4483 final Entry<String, StructureViewerModel> viewerData,
4484 AlignFrame af, jarInputStreamProvider jprovider)
4486 final StructureViewerModel svattrib = viewerData.getValue();
4487 String state = svattrib.getStateData();
4490 * Pre-2.9: state element value is the Jmol state string
4492 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
4495 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
4497 state = readJarEntry(jprovider,
4498 getViewerJarEntryName(svattrib.getViewId()));
4501 List<String> pdbfilenames = new ArrayList<>();
4502 List<SequenceI[]> seqmaps = new ArrayList<>();
4503 List<String> pdbids = new ArrayList<>();
4504 StringBuilder newFileLoc = new StringBuilder(64);
4505 int cp = 0, ncp, ecp;
4506 Map<File, StructureData> oldFiles = svattrib.getFileData();
4507 while ((ncp = state.indexOf("load ", cp)) > -1)
4511 // look for next filename in load statement
4512 newFileLoc.append(state.substring(cp,
4513 ncp = (state.indexOf("\"", ncp + 1) + 1)));
4514 String oldfilenam = state.substring(ncp,
4515 ecp = state.indexOf("\"", ncp));
4516 // recover the new mapping data for this old filename
4517 // have to normalize filename - since Jmol and jalview do
4519 // translation differently.
4520 StructureData filedat = oldFiles.get(new File(oldfilenam));
4521 if (filedat == null)
4523 String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\");
4524 filedat = oldFiles.get(new File(reformatedOldFilename));
4526 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
4527 pdbfilenames.add(filedat.getFilePath());
4528 pdbids.add(filedat.getPdbId());
4529 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4530 newFileLoc.append("\"");
4531 cp = ecp + 1; // advance beyond last \" and set cursor so we can
4532 // look for next file statement.
4533 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
4537 // just append rest of state
4538 newFileLoc.append(state.substring(cp));
4542 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
4543 newFileLoc = new StringBuilder(state);
4544 newFileLoc.append("; load append ");
4545 for (File id : oldFiles.keySet())
4547 // add this and any other pdb files that should be present in
4549 StructureData filedat = oldFiles.get(id);
4550 newFileLoc.append(filedat.getFilePath());
4551 pdbfilenames.add(filedat.getFilePath());
4552 pdbids.add(filedat.getPdbId());
4553 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4554 newFileLoc.append(" \"");
4555 newFileLoc.append(filedat.getFilePath());
4556 newFileLoc.append("\"");
4559 newFileLoc.append(";");
4562 if (newFileLoc.length() == 0)
4566 int histbug = newFileLoc.indexOf("history = ");
4570 * change "history = [true|false];" to "history = [1|0];"
4573 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
4574 String val = (diff == -1) ? null
4575 : newFileLoc.substring(histbug, diff);
4576 if (val != null && val.length() >= 4)
4578 if (val.contains("e")) // eh? what can it be?
4580 if (val.trim().equals("true"))
4588 newFileLoc.replace(histbug, diff, val);
4593 final String[] pdbf = pdbfilenames
4594 .toArray(new String[pdbfilenames.size()]);
4595 final String[] id = pdbids.toArray(new String[pdbids.size()]);
4596 final SequenceI[][] sq = seqmaps
4597 .toArray(new SequenceI[seqmaps.size()][]);
4598 final String fileloc = newFileLoc.toString();
4599 final String sviewid = viewerData.getKey();
4600 final AlignFrame alf = af;
4601 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
4602 svattrib.getWidth(), svattrib.getHeight());
4605 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
4610 JalviewStructureDisplayI sview = null;
4613 sview = new StructureViewer(
4614 alf.alignPanel.getStructureSelectionManager())
4615 .createView(StructureViewer.ViewerType.JMOL,
4616 pdbf, id, sq, alf.alignPanel, svattrib,
4617 fileloc, rect, sviewid);
4618 addNewStructureViewer(sview);
4619 } catch (OutOfMemoryError ex)
4621 new OOMWarning("restoring structure view for PDB id " + id,
4622 (OutOfMemoryError) ex.getCause());
4623 if (sview != null && sview.isVisible())
4625 sview.closeViewer(false);
4626 sview.setVisible(false);
4632 } catch (InvocationTargetException ex)
4634 warn("Unexpected error when opening Jmol view.", ex);
4636 } catch (InterruptedException e)
4638 // e.printStackTrace();
4644 * Generates a name for the entry in the project jar file to hold state
4645 * information for a structure viewer
4650 protected String getViewerJarEntryName(String viewId)
4652 return VIEWER_PREFIX + viewId;
4656 * Returns any open frame that matches given structure viewer data. The match
4657 * is based on the unique viewId, or (for older project versions) the frame's
4663 protected StructureViewerBase findMatchingViewer(
4664 Entry<String, StructureViewerModel> viewerData)
4666 final String sviewid = viewerData.getKey();
4667 final StructureViewerModel svattrib = viewerData.getValue();
4668 StructureViewerBase comp = null;
4669 JInternalFrame[] frames = getAllFrames();
4670 for (JInternalFrame frame : frames)
4672 if (frame instanceof StructureViewerBase)
4675 * Post jalview 2.4 schema includes structure view id
4677 if (sviewid != null && ((StructureViewerBase) frame).getViewId()
4680 comp = (StructureViewerBase) frame;
4681 break; // break added in 2.9
4684 * Otherwise test for matching position and size of viewer frame
4686 else if (frame.getX() == svattrib.getX()
4687 && frame.getY() == svattrib.getY()
4688 && frame.getHeight() == svattrib.getHeight()
4689 && frame.getWidth() == svattrib.getWidth())
4691 comp = (StructureViewerBase) frame;
4692 // no break in faint hope of an exact match on viewId
4700 * Link an AlignmentPanel to an existing structure viewer.
4705 * @param useinViewerSuperpos
4706 * @param usetoColourbyseq
4707 * @param viewerColouring
4709 protected void linkStructureViewer(AlignmentPanel ap,
4710 StructureViewerBase viewer, StructureViewerModel stateData)
4712 // NOTE: if the jalview project is part of a shared session then
4713 // view synchronization should/could be done here.
4715 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4716 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4717 final boolean viewerColouring = stateData.isColourByViewer();
4718 Map<File, StructureData> oldFiles = stateData.getFileData();
4721 * Add mapping for sequences in this view to an already open viewer
4723 final AAStructureBindingModel binding = viewer.getBinding();
4724 for (File id : oldFiles.keySet())
4726 // add this and any other pdb files that should be present in the
4728 StructureData filedat = oldFiles.get(id);
4729 String pdbFile = filedat.getFilePath();
4730 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4731 binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE,
4733 binding.addSequenceForStructFile(pdbFile, seq);
4735 // and add the AlignmentPanel's reference to the view panel
4736 viewer.addAlignmentPanel(ap);
4737 if (useinViewerSuperpos)
4739 viewer.useAlignmentPanelForSuperposition(ap);
4743 viewer.excludeAlignmentPanelForSuperposition(ap);
4745 if (usetoColourbyseq)
4747 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4751 viewer.excludeAlignmentPanelForColourbyseq(ap);
4756 * Get all frames within the Desktop.
4760 protected JInternalFrame[] getAllFrames()
4762 JInternalFrame[] frames = null;
4763 // TODO is this necessary - is it safe - risk of hanging?
4768 frames = Desktop.desktop.getAllFrames();
4769 } catch (ArrayIndexOutOfBoundsException e)
4771 // occasional No such child exceptions are thrown here...
4775 } catch (InterruptedException f)
4779 } while (frames == null);
4784 * Answers true if 'version' is equal to or later than 'supported', where each
4785 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4786 * changes. Development and test values for 'version' are leniently treated
4790 * - minimum version we are comparing against
4792 * - version of data being processsed
4795 public static boolean isVersionStringLaterThan(String supported,
4798 if (supported == null || version == null
4799 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4800 || version.equalsIgnoreCase("Test")
4801 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4803 System.err.println("Assuming project file with "
4804 + (version == null ? "null" : version)
4805 + " is compatible with Jalview version " + supported);
4810 return StringUtils.compareVersions(version, supported, "b") >= 0;
4814 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4816 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4818 if (newStructureViewers != null)
4820 sview.getBinding().setFinishedLoadingFromArchive(false);
4821 newStructureViewers.add(sview);
4825 protected void setLoadingFinishedForNewStructureViewers()
4827 if (newStructureViewers != null)
4829 for (JalviewStructureDisplayI sview : newStructureViewers)
4831 sview.getBinding().setFinishedLoadingFromArchive(true);
4833 newStructureViewers.clear();
4834 newStructureViewers = null;
4838 AlignFrame loadViewport(String file, List<JSeq> JSEQ,
4839 List<SequenceI> hiddenSeqs, AlignmentI al,
4840 JalviewModel jm, Viewport view, String uniqueSeqSetId,
4841 String viewId, List<JvAnnotRow> autoAlan)
4843 AlignFrame af = null;
4844 af = new AlignFrame(al, safeInt(view.getWidth()),
4845 safeInt(view.getHeight()), uniqueSeqSetId, viewId);
4847 af.setFileName(file, FileFormat.Jalview);
4849 final AlignViewport viewport = af.getViewport();
4850 for (int i = 0; i < JSEQ.size(); i++)
4852 int colour = safeInt(JSEQ.get(i).getColour());
4853 viewport.setSequenceColour(viewport.getAlignment().getSequenceAt(i),
4859 viewport.setColourByReferenceSeq(true);
4860 viewport.setDisplayReferenceSeq(true);
4863 viewport.setGatherViewsHere(safeBoolean(view.isGatheredViews()));
4865 if (view.getSequenceSetId() != null)
4867 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4869 viewport.setSequenceSetId(uniqueSeqSetId);
4872 // propagate shared settings to this new view
4873 viewport.setHistoryList(av.getHistoryList());
4874 viewport.setRedoList(av.getRedoList());
4878 viewportsAdded.put(uniqueSeqSetId, viewport);
4880 // TODO: check if this method can be called repeatedly without
4881 // side-effects if alignpanel already registered.
4882 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4884 // apply Hidden regions to view.
4885 if (hiddenSeqs != null)
4887 for (int s = 0; s < JSEQ.size(); s++)
4889 SequenceGroup hidden = new SequenceGroup();
4890 boolean isRepresentative = false;
4891 for (int r = 0; r < JSEQ.get(s).getHiddenSequences().size(); r++)
4893 isRepresentative = true;
4894 SequenceI sequenceToHide = al
4895 .getSequenceAt(JSEQ.get(s).getHiddenSequences().get(r));
4896 hidden.addSequence(sequenceToHide, false);
4897 // remove from hiddenSeqs list so we don't try to hide it twice
4898 hiddenSeqs.remove(sequenceToHide);
4900 if (isRepresentative)
4902 SequenceI representativeSequence = al.getSequenceAt(s);
4903 hidden.addSequence(representativeSequence, false);
4904 viewport.hideRepSequences(representativeSequence, hidden);
4908 SequenceI[] hseqs = hiddenSeqs
4909 .toArray(new SequenceI[hiddenSeqs.size()]);
4910 viewport.hideSequence(hseqs);
4913 // recover view properties and display parameters
4915 viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
4916 viewport.setAbovePIDThreshold(safeBoolean(view.isPidSelected()));
4917 final int pidThreshold = safeInt(view.getPidThreshold());
4918 viewport.setThreshold(pidThreshold);
4920 viewport.setColourText(safeBoolean(view.isShowColourText()));
4922 viewport.setConservationSelected(
4923 safeBoolean(view.isConservationSelected()));
4924 viewport.setIncrement(safeInt(view.getConsThreshold()));
4925 viewport.setShowJVSuffix(safeBoolean(view.isShowFullId()));
4926 viewport.setRightAlignIds(safeBoolean(view.isRightAlignIds()));
4927 viewport.setFont(new Font(view.getFontName(),
4928 safeInt(view.getFontStyle()), safeInt(view.getFontSize())),
4930 ViewStyleI vs = viewport.getViewStyle();
4931 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
4932 viewport.setViewStyle(vs);
4933 // TODO: allow custom charWidth/Heights to be restored by updating them
4934 // after setting font - which means set above to false
4935 viewport.setRenderGaps(safeBoolean(view.isRenderGaps()));
4936 viewport.setWrapAlignment(safeBoolean(view.isWrapAlignment()));
4937 viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
4939 Boolean autocalcFirst = view.isShowAutocalcAbove();
4940 if (autocalcFirst != null)
4942 af.setShowAutoCalculatedAbove(autocalcFirst.booleanValue());
4944 String sortBy = view.getSortAnnotationsBy();
4949 viewport.setSortAnnotationsBy(
4950 SequenceAnnotationOrder.valueOf(sortBy));
4951 } catch (IllegalArgumentException e)
4954 "Invalid annotation sort specifier in project: " + sortBy);
4958 viewport.setShowBoxes(safeBoolean(view.isShowBoxes()));
4959 viewport.setShowText(safeBoolean(view.isShowText()));
4960 viewport.setTextColour(new Color(safeInt(view.getTextCol1())));
4961 viewport.setTextColour2(new Color(safeInt(view.getTextCol2())));
4962 viewport.setThresholdTextColour(safeInt(view.getTextColThreshold()));
4963 viewport.setShowUnconserved(view.isShowUnconserved());
4964 viewport.getRanges().setStartRes(safeInt(view.getStartRes()));
4966 if (view.getViewName() != null)
4968 viewport.setViewName(view.getViewName());
4969 af.setInitialTabVisible();
4971 af.setBounds(safeInt(view.getXpos()), safeInt(view.getYpos()),
4972 safeInt(view.getWidth()), safeInt(view.getHeight()));
4973 // startSeq set in af.alignPanel.updateLayout below
4974 af.alignPanel.updateLayout();
4975 ColourSchemeI cs = null;
4976 // apply colourschemes
4977 if (view.getBgColour() != null)
4979 if (view.getBgColour().startsWith("ucs"))
4981 cs = getUserColourScheme(jm, view.getBgColour());
4983 else if (view.getBgColour().startsWith("Annotation"))
4985 AnnotationColourScheme viewAnnColour = view.getAnnotationColours();
4986 cs = constructAnnotationColour(viewAnnColour, af, al, jm, true);
4993 cs = ColourSchemeProperty.getColourScheme(af.getViewport(), al,
4994 view.getBgColour());
4999 * turn off 'alignment colour applies to all groups'
5000 * while restoring global colour scheme
5002 viewport.setColourAppliesToAllGroups(false);
5003 viewport.setGlobalColourScheme(cs);
5004 viewport.getResidueShading().setThreshold(pidThreshold,
5005 view.isIgnoreGapsinConsensus());
5006 viewport.getResidueShading()
5007 .setConsensus(viewport.getSequenceConsensusHash());
5008 if (safeBoolean(view.isConservationSelected()) && cs != null)
5010 viewport.getResidueShading()
5011 .setConservationInc(safeInt(view.getConsThreshold()));
5013 af.changeColour(cs);
5014 viewport.setColourAppliesToAllGroups(true);
5017 .setShowSequenceFeatures(
5018 safeBoolean(view.isShowSequenceFeatures()));
5020 viewport.setCentreColumnLabels(view.isCentreColumnLabels());
5021 viewport.setIgnoreGapsConsensus(view.isIgnoreGapsinConsensus(), null);
5022 viewport.setFollowHighlight(view.isFollowHighlight());
5023 viewport.followSelection = view.isFollowSelection();
5024 viewport.setShowConsensusHistogram(view.isShowConsensusHistogram());
5025 viewport.setShowSequenceLogo(view.isShowSequenceLogo());
5026 viewport.setNormaliseSequenceLogo(view.isNormaliseSequenceLogo());
5027 viewport.setShowDBRefs(safeBoolean(view.isShowDbRefTooltip()));
5028 viewport.setShowNPFeats(safeBoolean(view.isShowNPfeatureTooltip()));
5029 viewport.setShowGroupConsensus(view.isShowGroupConsensus());
5030 viewport.setShowGroupConservation(view.isShowGroupConservation());
5032 // recover feature settings
5033 if (jm.getFeatureSettings() != null)
5035 FeatureRenderer fr = af.alignPanel.getSeqPanel().seqCanvas
5036 .getFeatureRenderer();
5037 FeaturesDisplayed fdi;
5038 viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
5039 String[] renderOrder = new String[jm.getFeatureSettings()
5040 .getSetting().size()];
5041 Map<String, FeatureColourI> featureColours = new Hashtable<>();
5042 Map<String, Float> featureOrder = new Hashtable<>();
5044 for (int fs = 0; fs < jm.getFeatureSettings()
5045 .getSetting().size(); fs++)
5047 Setting setting = jm.getFeatureSettings().getSetting().get(fs);
5048 String featureType = setting.getType();
5051 * restore feature filters (if any)
5053 jalview.xml.binding.jalview.FeatureMatcherSet filters = setting
5055 if (filters != null)
5057 FeatureMatcherSetI filter = Jalview2XML
5058 .parseFilter(featureType, filters);
5059 if (!filter.isEmpty())
5061 fr.setFeatureFilter(featureType, filter);
5066 * restore feature colour scheme
5068 Color maxColour = new Color(setting.getColour());
5069 if (setting.getMincolour() != null)
5072 * minColour is always set unless a simple colour
5073 * (including for colour by label though it doesn't use it)
5075 Color minColour = new Color(setting.getMincolour().intValue());
5076 Color noValueColour = minColour;
5077 NoValueColour noColour = setting.getNoValueColour();
5078 if (noColour == NoValueColour.NONE)
5080 noValueColour = null;
5082 else if (noColour == NoValueColour.MAX)
5084 noValueColour = maxColour;
5086 float min = safeFloat(safeFloat(setting.getMin()));
5087 float max = setting.getMax() == null ? 1f
5088 : setting.getMax().floatValue();
5089 FeatureColourI gc = new FeatureColour(maxColour, minColour,
5091 noValueColour, min, max);
5092 if (setting.getAttributeName().size() > 0)
5094 gc.setAttributeName(setting.getAttributeName().toArray(
5095 new String[setting.getAttributeName().size()]));
5097 if (setting.getThreshold() != null)
5099 gc.setThreshold(setting.getThreshold().floatValue());
5100 int threshstate = safeInt(setting.getThreshstate());
5101 // -1 = None, 0 = Below, 1 = Above threshold
5102 if (threshstate == 0)
5104 gc.setBelowThreshold(true);
5106 else if (threshstate == 1)
5108 gc.setAboveThreshold(true);
5111 gc.setAutoScaled(true); // default
5112 if (setting.isAutoScale() != null)
5114 gc.setAutoScaled(setting.isAutoScale());
5116 if (setting.isColourByLabel() != null)
5118 gc.setColourByLabel(setting.isColourByLabel());
5120 // and put in the feature colour table.
5121 featureColours.put(featureType, gc);
5125 featureColours.put(featureType,
5126 new FeatureColour(maxColour));
5128 renderOrder[fs] = featureType;
5129 if (setting.getOrder() != null)
5131 featureOrder.put(featureType, setting.getOrder().floatValue());
5135 featureOrder.put(featureType, new Float(
5136 fs / jm.getFeatureSettings().getSetting().size()));
5138 if (safeBoolean(setting.isDisplay()))
5140 fdi.setVisible(featureType);
5143 Map<String, Boolean> fgtable = new Hashtable<>();
5144 for (int gs = 0; gs < jm.getFeatureSettings().getGroup().size(); gs++)
5146 Group grp = jm.getFeatureSettings().getGroup().get(gs);
5147 fgtable.put(grp.getName(), new Boolean(grp.isDisplay()));
5149 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
5150 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
5151 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
5152 FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
5153 fgtable, featureColours, 1.0f, featureOrder);
5154 fr.transferSettings(frs);
5157 if (view.getHiddenColumns().size() > 0)
5159 for (int c = 0; c < view.getHiddenColumns().size(); c++)
5161 final HiddenColumns hc = view.getHiddenColumns().get(c);
5162 viewport.hideColumns(safeInt(hc.getStart()),
5163 safeInt(hc.getEnd()) /* +1 */);
5166 if (view.getCalcIdParam() != null)
5168 for (CalcIdParam calcIdParam : view.getCalcIdParam())
5170 if (calcIdParam != null)
5172 if (recoverCalcIdParam(calcIdParam, viewport))
5177 warn("Couldn't recover parameters for "
5178 + calcIdParam.getCalcId());
5183 af.setMenusFromViewport(viewport);
5184 af.setTitle(view.getTitle());
5185 // TODO: we don't need to do this if the viewport is aready visible.
5187 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
5188 * has a 'cdna/protein complement' view, in which case save it in order to
5189 * populate a SplitFrame once all views have been read in.
5191 String complementaryViewId = view.getComplementId();
5192 if (complementaryViewId == null)
5194 Desktop.addInternalFrame(af, view.getTitle(),
5195 safeInt(view.getWidth()), safeInt(view.getHeight()));
5196 // recompute any autoannotation
5197 af.alignPanel.updateAnnotation(false, true);
5198 reorderAutoannotation(af, al, autoAlan);
5199 af.sortAnnotations();
5200 af.alignPanel.alignmentChanged();
5204 splitFrameCandidates.put(view, af);
5210 * Reads saved data to restore Colour by Annotation settings
5212 * @param viewAnnColour
5216 * @param checkGroupAnnColour
5219 private ColourSchemeI constructAnnotationColour(
5220 AnnotationColourScheme viewAnnColour, AlignFrame af,
5221 AlignmentI al, JalviewModel model, boolean checkGroupAnnColour)
5223 boolean propagateAnnColour = false;
5224 AlignmentI annAlignment = af != null ? af.getViewport().getAlignment()
5226 if (checkGroupAnnColour && al.getGroups() != null
5227 && al.getGroups().size() > 0)
5229 // pre 2.8.1 behaviour
5230 // check to see if we should transfer annotation colours
5231 propagateAnnColour = true;
5232 for (SequenceGroup sg : al.getGroups())
5234 if (sg.getColourScheme() instanceof AnnotationColourGradient)
5236 propagateAnnColour = false;
5242 * 2.10.2- : saved annotationId is AlignmentAnnotation.annotationId
5244 String annotationId = viewAnnColour.getAnnotation();
5245 AlignmentAnnotation matchedAnnotation = annotationIds.get(annotationId);
5248 * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
5250 if (matchedAnnotation == null
5251 && annAlignment.getAlignmentAnnotation() != null)
5253 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
5256 .equals(annAlignment.getAlignmentAnnotation()[i].label))
5258 matchedAnnotation = annAlignment.getAlignmentAnnotation()[i];
5263 if (matchedAnnotation == null)
5265 System.err.println("Failed to match annotation colour scheme for "
5269 if (matchedAnnotation.getThreshold() == null)
5271 matchedAnnotation.setThreshold(
5272 new GraphLine(safeFloat(viewAnnColour.getThreshold()),
5273 "Threshold", Color.black));
5276 AnnotationColourGradient cs = null;
5277 if (viewAnnColour.getColourScheme().equals("None"))
5279 cs = new AnnotationColourGradient(matchedAnnotation,
5280 new Color(safeInt(viewAnnColour.getMinColour())),
5281 new Color(safeInt(viewAnnColour.getMaxColour())),
5282 safeInt(viewAnnColour.getAboveThreshold()));
5284 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
5286 cs = new AnnotationColourGradient(matchedAnnotation,
5287 getUserColourScheme(model, viewAnnColour.getColourScheme()),
5288 safeInt(viewAnnColour.getAboveThreshold()));
5292 cs = new AnnotationColourGradient(matchedAnnotation,
5293 ColourSchemeProperty.getColourScheme(af.getViewport(), al,
5294 viewAnnColour.getColourScheme()),
5295 safeInt(viewAnnColour.getAboveThreshold()));
5298 boolean perSequenceOnly = safeBoolean(viewAnnColour.isPerSequence());
5299 boolean useOriginalColours = safeBoolean(
5300 viewAnnColour.isPredefinedColours());
5301 cs.setSeqAssociated(perSequenceOnly);
5302 cs.setPredefinedColours(useOriginalColours);
5304 if (propagateAnnColour && al.getGroups() != null)
5306 // Also use these settings for all the groups
5307 for (int g = 0; g < al.getGroups().size(); g++)
5309 SequenceGroup sg = al.getGroups().get(g);
5310 if (sg.getGroupColourScheme() == null)
5315 AnnotationColourGradient groupScheme = new AnnotationColourGradient(
5316 matchedAnnotation, sg.getColourScheme(),
5317 safeInt(viewAnnColour.getAboveThreshold()));
5318 sg.setColourScheme(groupScheme);
5319 groupScheme.setSeqAssociated(perSequenceOnly);
5320 groupScheme.setPredefinedColours(useOriginalColours);
5326 private void reorderAutoannotation(AlignFrame af, AlignmentI al,
5327 List<JvAnnotRow> autoAlan)
5329 // copy over visualization settings for autocalculated annotation in the
5331 if (al.getAlignmentAnnotation() != null)
5334 * Kludge for magic autoannotation names (see JAL-811)
5336 String[] magicNames = new String[] { "Consensus", "Quality",
5338 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
5339 Hashtable<String, JvAnnotRow> visan = new Hashtable<>();
5340 for (String nm : magicNames)
5342 visan.put(nm, nullAnnot);
5344 for (JvAnnotRow auan : autoAlan)
5346 visan.put(auan.template.label
5347 + (auan.template.getCalcId() == null ? ""
5348 : "\t" + auan.template.getCalcId()),
5351 int hSize = al.getAlignmentAnnotation().length;
5352 List<JvAnnotRow> reorder = new ArrayList<>();
5353 // work through any autoCalculated annotation already on the view
5354 // removing it if it should be placed in a different location on the
5355 // annotation panel.
5356 List<String> remains = new ArrayList<>(visan.keySet());
5357 for (int h = 0; h < hSize; h++)
5359 jalview.datamodel.AlignmentAnnotation jalan = al
5360 .getAlignmentAnnotation()[h];
5361 if (jalan.autoCalculated)
5364 JvAnnotRow valan = visan.get(k = jalan.label);
5365 if (jalan.getCalcId() != null)
5367 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
5372 // delete the auto calculated row from the alignment
5373 al.deleteAnnotation(jalan, false);
5377 if (valan != nullAnnot)
5379 if (jalan != valan.template)
5381 // newly created autoannotation row instance
5382 // so keep a reference to the visible annotation row
5383 // and copy over all relevant attributes
5384 if (valan.template.graphHeight >= 0)
5387 jalan.graphHeight = valan.template.graphHeight;
5389 jalan.visible = valan.template.visible;
5391 reorder.add(new JvAnnotRow(valan.order, jalan));
5396 // Add any (possibly stale) autocalculated rows that were not appended to
5397 // the view during construction
5398 for (String other : remains)
5400 JvAnnotRow othera = visan.get(other);
5401 if (othera != nullAnnot && othera.template.getCalcId() != null
5402 && othera.template.getCalcId().length() > 0)
5404 reorder.add(othera);
5407 // now put the automatic annotation in its correct place
5408 int s = 0, srt[] = new int[reorder.size()];
5409 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
5410 for (JvAnnotRow jvar : reorder)
5413 srt[s++] = jvar.order;
5416 jalview.util.QuickSort.sort(srt, rws);
5417 // and re-insert the annotation at its correct position
5418 for (JvAnnotRow jvar : rws)
5420 al.addAnnotation(jvar.template, jvar.order);
5422 af.alignPanel.adjustAnnotationHeight();
5426 Hashtable skipList = null;
5429 * TODO remove this method
5432 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
5433 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
5434 * throw new Error("Implementation Error. No skipList defined for this
5435 * Jalview2XML instance."); } return (AlignFrame)
5436 * skipList.get(view.getSequenceSetId()); }
5440 * Check if the Jalview view contained in object should be skipped or not.
5443 * @return true if view's sequenceSetId is a key in skipList
5445 private boolean skipViewport(JalviewModel object)
5447 if (skipList == null)
5451 String id = object.getViewport().get(0).getSequenceSetId();
5452 if (skipList.containsKey(id))
5454 if (Cache.log != null && Cache.log.isDebugEnabled())
5456 Cache.log.debug("Skipping seuqence set id " + id);
5463 public void addToSkipList(AlignFrame af)
5465 if (skipList == null)
5467 skipList = new Hashtable();
5469 skipList.put(af.getViewport().getSequenceSetId(), af);
5472 public void clearSkipList()
5474 if (skipList != null)
5481 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
5482 boolean ignoreUnrefed, String uniqueSeqSetId)
5484 jalview.datamodel.AlignmentI ds = getDatasetFor(
5485 vamsasSet.getDatasetId());
5486 AlignmentI xtant_ds = ds;
5487 if (xtant_ds == null)
5489 // good chance we are about to create a new dataset, but check if we've
5490 // seen some of the dataset sequence IDs before.
5491 // TODO: skip this check if we are working with project generated by
5492 // version 2.11 or later
5493 xtant_ds = checkIfHasDataset(vamsasSet.getSequence());
5494 if (xtant_ds != null)
5497 addDatasetRef(vamsasSet.getDatasetId(), ds);
5500 Vector dseqs = null;
5503 // recovering an alignment View
5504 AlignmentI seqSetDS = getDatasetFor(UNIQSEQSETID + uniqueSeqSetId);
5505 if (seqSetDS != null)
5507 if (ds != null && ds != seqSetDS)
5509 warn("JAL-3171 regression: Overwriting a dataset reference for an alignment"
5510 + " - CDS/Protein crossreference data may be lost");
5511 if (xtant_ds != null)
5513 // This can only happen if the unique sequence set ID was bound to a
5514 // dataset that did not contain any of the sequences in the view
5515 // currently being restored.
5516 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.");
5520 addDatasetRef(vamsasSet.getDatasetId(), ds);
5525 // try even harder to restore dataset
5526 AlignmentI xtantDS = checkIfHasDataset(vamsasSet.getSequence());
5527 // create a list of new dataset sequences
5528 dseqs = new Vector();
5530 for (int i = 0, iSize = vamsasSet.getSequence().size(); i < iSize; i++)
5532 Sequence vamsasSeq = vamsasSet.getSequence().get(i);
5533 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
5535 // create a new dataset
5538 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
5539 dseqs.copyInto(dsseqs);
5540 ds = new jalview.datamodel.Alignment(dsseqs);
5541 debug("Created new dataset " + vamsasSet.getDatasetId()
5542 + " for alignment " + System.identityHashCode(al));
5543 addDatasetRef(vamsasSet.getDatasetId(), ds);
5545 // set the dataset for the newly imported alignment.
5546 if (al.getDataset() == null && !ignoreUnrefed)
5549 // register dataset for the alignment's uniqueSeqSetId for legacy projects
5550 addDatasetRef(UNIQSEQSETID + uniqueSeqSetId, ds);
5552 updateSeqDatasetBinding(vamsasSet.getSequence(), ds);
5556 * XML dataset sequence ID to materialised dataset reference
5558 HashMap<String, AlignmentI> seqToDataset = new HashMap<>();
5561 * @return the first materialised dataset reference containing a dataset
5562 * sequence referenced in the given view
5564 * - sequences from the view
5566 AlignmentI checkIfHasDataset(List<Sequence> list)
5568 for (Sequence restoredSeq : list)
5570 AlignmentI datasetFor = seqToDataset.get(restoredSeq.getDsseqid());
5571 if (datasetFor != null)
5580 * Register ds as the containing dataset for the dataset sequences referenced
5581 * by sequences in list
5584 * - sequences in a view
5587 void updateSeqDatasetBinding(List<Sequence> list, AlignmentI ds)
5589 for (Sequence restoredSeq : list)
5591 AlignmentI prevDS = seqToDataset.put(restoredSeq.getDsseqid(), ds);
5592 if (prevDS != null && prevDS != ds)
5594 warn("Dataset sequence appears in many datasets: "
5595 + restoredSeq.getDsseqid());
5596 // TODO: try to merge!
5603 * sequence definition to create/merge dataset sequence for
5607 * vector to add new dataset sequence to
5608 * @param ignoreUnrefed
5609 * - when true, don't create new sequences from vamsasSeq if it's id
5610 * doesn't already have an asssociated Jalview sequence.
5612 * - used to reorder the sequence in the alignment according to the
5613 * vamsasSeq array ordering, to preserve ordering of dataset
5615 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
5616 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed, int vseqpos)
5618 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
5620 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
5621 boolean reorder = false;
5622 SequenceI dsq = null;
5623 if (sq != null && sq.getDatasetSequence() != null)
5625 dsq = sq.getDatasetSequence();
5631 if (sq == null && ignoreUnrefed)
5635 String sqid = vamsasSeq.getDsseqid();
5638 // need to create or add a new dataset sequence reference to this sequence
5641 dsq = seqRefIds.get(sqid);
5646 // make a new dataset sequence
5647 dsq = sq.createDatasetSequence();
5650 // make up a new dataset reference for this sequence
5651 sqid = seqHash(dsq);
5653 dsq.setVamsasId(uniqueSetSuffix + sqid);
5654 seqRefIds.put(sqid, dsq);
5659 dseqs.addElement(dsq);
5664 ds.addSequence(dsq);
5670 { // make this dataset sequence sq's dataset sequence
5671 sq.setDatasetSequence(dsq);
5672 // and update the current dataset alignment
5677 if (!dseqs.contains(dsq))
5684 if (ds.findIndex(dsq) < 0)
5686 ds.addSequence(dsq);
5693 // TODO: refactor this as a merge dataset sequence function
5694 // now check that sq (the dataset sequence) sequence really is the union of
5695 // all references to it
5696 // boolean pre = sq.getStart() < dsq.getStart();
5697 // boolean post = sq.getEnd() > dsq.getEnd();
5701 // StringBuffer sb = new StringBuffer();
5702 String newres = jalview.analysis.AlignSeq.extractGaps(
5703 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
5704 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
5705 && newres.length() > dsq.getLength())
5707 // Update with the longer sequence.
5711 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
5712 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
5713 * sb.append(newres.substring(newres.length() - sq.getEnd() -
5714 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
5716 dsq.setSequence(newres);
5718 // TODO: merges will never happen if we 'know' we have the real dataset
5719 // sequence - this should be detected when id==dssid
5721 "DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
5722 // + (pre ? "prepended" : "") + " "
5723 // + (post ? "appended" : ""));
5728 // sequence refs are identical. We may need to update the existing dataset
5729 // alignment with this one, though.
5730 if (ds != null && dseqs == null)
5732 int opos = ds.findIndex(dsq);
5733 SequenceI tseq = null;
5734 if (opos != -1 && vseqpos != opos)
5736 // remove from old position
5737 ds.deleteSequence(dsq);
5739 if (vseqpos < ds.getHeight())
5741 if (vseqpos != opos)
5743 // save sequence at destination position
5744 tseq = ds.getSequenceAt(vseqpos);
5745 ds.replaceSequenceAt(vseqpos, dsq);
5746 ds.addSequence(tseq);
5751 ds.addSequence(dsq);
5758 * TODO use AlignmentI here and in related methods - needs
5759 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
5761 Hashtable<String, AlignmentI> datasetIds = null;
5763 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
5765 private AlignmentI getDatasetFor(String datasetId)
5767 if (datasetIds == null)
5769 datasetIds = new Hashtable<>();
5772 if (datasetIds.containsKey(datasetId))
5774 return datasetIds.get(datasetId);
5779 private void addDatasetRef(String datasetId, AlignmentI dataset)
5781 if (datasetIds == null)
5783 datasetIds = new Hashtable<>();
5785 datasetIds.put(datasetId, dataset);
5789 * make a new dataset ID for this jalview dataset alignment
5794 private String getDatasetIdRef(AlignmentI dataset)
5796 if (dataset.getDataset() != null)
5798 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
5800 String datasetId = makeHashCode(dataset, null);
5801 if (datasetId == null)
5803 // make a new datasetId and record it
5804 if (dataset2Ids == null)
5806 dataset2Ids = new IdentityHashMap<>();
5810 datasetId = dataset2Ids.get(dataset);
5812 if (datasetId == null)
5814 datasetId = "ds" + dataset2Ids.size() + 1;
5815 dataset2Ids.put(dataset, datasetId);
5821 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5823 for (int d = 0; d < sequence.getDBRef().size(); d++)
5825 DBRef dr = sequence.getDBRef().get(d);
5826 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
5827 dr.getSource(), dr.getVersion(), dr.getAccessionId());
5828 if (dr.getMapping() != null)
5830 entry.setMap(addMapping(dr.getMapping()));
5832 datasetSequence.addDBRef(entry);
5836 private jalview.datamodel.Mapping addMapping(Mapping m)
5838 SequenceI dsto = null;
5839 // Mapping m = dr.getMapping();
5840 int fr[] = new int[m.getMapListFrom().size() * 2];
5841 Iterator<MapListFrom> from = m.getMapListFrom().iterator();// enumerateMapListFrom();
5842 for (int _i = 0; from.hasNext(); _i += 2)
5844 MapListFrom mf = from.next();
5845 fr[_i] = mf.getStart();
5846 fr[_i + 1] = mf.getEnd();
5848 int fto[] = new int[m.getMapListTo().size() * 2];
5849 Iterator<MapListTo> to = m.getMapListTo().iterator();// enumerateMapListTo();
5850 for (int _i = 0; to.hasNext(); _i += 2)
5852 MapListTo mf = to.next();
5853 fto[_i] = mf.getStart();
5854 fto[_i + 1] = mf.getEnd();
5856 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto, fr,
5857 fto, m.getMapFromUnit().intValue(),
5858 m.getMapToUnit().intValue());
5861 * (optional) choice of dseqFor or Sequence
5863 if (m.getDseqFor() != null)
5865 String dsfor = m.getDseqFor();
5866 if (seqRefIds.containsKey(dsfor))
5871 jmap.setTo(seqRefIds.get(dsfor));
5875 frefedSequence.add(newMappingRef(dsfor, jmap));
5878 else if (m.getSequence() != null)
5881 * local sequence definition
5883 Sequence ms = m.getSequence();
5884 SequenceI djs = null;
5885 String sqid = ms.getDsseqid();
5886 if (sqid != null && sqid.length() > 0)
5889 * recover dataset sequence
5891 djs = seqRefIds.get(sqid);
5896 "Warning - making up dataset sequence id for DbRef sequence map reference");
5897 sqid = ((Object) ms).toString(); // make up a new hascode for
5898 // undefined dataset sequence hash
5899 // (unlikely to happen)
5905 * make a new dataset sequence and add it to refIds hash
5907 djs = new jalview.datamodel.Sequence(ms.getName(),
5909 djs.setStart(jmap.getMap().getToLowest());
5910 djs.setEnd(jmap.getMap().getToHighest());
5911 djs.setVamsasId(uniqueSetSuffix + sqid);
5913 incompleteSeqs.put(sqid, djs);
5914 seqRefIds.put(sqid, djs);
5917 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5926 * Provides a 'copy' of an alignment view (on action New View) by 'saving' the
5927 * view as XML (but not to file), and then reloading it
5932 public AlignmentPanel copyAlignPanel(AlignmentPanel ap)
5935 JalviewModel jm = saveState(ap, null, null, null);
5938 jm.getVamsasModel().getSequenceSet().get(0).getDatasetId(),
5939 ap.getAlignment().getDataset());
5941 uniqueSetSuffix = "";
5942 // jm.getJalviewModelSequence().getViewport(0).setId(null);
5943 jm.getViewport().get(0).setId(null);
5944 // we don't overwrite the view we just copied
5946 if (this.frefedSequence == null)
5948 frefedSequence = new Vector<>();
5951 viewportsAdded.clear();
5953 AlignFrame af = loadFromObject(jm, null, false, null);
5954 af.getAlignPanels().clear();
5955 af.closeMenuItem_actionPerformed(true);
5958 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5959 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5960 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5961 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5962 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5965 return af.alignPanel;
5968 private Hashtable jvids2vobj;
5970 private void warn(String msg)
5975 private void warn(String msg, Exception e)
5977 if (Cache.log != null)
5981 Cache.log.warn(msg, e);
5985 Cache.log.warn(msg);
5990 System.err.println("Warning: " + msg);
5993 e.printStackTrace();
5998 private void debug(String string)
6000 debug(string, null);
6003 private void debug(String msg, Exception e)
6005 if (Cache.log != null)
6009 Cache.log.debug(msg, e);
6013 Cache.log.debug(msg);
6018 System.err.println("Warning: " + msg);
6021 e.printStackTrace();
6027 * set the object to ID mapping tables used to write/recover objects and XML
6028 * ID strings for the jalview project. If external tables are provided then
6029 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
6030 * object goes out of scope. - also populates the datasetIds hashtable with
6031 * alignment objects containing dataset sequences
6034 * Map from ID strings to jalview datamodel
6036 * Map from jalview datamodel to ID strings
6040 public void setObjectMappingTables(Hashtable vobj2jv,
6041 IdentityHashMap jv2vobj)
6043 this.jv2vobj = jv2vobj;
6044 this.vobj2jv = vobj2jv;
6045 Iterator ds = jv2vobj.keySet().iterator();
6047 while (ds.hasNext())
6049 Object jvobj = ds.next();
6050 id = jv2vobj.get(jvobj).toString();
6051 if (jvobj instanceof jalview.datamodel.Alignment)
6053 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
6055 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
6058 else if (jvobj instanceof jalview.datamodel.Sequence)
6060 // register sequence object so the XML parser can recover it.
6061 if (seqRefIds == null)
6063 seqRefIds = new HashMap<>();
6065 if (seqsToIds == null)
6067 seqsToIds = new IdentityHashMap<>();
6069 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
6070 seqsToIds.put((SequenceI) jvobj, id);
6072 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
6075 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
6076 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
6077 if (jvann.annotationId == null)
6079 jvann.annotationId = anid;
6081 if (!jvann.annotationId.equals(anid))
6083 // TODO verify that this is the correct behaviour
6084 this.warn("Overriding Annotation ID for " + anid
6085 + " from different id : " + jvann.annotationId);
6086 jvann.annotationId = anid;
6089 else if (jvobj instanceof String)
6091 if (jvids2vobj == null)
6093 jvids2vobj = new Hashtable();
6094 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
6099 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
6105 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
6106 * objects created from the project archive. If string is null (default for
6107 * construction) then suffix will be set automatically.
6111 public void setUniqueSetSuffix(String string)
6113 uniqueSetSuffix = string;
6118 * uses skipList2 as the skipList for skipping views on sequence sets
6119 * associated with keys in the skipList
6123 public void setSkipList(Hashtable skipList2)
6125 skipList = skipList2;
6129 * Reads the jar entry of given name and returns its contents, or null if the
6130 * entry is not found.
6133 * @param jarEntryName
6136 protected String readJarEntry(jarInputStreamProvider jprovider,
6137 String jarEntryName)
6139 String result = null;
6140 BufferedReader in = null;
6145 * Reopen the jar input stream and traverse its entries to find a matching
6148 JarInputStream jin = jprovider.getJarInputStream();
6149 JarEntry entry = null;
6152 entry = jin.getNextJarEntry();
6153 } while (entry != null && !entry.getName().equals(jarEntryName));
6157 StringBuilder out = new StringBuilder(256);
6158 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
6161 while ((data = in.readLine()) != null)
6165 result = out.toString();
6169 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
6171 } catch (Exception ex)
6173 ex.printStackTrace();
6181 } catch (IOException e)
6192 * Returns an incrementing counter (0, 1, 2...)
6196 private synchronized int nextCounter()
6202 * Loads any saved PCA viewers
6207 protected void loadPCAViewers(JalviewModel model, AlignmentPanel ap)
6211 List<PcaViewer> pcaviewers = model.getPcaViewer();
6212 for (PcaViewer viewer : pcaviewers)
6214 String modelName = viewer.getScoreModelName();
6215 SimilarityParamsI params = new SimilarityParams(
6216 viewer.isIncludeGappedColumns(), viewer.isMatchGaps(),
6217 viewer.isIncludeGaps(),
6218 viewer.isDenominateByShortestLength());
6221 * create the panel (without computing the PCA)
6223 PCAPanel panel = new PCAPanel(ap, modelName, params);
6225 panel.setTitle(viewer.getTitle());
6226 panel.setBounds(new Rectangle(viewer.getXpos(), viewer.getYpos(),
6227 viewer.getWidth(), viewer.getHeight()));
6229 boolean showLabels = viewer.isShowLabels();
6230 panel.setShowLabels(showLabels);
6231 panel.getRotatableCanvas().setShowLabels(showLabels);
6232 panel.getRotatableCanvas()
6233 .setBgColour(new Color(viewer.getBgColour()));
6234 panel.getRotatableCanvas()
6235 .setApplyToAllViews(viewer.isLinkToAllViews());
6238 * load PCA output data
6240 ScoreModelI scoreModel = ScoreModels.getInstance()
6241 .getScoreModel(modelName, ap);
6242 PCA pca = new PCA(null, scoreModel, params);
6243 PcaDataType pcaData = viewer.getPcaData();
6245 MatrixI pairwise = loadDoubleMatrix(pcaData.getPairwiseMatrix());
6246 pca.setPairwiseScores(pairwise);
6248 MatrixI triDiag = loadDoubleMatrix(pcaData.getTridiagonalMatrix());
6249 pca.setTridiagonal(triDiag);
6251 MatrixI result = loadDoubleMatrix(pcaData.getEigenMatrix());
6252 pca.setEigenmatrix(result);
6254 panel.getPcaModel().setPCA(pca);
6257 * we haven't saved the input data! (JAL-2647 to do)
6259 panel.setInputData(null);
6262 * add the sequence points for the PCA display
6264 List<jalview.datamodel.SequencePoint> seqPoints = new ArrayList<>();
6265 for (SequencePoint sp : viewer.getSequencePoint())
6267 String seqId = sp.getSequenceRef();
6268 SequenceI seq = seqRefIds.get(seqId);
6271 throw new IllegalStateException(
6272 "Unmatched seqref for PCA: " + seqId);
6274 Point pt = new Point(sp.getXPos(), sp.getYPos(), sp.getZPos());
6275 jalview.datamodel.SequencePoint seqPoint = new jalview.datamodel.SequencePoint(
6277 seqPoints.add(seqPoint);
6279 panel.getRotatableCanvas().setPoints(seqPoints, seqPoints.size());
6282 * set min-max ranges and scale after setPoints (which recomputes them)
6284 panel.getRotatableCanvas().setScaleFactor(viewer.getScaleFactor());
6285 SeqPointMin spMin = viewer.getSeqPointMin();
6286 float[] min = new float[] { spMin.getXPos(), spMin.getYPos(),
6288 SeqPointMax spMax = viewer.getSeqPointMax();
6289 float[] max = new float[] { spMax.getXPos(), spMax.getYPos(),
6291 panel.getRotatableCanvas().setSeqMinMax(min, max);
6293 // todo: hold points list in PCAModel only
6294 panel.getPcaModel().setSequencePoints(seqPoints);
6296 panel.setSelectedDimensionIndex(viewer.getXDim(), X);
6297 panel.setSelectedDimensionIndex(viewer.getYDim(), Y);
6298 panel.setSelectedDimensionIndex(viewer.getZDim(), Z);
6300 // is this duplication needed?
6301 panel.setTop(seqPoints.size() - 1);
6302 panel.getPcaModel().setTop(seqPoints.size() - 1);
6305 * add the axes' end points for the display
6307 for (int i = 0; i < 3; i++)
6309 Axis axis = viewer.getAxis().get(i);
6310 panel.getRotatableCanvas().getAxisEndPoints()[i] = new Point(
6311 axis.getXPos(), axis.getYPos(), axis.getZPos());
6314 Desktop.addInternalFrame(panel, MessageManager.formatMessage(
6315 "label.calc_title", "PCA", modelName), 475, 450);
6317 } catch (Exception ex)
6319 Cache.log.error("Error loading PCA: " + ex.toString());
6324 * Populates an XML model of the feature colour scheme for one feature type
6326 * @param featureType
6330 public static Colour marshalColour(
6331 String featureType, FeatureColourI fcol)
6333 Colour col = new Colour();
6334 if (fcol.isSimpleColour())
6336 col.setRGB(Format.getHexString(fcol.getColour()));
6340 col.setRGB(Format.getHexString(fcol.getMaxColour()));
6341 col.setMin(fcol.getMin());
6342 col.setMax(fcol.getMax());
6343 col.setMinRGB(jalview.util.Format.getHexString(fcol.getMinColour()));
6344 col.setAutoScale(fcol.isAutoScaled());
6345 col.setThreshold(fcol.getThreshold());
6346 col.setColourByLabel(fcol.isColourByLabel());
6347 col.setThreshType(fcol.isAboveThreshold() ? ThresholdType.ABOVE
6348 : (fcol.isBelowThreshold() ? ThresholdType.BELOW
6349 : ThresholdType.NONE));
6350 if (fcol.isColourByAttribute())
6352 final String[] attName = fcol.getAttributeName();
6353 col.getAttributeName().add(attName[0]);
6354 if (attName.length > 1)
6356 col.getAttributeName().add(attName[1]);
6359 Color noColour = fcol.getNoColour();
6360 if (noColour == null)
6362 col.setNoValueColour(NoValueColour.NONE);
6364 else if (noColour == fcol.getMaxColour())
6366 col.setNoValueColour(NoValueColour.MAX);
6370 col.setNoValueColour(NoValueColour.MIN);
6373 col.setName(featureType);
6378 * Populates an XML model of the feature filter(s) for one feature type
6380 * @param firstMatcher
6381 * the first (or only) match condition)
6383 * remaining match conditions (if any)
6385 * if true, conditions are and-ed, else or-ed
6387 public static jalview.xml.binding.jalview.FeatureMatcherSet marshalFilter(
6388 FeatureMatcherI firstMatcher, Iterator<FeatureMatcherI> filters,
6391 jalview.xml.binding.jalview.FeatureMatcherSet result = new jalview.xml.binding.jalview.FeatureMatcherSet();
6393 if (filters.hasNext())
6398 CompoundMatcher compound = new CompoundMatcher();
6399 compound.setAnd(and);
6400 jalview.xml.binding.jalview.FeatureMatcherSet matcher1 = marshalFilter(
6401 firstMatcher, Collections.emptyIterator(), and);
6402 // compound.addMatcherSet(matcher1);
6403 compound.getMatcherSet().add(matcher1);
6404 FeatureMatcherI nextMatcher = filters.next();
6405 jalview.xml.binding.jalview.FeatureMatcherSet matcher2 = marshalFilter(
6406 nextMatcher, filters, and);
6407 // compound.addMatcherSet(matcher2);
6408 compound.getMatcherSet().add(matcher2);
6409 result.setCompoundMatcher(compound);
6414 * single condition matcher
6416 // MatchCondition matcherModel = new MatchCondition();
6417 jalview.xml.binding.jalview.FeatureMatcher matcherModel = new jalview.xml.binding.jalview.FeatureMatcher();
6418 matcherModel.setCondition(
6419 firstMatcher.getMatcher().getCondition().getStableName());
6420 matcherModel.setValue(firstMatcher.getMatcher().getPattern());
6421 if (firstMatcher.isByAttribute())
6423 matcherModel.setBy(FilterBy.BY_ATTRIBUTE);
6424 // matcherModel.setAttributeName(firstMatcher.getAttribute());
6425 String[] attName = firstMatcher.getAttribute();
6426 matcherModel.getAttributeName().add(attName[0]); // attribute
6427 if (attName.length > 1)
6429 matcherModel.getAttributeName().add(attName[1]); // sub-attribute
6432 else if (firstMatcher.isByLabel())
6434 matcherModel.setBy(FilterBy.BY_LABEL);
6436 else if (firstMatcher.isByScore())
6438 matcherModel.setBy(FilterBy.BY_SCORE);
6440 result.setMatchCondition(matcherModel);
6447 * Loads one XML model of a feature filter to a Jalview object
6449 * @param featureType
6450 * @param matcherSetModel
6453 public static FeatureMatcherSetI parseFilter(
6455 jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel)
6457 FeatureMatcherSetI result = new FeatureMatcherSet();
6460 parseFilterConditions(result, matcherSetModel, true);
6461 } catch (IllegalStateException e)
6463 // mixing AND and OR conditions perhaps
6465 String.format("Error reading filter conditions for '%s': %s",
6466 featureType, e.getMessage()));
6467 // return as much as was parsed up to the error
6474 * Adds feature match conditions to matcherSet as unmarshalled from XML
6475 * (possibly recursively for compound conditions)
6478 * @param matcherSetModel
6480 * if true, multiple conditions are AND-ed, else they are OR-ed
6481 * @throws IllegalStateException
6482 * if AND and OR conditions are mixed
6484 protected static void parseFilterConditions(
6485 FeatureMatcherSetI matcherSet,
6486 jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel,
6489 jalview.xml.binding.jalview.FeatureMatcher mc = matcherSetModel
6490 .getMatchCondition();
6496 FilterBy filterBy = mc.getBy();
6497 Condition cond = Condition.fromString(mc.getCondition());
6498 String pattern = mc.getValue();
6499 FeatureMatcherI matchCondition = null;
6500 if (filterBy == FilterBy.BY_LABEL)
6502 matchCondition = FeatureMatcher.byLabel(cond, pattern);
6504 else if (filterBy == FilterBy.BY_SCORE)
6506 matchCondition = FeatureMatcher.byScore(cond, pattern);
6509 else if (filterBy == FilterBy.BY_ATTRIBUTE)
6511 final List<String> attributeName = mc.getAttributeName();
6512 String[] attNames = attributeName
6513 .toArray(new String[attributeName.size()]);
6514 matchCondition = FeatureMatcher.byAttribute(cond, pattern,
6519 * note this throws IllegalStateException if AND-ing to a
6520 * previously OR-ed compound condition, or vice versa
6524 matcherSet.and(matchCondition);
6528 matcherSet.or(matchCondition);
6534 * compound condition
6536 List<jalview.xml.binding.jalview.FeatureMatcherSet> matchers = matcherSetModel
6537 .getCompoundMatcher().getMatcherSet();
6538 boolean anded = matcherSetModel.getCompoundMatcher().isAnd();
6539 if (matchers.size() == 2)
6541 parseFilterConditions(matcherSet, matchers.get(0), anded);
6542 parseFilterConditions(matcherSet, matchers.get(1), anded);
6546 System.err.println("Malformed compound filter condition");
6552 * Loads one XML model of a feature colour to a Jalview object
6554 * @param colourModel
6557 public static FeatureColourI parseColour(Colour colourModel)
6559 FeatureColourI colour = null;
6561 if (colourModel.getMax() != null)
6563 Color mincol = null;
6564 Color maxcol = null;
6565 Color noValueColour = null;
6569 mincol = new Color(Integer.parseInt(colourModel.getMinRGB(), 16));
6570 maxcol = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6571 } catch (Exception e)
6573 Cache.log.warn("Couldn't parse out graduated feature color.", e);
6576 NoValueColour noCol = colourModel.getNoValueColour();
6577 if (noCol == NoValueColour.MIN)
6579 noValueColour = mincol;
6581 else if (noCol == NoValueColour.MAX)
6583 noValueColour = maxcol;
6586 colour = new FeatureColour(maxcol, mincol, maxcol, noValueColour,
6587 safeFloat(colourModel.getMin()),
6588 safeFloat(colourModel.getMax()));
6589 final List<String> attributeName = colourModel.getAttributeName();
6590 String[] attributes = attributeName
6591 .toArray(new String[attributeName.size()]);
6592 if (attributes != null && attributes.length > 0)
6594 colour.setAttributeName(attributes);
6596 if (colourModel.isAutoScale() != null)
6598 colour.setAutoScaled(colourModel.isAutoScale().booleanValue());
6600 if (colourModel.isColourByLabel() != null)
6602 colour.setColourByLabel(
6603 colourModel.isColourByLabel().booleanValue());
6605 if (colourModel.getThreshold() != null)
6607 colour.setThreshold(colourModel.getThreshold().floatValue());
6609 ThresholdType ttyp = colourModel.getThreshType();
6610 if (ttyp == ThresholdType.ABOVE)
6612 colour.setAboveThreshold(true);
6614 else if (ttyp == ThresholdType.BELOW)
6616 colour.setBelowThreshold(true);
6621 Color color = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6622 colour = new FeatureColour(color);