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 // TODO resort annotations here to their order in the project?
4033 av = af.getViewport();
4038 * Load any trees, PDB structures and viewers
4040 * Not done if flag is false (when this method is used for New View)
4042 if (loadTreesAndStructures)
4044 loadTrees(jalviewModel, view, af, av, ap);
4045 loadPCAViewers(jalviewModel, ap);
4046 loadPDBStructures(jprovider, jseqs, af, ap);
4047 loadRnaViewers(jprovider, jseqs, ap);
4049 // and finally return.
4054 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
4055 * panel is restored from separate jar entries, two (gapped and trimmed) per
4056 * sequence and secondary structure.
4058 * Currently each viewer shows just one sequence and structure (gapped and
4059 * trimmed), however this method is designed to support multiple sequences or
4060 * structures in viewers if wanted in future.
4066 private void loadRnaViewers(jarInputStreamProvider jprovider,
4067 List<JSeq> jseqs, AlignmentPanel ap)
4070 * scan the sequences for references to viewers; create each one the first
4071 * time it is referenced, add Rna models to existing viewers
4073 for (JSeq jseq : jseqs)
4075 for (int i = 0; i < jseq.getRnaViewer().size(); i++)
4077 RnaViewer viewer = jseq.getRnaViewer().get(i);
4078 AppVarna appVarna = findOrCreateVarnaViewer(viewer, uniqueSetSuffix,
4081 for (int j = 0; j < viewer.getSecondaryStructure().size(); j++)
4083 SecondaryStructure ss = viewer.getSecondaryStructure().get(j);
4084 SequenceI seq = seqRefIds.get(jseq.getId());
4085 AlignmentAnnotation ann = this.annotationIds
4086 .get(ss.getAnnotationId());
4089 * add the structure to the Varna display (with session state copied
4090 * from the jar to a temporary file)
4092 boolean gapped = safeBoolean(ss.isGapped());
4093 String rnaTitle = ss.getTitle();
4094 String sessionState = ss.getViewerState();
4095 String tempStateFile = copyJarEntry(jprovider, sessionState,
4097 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
4098 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
4100 appVarna.setInitialSelection(safeInt(viewer.getSelectedRna()));
4106 * Locate and return an already instantiated matching AppVarna, or create one
4110 * @param viewIdSuffix
4114 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
4115 String viewIdSuffix, AlignmentPanel ap)
4118 * on each load a suffix is appended to the saved viewId, to avoid conflicts
4119 * if load is repeated
4121 String postLoadId = viewer.getViewId() + viewIdSuffix;
4122 for (JInternalFrame frame : getAllFrames())
4124 if (frame instanceof AppVarna)
4126 AppVarna varna = (AppVarna) frame;
4127 if (postLoadId.equals(varna.getViewId()))
4129 // this viewer is already instantiated
4130 // could in future here add ap as another 'parent' of the
4131 // AppVarna window; currently just 1-to-many
4138 * viewer not found - make it
4140 RnaViewerModel model = new RnaViewerModel(postLoadId, viewer.getTitle(),
4141 safeInt(viewer.getXpos()), safeInt(viewer.getYpos()),
4142 safeInt(viewer.getWidth()), safeInt(viewer.getHeight()),
4143 safeInt(viewer.getDividerLocation()));
4144 AppVarna varna = new AppVarna(model, ap);
4150 * Load any saved trees
4158 protected void loadTrees(JalviewModel jm, Viewport view,
4159 AlignFrame af, AlignViewport av, AlignmentPanel ap)
4161 // TODO result of automated refactoring - are all these parameters needed?
4164 for (int t = 0; t < jm.getTree().size(); t++)
4167 Tree tree = jm.getTree().get(t);
4169 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
4172 tp = af.showNewickTree(new NewickFile(tree.getNewick()),
4173 tree.getTitle(), safeInt(tree.getWidth()),
4174 safeInt(tree.getHeight()), safeInt(tree.getXpos()),
4175 safeInt(tree.getYpos()));
4176 if (tree.getId() != null)
4178 // perhaps bind the tree id to something ?
4183 // update local tree attributes ?
4184 // TODO: should check if tp has been manipulated by user - if so its
4185 // settings shouldn't be modified
4186 tp.setTitle(tree.getTitle());
4187 tp.setBounds(new Rectangle(safeInt(tree.getXpos()),
4188 safeInt(tree.getYpos()), safeInt(tree.getWidth()),
4189 safeInt(tree.getHeight())));
4190 tp.setViewport(av); // af.viewport;
4191 // TODO: verify 'associate with all views' works still
4192 tp.getTreeCanvas().setViewport(av); // af.viewport;
4193 tp.getTreeCanvas().setAssociatedPanel(ap); // af.alignPanel;
4195 tp.getTreeCanvas().setApplyToAllViews(tree.isLinkToAllViews());
4198 warn("There was a problem recovering stored Newick tree: \n"
4199 + tree.getNewick());
4203 tp.fitToWindow.setState(safeBoolean(tree.isFitToWindow()));
4204 tp.fitToWindow_actionPerformed(null);
4206 if (tree.getFontName() != null)
4209 new Font(tree.getFontName(), safeInt(tree.getFontStyle()),
4210 safeInt(tree.getFontSize())));
4215 new Font(view.getFontName(), safeInt(view.getFontStyle()),
4216 safeInt(view.getFontSize())));
4219 tp.showPlaceholders(safeBoolean(tree.isMarkUnlinked()));
4220 tp.showBootstrap(safeBoolean(tree.isShowBootstrap()));
4221 tp.showDistances(safeBoolean(tree.isShowDistances()));
4223 tp.getTreeCanvas().setThreshold(safeFloat(tree.getThreshold()));
4225 if (safeBoolean(tree.isCurrentTree()))
4227 af.getViewport().setCurrentTree(tp.getTree());
4231 } catch (Exception ex)
4233 ex.printStackTrace();
4238 * Load and link any saved structure viewers.
4245 protected void loadPDBStructures(jarInputStreamProvider jprovider,
4246 List<JSeq> jseqs, AlignFrame af, AlignmentPanel ap)
4249 * Run through all PDB ids on the alignment, and collect mappings between
4250 * distinct view ids and all sequences referring to that view.
4252 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<>();
4254 for (int i = 0; i < jseqs.size(); i++)
4256 JSeq jseq = jseqs.get(i);
4257 if (jseq.getPdbids().size() > 0)
4259 List<Pdbids> ids = jseq.getPdbids();
4260 for (int p = 0; p < ids.size(); p++)
4262 Pdbids pdbid = ids.get(p);
4263 final int structureStateCount = pdbid.getStructureState().size();
4264 for (int s = 0; s < structureStateCount; s++)
4266 // check to see if we haven't already created this structure view
4267 final StructureState structureState = pdbid
4268 .getStructureState().get(s);
4269 String sviewid = (structureState.getViewId() == null) ? null
4270 : structureState.getViewId() + uniqueSetSuffix;
4271 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
4272 // Originally : pdbid.getFile()
4273 // : TODO: verify external PDB file recovery still works in normal
4274 // jalview project load
4276 loadPDBFile(jprovider, pdbid.getId(), pdbid.getFile()));
4277 jpdb.setId(pdbid.getId());
4279 int x = safeInt(structureState.getXpos());
4280 int y = safeInt(structureState.getYpos());
4281 int width = safeInt(structureState.getWidth());
4282 int height = safeInt(structureState.getHeight());
4284 // Probably don't need to do this anymore...
4285 // Desktop.desktop.getComponentAt(x, y);
4286 // TODO: NOW: check that this recovers the PDB file correctly.
4287 String pdbFile = loadPDBFile(jprovider, pdbid.getId(),
4289 jalview.datamodel.SequenceI seq = seqRefIds
4290 .get(jseq.getId() + "");
4291 if (sviewid == null)
4293 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width + ","
4296 if (!structureViewers.containsKey(sviewid))
4298 structureViewers.put(sviewid,
4299 new StructureViewerModel(x, y, width, height, false,
4300 false, true, structureState.getViewId(),
4301 structureState.getType()));
4302 // Legacy pre-2.7 conversion JAL-823 :
4303 // do not assume any view has to be linked for colour by
4307 // assemble String[] { pdb files }, String[] { id for each
4308 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
4309 // seqs_file 2}, boolean[] {
4310 // linkAlignPanel,superposeWithAlignpanel}} from hash
4311 StructureViewerModel jmoldat = structureViewers.get(sviewid);
4312 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
4313 || structureState.isAlignwithAlignPanel());
4316 * Default colour by linked panel to false if not specified (e.g.
4317 * for pre-2.7 projects)
4319 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
4320 colourWithAlignPanel |= structureState.isColourwithAlignPanel();
4321 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
4324 * Default colour by viewer to true if not specified (e.g. for
4327 boolean colourByViewer = jmoldat.isColourByViewer();
4328 colourByViewer &= structureState.isColourByJmol();
4329 jmoldat.setColourByViewer(colourByViewer);
4331 if (jmoldat.getStateData().length() < structureState
4332 .getValue()/*Content()*/.length())
4334 jmoldat.setStateData(structureState.getValue());// Content());
4336 if (pdbid.getFile() != null)
4338 File mapkey = new File(pdbid.getFile());
4339 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
4340 if (seqstrmaps == null)
4342 jmoldat.getFileData().put(mapkey,
4343 seqstrmaps = jmoldat.new StructureData(pdbFile,
4346 if (!seqstrmaps.getSeqList().contains(seq))
4348 seqstrmaps.getSeqList().add(seq);
4354 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");
4361 // Instantiate the associated structure views
4362 for (Entry<String, StructureViewerModel> entry : structureViewers
4367 createOrLinkStructureViewer(entry, af, ap, jprovider);
4368 } catch (Exception e)
4371 "Error loading structure viewer: " + e.getMessage());
4372 // failed - try the next one
4384 protected void createOrLinkStructureViewer(
4385 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4386 AlignmentPanel ap, jarInputStreamProvider jprovider)
4388 final StructureViewerModel stateData = viewerData.getValue();
4391 * Search for any viewer windows already open from other alignment views
4392 * that exactly match the stored structure state
4394 StructureViewerBase comp = findMatchingViewer(viewerData);
4398 linkStructureViewer(ap, comp, stateData);
4403 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
4404 * "viewer_"+stateData.viewId
4406 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
4408 createChimeraViewer(viewerData, af, jprovider);
4413 * else Jmol (if pre-2.9, stateData contains JMOL state string)
4415 createJmolViewer(viewerData, af, jprovider);
4420 * Create a new Chimera viewer.
4426 protected void createChimeraViewer(
4427 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4428 jarInputStreamProvider jprovider)
4430 StructureViewerModel data = viewerData.getValue();
4431 String chimeraSessionFile = data.getStateData();
4434 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
4436 * NB this is the 'saved' viewId as in the project file XML, _not_ the
4437 * 'uniquified' sviewid used to reconstruct the viewer here
4439 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
4440 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
4443 Set<Entry<File, StructureData>> fileData = data.getFileData()
4445 List<PDBEntry> pdbs = new ArrayList<>();
4446 List<SequenceI[]> allseqs = new ArrayList<>();
4447 for (Entry<File, StructureData> pdb : fileData)
4449 String filePath = pdb.getValue().getFilePath();
4450 String pdbId = pdb.getValue().getPdbId();
4451 // pdbs.add(new PDBEntry(filePath, pdbId));
4452 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
4453 final List<SequenceI> seqList = pdb.getValue().getSeqList();
4454 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
4458 boolean colourByChimera = data.isColourByViewer();
4459 boolean colourBySequence = data.isColourWithAlignPanel();
4461 // TODO use StructureViewer as a factory here, see JAL-1761
4462 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
4463 final SequenceI[][] seqsArray = allseqs
4464 .toArray(new SequenceI[allseqs.size()][]);
4465 String newViewId = viewerData.getKey();
4467 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
4468 af.alignPanel, pdbArray, seqsArray, colourByChimera,
4469 colourBySequence, newViewId);
4470 cvf.setSize(data.getWidth(), data.getHeight());
4471 cvf.setLocation(data.getX(), data.getY());
4475 * Create a new Jmol window. First parse the Jmol state to translate filenames
4476 * loaded into the view, and record the order in which files are shown in the
4477 * Jmol view, so we can add the sequence mappings in same order.
4483 protected void createJmolViewer(
4484 final Entry<String, StructureViewerModel> viewerData,
4485 AlignFrame af, jarInputStreamProvider jprovider)
4487 final StructureViewerModel svattrib = viewerData.getValue();
4488 String state = svattrib.getStateData();
4491 * Pre-2.9: state element value is the Jmol state string
4493 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
4496 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
4498 state = readJarEntry(jprovider,
4499 getViewerJarEntryName(svattrib.getViewId()));
4502 List<String> pdbfilenames = new ArrayList<>();
4503 List<SequenceI[]> seqmaps = new ArrayList<>();
4504 List<String> pdbids = new ArrayList<>();
4505 StringBuilder newFileLoc = new StringBuilder(64);
4506 int cp = 0, ncp, ecp;
4507 Map<File, StructureData> oldFiles = svattrib.getFileData();
4508 while ((ncp = state.indexOf("load ", cp)) > -1)
4512 // look for next filename in load statement
4513 newFileLoc.append(state.substring(cp,
4514 ncp = (state.indexOf("\"", ncp + 1) + 1)));
4515 String oldfilenam = state.substring(ncp,
4516 ecp = state.indexOf("\"", ncp));
4517 // recover the new mapping data for this old filename
4518 // have to normalize filename - since Jmol and jalview do
4520 // translation differently.
4521 StructureData filedat = oldFiles.get(new File(oldfilenam));
4522 if (filedat == null)
4524 String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\");
4525 filedat = oldFiles.get(new File(reformatedOldFilename));
4527 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
4528 pdbfilenames.add(filedat.getFilePath());
4529 pdbids.add(filedat.getPdbId());
4530 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4531 newFileLoc.append("\"");
4532 cp = ecp + 1; // advance beyond last \" and set cursor so we can
4533 // look for next file statement.
4534 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
4538 // just append rest of state
4539 newFileLoc.append(state.substring(cp));
4543 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
4544 newFileLoc = new StringBuilder(state);
4545 newFileLoc.append("; load append ");
4546 for (File id : oldFiles.keySet())
4548 // add this and any other pdb files that should be present in
4550 StructureData filedat = oldFiles.get(id);
4551 newFileLoc.append(filedat.getFilePath());
4552 pdbfilenames.add(filedat.getFilePath());
4553 pdbids.add(filedat.getPdbId());
4554 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4555 newFileLoc.append(" \"");
4556 newFileLoc.append(filedat.getFilePath());
4557 newFileLoc.append("\"");
4560 newFileLoc.append(";");
4563 if (newFileLoc.length() == 0)
4567 int histbug = newFileLoc.indexOf("history = ");
4571 * change "history = [true|false];" to "history = [1|0];"
4574 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
4575 String val = (diff == -1) ? null
4576 : newFileLoc.substring(histbug, diff);
4577 if (val != null && val.length() >= 4)
4579 if (val.contains("e")) // eh? what can it be?
4581 if (val.trim().equals("true"))
4589 newFileLoc.replace(histbug, diff, val);
4594 final String[] pdbf = pdbfilenames
4595 .toArray(new String[pdbfilenames.size()]);
4596 final String[] id = pdbids.toArray(new String[pdbids.size()]);
4597 final SequenceI[][] sq = seqmaps
4598 .toArray(new SequenceI[seqmaps.size()][]);
4599 final String fileloc = newFileLoc.toString();
4600 final String sviewid = viewerData.getKey();
4601 final AlignFrame alf = af;
4602 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
4603 svattrib.getWidth(), svattrib.getHeight());
4606 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
4611 JalviewStructureDisplayI sview = null;
4614 sview = new StructureViewer(
4615 alf.alignPanel.getStructureSelectionManager())
4616 .createView(StructureViewer.ViewerType.JMOL,
4617 pdbf, id, sq, alf.alignPanel, svattrib,
4618 fileloc, rect, sviewid);
4619 addNewStructureViewer(sview);
4620 } catch (OutOfMemoryError ex)
4622 new OOMWarning("restoring structure view for PDB id " + id,
4623 (OutOfMemoryError) ex.getCause());
4624 if (sview != null && sview.isVisible())
4626 sview.closeViewer(false);
4627 sview.setVisible(false);
4633 } catch (InvocationTargetException ex)
4635 warn("Unexpected error when opening Jmol view.", ex);
4637 } catch (InterruptedException e)
4639 // e.printStackTrace();
4645 * Generates a name for the entry in the project jar file to hold state
4646 * information for a structure viewer
4651 protected String getViewerJarEntryName(String viewId)
4653 return VIEWER_PREFIX + viewId;
4657 * Returns any open frame that matches given structure viewer data. The match
4658 * is based on the unique viewId, or (for older project versions) the frame's
4664 protected StructureViewerBase findMatchingViewer(
4665 Entry<String, StructureViewerModel> viewerData)
4667 final String sviewid = viewerData.getKey();
4668 final StructureViewerModel svattrib = viewerData.getValue();
4669 StructureViewerBase comp = null;
4670 JInternalFrame[] frames = getAllFrames();
4671 for (JInternalFrame frame : frames)
4673 if (frame instanceof StructureViewerBase)
4676 * Post jalview 2.4 schema includes structure view id
4678 if (sviewid != null && ((StructureViewerBase) frame).getViewId()
4681 comp = (StructureViewerBase) frame;
4682 break; // break added in 2.9
4685 * Otherwise test for matching position and size of viewer frame
4687 else if (frame.getX() == svattrib.getX()
4688 && frame.getY() == svattrib.getY()
4689 && frame.getHeight() == svattrib.getHeight()
4690 && frame.getWidth() == svattrib.getWidth())
4692 comp = (StructureViewerBase) frame;
4693 // no break in faint hope of an exact match on viewId
4701 * Link an AlignmentPanel to an existing structure viewer.
4706 * @param useinViewerSuperpos
4707 * @param usetoColourbyseq
4708 * @param viewerColouring
4710 protected void linkStructureViewer(AlignmentPanel ap,
4711 StructureViewerBase viewer, StructureViewerModel stateData)
4713 // NOTE: if the jalview project is part of a shared session then
4714 // view synchronization should/could be done here.
4716 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4717 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4718 final boolean viewerColouring = stateData.isColourByViewer();
4719 Map<File, StructureData> oldFiles = stateData.getFileData();
4722 * Add mapping for sequences in this view to an already open viewer
4724 final AAStructureBindingModel binding = viewer.getBinding();
4725 for (File id : oldFiles.keySet())
4727 // add this and any other pdb files that should be present in the
4729 StructureData filedat = oldFiles.get(id);
4730 String pdbFile = filedat.getFilePath();
4731 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4732 binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE,
4734 binding.addSequenceForStructFile(pdbFile, seq);
4736 // and add the AlignmentPanel's reference to the view panel
4737 viewer.addAlignmentPanel(ap);
4738 if (useinViewerSuperpos)
4740 viewer.useAlignmentPanelForSuperposition(ap);
4744 viewer.excludeAlignmentPanelForSuperposition(ap);
4746 if (usetoColourbyseq)
4748 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4752 viewer.excludeAlignmentPanelForColourbyseq(ap);
4757 * Get all frames within the Desktop.
4761 protected JInternalFrame[] getAllFrames()
4763 JInternalFrame[] frames = null;
4764 // TODO is this necessary - is it safe - risk of hanging?
4769 frames = Desktop.desktop.getAllFrames();
4770 } catch (ArrayIndexOutOfBoundsException e)
4772 // occasional No such child exceptions are thrown here...
4776 } catch (InterruptedException f)
4780 } while (frames == null);
4785 * Answers true if 'version' is equal to or later than 'supported', where each
4786 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4787 * changes. Development and test values for 'version' are leniently treated
4791 * - minimum version we are comparing against
4793 * - version of data being processsed
4796 public static boolean isVersionStringLaterThan(String supported,
4799 if (supported == null || version == null
4800 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4801 || version.equalsIgnoreCase("Test")
4802 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4804 System.err.println("Assuming project file with "
4805 + (version == null ? "null" : version)
4806 + " is compatible with Jalview version " + supported);
4811 return StringUtils.compareVersions(version, supported, "b") >= 0;
4815 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4817 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4819 if (newStructureViewers != null)
4821 sview.getBinding().setFinishedLoadingFromArchive(false);
4822 newStructureViewers.add(sview);
4826 protected void setLoadingFinishedForNewStructureViewers()
4828 if (newStructureViewers != null)
4830 for (JalviewStructureDisplayI sview : newStructureViewers)
4832 sview.getBinding().setFinishedLoadingFromArchive(true);
4834 newStructureViewers.clear();
4835 newStructureViewers = null;
4839 AlignFrame loadViewport(String file, List<JSeq> JSEQ,
4840 List<SequenceI> hiddenSeqs, AlignmentI al,
4841 JalviewModel jm, Viewport view, String uniqueSeqSetId,
4842 String viewId, List<JvAnnotRow> autoAlan)
4844 AlignFrame af = null;
4845 af = new AlignFrame(al, safeInt(view.getWidth()),
4846 safeInt(view.getHeight()), uniqueSeqSetId, viewId);
4848 af.setFileName(file, FileFormat.Jalview);
4850 final AlignViewport viewport = af.getViewport();
4851 for (int i = 0; i < JSEQ.size(); i++)
4853 int colour = safeInt(JSEQ.get(i).getColour());
4854 viewport.setSequenceColour(viewport.getAlignment().getSequenceAt(i),
4860 viewport.setColourByReferenceSeq(true);
4861 viewport.setDisplayReferenceSeq(true);
4864 viewport.setGatherViewsHere(safeBoolean(view.isGatheredViews()));
4866 if (view.getSequenceSetId() != null)
4868 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4870 viewport.setSequenceSetId(uniqueSeqSetId);
4873 // propagate shared settings to this new view
4874 viewport.setHistoryList(av.getHistoryList());
4875 viewport.setRedoList(av.getRedoList());
4879 viewportsAdded.put(uniqueSeqSetId, viewport);
4881 // TODO: check if this method can be called repeatedly without
4882 // side-effects if alignpanel already registered.
4883 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4885 // apply Hidden regions to view.
4886 if (hiddenSeqs != null)
4888 for (int s = 0; s < JSEQ.size(); s++)
4890 SequenceGroup hidden = new SequenceGroup();
4891 boolean isRepresentative = false;
4892 for (int r = 0; r < JSEQ.get(s).getHiddenSequences().size(); r++)
4894 isRepresentative = true;
4895 SequenceI sequenceToHide = al
4896 .getSequenceAt(JSEQ.get(s).getHiddenSequences().get(r));
4897 hidden.addSequence(sequenceToHide, false);
4898 // remove from hiddenSeqs list so we don't try to hide it twice
4899 hiddenSeqs.remove(sequenceToHide);
4901 if (isRepresentative)
4903 SequenceI representativeSequence = al.getSequenceAt(s);
4904 hidden.addSequence(representativeSequence, false);
4905 viewport.hideRepSequences(representativeSequence, hidden);
4909 SequenceI[] hseqs = hiddenSeqs
4910 .toArray(new SequenceI[hiddenSeqs.size()]);
4911 viewport.hideSequence(hseqs);
4914 // recover view properties and display parameters
4916 viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
4917 viewport.setAbovePIDThreshold(safeBoolean(view.isPidSelected()));
4918 final int pidThreshold = safeInt(view.getPidThreshold());
4919 viewport.setThreshold(pidThreshold);
4921 viewport.setColourText(safeBoolean(view.isShowColourText()));
4923 viewport.setConservationSelected(
4924 safeBoolean(view.isConservationSelected()));
4925 viewport.setIncrement(safeInt(view.getConsThreshold()));
4926 viewport.setShowJVSuffix(safeBoolean(view.isShowFullId()));
4927 viewport.setRightAlignIds(safeBoolean(view.isRightAlignIds()));
4928 viewport.setFont(new Font(view.getFontName(),
4929 safeInt(view.getFontStyle()), safeInt(view.getFontSize())),
4931 ViewStyleI vs = viewport.getViewStyle();
4932 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
4933 viewport.setViewStyle(vs);
4934 // TODO: allow custom charWidth/Heights to be restored by updating them
4935 // after setting font - which means set above to false
4936 viewport.setRenderGaps(safeBoolean(view.isRenderGaps()));
4937 viewport.setWrapAlignment(safeBoolean(view.isWrapAlignment()));
4938 viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
4940 Boolean autocalcFirst = view.isShowAutocalcAbove();
4941 if (autocalcFirst != null)
4943 af.setShowAutoCalculatedAbove(autocalcFirst.booleanValue());
4945 String sortBy = view.getSortAnnotationsBy();
4950 viewport.setSortAnnotationsBy(
4951 SequenceAnnotationOrder.valueOf(sortBy));
4952 } catch (IllegalArgumentException e)
4955 "Invalid annotation sort specifier in project: " + sortBy);
4959 viewport.setShowBoxes(safeBoolean(view.isShowBoxes()));
4960 viewport.setShowText(safeBoolean(view.isShowText()));
4961 viewport.setTextColour(new Color(safeInt(view.getTextCol1())));
4962 viewport.setTextColour2(new Color(safeInt(view.getTextCol2())));
4963 viewport.setThresholdTextColour(safeInt(view.getTextColThreshold()));
4964 viewport.setShowUnconserved(view.isShowUnconserved());
4965 viewport.getRanges().setStartRes(safeInt(view.getStartRes()));
4967 if (view.getViewName() != null)
4969 viewport.setViewName(view.getViewName());
4970 af.setInitialTabVisible();
4972 af.setBounds(safeInt(view.getXpos()), safeInt(view.getYpos()),
4973 safeInt(view.getWidth()), safeInt(view.getHeight()));
4974 // startSeq set in af.alignPanel.updateLayout below
4975 af.alignPanel.updateLayout();
4976 ColourSchemeI cs = null;
4977 // apply colourschemes
4978 if (view.getBgColour() != null)
4980 if (view.getBgColour().startsWith("ucs"))
4982 cs = getUserColourScheme(jm, view.getBgColour());
4984 else if (view.getBgColour().startsWith("Annotation"))
4986 AnnotationColourScheme viewAnnColour = view.getAnnotationColours();
4987 cs = constructAnnotationColour(viewAnnColour, af, al, jm, true);
4994 cs = ColourSchemeProperty.getColourScheme(af.getViewport(), al,
4995 view.getBgColour());
5000 * turn off 'alignment colour applies to all groups'
5001 * while restoring global colour scheme
5003 viewport.setColourAppliesToAllGroups(false);
5004 viewport.setGlobalColourScheme(cs);
5005 viewport.getResidueShading().setThreshold(pidThreshold,
5006 view.isIgnoreGapsinConsensus());
5007 viewport.getResidueShading()
5008 .setConsensus(viewport.getSequenceConsensusHash());
5009 if (safeBoolean(view.isConservationSelected()) && cs != null)
5011 viewport.getResidueShading()
5012 .setConservationInc(safeInt(view.getConsThreshold()));
5014 af.changeColour(cs);
5015 viewport.setColourAppliesToAllGroups(true);
5018 .setShowSequenceFeatures(
5019 safeBoolean(view.isShowSequenceFeatures()));
5021 viewport.setCentreColumnLabels(view.isCentreColumnLabels());
5022 viewport.setIgnoreGapsConsensus(view.isIgnoreGapsinConsensus(), null);
5023 viewport.setFollowHighlight(view.isFollowHighlight());
5024 viewport.followSelection = view.isFollowSelection();
5025 viewport.setShowConsensusHistogram(view.isShowConsensusHistogram());
5026 viewport.setShowSequenceLogo(view.isShowSequenceLogo());
5027 viewport.setNormaliseSequenceLogo(view.isNormaliseSequenceLogo());
5028 viewport.setShowDBRefs(safeBoolean(view.isShowDbRefTooltip()));
5029 viewport.setShowNPFeats(safeBoolean(view.isShowNPfeatureTooltip()));
5030 viewport.setShowGroupConsensus(view.isShowGroupConsensus());
5031 viewport.setShowGroupConservation(view.isShowGroupConservation());
5033 // recover feature settings
5034 if (jm.getFeatureSettings() != null)
5036 FeatureRenderer fr = af.alignPanel.getSeqPanel().seqCanvas
5037 .getFeatureRenderer();
5038 FeaturesDisplayed fdi;
5039 viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
5040 String[] renderOrder = new String[jm.getFeatureSettings()
5041 .getSetting().size()];
5042 Map<String, FeatureColourI> featureColours = new Hashtable<>();
5043 Map<String, Float> featureOrder = new Hashtable<>();
5045 for (int fs = 0; fs < jm.getFeatureSettings()
5046 .getSetting().size(); fs++)
5048 Setting setting = jm.getFeatureSettings().getSetting().get(fs);
5049 String featureType = setting.getType();
5052 * restore feature filters (if any)
5054 jalview.xml.binding.jalview.FeatureMatcherSet filters = setting
5056 if (filters != null)
5058 FeatureMatcherSetI filter = Jalview2XML
5059 .parseFilter(featureType, filters);
5060 if (!filter.isEmpty())
5062 fr.setFeatureFilter(featureType, filter);
5067 * restore feature colour scheme
5069 Color maxColour = new Color(setting.getColour());
5070 if (setting.getMincolour() != null)
5073 * minColour is always set unless a simple colour
5074 * (including for colour by label though it doesn't use it)
5076 Color minColour = new Color(setting.getMincolour().intValue());
5077 Color noValueColour = minColour;
5078 NoValueColour noColour = setting.getNoValueColour();
5079 if (noColour == NoValueColour.NONE)
5081 noValueColour = null;
5083 else if (noColour == NoValueColour.MAX)
5085 noValueColour = maxColour;
5087 float min = safeFloat(safeFloat(setting.getMin()));
5088 float max = setting.getMax() == null ? 1f
5089 : setting.getMax().floatValue();
5090 FeatureColourI gc = new FeatureColour(maxColour, minColour,
5092 noValueColour, min, max);
5093 if (setting.getAttributeName().size() > 0)
5095 gc.setAttributeName(setting.getAttributeName().toArray(
5096 new String[setting.getAttributeName().size()]));
5098 if (setting.getThreshold() != null)
5100 gc.setThreshold(setting.getThreshold().floatValue());
5101 int threshstate = safeInt(setting.getThreshstate());
5102 // -1 = None, 0 = Below, 1 = Above threshold
5103 if (threshstate == 0)
5105 gc.setBelowThreshold(true);
5107 else if (threshstate == 1)
5109 gc.setAboveThreshold(true);
5112 gc.setAutoScaled(true); // default
5113 if (setting.isAutoScale() != null)
5115 gc.setAutoScaled(setting.isAutoScale());
5117 if (setting.isColourByLabel() != null)
5119 gc.setColourByLabel(setting.isColourByLabel());
5121 // and put in the feature colour table.
5122 featureColours.put(featureType, gc);
5126 featureColours.put(featureType,
5127 new FeatureColour(maxColour));
5129 renderOrder[fs] = featureType;
5130 if (setting.getOrder() != null)
5132 featureOrder.put(featureType, setting.getOrder().floatValue());
5136 featureOrder.put(featureType, new Float(
5137 fs / jm.getFeatureSettings().getSetting().size()));
5139 if (safeBoolean(setting.isDisplay()))
5141 fdi.setVisible(featureType);
5144 Map<String, Boolean> fgtable = new Hashtable<>();
5145 for (int gs = 0; gs < jm.getFeatureSettings().getGroup().size(); gs++)
5147 Group grp = jm.getFeatureSettings().getGroup().get(gs);
5148 fgtable.put(grp.getName(), new Boolean(grp.isDisplay()));
5150 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
5151 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
5152 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
5153 FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
5154 fgtable, featureColours, 1.0f, featureOrder);
5155 fr.transferSettings(frs);
5158 if (view.getHiddenColumns().size() > 0)
5160 for (int c = 0; c < view.getHiddenColumns().size(); c++)
5162 final HiddenColumns hc = view.getHiddenColumns().get(c);
5163 viewport.hideColumns(safeInt(hc.getStart()),
5164 safeInt(hc.getEnd()) /* +1 */);
5167 if (view.getCalcIdParam() != null)
5169 for (CalcIdParam calcIdParam : view.getCalcIdParam())
5171 if (calcIdParam != null)
5173 if (recoverCalcIdParam(calcIdParam, viewport))
5178 warn("Couldn't recover parameters for "
5179 + calcIdParam.getCalcId());
5184 af.setMenusFromViewport(viewport);
5185 af.setTitle(view.getTitle());
5186 // TODO: we don't need to do this if the viewport is aready visible.
5188 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
5189 * has a 'cdna/protein complement' view, in which case save it in order to
5190 * populate a SplitFrame once all views have been read in.
5192 String complementaryViewId = view.getComplementId();
5193 if (complementaryViewId == null)
5195 Desktop.addInternalFrame(af, view.getTitle(),
5196 safeInt(view.getWidth()), safeInt(view.getHeight()));
5197 // recompute any autoannotation
5198 af.alignPanel.updateAnnotation(false, true);
5199 reorderAutoannotation(af, al, autoAlan);
5200 af.sortAnnotations(false);
5201 af.alignPanel.alignmentChanged();
5205 splitFrameCandidates.put(view, af);
5211 * Reads saved data to restore Colour by Annotation settings
5213 * @param viewAnnColour
5217 * @param checkGroupAnnColour
5220 private ColourSchemeI constructAnnotationColour(
5221 AnnotationColourScheme viewAnnColour, AlignFrame af,
5222 AlignmentI al, JalviewModel model, boolean checkGroupAnnColour)
5224 boolean propagateAnnColour = false;
5225 AlignmentI annAlignment = af != null ? af.getViewport().getAlignment()
5227 if (checkGroupAnnColour && al.getGroups() != null
5228 && al.getGroups().size() > 0)
5230 // pre 2.8.1 behaviour
5231 // check to see if we should transfer annotation colours
5232 propagateAnnColour = true;
5233 for (SequenceGroup sg : al.getGroups())
5235 if (sg.getColourScheme() instanceof AnnotationColourGradient)
5237 propagateAnnColour = false;
5243 * 2.10.2- : saved annotationId is AlignmentAnnotation.annotationId
5245 String annotationId = viewAnnColour.getAnnotation();
5246 AlignmentAnnotation matchedAnnotation = annotationIds.get(annotationId);
5249 * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
5251 if (matchedAnnotation == null
5252 && annAlignment.getAlignmentAnnotation() != null)
5254 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
5257 .equals(annAlignment.getAlignmentAnnotation()[i].label))
5259 matchedAnnotation = annAlignment.getAlignmentAnnotation()[i];
5264 if (matchedAnnotation == null)
5266 System.err.println("Failed to match annotation colour scheme for "
5270 if (matchedAnnotation.getThreshold() == null)
5272 matchedAnnotation.setThreshold(
5273 new GraphLine(safeFloat(viewAnnColour.getThreshold()),
5274 "Threshold", Color.black));
5277 AnnotationColourGradient cs = null;
5278 if (viewAnnColour.getColourScheme().equals("None"))
5280 cs = new AnnotationColourGradient(matchedAnnotation,
5281 new Color(safeInt(viewAnnColour.getMinColour())),
5282 new Color(safeInt(viewAnnColour.getMaxColour())),
5283 safeInt(viewAnnColour.getAboveThreshold()));
5285 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
5287 cs = new AnnotationColourGradient(matchedAnnotation,
5288 getUserColourScheme(model, viewAnnColour.getColourScheme()),
5289 safeInt(viewAnnColour.getAboveThreshold()));
5293 cs = new AnnotationColourGradient(matchedAnnotation,
5294 ColourSchemeProperty.getColourScheme(af.getViewport(), al,
5295 viewAnnColour.getColourScheme()),
5296 safeInt(viewAnnColour.getAboveThreshold()));
5299 boolean perSequenceOnly = safeBoolean(viewAnnColour.isPerSequence());
5300 boolean useOriginalColours = safeBoolean(
5301 viewAnnColour.isPredefinedColours());
5302 cs.setSeqAssociated(perSequenceOnly);
5303 cs.setPredefinedColours(useOriginalColours);
5305 if (propagateAnnColour && al.getGroups() != null)
5307 // Also use these settings for all the groups
5308 for (int g = 0; g < al.getGroups().size(); g++)
5310 SequenceGroup sg = al.getGroups().get(g);
5311 if (sg.getGroupColourScheme() == null)
5316 AnnotationColourGradient groupScheme = new AnnotationColourGradient(
5317 matchedAnnotation, sg.getColourScheme(),
5318 safeInt(viewAnnColour.getAboveThreshold()));
5319 sg.setColourScheme(groupScheme);
5320 groupScheme.setSeqAssociated(perSequenceOnly);
5321 groupScheme.setPredefinedColours(useOriginalColours);
5327 private void reorderAutoannotation(AlignFrame af, AlignmentI al,
5328 List<JvAnnotRow> autoAlan)
5330 // copy over visualization settings for autocalculated annotation in the
5332 if (al.getAlignmentAnnotation() != null)
5335 * Kludge for magic autoannotation names (see JAL-811)
5337 String[] magicNames = new String[] { "Consensus", "Quality",
5339 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
5340 Hashtable<String, JvAnnotRow> visan = new Hashtable<>();
5341 for (String nm : magicNames)
5343 visan.put(nm, nullAnnot);
5345 for (JvAnnotRow auan : autoAlan)
5347 visan.put(auan.template.label
5348 + (auan.template.getCalcId() == null ? ""
5349 : "\t" + auan.template.getCalcId()),
5352 int hSize = al.getAlignmentAnnotation().length;
5353 List<JvAnnotRow> reorder = new ArrayList<>();
5354 // work through any autoCalculated annotation already on the view
5355 // removing it if it should be placed in a different location on the
5356 // annotation panel.
5357 List<String> remains = new ArrayList<>(visan.keySet());
5358 for (int h = 0; h < hSize; h++)
5360 jalview.datamodel.AlignmentAnnotation jalan = al
5361 .getAlignmentAnnotation()[h];
5362 if (jalan.autoCalculated)
5365 JvAnnotRow valan = visan.get(k = jalan.label);
5366 if (jalan.getCalcId() != null)
5368 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
5373 // delete the auto calculated row from the alignment
5374 al.deleteAnnotation(jalan, false);
5378 if (valan != nullAnnot)
5380 if (jalan != valan.template)
5382 // newly created autoannotation row instance
5383 // so keep a reference to the visible annotation row
5384 // and copy over all relevant attributes
5385 if (valan.template.graphHeight >= 0)
5388 jalan.graphHeight = valan.template.graphHeight;
5390 jalan.visible = valan.template.visible;
5392 reorder.add(new JvAnnotRow(valan.order, jalan));
5397 // Add any (possibly stale) autocalculated rows that were not appended to
5398 // the view during construction
5399 for (String other : remains)
5401 JvAnnotRow othera = visan.get(other);
5402 if (othera != nullAnnot && othera.template.getCalcId() != null
5403 && othera.template.getCalcId().length() > 0)
5405 reorder.add(othera);
5408 // now put the automatic annotation in its correct place
5409 int s = 0, srt[] = new int[reorder.size()];
5410 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
5411 for (JvAnnotRow jvar : reorder)
5414 srt[s++] = jvar.order;
5417 jalview.util.QuickSort.sort(srt, rws);
5418 // and re-insert the annotation at its correct position
5419 for (JvAnnotRow jvar : rws)
5421 al.addAnnotation(jvar.template, jvar.order);
5423 af.alignPanel.adjustAnnotationHeight();
5427 Hashtable skipList = null;
5430 * TODO remove this method
5433 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
5434 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
5435 * throw new Error("Implementation Error. No skipList defined for this
5436 * Jalview2XML instance."); } return (AlignFrame)
5437 * skipList.get(view.getSequenceSetId()); }
5441 * Check if the Jalview view contained in object should be skipped or not.
5444 * @return true if view's sequenceSetId is a key in skipList
5446 private boolean skipViewport(JalviewModel object)
5448 if (skipList == null)
5452 String id = object.getViewport().get(0).getSequenceSetId();
5453 if (skipList.containsKey(id))
5455 if (Cache.log != null && Cache.log.isDebugEnabled())
5457 Cache.log.debug("Skipping seuqence set id " + id);
5464 public void addToSkipList(AlignFrame af)
5466 if (skipList == null)
5468 skipList = new Hashtable();
5470 skipList.put(af.getViewport().getSequenceSetId(), af);
5473 public void clearSkipList()
5475 if (skipList != null)
5482 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
5483 boolean ignoreUnrefed, String uniqueSeqSetId)
5485 jalview.datamodel.AlignmentI ds = getDatasetFor(
5486 vamsasSet.getDatasetId());
5487 AlignmentI xtant_ds = ds;
5488 if (xtant_ds == null)
5490 // good chance we are about to create a new dataset, but check if we've
5491 // seen some of the dataset sequence IDs before.
5492 // TODO: skip this check if we are working with project generated by
5493 // version 2.11 or later
5494 xtant_ds = checkIfHasDataset(vamsasSet.getSequence());
5495 if (xtant_ds != null)
5498 addDatasetRef(vamsasSet.getDatasetId(), ds);
5501 Vector dseqs = null;
5504 // recovering an alignment View
5505 AlignmentI seqSetDS = getDatasetFor(UNIQSEQSETID + uniqueSeqSetId);
5506 if (seqSetDS != null)
5508 if (ds != null && ds != seqSetDS)
5510 warn("JAL-3171 regression: Overwriting a dataset reference for an alignment"
5511 + " - CDS/Protein crossreference data may be lost");
5512 if (xtant_ds != null)
5514 // This can only happen if the unique sequence set ID was bound to a
5515 // dataset that did not contain any of the sequences in the view
5516 // currently being restored.
5517 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.");
5521 addDatasetRef(vamsasSet.getDatasetId(), ds);
5526 // try even harder to restore dataset
5527 AlignmentI xtantDS = checkIfHasDataset(vamsasSet.getSequence());
5528 // create a list of new dataset sequences
5529 dseqs = new Vector();
5531 for (int i = 0, iSize = vamsasSet.getSequence().size(); i < iSize; i++)
5533 Sequence vamsasSeq = vamsasSet.getSequence().get(i);
5534 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
5536 // create a new dataset
5539 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
5540 dseqs.copyInto(dsseqs);
5541 ds = new jalview.datamodel.Alignment(dsseqs);
5542 debug("Created new dataset " + vamsasSet.getDatasetId()
5543 + " for alignment " + System.identityHashCode(al));
5544 addDatasetRef(vamsasSet.getDatasetId(), ds);
5546 // set the dataset for the newly imported alignment.
5547 if (al.getDataset() == null && !ignoreUnrefed)
5550 // register dataset for the alignment's uniqueSeqSetId for legacy projects
5551 addDatasetRef(UNIQSEQSETID + uniqueSeqSetId, ds);
5553 updateSeqDatasetBinding(vamsasSet.getSequence(), ds);
5557 * XML dataset sequence ID to materialised dataset reference
5559 HashMap<String, AlignmentI> seqToDataset = new HashMap<>();
5562 * @return the first materialised dataset reference containing a dataset
5563 * sequence referenced in the given view
5565 * - sequences from the view
5567 AlignmentI checkIfHasDataset(List<Sequence> list)
5569 for (Sequence restoredSeq : list)
5571 AlignmentI datasetFor = seqToDataset.get(restoredSeq.getDsseqid());
5572 if (datasetFor != null)
5581 * Register ds as the containing dataset for the dataset sequences referenced
5582 * by sequences in list
5585 * - sequences in a view
5588 void updateSeqDatasetBinding(List<Sequence> list, AlignmentI ds)
5590 for (Sequence restoredSeq : list)
5592 AlignmentI prevDS = seqToDataset.put(restoredSeq.getDsseqid(), ds);
5593 if (prevDS != null && prevDS != ds)
5595 warn("Dataset sequence appears in many datasets: "
5596 + restoredSeq.getDsseqid());
5597 // TODO: try to merge!
5604 * sequence definition to create/merge dataset sequence for
5608 * vector to add new dataset sequence to
5609 * @param ignoreUnrefed
5610 * - when true, don't create new sequences from vamsasSeq if it's id
5611 * doesn't already have an asssociated Jalview sequence.
5613 * - used to reorder the sequence in the alignment according to the
5614 * vamsasSeq array ordering, to preserve ordering of dataset
5616 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
5617 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed, int vseqpos)
5619 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
5621 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
5622 boolean reorder = false;
5623 SequenceI dsq = null;
5624 if (sq != null && sq.getDatasetSequence() != null)
5626 dsq = sq.getDatasetSequence();
5632 if (sq == null && ignoreUnrefed)
5636 String sqid = vamsasSeq.getDsseqid();
5639 // need to create or add a new dataset sequence reference to this sequence
5642 dsq = seqRefIds.get(sqid);
5647 // make a new dataset sequence
5648 dsq = sq.createDatasetSequence();
5651 // make up a new dataset reference for this sequence
5652 sqid = seqHash(dsq);
5654 dsq.setVamsasId(uniqueSetSuffix + sqid);
5655 seqRefIds.put(sqid, dsq);
5660 dseqs.addElement(dsq);
5665 ds.addSequence(dsq);
5671 { // make this dataset sequence sq's dataset sequence
5672 sq.setDatasetSequence(dsq);
5673 // and update the current dataset alignment
5678 if (!dseqs.contains(dsq))
5685 if (ds.findIndex(dsq) < 0)
5687 ds.addSequence(dsq);
5694 // TODO: refactor this as a merge dataset sequence function
5695 // now check that sq (the dataset sequence) sequence really is the union of
5696 // all references to it
5697 // boolean pre = sq.getStart() < dsq.getStart();
5698 // boolean post = sq.getEnd() > dsq.getEnd();
5702 // StringBuffer sb = new StringBuffer();
5703 String newres = jalview.analysis.AlignSeq.extractGaps(
5704 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
5705 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
5706 && newres.length() > dsq.getLength())
5708 // Update with the longer sequence.
5712 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
5713 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
5714 * sb.append(newres.substring(newres.length() - sq.getEnd() -
5715 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
5717 dsq.setSequence(newres);
5719 // TODO: merges will never happen if we 'know' we have the real dataset
5720 // sequence - this should be detected when id==dssid
5722 "DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
5723 // + (pre ? "prepended" : "") + " "
5724 // + (post ? "appended" : ""));
5729 // sequence refs are identical. We may need to update the existing dataset
5730 // alignment with this one, though.
5731 if (ds != null && dseqs == null)
5733 int opos = ds.findIndex(dsq);
5734 SequenceI tseq = null;
5735 if (opos != -1 && vseqpos != opos)
5737 // remove from old position
5738 ds.deleteSequence(dsq);
5740 if (vseqpos < ds.getHeight())
5742 if (vseqpos != opos)
5744 // save sequence at destination position
5745 tseq = ds.getSequenceAt(vseqpos);
5746 ds.replaceSequenceAt(vseqpos, dsq);
5747 ds.addSequence(tseq);
5752 ds.addSequence(dsq);
5759 * TODO use AlignmentI here and in related methods - needs
5760 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
5762 Hashtable<String, AlignmentI> datasetIds = null;
5764 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
5766 private AlignmentI getDatasetFor(String datasetId)
5768 if (datasetIds == null)
5770 datasetIds = new Hashtable<>();
5773 if (datasetIds.containsKey(datasetId))
5775 return datasetIds.get(datasetId);
5780 private void addDatasetRef(String datasetId, AlignmentI dataset)
5782 if (datasetIds == null)
5784 datasetIds = new Hashtable<>();
5786 datasetIds.put(datasetId, dataset);
5790 * make a new dataset ID for this jalview dataset alignment
5795 private String getDatasetIdRef(AlignmentI dataset)
5797 if (dataset.getDataset() != null)
5799 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
5801 String datasetId = makeHashCode(dataset, null);
5802 if (datasetId == null)
5804 // make a new datasetId and record it
5805 if (dataset2Ids == null)
5807 dataset2Ids = new IdentityHashMap<>();
5811 datasetId = dataset2Ids.get(dataset);
5813 if (datasetId == null)
5815 datasetId = "ds" + dataset2Ids.size() + 1;
5816 dataset2Ids.put(dataset, datasetId);
5822 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5824 for (int d = 0; d < sequence.getDBRef().size(); d++)
5826 DBRef dr = sequence.getDBRef().get(d);
5827 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
5828 dr.getSource(), dr.getVersion(), dr.getAccessionId());
5829 if (dr.getMapping() != null)
5831 entry.setMap(addMapping(dr.getMapping()));
5833 datasetSequence.addDBRef(entry);
5837 private jalview.datamodel.Mapping addMapping(Mapping m)
5839 SequenceI dsto = null;
5840 // Mapping m = dr.getMapping();
5841 int fr[] = new int[m.getMapListFrom().size() * 2];
5842 Iterator<MapListFrom> from = m.getMapListFrom().iterator();// enumerateMapListFrom();
5843 for (int _i = 0; from.hasNext(); _i += 2)
5845 MapListFrom mf = from.next();
5846 fr[_i] = mf.getStart();
5847 fr[_i + 1] = mf.getEnd();
5849 int fto[] = new int[m.getMapListTo().size() * 2];
5850 Iterator<MapListTo> to = m.getMapListTo().iterator();// enumerateMapListTo();
5851 for (int _i = 0; to.hasNext(); _i += 2)
5853 MapListTo mf = to.next();
5854 fto[_i] = mf.getStart();
5855 fto[_i + 1] = mf.getEnd();
5857 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto, fr,
5858 fto, m.getMapFromUnit().intValue(),
5859 m.getMapToUnit().intValue());
5862 * (optional) choice of dseqFor or Sequence
5864 if (m.getDseqFor() != null)
5866 String dsfor = m.getDseqFor();
5867 if (seqRefIds.containsKey(dsfor))
5872 jmap.setTo(seqRefIds.get(dsfor));
5876 frefedSequence.add(newMappingRef(dsfor, jmap));
5879 else if (m.getSequence() != null)
5882 * local sequence definition
5884 Sequence ms = m.getSequence();
5885 SequenceI djs = null;
5886 String sqid = ms.getDsseqid();
5887 if (sqid != null && sqid.length() > 0)
5890 * recover dataset sequence
5892 djs = seqRefIds.get(sqid);
5897 "Warning - making up dataset sequence id for DbRef sequence map reference");
5898 sqid = ((Object) ms).toString(); // make up a new hascode for
5899 // undefined dataset sequence hash
5900 // (unlikely to happen)
5906 * make a new dataset sequence and add it to refIds hash
5908 djs = new jalview.datamodel.Sequence(ms.getName(),
5910 djs.setStart(jmap.getMap().getToLowest());
5911 djs.setEnd(jmap.getMap().getToHighest());
5912 djs.setVamsasId(uniqueSetSuffix + sqid);
5914 incompleteSeqs.put(sqid, djs);
5915 seqRefIds.put(sqid, djs);
5918 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5927 * Provides a 'copy' of an alignment view (on action New View) by 'saving' the
5928 * view as XML (but not to file), and then reloading it
5933 public AlignmentPanel copyAlignPanel(AlignmentPanel ap)
5936 JalviewModel jm = saveState(ap, null, null, null);
5939 jm.getVamsasModel().getSequenceSet().get(0).getDatasetId(),
5940 ap.getAlignment().getDataset());
5942 uniqueSetSuffix = "";
5943 // jm.getJalviewModelSequence().getViewport(0).setId(null);
5944 jm.getViewport().get(0).setId(null);
5945 // we don't overwrite the view we just copied
5947 if (this.frefedSequence == null)
5949 frefedSequence = new Vector<>();
5952 viewportsAdded.clear();
5954 AlignFrame af = loadFromObject(jm, null, false, null);
5955 af.getAlignPanels().clear();
5956 af.closeMenuItem_actionPerformed(true);
5959 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5960 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5961 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5962 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5963 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5966 return af.alignPanel;
5969 private Hashtable jvids2vobj;
5971 private void warn(String msg)
5976 private void warn(String msg, Exception e)
5978 if (Cache.log != null)
5982 Cache.log.warn(msg, e);
5986 Cache.log.warn(msg);
5991 System.err.println("Warning: " + msg);
5994 e.printStackTrace();
5999 private void debug(String string)
6001 debug(string, null);
6004 private void debug(String msg, Exception e)
6006 if (Cache.log != null)
6010 Cache.log.debug(msg, e);
6014 Cache.log.debug(msg);
6019 System.err.println("Warning: " + msg);
6022 e.printStackTrace();
6028 * set the object to ID mapping tables used to write/recover objects and XML
6029 * ID strings for the jalview project. If external tables are provided then
6030 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
6031 * object goes out of scope. - also populates the datasetIds hashtable with
6032 * alignment objects containing dataset sequences
6035 * Map from ID strings to jalview datamodel
6037 * Map from jalview datamodel to ID strings
6041 public void setObjectMappingTables(Hashtable vobj2jv,
6042 IdentityHashMap jv2vobj)
6044 this.jv2vobj = jv2vobj;
6045 this.vobj2jv = vobj2jv;
6046 Iterator ds = jv2vobj.keySet().iterator();
6048 while (ds.hasNext())
6050 Object jvobj = ds.next();
6051 id = jv2vobj.get(jvobj).toString();
6052 if (jvobj instanceof jalview.datamodel.Alignment)
6054 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
6056 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
6059 else if (jvobj instanceof jalview.datamodel.Sequence)
6061 // register sequence object so the XML parser can recover it.
6062 if (seqRefIds == null)
6064 seqRefIds = new HashMap<>();
6066 if (seqsToIds == null)
6068 seqsToIds = new IdentityHashMap<>();
6070 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
6071 seqsToIds.put((SequenceI) jvobj, id);
6073 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
6076 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
6077 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
6078 if (jvann.annotationId == null)
6080 jvann.annotationId = anid;
6082 if (!jvann.annotationId.equals(anid))
6084 // TODO verify that this is the correct behaviour
6085 this.warn("Overriding Annotation ID for " + anid
6086 + " from different id : " + jvann.annotationId);
6087 jvann.annotationId = anid;
6090 else if (jvobj instanceof String)
6092 if (jvids2vobj == null)
6094 jvids2vobj = new Hashtable();
6095 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
6100 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
6106 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
6107 * objects created from the project archive. If string is null (default for
6108 * construction) then suffix will be set automatically.
6112 public void setUniqueSetSuffix(String string)
6114 uniqueSetSuffix = string;
6119 * uses skipList2 as the skipList for skipping views on sequence sets
6120 * associated with keys in the skipList
6124 public void setSkipList(Hashtable skipList2)
6126 skipList = skipList2;
6130 * Reads the jar entry of given name and returns its contents, or null if the
6131 * entry is not found.
6134 * @param jarEntryName
6137 protected String readJarEntry(jarInputStreamProvider jprovider,
6138 String jarEntryName)
6140 String result = null;
6141 BufferedReader in = null;
6146 * Reopen the jar input stream and traverse its entries to find a matching
6149 JarInputStream jin = jprovider.getJarInputStream();
6150 JarEntry entry = null;
6153 entry = jin.getNextJarEntry();
6154 } while (entry != null && !entry.getName().equals(jarEntryName));
6158 StringBuilder out = new StringBuilder(256);
6159 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
6162 while ((data = in.readLine()) != null)
6166 result = out.toString();
6170 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
6172 } catch (Exception ex)
6174 ex.printStackTrace();
6182 } catch (IOException e)
6193 * Returns an incrementing counter (0, 1, 2...)
6197 private synchronized int nextCounter()
6203 * Loads any saved PCA viewers
6208 protected void loadPCAViewers(JalviewModel model, AlignmentPanel ap)
6212 List<PcaViewer> pcaviewers = model.getPcaViewer();
6213 for (PcaViewer viewer : pcaviewers)
6215 String modelName = viewer.getScoreModelName();
6216 SimilarityParamsI params = new SimilarityParams(
6217 viewer.isIncludeGappedColumns(), viewer.isMatchGaps(),
6218 viewer.isIncludeGaps(),
6219 viewer.isDenominateByShortestLength());
6222 * create the panel (without computing the PCA)
6224 PCAPanel panel = new PCAPanel(ap, modelName, params);
6226 panel.setTitle(viewer.getTitle());
6227 panel.setBounds(new Rectangle(viewer.getXpos(), viewer.getYpos(),
6228 viewer.getWidth(), viewer.getHeight()));
6230 boolean showLabels = viewer.isShowLabels();
6231 panel.setShowLabels(showLabels);
6232 panel.getRotatableCanvas().setShowLabels(showLabels);
6233 panel.getRotatableCanvas()
6234 .setBgColour(new Color(viewer.getBgColour()));
6235 panel.getRotatableCanvas()
6236 .setApplyToAllViews(viewer.isLinkToAllViews());
6239 * load PCA output data
6241 ScoreModelI scoreModel = ScoreModels.getInstance()
6242 .getScoreModel(modelName, ap);
6243 PCA pca = new PCA(null, scoreModel, params);
6244 PcaDataType pcaData = viewer.getPcaData();
6246 MatrixI pairwise = loadDoubleMatrix(pcaData.getPairwiseMatrix());
6247 pca.setPairwiseScores(pairwise);
6249 MatrixI triDiag = loadDoubleMatrix(pcaData.getTridiagonalMatrix());
6250 pca.setTridiagonal(triDiag);
6252 MatrixI result = loadDoubleMatrix(pcaData.getEigenMatrix());
6253 pca.setEigenmatrix(result);
6255 panel.getPcaModel().setPCA(pca);
6258 * we haven't saved the input data! (JAL-2647 to do)
6260 panel.setInputData(null);
6263 * add the sequence points for the PCA display
6265 List<jalview.datamodel.SequencePoint> seqPoints = new ArrayList<>();
6266 for (SequencePoint sp : viewer.getSequencePoint())
6268 String seqId = sp.getSequenceRef();
6269 SequenceI seq = seqRefIds.get(seqId);
6272 throw new IllegalStateException(
6273 "Unmatched seqref for PCA: " + seqId);
6275 Point pt = new Point(sp.getXPos(), sp.getYPos(), sp.getZPos());
6276 jalview.datamodel.SequencePoint seqPoint = new jalview.datamodel.SequencePoint(
6278 seqPoints.add(seqPoint);
6280 panel.getRotatableCanvas().setPoints(seqPoints, seqPoints.size());
6283 * set min-max ranges and scale after setPoints (which recomputes them)
6285 panel.getRotatableCanvas().setScaleFactor(viewer.getScaleFactor());
6286 SeqPointMin spMin = viewer.getSeqPointMin();
6287 float[] min = new float[] { spMin.getXPos(), spMin.getYPos(),
6289 SeqPointMax spMax = viewer.getSeqPointMax();
6290 float[] max = new float[] { spMax.getXPos(), spMax.getYPos(),
6292 panel.getRotatableCanvas().setSeqMinMax(min, max);
6294 // todo: hold points list in PCAModel only
6295 panel.getPcaModel().setSequencePoints(seqPoints);
6297 panel.setSelectedDimensionIndex(viewer.getXDim(), X);
6298 panel.setSelectedDimensionIndex(viewer.getYDim(), Y);
6299 panel.setSelectedDimensionIndex(viewer.getZDim(), Z);
6301 // is this duplication needed?
6302 panel.setTop(seqPoints.size() - 1);
6303 panel.getPcaModel().setTop(seqPoints.size() - 1);
6306 * add the axes' end points for the display
6308 for (int i = 0; i < 3; i++)
6310 Axis axis = viewer.getAxis().get(i);
6311 panel.getRotatableCanvas().getAxisEndPoints()[i] = new Point(
6312 axis.getXPos(), axis.getYPos(), axis.getZPos());
6315 Desktop.addInternalFrame(panel, MessageManager.formatMessage(
6316 "label.calc_title", "PCA", modelName), 475, 450);
6318 } catch (Exception ex)
6320 Cache.log.error("Error loading PCA: " + ex.toString());
6325 * Populates an XML model of the feature colour scheme for one feature type
6327 * @param featureType
6331 public static Colour marshalColour(
6332 String featureType, FeatureColourI fcol)
6334 Colour col = new Colour();
6335 if (fcol.isSimpleColour())
6337 col.setRGB(Format.getHexString(fcol.getColour()));
6341 col.setRGB(Format.getHexString(fcol.getMaxColour()));
6342 col.setMin(fcol.getMin());
6343 col.setMax(fcol.getMax());
6344 col.setMinRGB(jalview.util.Format.getHexString(fcol.getMinColour()));
6345 col.setAutoScale(fcol.isAutoScaled());
6346 col.setThreshold(fcol.getThreshold());
6347 col.setColourByLabel(fcol.isColourByLabel());
6348 col.setThreshType(fcol.isAboveThreshold() ? ThresholdType.ABOVE
6349 : (fcol.isBelowThreshold() ? ThresholdType.BELOW
6350 : ThresholdType.NONE));
6351 if (fcol.isColourByAttribute())
6353 final String[] attName = fcol.getAttributeName();
6354 col.getAttributeName().add(attName[0]);
6355 if (attName.length > 1)
6357 col.getAttributeName().add(attName[1]);
6360 Color noColour = fcol.getNoColour();
6361 if (noColour == null)
6363 col.setNoValueColour(NoValueColour.NONE);
6365 else if (noColour == fcol.getMaxColour())
6367 col.setNoValueColour(NoValueColour.MAX);
6371 col.setNoValueColour(NoValueColour.MIN);
6374 col.setName(featureType);
6379 * Populates an XML model of the feature filter(s) for one feature type
6381 * @param firstMatcher
6382 * the first (or only) match condition)
6384 * remaining match conditions (if any)
6386 * if true, conditions are and-ed, else or-ed
6388 public static jalview.xml.binding.jalview.FeatureMatcherSet marshalFilter(
6389 FeatureMatcherI firstMatcher, Iterator<FeatureMatcherI> filters,
6392 jalview.xml.binding.jalview.FeatureMatcherSet result = new jalview.xml.binding.jalview.FeatureMatcherSet();
6394 if (filters.hasNext())
6399 CompoundMatcher compound = new CompoundMatcher();
6400 compound.setAnd(and);
6401 jalview.xml.binding.jalview.FeatureMatcherSet matcher1 = marshalFilter(
6402 firstMatcher, Collections.emptyIterator(), and);
6403 // compound.addMatcherSet(matcher1);
6404 compound.getMatcherSet().add(matcher1);
6405 FeatureMatcherI nextMatcher = filters.next();
6406 jalview.xml.binding.jalview.FeatureMatcherSet matcher2 = marshalFilter(
6407 nextMatcher, filters, and);
6408 // compound.addMatcherSet(matcher2);
6409 compound.getMatcherSet().add(matcher2);
6410 result.setCompoundMatcher(compound);
6415 * single condition matcher
6417 // MatchCondition matcherModel = new MatchCondition();
6418 jalview.xml.binding.jalview.FeatureMatcher matcherModel = new jalview.xml.binding.jalview.FeatureMatcher();
6419 matcherModel.setCondition(
6420 firstMatcher.getMatcher().getCondition().getStableName());
6421 matcherModel.setValue(firstMatcher.getMatcher().getPattern());
6422 if (firstMatcher.isByAttribute())
6424 matcherModel.setBy(FilterBy.BY_ATTRIBUTE);
6425 // matcherModel.setAttributeName(firstMatcher.getAttribute());
6426 String[] attName = firstMatcher.getAttribute();
6427 matcherModel.getAttributeName().add(attName[0]); // attribute
6428 if (attName.length > 1)
6430 matcherModel.getAttributeName().add(attName[1]); // sub-attribute
6433 else if (firstMatcher.isByLabel())
6435 matcherModel.setBy(FilterBy.BY_LABEL);
6437 else if (firstMatcher.isByScore())
6439 matcherModel.setBy(FilterBy.BY_SCORE);
6441 result.setMatchCondition(matcherModel);
6448 * Loads one XML model of a feature filter to a Jalview object
6450 * @param featureType
6451 * @param matcherSetModel
6454 public static FeatureMatcherSetI parseFilter(
6456 jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel)
6458 FeatureMatcherSetI result = new FeatureMatcherSet();
6461 parseFilterConditions(result, matcherSetModel, true);
6462 } catch (IllegalStateException e)
6464 // mixing AND and OR conditions perhaps
6466 String.format("Error reading filter conditions for '%s': %s",
6467 featureType, e.getMessage()));
6468 // return as much as was parsed up to the error
6475 * Adds feature match conditions to matcherSet as unmarshalled from XML
6476 * (possibly recursively for compound conditions)
6479 * @param matcherSetModel
6481 * if true, multiple conditions are AND-ed, else they are OR-ed
6482 * @throws IllegalStateException
6483 * if AND and OR conditions are mixed
6485 protected static void parseFilterConditions(
6486 FeatureMatcherSetI matcherSet,
6487 jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel,
6490 jalview.xml.binding.jalview.FeatureMatcher mc = matcherSetModel
6491 .getMatchCondition();
6497 FilterBy filterBy = mc.getBy();
6498 Condition cond = Condition.fromString(mc.getCondition());
6499 String pattern = mc.getValue();
6500 FeatureMatcherI matchCondition = null;
6501 if (filterBy == FilterBy.BY_LABEL)
6503 matchCondition = FeatureMatcher.byLabel(cond, pattern);
6505 else if (filterBy == FilterBy.BY_SCORE)
6507 matchCondition = FeatureMatcher.byScore(cond, pattern);
6510 else if (filterBy == FilterBy.BY_ATTRIBUTE)
6512 final List<String> attributeName = mc.getAttributeName();
6513 String[] attNames = attributeName
6514 .toArray(new String[attributeName.size()]);
6515 matchCondition = FeatureMatcher.byAttribute(cond, pattern,
6520 * note this throws IllegalStateException if AND-ing to a
6521 * previously OR-ed compound condition, or vice versa
6525 matcherSet.and(matchCondition);
6529 matcherSet.or(matchCondition);
6535 * compound condition
6537 List<jalview.xml.binding.jalview.FeatureMatcherSet> matchers = matcherSetModel
6538 .getCompoundMatcher().getMatcherSet();
6539 boolean anded = matcherSetModel.getCompoundMatcher().isAnd();
6540 if (matchers.size() == 2)
6542 parseFilterConditions(matcherSet, matchers.get(0), anded);
6543 parseFilterConditions(matcherSet, matchers.get(1), anded);
6547 System.err.println("Malformed compound filter condition");
6553 * Loads one XML model of a feature colour to a Jalview object
6555 * @param colourModel
6558 public static FeatureColourI parseColour(Colour colourModel)
6560 FeatureColourI colour = null;
6562 if (colourModel.getMax() != null)
6564 Color mincol = null;
6565 Color maxcol = null;
6566 Color noValueColour = null;
6570 mincol = new Color(Integer.parseInt(colourModel.getMinRGB(), 16));
6571 maxcol = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6572 } catch (Exception e)
6574 Cache.log.warn("Couldn't parse out graduated feature color.", e);
6577 NoValueColour noCol = colourModel.getNoValueColour();
6578 if (noCol == NoValueColour.MIN)
6580 noValueColour = mincol;
6582 else if (noCol == NoValueColour.MAX)
6584 noValueColour = maxcol;
6587 colour = new FeatureColour(maxcol, mincol, maxcol, noValueColour,
6588 safeFloat(colourModel.getMin()),
6589 safeFloat(colourModel.getMax()));
6590 final List<String> attributeName = colourModel.getAttributeName();
6591 String[] attributes = attributeName
6592 .toArray(new String[attributeName.size()]);
6593 if (attributes != null && attributes.length > 0)
6595 colour.setAttributeName(attributes);
6597 if (colourModel.isAutoScale() != null)
6599 colour.setAutoScaled(colourModel.isAutoScale().booleanValue());
6601 if (colourModel.isColourByLabel() != null)
6603 colour.setColourByLabel(
6604 colourModel.isColourByLabel().booleanValue());
6606 if (colourModel.getThreshold() != null)
6608 colour.setThreshold(colourModel.getThreshold().floatValue());
6610 ThresholdType ttyp = colourModel.getThreshType();
6611 if (ttyp == ThresholdType.ABOVE)
6613 colour.setAboveThreshold(true);
6615 else if (ttyp == ThresholdType.BELOW)
6617 colour.setBelowThreshold(true);
6622 Color color = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6623 colour = new FeatureColour(color);