2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
21 package jalview.project;
23 import static jalview.math.RotatableMatrix.Axis.X;
24 import static jalview.math.RotatableMatrix.Axis.Y;
25 import static jalview.math.RotatableMatrix.Axis.Z;
27 import jalview.analysis.Conservation;
28 import jalview.analysis.PCA;
29 import jalview.analysis.scoremodels.ScoreModels;
30 import jalview.analysis.scoremodels.SimilarityParams;
31 import jalview.api.FeatureColourI;
32 import jalview.api.ViewStyleI;
33 import jalview.api.analysis.ScoreModelI;
34 import jalview.api.analysis.SimilarityParamsI;
35 import jalview.api.structures.JalviewStructureDisplayI;
36 import jalview.bin.Cache;
37 import jalview.datamodel.AlignedCodonFrame;
38 import jalview.datamodel.Alignment;
39 import jalview.datamodel.AlignmentAnnotation;
40 import jalview.datamodel.AlignmentI;
41 import jalview.datamodel.GraphLine;
42 import jalview.datamodel.HiddenMarkovModel;
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.HMMFile;
76 import jalview.io.NewickFile;
77 import jalview.math.Matrix;
78 import jalview.math.MatrixI;
79 import jalview.renderer.ResidueShaderI;
80 import jalview.schemes.AnnotationColourGradient;
81 import jalview.schemes.ColourSchemeI;
82 import jalview.schemes.ColourSchemeProperty;
83 import jalview.schemes.FeatureColour;
84 import jalview.schemes.ResidueProperties;
85 import jalview.schemes.UserColourScheme;
86 import jalview.structure.StructureSelectionManager;
87 import jalview.structures.models.AAStructureBindingModel;
88 import jalview.util.Format;
89 import jalview.util.MessageManager;
90 import jalview.util.Platform;
91 import jalview.util.StringUtils;
92 import jalview.util.jarInputStreamProvider;
93 import jalview.util.matcher.Condition;
94 import jalview.viewmodel.AlignmentViewport;
95 import jalview.viewmodel.PCAModel;
96 import jalview.viewmodel.ViewportRanges;
97 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
98 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
99 import jalview.ws.jws2.Jws2Discoverer;
100 import jalview.ws.jws2.dm.AAConSettings;
101 import jalview.ws.jws2.jabaws2.Jws2Instance;
102 import jalview.ws.params.ArgumentI;
103 import jalview.ws.params.AutoCalcSetting;
104 import jalview.ws.params.WsParamSetI;
105 import jalview.xml.binding.jalview.AlcodonFrame;
106 import jalview.xml.binding.jalview.AlcodonFrame.AlcodMap;
107 import jalview.xml.binding.jalview.Annotation;
108 import jalview.xml.binding.jalview.Annotation.ThresholdLine;
109 import jalview.xml.binding.jalview.AnnotationColourScheme;
110 import jalview.xml.binding.jalview.AnnotationElement;
111 import jalview.xml.binding.jalview.DoubleMatrix;
112 import jalview.xml.binding.jalview.DoubleVector;
113 import jalview.xml.binding.jalview.Feature;
114 import jalview.xml.binding.jalview.Feature.OtherData;
115 import jalview.xml.binding.jalview.FeatureMatcherSet.CompoundMatcher;
116 import jalview.xml.binding.jalview.FilterBy;
117 import jalview.xml.binding.jalview.JalviewModel;
118 import jalview.xml.binding.jalview.JalviewModel.FeatureSettings;
119 import jalview.xml.binding.jalview.JalviewModel.FeatureSettings.Group;
120 import jalview.xml.binding.jalview.JalviewModel.FeatureSettings.Setting;
121 import jalview.xml.binding.jalview.JalviewModel.JGroup;
122 import jalview.xml.binding.jalview.JalviewModel.JSeq;
123 import jalview.xml.binding.jalview.JalviewModel.JSeq.Pdbids;
124 import jalview.xml.binding.jalview.JalviewModel.JSeq.Pdbids.StructureState;
125 import jalview.xml.binding.jalview.JalviewModel.JSeq.RnaViewer;
126 import jalview.xml.binding.jalview.JalviewModel.JSeq.RnaViewer.SecondaryStructure;
127 import jalview.xml.binding.jalview.JalviewModel.PcaViewer;
128 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.Axis;
129 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.SeqPointMax;
130 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.SeqPointMin;
131 import jalview.xml.binding.jalview.JalviewModel.PcaViewer.SequencePoint;
132 import jalview.xml.binding.jalview.JalviewModel.Tree;
133 import jalview.xml.binding.jalview.JalviewModel.UserColours;
134 import jalview.xml.binding.jalview.JalviewModel.Viewport;
135 import jalview.xml.binding.jalview.JalviewModel.Viewport.CalcIdParam;
136 import jalview.xml.binding.jalview.JalviewModel.Viewport.HiddenColumns;
137 import jalview.xml.binding.jalview.JalviewUserColours;
138 import jalview.xml.binding.jalview.JalviewUserColours.Colour;
139 import jalview.xml.binding.jalview.MapListType.MapListFrom;
140 import jalview.xml.binding.jalview.MapListType.MapListTo;
141 import jalview.xml.binding.jalview.Mapping;
142 import jalview.xml.binding.jalview.NoValueColour;
143 import jalview.xml.binding.jalview.ObjectFactory;
144 import jalview.xml.binding.jalview.PcaDataType;
145 import jalview.xml.binding.jalview.Pdbentry.Property;
146 import jalview.xml.binding.jalview.Sequence;
147 import jalview.xml.binding.jalview.Sequence.DBRef;
148 import jalview.xml.binding.jalview.SequenceSet;
149 import jalview.xml.binding.jalview.SequenceSet.SequenceSetProperties;
150 import jalview.xml.binding.jalview.ThresholdType;
151 import jalview.xml.binding.jalview.VAMSAS;
153 import java.awt.Color;
154 import java.awt.Font;
155 import java.awt.Rectangle;
156 import java.io.BufferedReader;
157 import java.io.DataInputStream;
158 import java.io.DataOutputStream;
160 import java.io.FileInputStream;
161 import java.io.FileOutputStream;
162 import java.io.IOException;
163 import java.io.InputStreamReader;
164 import java.io.OutputStreamWriter;
165 import java.io.PrintWriter;
166 import java.lang.reflect.InvocationTargetException;
167 import java.math.BigInteger;
168 import java.net.MalformedURLException;
170 import java.util.ArrayList;
171 import java.util.Arrays;
172 import java.util.Collections;
173 import java.util.Enumeration;
174 import java.util.GregorianCalendar;
175 import java.util.HashMap;
176 import java.util.HashSet;
177 import java.util.Hashtable;
178 import java.util.IdentityHashMap;
179 import java.util.Iterator;
180 import java.util.LinkedHashMap;
181 import java.util.List;
182 import java.util.Map;
183 import java.util.Map.Entry;
184 import java.util.Set;
185 import java.util.Vector;
186 import java.util.jar.JarEntry;
187 import java.util.jar.JarInputStream;
188 import java.util.jar.JarOutputStream;
190 import javax.swing.JInternalFrame;
191 import javax.swing.SwingUtilities;
192 import javax.xml.bind.JAXBContext;
193 import javax.xml.bind.JAXBElement;
194 import javax.xml.bind.Marshaller;
195 import javax.xml.datatype.DatatypeConfigurationException;
196 import javax.xml.datatype.DatatypeFactory;
197 import javax.xml.datatype.XMLGregorianCalendar;
198 import javax.xml.stream.XMLInputFactory;
199 import javax.xml.stream.XMLStreamReader;
202 * Write out the current jalview desktop state as a Jalview XML stream.
204 * Note: the vamsas objects referred to here are primitive versions of the
205 * VAMSAS project schema elements - they are not the same and most likely never
209 * @version $Revision: 1.134 $
211 public class Jalview2XML
213 private static final String VIEWER_PREFIX = "viewer_";
215 private static final String RNA_PREFIX = "rna_";
217 private static final String HMMER_PREFIX = "hmmer_";
219 private static final String UTF_8 = "UTF-8";
222 * prefix for recovering datasets for alignments with multiple views where
223 * non-existent dataset IDs were written for some views
225 private static final String UNIQSEQSETID = "uniqueSeqSetId.";
227 // use this with nextCounter() to make unique names for entities
228 private int counter = 0;
231 * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
232 * of sequence objects are created.
234 IdentityHashMap<SequenceI, String> seqsToIds = null;
237 * jalview XML Sequence ID to jalview sequence object reference (both dataset
238 * and alignment sequences. Populated as XML reps of sequence objects are
241 Map<String, SequenceI> seqRefIds = null;
243 Map<String, SequenceI> incompleteSeqs = null;
245 List<SeqFref> frefedSequence = null;
247 boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
250 * Map of reconstructed AlignFrame objects that appear to have come from
251 * SplitFrame objects (have a dna/protein complement view).
253 private Map<Viewport, AlignFrame> splitFrameCandidates = new HashMap<>();
256 * Map from displayed rna structure models to their saved session state jar
259 private Map<RnaModel, String> rnaSessions = new HashMap<>();
262 * A helper method for safely using the value of an optional attribute that
263 * may be null if not present in the XML. Answers the boolean value, or false
269 public static boolean safeBoolean(Boolean b)
271 return b == null ? false : b.booleanValue();
275 * A helper method for safely using the value of an optional attribute that
276 * may be null if not present in the XML. Answers the integer value, or zero
282 public static int safeInt(Integer i)
284 return i == null ? 0 : i.intValue();
288 * A helper method for safely using the value of an optional attribute that
289 * may be null if not present in the XML. Answers the float value, or zero if
295 public static float safeFloat(Float f)
297 return f == null ? 0f : f.floatValue();
301 * create/return unique hash string for sq
304 * @return new or existing unique string for sq
306 String seqHash(SequenceI sq)
308 if (seqsToIds == null)
312 if (seqsToIds.containsKey(sq))
314 return seqsToIds.get(sq);
318 // create sequential key
319 String key = "sq" + (seqsToIds.size() + 1);
320 key = makeHashCode(sq, key); // check we don't have an external reference
322 seqsToIds.put(sq, key);
329 if (seqsToIds == null)
331 seqsToIds = new IdentityHashMap<>();
333 if (seqRefIds == null)
335 seqRefIds = new HashMap<>();
337 if (incompleteSeqs == null)
339 incompleteSeqs = new HashMap<>();
341 if (frefedSequence == null)
343 frefedSequence = new ArrayList<>();
351 public Jalview2XML(boolean raiseGUI)
353 this.raiseGUI = raiseGUI;
357 * base class for resolving forward references to sequences by their ID
362 abstract class SeqFref
368 public SeqFref(String _sref, String type)
374 public String getSref()
379 public SequenceI getSrefSeq()
381 return seqRefIds.get(sref);
384 public boolean isResolvable()
386 return seqRefIds.get(sref) != null;
389 public SequenceI getSrefDatasetSeq()
391 SequenceI sq = seqRefIds.get(sref);
394 while (sq.getDatasetSequence() != null)
396 sq = sq.getDatasetSequence();
403 * @return true if the forward reference was fully resolved
405 abstract boolean resolve();
408 public String toString()
410 return type + " reference to " + sref;
415 * create forward reference for a mapping
421 public SeqFref newMappingRef(final String sref,
422 final jalview.datamodel.Mapping _jmap)
424 SeqFref fref = new SeqFref(sref, "Mapping")
426 public jalview.datamodel.Mapping jmap = _jmap;
431 SequenceI seq = getSrefDatasetSeq();
443 public SeqFref newAlcodMapRef(final String sref,
444 final AlignedCodonFrame _cf,
445 final jalview.datamodel.Mapping _jmap)
448 SeqFref fref = new SeqFref(sref, "Codon Frame")
450 AlignedCodonFrame cf = _cf;
452 public jalview.datamodel.Mapping mp = _jmap;
455 public boolean isResolvable()
457 return super.isResolvable() && mp.getTo() != null;
463 SequenceI seq = getSrefDatasetSeq();
468 cf.addMap(seq, mp.getTo(), mp.getMap());
475 public void resolveFrefedSequences()
477 Iterator<SeqFref> nextFref = frefedSequence.iterator();
478 int toresolve = frefedSequence.size();
479 int unresolved = 0, failedtoresolve = 0;
480 while (nextFref.hasNext())
482 SeqFref ref = nextFref.next();
483 if (ref.isResolvable())
495 } catch (Exception x)
498 "IMPLEMENTATION ERROR: Failed to resolve forward reference for sequence "
511 System.err.println("Jalview Project Import: There were " + unresolved
512 + " forward references left unresolved on the stack.");
514 if (failedtoresolve > 0)
516 System.err.println("SERIOUS! " + failedtoresolve
517 + " resolvable forward references failed to resolve.");
519 if (incompleteSeqs != null && incompleteSeqs.size() > 0)
522 "Jalview Project Import: There are " + incompleteSeqs.size()
523 + " sequences which may have incomplete metadata.");
524 if (incompleteSeqs.size() < 10)
526 for (SequenceI s : incompleteSeqs.values())
528 System.err.println(s.toString());
534 "Too many to report. Skipping output of incomplete sequences.");
540 * This maintains a map of viewports, the key being the seqSetId. Important to
541 * set historyItem and redoList for multiple views
543 Map<String, AlignViewport> viewportsAdded = new HashMap<>();
545 Map<String, AlignmentAnnotation> annotationIds = new HashMap<>();
547 String uniqueSetSuffix = "";
550 * List of pdbfiles added to Jar
552 List<String> pdbfiles = null;
554 // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
555 public void saveState(File statefile)
557 FileOutputStream fos = null;
562 fos = new FileOutputStream(statefile);
564 JarOutputStream jout = new JarOutputStream(fos);
568 } catch (Exception e)
570 Cache.log.error("Couln't write Jalview state to " + statefile, e);
571 // TODO: inform user of the problem - they need to know if their data was
573 if (errorMessage == null)
575 errorMessage = "Did't write Jalview Archive to output file '"
576 + statefile + "' - See console error log for details";
580 errorMessage += "(Didn't write Jalview Archive to output file '"
591 } catch (IOException e)
601 * Writes a jalview project archive to the given Jar output stream.
605 public void saveState(JarOutputStream jout)
607 AlignFrame[] frames = Desktop.getAlignFrames();
613 saveAllFrames(Arrays.asList(frames), jout);
617 * core method for storing state for a set of AlignFrames.
620 * - frames involving all data to be exported (including containing
623 * - project output stream
625 private void saveAllFrames(List<AlignFrame> frames, JarOutputStream jout)
627 Hashtable<String, AlignFrame> dsses = new Hashtable<>();
630 * ensure cached data is clear before starting
632 // todo tidy up seqRefIds, seqsToIds initialisation / reset
634 splitFrameCandidates.clear();
639 // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
640 // //////////////////////////////////////////////////
642 List<String> shortNames = new ArrayList<>();
643 List<String> viewIds = new ArrayList<>();
646 for (int i = frames.size() - 1; i > -1; i--)
648 AlignFrame af = frames.get(i);
650 if (skipList != null && skipList
651 .containsKey(af.getViewport().getSequenceSetId()))
656 String shortName = makeFilename(af, shortNames);
658 int apSize = af.getAlignPanels().size();
660 for (int ap = 0; ap < apSize; ap++)
662 AlignmentPanel apanel = (AlignmentPanel) af.getAlignPanels()
664 String fileName = apSize == 1 ? shortName : ap + shortName;
665 if (!fileName.endsWith(".xml"))
667 fileName = fileName + ".xml";
670 saveState(apanel, fileName, jout, viewIds);
672 String dssid = getDatasetIdRef(
673 af.getViewport().getAlignment().getDataset());
674 if (!dsses.containsKey(dssid))
676 dsses.put(dssid, af);
681 writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix,
687 } catch (Exception foo)
692 } catch (Exception ex)
694 // TODO: inform user of the problem - they need to know if their data was
696 if (errorMessage == null)
698 errorMessage = "Couldn't write Jalview Archive - see error output for details";
700 ex.printStackTrace();
705 * Generates a distinct file name, based on the title of the AlignFrame, by
706 * appending _n for increasing n until an unused name is generated. The new
707 * name (without its extension) is added to the list.
711 * @return the generated name, with .xml extension
713 protected String makeFilename(AlignFrame af, List<String> namesUsed)
715 String shortName = af.getTitle();
717 if (shortName.indexOf(File.separatorChar) > -1)
719 shortName = shortName
720 .substring(shortName.lastIndexOf(File.separatorChar) + 1);
725 while (namesUsed.contains(shortName))
727 if (shortName.endsWith("_" + (count - 1)))
729 shortName = shortName.substring(0, shortName.lastIndexOf("_"));
732 shortName = shortName.concat("_" + count);
736 namesUsed.add(shortName);
738 if (!shortName.endsWith(".xml"))
740 shortName = shortName + ".xml";
745 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
746 public boolean saveAlignment(AlignFrame af, String jarFile,
751 // create backupfiles object and get new temp filename destination
752 BackupFiles backupfiles = new BackupFiles(jarFile);
753 FileOutputStream fos = new FileOutputStream(
754 backupfiles.getTempFilePath());
756 JarOutputStream jout = new JarOutputStream(fos);
757 List<AlignFrame> frames = new ArrayList<>();
759 // resolve splitframes
760 if (af.getViewport().getCodingComplement() != null)
762 frames = ((SplitFrame) af.getSplitViewContainer()).getAlignFrames();
768 saveAllFrames(frames, jout);
772 } catch (Exception foo)
777 boolean success = true;
779 backupfiles.setWriteSuccess(success);
780 success = backupfiles.rollBackupsAndRenameTempFile();
783 } catch (Exception ex)
785 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
786 ex.printStackTrace();
791 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
792 String fileName, JarOutputStream jout)
795 for (String dssids : dsses.keySet())
797 AlignFrame _af = dsses.get(dssids);
798 String jfileName = fileName + " Dataset for " + _af.getTitle();
799 if (!jfileName.endsWith(".xml"))
801 jfileName = jfileName + ".xml";
803 saveState(_af.alignPanel, jfileName, true, jout, null);
808 * create a JalviewModel from an alignment view and marshall it to a
812 * panel to create jalview model for
814 * name of alignment panel written to output stream
821 public JalviewModel saveState(AlignmentPanel ap, String fileName,
822 JarOutputStream jout, List<String> viewIds)
824 return saveState(ap, fileName, false, jout, viewIds);
828 * create a JalviewModel from an alignment view and marshall it to a
832 * panel to create jalview model for
834 * name of alignment panel written to output stream
836 * when true, only write the dataset for the alignment, not the data
837 * associated with the view.
843 public JalviewModel saveState(AlignmentPanel ap, String fileName,
844 boolean storeDS, JarOutputStream jout, List<String> viewIds)
848 viewIds = new ArrayList<>();
853 List<UserColourScheme> userColours = new ArrayList<>();
855 AlignViewport av = ap.av;
856 ViewportRanges vpRanges = av.getRanges();
858 final ObjectFactory objectFactory = new ObjectFactory();
859 JalviewModel object = objectFactory.createJalviewModel();
860 object.setVamsasModel(new VAMSAS());
862 // object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
865 GregorianCalendar c = new GregorianCalendar();
866 DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
867 XMLGregorianCalendar now = datatypeFactory.newXMLGregorianCalendar(c);// gregorianCalendar);
868 object.setCreationDate(now);
869 } catch (DatatypeConfigurationException e)
871 System.err.println("error writing date: " + e.toString());
874 jalview.bin.Cache.getDefault("VERSION", "Development Build"));
877 * rjal is full height alignment, jal is actual alignment with full metadata
878 * but excludes hidden sequences.
880 jalview.datamodel.AlignmentI rjal = av.getAlignment(), jal = rjal;
882 if (av.hasHiddenRows())
884 rjal = jal.getHiddenSequences().getFullAlignment();
887 SequenceSet vamsasSet = new SequenceSet();
889 // JalviewModelSequence jms = new JalviewModelSequence();
891 vamsasSet.setGapChar(jal.getGapCharacter() + "");
893 if (jal.getDataset() != null)
895 // dataset id is the dataset's hashcode
896 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
899 // switch jal and the dataset
900 jal = jal.getDataset();
904 if (jal.getProperties() != null)
906 Enumeration en = jal.getProperties().keys();
907 while (en.hasMoreElements())
909 String key = en.nextElement().toString();
910 SequenceSetProperties ssp = new SequenceSetProperties();
912 ssp.setValue(jal.getProperties().get(key).toString());
913 // vamsasSet.addSequenceSetProperties(ssp);
914 vamsasSet.getSequenceSetProperties().add(ssp);
919 Set<String> calcIdSet = new HashSet<>();
920 // record the set of vamsas sequence XML POJO we create.
921 HashMap<String, Sequence> vamsasSetIds = new HashMap<>();
923 for (final SequenceI jds : rjal.getSequences())
925 final SequenceI jdatasq = jds.getDatasetSequence() == null ? jds
926 : jds.getDatasetSequence();
927 String id = seqHash(jds);
928 if (vamsasSetIds.get(id) == null)
930 if (seqRefIds.get(id) != null && !storeDS)
932 // This happens for two reasons: 1. multiple views are being
934 // 2. the hashCode has collided with another sequence's code. This
936 // HAPPEN! (PF00072.15.stk does this)
937 // JBPNote: Uncomment to debug writing out of files that do not read
938 // back in due to ArrayOutOfBoundExceptions.
939 // System.err.println("vamsasSeq backref: "+id+"");
940 // System.err.println(jds.getName()+"
941 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
942 // System.err.println("Hashcode: "+seqHash(jds));
943 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
944 // System.err.println(rsq.getName()+"
945 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
946 // System.err.println("Hashcode: "+seqHash(rsq));
950 vamsasSeq = createVamsasSequence(id, jds);
951 // vamsasSet.addSequence(vamsasSeq);
952 vamsasSet.getSequence().add(vamsasSeq);
953 vamsasSetIds.put(id, vamsasSeq);
954 seqRefIds.put(id, jds);
958 jseq.setStart(jds.getStart());
959 jseq.setEnd(jds.getEnd());
960 jseq.setColour(av.getSequenceColour(jds).getRGB());
962 jseq.setId(id); // jseq id should be a string not a number
965 // Store any sequences this sequence represents
966 if (av.hasHiddenRows())
968 // use rjal, contains the full height alignment
970 av.getAlignment().getHiddenSequences().isHidden(jds));
972 if (av.isHiddenRepSequence(jds))
974 jalview.datamodel.SequenceI[] reps = av
975 .getRepresentedSequences(jds).getSequencesInOrder(rjal);
977 for (int h = 0; h < reps.length; h++)
981 // jseq.addHiddenSequences(rjal.findIndex(reps[h]));
982 jseq.getHiddenSequences().add(rjal.findIndex(reps[h]));
987 // mark sequence as reference - if it is the reference for this view
990 jseq.setViewreference(jds == jal.getSeqrep());
994 // TODO: omit sequence features from each alignment view's XML dump if we
995 // are storing dataset
996 List<SequenceFeature> sfs = jds.getSequenceFeatures();
997 for (SequenceFeature sf : sfs)
999 // Features features = new Features();
1000 Feature features = new Feature();
1002 features.setBegin(sf.getBegin());
1003 features.setEnd(sf.getEnd());
1004 features.setDescription(sf.getDescription());
1005 features.setType(sf.getType());
1006 features.setFeatureGroup(sf.getFeatureGroup());
1007 features.setScore(sf.getScore());
1008 if (sf.links != null)
1010 for (int l = 0; l < sf.links.size(); l++)
1012 OtherData keyValue = new OtherData();
1013 keyValue.setKey("LINK_" + l);
1014 keyValue.setValue(sf.links.elementAt(l).toString());
1015 // features.addOtherData(keyValue);
1016 features.getOtherData().add(keyValue);
1019 if (sf.otherDetails != null)
1022 * save feature attributes, which may be simple strings or
1023 * map valued (have sub-attributes)
1025 for (Entry<String, Object> entry : sf.otherDetails.entrySet())
1027 String key = entry.getKey();
1028 Object value = entry.getValue();
1029 if (value instanceof Map<?, ?>)
1031 for (Entry<String, Object> subAttribute : ((Map<String, Object>) value)
1034 OtherData otherData = new OtherData();
1035 otherData.setKey(key);
1036 otherData.setKey2(subAttribute.getKey());
1037 otherData.setValue(subAttribute.getValue().toString());
1038 // features.addOtherData(otherData);
1039 features.getOtherData().add(otherData);
1044 OtherData otherData = new OtherData();
1045 otherData.setKey(key);
1046 otherData.setValue(value.toString());
1047 // features.addOtherData(otherData);
1048 features.getOtherData().add(otherData);
1053 // jseq.addFeatures(features);
1054 jseq.getFeatures().add(features);
1058 * save PDB entries for sequence
1060 if (jdatasq.getAllPDBEntries() != null)
1062 Enumeration<PDBEntry> en = jdatasq.getAllPDBEntries().elements();
1063 while (en.hasMoreElements())
1065 Pdbids pdb = new Pdbids();
1066 jalview.datamodel.PDBEntry entry = en.nextElement();
1068 String pdbId = entry.getId();
1070 pdb.setType(entry.getType());
1073 * Store any structure views associated with this sequence. This
1074 * section copes with duplicate entries in the project, so a dataset
1075 * only view *should* be coped with sensibly.
1077 // This must have been loaded, is it still visible?
1078 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1079 String matchedFile = null;
1080 for (int f = frames.length - 1; f > -1; f--)
1082 if (frames[f] instanceof StructureViewerBase)
1084 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
1085 matchedFile = saveStructureState(ap, jds, pdb, entry, viewIds,
1086 matchedFile, viewFrame);
1088 * Only store each structure viewer's state once in the project
1089 * jar. First time through only (storeDS==false)
1091 String viewId = viewFrame.getViewId();
1092 if (!storeDS && !viewIds.contains(viewId))
1094 viewIds.add(viewId);
1097 String viewerState = viewFrame.getStateInfo();
1098 writeJarEntry(jout, getViewerJarEntryName(viewId),
1099 viewerState.getBytes());
1100 } catch (IOException e)
1103 "Error saving viewer state: " + e.getMessage());
1109 if (matchedFile != null || entry.getFile() != null)
1111 if (entry.getFile() != null)
1114 matchedFile = entry.getFile();
1116 pdb.setFile(matchedFile); // entry.getFile());
1117 if (pdbfiles == null)
1119 pdbfiles = new ArrayList<>();
1122 if (!pdbfiles.contains(pdbId))
1124 pdbfiles.add(pdbId);
1125 copyFileToJar(jout, matchedFile, pdbId);
1129 Enumeration<String> props = entry.getProperties();
1130 if (props.hasMoreElements())
1132 // PdbentryItem item = new PdbentryItem();
1133 while (props.hasMoreElements())
1135 Property prop = new Property();
1136 String key = props.nextElement();
1138 prop.setValue(entry.getProperty(key).toString());
1139 // item.addProperty(prop);
1140 pdb.getProperty().add(prop);
1142 // pdb.addPdbentryItem(item);
1145 // jseq.addPdbids(pdb);
1146 jseq.getPdbids().add(pdb);
1150 saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
1152 if (jds.hasHMMProfile())
1154 saveHmmerProfile(jout, jseq, jds);
1157 // jms.addJSeq(jseq);
1158 object.getJSeq().add(jseq);
1161 if (!storeDS && av.hasHiddenRows())
1163 jal = av.getAlignment();
1167 if (storeDS && jal.getCodonFrames() != null)
1169 List<AlignedCodonFrame> jac = jal.getCodonFrames();
1170 for (AlignedCodonFrame acf : jac)
1172 AlcodonFrame alc = new AlcodonFrame();
1173 if (acf.getProtMappings() != null
1174 && acf.getProtMappings().length > 0)
1176 boolean hasMap = false;
1177 SequenceI[] dnas = acf.getdnaSeqs();
1178 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1179 for (int m = 0; m < pmaps.length; m++)
1181 AlcodMap alcmap = new AlcodMap();
1182 alcmap.setDnasq(seqHash(dnas[m]));
1184 createVamsasMapping(pmaps[m], dnas[m], null, false));
1185 // alc.addAlcodMap(alcmap);
1186 alc.getAlcodMap().add(alcmap);
1191 // vamsasSet.addAlcodonFrame(alc);
1192 vamsasSet.getAlcodonFrame().add(alc);
1195 // TODO: delete this ? dead code from 2.8.3->2.9 ?
1197 // AlcodonFrame alc = new AlcodonFrame();
1198 // vamsasSet.addAlcodonFrame(alc);
1199 // for (int p = 0; p < acf.aaWidth; p++)
1201 // Alcodon cmap = new Alcodon();
1202 // if (acf.codons[p] != null)
1204 // // Null codons indicate a gapped column in the translated peptide
1206 // cmap.setPos1(acf.codons[p][0]);
1207 // cmap.setPos2(acf.codons[p][1]);
1208 // cmap.setPos3(acf.codons[p][2]);
1210 // alc.addAlcodon(cmap);
1212 // if (acf.getProtMappings() != null
1213 // && acf.getProtMappings().length > 0)
1215 // SequenceI[] dnas = acf.getdnaSeqs();
1216 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1217 // for (int m = 0; m < pmaps.length; m++)
1219 // AlcodMap alcmap = new AlcodMap();
1220 // alcmap.setDnasq(seqHash(dnas[m]));
1221 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
1223 // alc.addAlcodMap(alcmap);
1230 // /////////////////////////////////
1231 if (!storeDS && av.getCurrentTree() != null)
1233 // FIND ANY ASSOCIATED TREES
1234 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
1235 if (Desktop.desktop != null)
1237 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1239 for (int t = 0; t < frames.length; t++)
1241 if (frames[t] instanceof TreePanel)
1243 TreePanel tp = (TreePanel) frames[t];
1245 if (tp.getTreeCanvas().getViewport().getAlignment() == jal)
1247 JalviewModel.Tree tree = new JalviewModel.Tree();
1248 tree.setTitle(tp.getTitle());
1249 tree.setCurrentTree((av.getCurrentTree() == tp.getTree()));
1250 tree.setNewick(tp.getTree().print());
1251 tree.setThreshold(tp.getTreeCanvas().getThreshold());
1253 tree.setFitToWindow(tp.fitToWindow.getState());
1254 tree.setFontName(tp.getTreeFont().getName());
1255 tree.setFontSize(tp.getTreeFont().getSize());
1256 tree.setFontStyle(tp.getTreeFont().getStyle());
1257 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
1259 tree.setShowBootstrap(tp.bootstrapMenu.getState());
1260 tree.setShowDistances(tp.distanceMenu.getState());
1262 tree.setHeight(tp.getHeight());
1263 tree.setWidth(tp.getWidth());
1264 tree.setXpos(tp.getX());
1265 tree.setYpos(tp.getY());
1266 tree.setId(makeHashCode(tp, null));
1267 tree.setLinkToAllViews(
1268 tp.getTreeCanvas().isApplyToAllViews());
1270 // jms.addTree(tree);
1271 object.getTree().add(tree);
1281 if (!storeDS && Desktop.desktop != null)
1283 for (JInternalFrame frame : Desktop.desktop.getAllFrames())
1285 if (frame instanceof PCAPanel)
1287 PCAPanel panel = (PCAPanel) frame;
1288 if (panel.getAlignViewport().getAlignment() == jal)
1290 savePCA(panel, object);
1298 * store forward refs from an annotationRow to any groups
1300 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<>();
1303 for (SequenceI sq : jal.getSequences())
1305 // Store annotation on dataset sequences only
1306 AlignmentAnnotation[] aa = sq.getAnnotation();
1307 if (aa != null && aa.length > 0)
1309 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1316 if (jal.getAlignmentAnnotation() != null)
1318 // Store the annotation shown on the alignment.
1319 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1320 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1325 if (jal.getGroups() != null)
1327 JGroup[] groups = new JGroup[jal.getGroups().size()];
1329 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1331 JGroup jGroup = new JGroup();
1332 groups[++i] = jGroup;
1334 jGroup.setStart(sg.getStartRes());
1335 jGroup.setEnd(sg.getEndRes());
1336 jGroup.setName(sg.getName());
1337 if (groupRefs.containsKey(sg))
1339 // group has references so set its ID field
1340 jGroup.setId(groupRefs.get(sg));
1342 ColourSchemeI colourScheme = sg.getColourScheme();
1343 if (colourScheme != null)
1345 ResidueShaderI groupColourScheme = sg.getGroupColourScheme();
1346 if (groupColourScheme.conservationApplied())
1348 jGroup.setConsThreshold(groupColourScheme.getConservationInc());
1350 if (colourScheme instanceof jalview.schemes.UserColourScheme)
1353 setUserColourScheme(colourScheme, userColours,
1358 jGroup.setColour(colourScheme.getSchemeName());
1361 else if (colourScheme instanceof jalview.schemes.AnnotationColourGradient)
1363 jGroup.setColour("AnnotationColourGradient");
1364 jGroup.setAnnotationColours(constructAnnotationColours(
1365 (jalview.schemes.AnnotationColourGradient) colourScheme,
1366 userColours, object));
1368 else if (colourScheme instanceof jalview.schemes.UserColourScheme)
1371 setUserColourScheme(colourScheme, userColours, object));
1375 jGroup.setColour(colourScheme.getSchemeName());
1378 jGroup.setPidThreshold(groupColourScheme.getThreshold());
1381 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1382 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1383 jGroup.setDisplayText(sg.getDisplayText());
1384 jGroup.setColourText(sg.getColourText());
1385 jGroup.setTextCol1(sg.textColour.getRGB());
1386 jGroup.setTextCol2(sg.textColour2.getRGB());
1387 jGroup.setTextColThreshold(sg.thresholdTextColour);
1388 jGroup.setShowUnconserved(sg.getShowNonconserved());
1389 jGroup.setIgnoreGapsinConsensus(sg.isIgnoreGapsConsensus());
1390 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1391 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1392 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1393 for (SequenceI seq : sg.getSequences())
1395 // jGroup.addSeq(seqHash(seq));
1396 jGroup.getSeq().add(seqHash(seq));
1400 //jms.setJGroup(groups);
1402 for (JGroup grp : groups)
1404 object.getJGroup().add(grp);
1409 // /////////SAVE VIEWPORT
1410 Viewport view = new Viewport();
1411 view.setTitle(ap.alignFrame.getTitle());
1412 view.setSequenceSetId(
1413 makeHashCode(av.getSequenceSetId(), av.getSequenceSetId()));
1414 view.setId(av.getViewId());
1415 if (av.getCodingComplement() != null)
1417 view.setComplementId(av.getCodingComplement().getViewId());
1419 view.setViewName(av.getViewName());
1420 view.setGatheredViews(av.isGatherViewsHere());
1422 Rectangle size = ap.av.getExplodedGeometry();
1423 Rectangle position = size;
1426 size = ap.alignFrame.getBounds();
1427 if (av.getCodingComplement() != null)
1429 position = ((SplitFrame) ap.alignFrame.getSplitViewContainer())
1437 view.setXpos(position.x);
1438 view.setYpos(position.y);
1440 view.setWidth(size.width);
1441 view.setHeight(size.height);
1443 view.setStartRes(vpRanges.getStartRes());
1444 view.setStartSeq(vpRanges.getStartSeq());
1446 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1448 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1449 userColours, object));
1452 .getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1454 AnnotationColourScheme ac = constructAnnotationColours(
1455 (jalview.schemes.AnnotationColourGradient) av
1456 .getGlobalColourScheme(),
1457 userColours, object);
1459 view.setAnnotationColours(ac);
1460 view.setBgColour("AnnotationColourGradient");
1464 view.setBgColour(ColourSchemeProperty
1465 .getColourName(av.getGlobalColourScheme()));
1468 ResidueShaderI vcs = av.getResidueShading();
1469 ColourSchemeI cs = av.getGlobalColourScheme();
1473 if (vcs.conservationApplied())
1475 view.setConsThreshold(vcs.getConservationInc());
1476 if (cs instanceof jalview.schemes.UserColourScheme)
1478 view.setBgColour(setUserColourScheme(cs, userColours, object));
1481 view.setPidThreshold(vcs.getThreshold());
1484 view.setConservationSelected(av.getConservationSelected());
1485 view.setPidSelected(av.getAbovePIDThreshold());
1486 final Font font = av.getFont();
1487 view.setFontName(font.getName());
1488 view.setFontSize(font.getSize());
1489 view.setFontStyle(font.getStyle());
1490 view.setScaleProteinAsCdna(av.getViewStyle().isScaleProteinAsCdna());
1491 view.setRenderGaps(av.isRenderGaps());
1492 view.setShowAnnotation(av.isShowAnnotation());
1493 view.setShowBoxes(av.getShowBoxes());
1494 view.setShowColourText(av.getColourText());
1495 view.setShowFullId(av.getShowJVSuffix());
1496 view.setRightAlignIds(av.isRightAlignIds());
1497 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1498 view.setShowText(av.getShowText());
1499 view.setShowUnconserved(av.getShowUnconserved());
1500 view.setWrapAlignment(av.getWrapAlignment());
1501 view.setTextCol1(av.getTextColour().getRGB());
1502 view.setTextCol2(av.getTextColour2().getRGB());
1503 view.setTextColThreshold(av.getThresholdTextColour());
1504 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1505 view.setShowSequenceLogo(av.isShowSequenceLogo());
1506 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1507 view.setShowGroupConsensus(av.isShowGroupConsensus());
1508 view.setShowGroupConservation(av.isShowGroupConservation());
1509 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1510 view.setShowDbRefTooltip(av.isShowDBRefs());
1511 view.setFollowHighlight(av.isFollowHighlight());
1512 view.setFollowSelection(av.followSelection);
1513 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1514 if (av.getFeaturesDisplayed() != null)
1516 FeatureSettings fs = new FeatureSettings();
1518 FeatureRenderer fr = ap.getSeqPanel().seqCanvas
1519 .getFeatureRenderer();
1520 String[] renderOrder = fr.getRenderOrder().toArray(new String[0]);
1522 Vector<String> settingsAdded = new Vector<>();
1523 if (renderOrder != null)
1525 for (String featureType : renderOrder)
1527 FeatureSettings.Setting setting = new FeatureSettings.Setting();
1528 setting.setType(featureType);
1531 * save any filter for the feature type
1533 FeatureMatcherSetI filter = fr.getFeatureFilter(featureType);
1534 if (filter != null) {
1535 Iterator<FeatureMatcherI> filters = filter.getMatchers().iterator();
1536 FeatureMatcherI firstFilter = filters.next();
1537 setting.setMatcherSet(Jalview2XML.marshalFilter(
1538 firstFilter, filters, filter.isAnded()));
1542 * save colour scheme for the feature type
1544 FeatureColourI fcol = fr.getFeatureStyle(featureType);
1545 if (!fcol.isSimpleColour())
1547 setting.setColour(fcol.getMaxColour().getRGB());
1548 setting.setMincolour(fcol.getMinColour().getRGB());
1549 setting.setMin(fcol.getMin());
1550 setting.setMax(fcol.getMax());
1551 setting.setColourByLabel(fcol.isColourByLabel());
1552 if (fcol.isColourByAttribute())
1554 String[] attName = fcol.getAttributeName();
1555 setting.getAttributeName().add(attName[0]);
1556 if (attName.length > 1)
1558 setting.getAttributeName().add(attName[1]);
1561 setting.setAutoScale(fcol.isAutoScaled());
1562 setting.setThreshold(fcol.getThreshold());
1563 Color noColour = fcol.getNoColour();
1564 if (noColour == null)
1566 setting.setNoValueColour(NoValueColour.NONE);
1568 else if (noColour.equals(fcol.getMaxColour()))
1570 setting.setNoValueColour(NoValueColour.MAX);
1574 setting.setNoValueColour(NoValueColour.MIN);
1576 // -1 = No threshold, 0 = Below, 1 = Above
1577 setting.setThreshstate(fcol.isAboveThreshold() ? 1
1578 : (fcol.isBelowThreshold() ? 0 : -1));
1582 setting.setColour(fcol.getColour().getRGB());
1586 av.getFeaturesDisplayed().isVisible(featureType));
1588 .getOrder(featureType);
1591 setting.setOrder(rorder);
1593 /// fs.addSetting(setting);
1594 fs.getSetting().add(setting);
1595 settingsAdded.addElement(featureType);
1599 // is groups actually supposed to be a map here ?
1600 Iterator<String> en = fr.getFeatureGroups().iterator();
1601 Vector<String> groupsAdded = new Vector<>();
1602 while (en.hasNext())
1604 String grp = en.next();
1605 if (groupsAdded.contains(grp))
1609 Group g = new Group();
1611 g.setDisplay(((Boolean) fr.checkGroupVisibility(grp, false))
1614 fs.getGroup().add(g);
1615 groupsAdded.addElement(grp);
1617 // jms.setFeatureSettings(fs);
1618 object.setFeatureSettings(fs);
1621 if (av.hasHiddenColumns())
1623 jalview.datamodel.HiddenColumns hidden = av.getAlignment()
1624 .getHiddenColumns();
1627 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1631 Iterator<int[]> hiddenRegions = hidden.iterator();
1632 while (hiddenRegions.hasNext())
1634 int[] region = hiddenRegions.next();
1635 HiddenColumns hc = new HiddenColumns();
1636 hc.setStart(region[0]);
1637 hc.setEnd(region[1]);
1638 // view.addHiddenColumns(hc);
1639 view.getHiddenColumns().add(hc);
1643 if (calcIdSet.size() > 0)
1645 for (String calcId : calcIdSet)
1647 if (calcId.trim().length() > 0)
1649 CalcIdParam cidp = createCalcIdParam(calcId, av);
1650 // Some calcIds have no parameters.
1653 // view.addCalcIdParam(cidp);
1654 view.getCalcIdParam().add(cidp);
1660 // jms.addViewport(view);
1661 object.getViewport().add(view);
1663 // object.setJalviewModelSequence(jms);
1664 // object.getVamsasModel().addSequenceSet(vamsasSet);
1665 object.getVamsasModel().getSequenceSet().add(vamsasSet);
1667 if (jout != null && fileName != null)
1669 // We may not want to write the object to disk,
1670 // eg we can copy the alignViewport to a new view object
1671 // using save and then load
1674 System.out.println("Writing jar entry " + fileName);
1675 JarEntry entry = new JarEntry(fileName);
1676 jout.putNextEntry(entry);
1677 PrintWriter pout = new PrintWriter(
1678 new OutputStreamWriter(jout, UTF_8));
1679 JAXBContext jaxbContext = JAXBContext
1680 .newInstance(JalviewModel.class);
1681 Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
1683 // output pretty printed
1684 // jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
1685 jaxbMarshaller.marshal(
1686 new ObjectFactory().createJalviewModel(object), pout);
1688 // jaxbMarshaller.marshal(object, pout);
1689 // marshaller.marshal(object);
1692 } catch (Exception ex)
1694 // TODO: raise error in GUI if marshalling failed.
1695 System.err.println("Error writing Jalview project");
1696 ex.printStackTrace();
1702 * Saves the HMMER profile associated with the sequence as a file in the jar,
1703 * in HMMER format, and saves the name of the file as a child element of the
1704 * XML sequence element
1710 protected void saveHmmerProfile(JarOutputStream jout, JSeq xmlSeq,
1713 HiddenMarkovModel profile = seq.getHMM();
1714 if (profile == null)
1716 warn("Want to save HMM profile for " + seq.getName()
1717 + " but none found");
1720 HMMFile hmmFile = new HMMFile(profile);
1721 String hmmAsString = hmmFile.print();
1722 String jarEntryName = HMMER_PREFIX + nextCounter();
1725 writeJarEntry(jout, jarEntryName, hmmAsString.getBytes());
1726 xmlSeq.setHmmerProfile(jarEntryName);
1727 } catch (IOException e)
1729 warn("Error saving HMM profile: " + e.getMessage());
1735 * Writes PCA viewer attributes and computed values to an XML model object and
1736 * adds it to the JalviewModel. Any exceptions are reported by logging.
1738 protected void savePCA(PCAPanel panel, JalviewModel object)
1742 PcaViewer viewer = new PcaViewer();
1743 viewer.setHeight(panel.getHeight());
1744 viewer.setWidth(panel.getWidth());
1745 viewer.setXpos(panel.getX());
1746 viewer.setYpos(panel.getY());
1747 viewer.setTitle(panel.getTitle());
1748 PCAModel pcaModel = panel.getPcaModel();
1749 viewer.setScoreModelName(pcaModel.getScoreModelName());
1750 viewer.setXDim(panel.getSelectedDimensionIndex(X));
1751 viewer.setYDim(panel.getSelectedDimensionIndex(Y));
1752 viewer.setZDim(panel.getSelectedDimensionIndex(Z));
1754 panel.getRotatableCanvas().getBackgroundColour().getRGB());
1755 viewer.setScaleFactor(panel.getRotatableCanvas().getScaleFactor());
1756 float[] spMin = panel.getRotatableCanvas().getSeqMin();
1757 SeqPointMin spmin = new SeqPointMin();
1758 spmin.setXPos(spMin[0]);
1759 spmin.setYPos(spMin[1]);
1760 spmin.setZPos(spMin[2]);
1761 viewer.setSeqPointMin(spmin);
1762 float[] spMax = panel.getRotatableCanvas().getSeqMax();
1763 SeqPointMax spmax = new SeqPointMax();
1764 spmax.setXPos(spMax[0]);
1765 spmax.setYPos(spMax[1]);
1766 spmax.setZPos(spMax[2]);
1767 viewer.setSeqPointMax(spmax);
1768 viewer.setShowLabels(panel.getRotatableCanvas().isShowLabels());
1769 viewer.setLinkToAllViews(
1770 panel.getRotatableCanvas().isApplyToAllViews());
1771 SimilarityParamsI sp = pcaModel.getSimilarityParameters();
1772 viewer.setIncludeGaps(sp.includeGaps());
1773 viewer.setMatchGaps(sp.matchGaps());
1774 viewer.setIncludeGappedColumns(sp.includeGappedColumns());
1775 viewer.setDenominateByShortestLength(sp.denominateByShortestLength());
1778 * sequence points on display
1780 for (jalview.datamodel.SequencePoint spt : pcaModel
1781 .getSequencePoints())
1783 SequencePoint point = new SequencePoint();
1784 point.setSequenceRef(seqHash(spt.getSequence()));
1785 point.setXPos(spt.coord.x);
1786 point.setYPos(spt.coord.y);
1787 point.setZPos(spt.coord.z);
1788 viewer.getSequencePoint().add(point);
1792 * (end points of) axes on display
1794 for (Point p : panel.getRotatableCanvas().getAxisEndPoints())
1797 Axis axis = new Axis();
1801 viewer.getAxis().add(axis);
1805 * raw PCA data (note we are not restoring PCA inputs here -
1806 * alignment view, score model, similarity parameters)
1808 PcaDataType data = new PcaDataType();
1809 viewer.setPcaData(data);
1810 PCA pca = pcaModel.getPcaData();
1812 DoubleMatrix pm = new DoubleMatrix();
1813 saveDoubleMatrix(pca.getPairwiseScores(), pm);
1814 data.setPairwiseMatrix(pm);
1816 DoubleMatrix tm = new DoubleMatrix();
1817 saveDoubleMatrix(pca.getTridiagonal(), tm);
1818 data.setTridiagonalMatrix(tm);
1820 DoubleMatrix eigenMatrix = new DoubleMatrix();
1821 data.setEigenMatrix(eigenMatrix);
1822 saveDoubleMatrix(pca.getEigenmatrix(), eigenMatrix);
1824 object.getPcaViewer().add(viewer);
1825 } catch (Throwable t)
1827 Cache.log.error("Error saving PCA: " + t.getMessage());
1832 * Stores values from a matrix into an XML element, including (if present) the
1837 * @see #loadDoubleMatrix(DoubleMatrix)
1839 protected void saveDoubleMatrix(MatrixI m, DoubleMatrix xmlMatrix)
1841 xmlMatrix.setRows(m.height());
1842 xmlMatrix.setColumns(m.width());
1843 for (int i = 0; i < m.height(); i++)
1845 DoubleVector row = new DoubleVector();
1846 for (int j = 0; j < m.width(); j++)
1848 row.getV().add(m.getValue(i, j));
1850 xmlMatrix.getRow().add(row);
1852 if (m.getD() != null)
1854 DoubleVector dVector = new DoubleVector();
1855 for (double d : m.getD())
1857 dVector.getV().add(d);
1859 xmlMatrix.setD(dVector);
1861 if (m.getE() != null)
1863 DoubleVector eVector = new DoubleVector();
1864 for (double e : m.getE())
1866 eVector.getV().add(e);
1868 xmlMatrix.setE(eVector);
1873 * Loads XML matrix data into a new Matrix object, including the D and/or E
1874 * vectors (if present)
1878 * @see Jalview2XML#saveDoubleMatrix(MatrixI, DoubleMatrix)
1880 protected MatrixI loadDoubleMatrix(DoubleMatrix mData)
1882 int rows = mData.getRows();
1883 double[][] vals = new double[rows][];
1885 for (int i = 0; i < rows; i++)
1887 List<Double> dVector = mData.getRow().get(i).getV();
1888 vals[i] = new double[dVector.size()];
1890 for (Double d : dVector)
1896 MatrixI m = new Matrix(vals);
1898 if (mData.getD() != null)
1900 List<Double> dVector = mData.getD().getV();
1901 double[] vec = new double[dVector.size()];
1903 for (Double d : dVector)
1909 if (mData.getE() != null)
1911 List<Double> dVector = mData.getE().getV();
1912 double[] vec = new double[dVector.size()];
1914 for (Double d : dVector)
1925 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1926 * for each viewer, with
1928 * <li>viewer geometry (position, size, split pane divider location)</li>
1929 * <li>index of the selected structure in the viewer (currently shows gapped
1931 * <li>the id of the annotation holding RNA secondary structure</li>
1932 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1934 * Varna viewer state is also written out (in native Varna XML) to separate
1935 * project jar entries. A separate entry is written for each RNA structure
1936 * displayed, with the naming convention
1938 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
1946 * @param storeDataset
1948 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
1949 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
1950 boolean storeDataset)
1952 if (Desktop.desktop == null)
1956 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1957 for (int f = frames.length - 1; f > -1; f--)
1959 if (frames[f] instanceof AppVarna)
1961 AppVarna varna = (AppVarna) frames[f];
1963 * link the sequence to every viewer that is showing it and is linked to
1964 * its alignment panel
1966 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1968 String viewId = varna.getViewId();
1969 RnaViewer rna = new RnaViewer();
1970 rna.setViewId(viewId);
1971 rna.setTitle(varna.getTitle());
1972 rna.setXpos(varna.getX());
1973 rna.setYpos(varna.getY());
1974 rna.setWidth(varna.getWidth());
1975 rna.setHeight(varna.getHeight());
1976 rna.setDividerLocation(varna.getDividerLocation());
1977 rna.setSelectedRna(varna.getSelectedIndex());
1978 // jseq.addRnaViewer(rna);
1979 jseq.getRnaViewer().add(rna);
1982 * Store each Varna panel's state once in the project per sequence.
1983 * First time through only (storeDataset==false)
1985 // boolean storeSessions = false;
1986 // String sequenceViewId = viewId + seqsToIds.get(jds);
1987 // if (!storeDataset && !viewIds.contains(sequenceViewId))
1989 // viewIds.add(sequenceViewId);
1990 // storeSessions = true;
1992 for (RnaModel model : varna.getModels())
1994 if (model.seq == jds)
1997 * VARNA saves each view (sequence or alignment secondary
1998 * structure, gapped or trimmed) as a separate XML file
2000 String jarEntryName = rnaSessions.get(model);
2001 if (jarEntryName == null)
2004 String varnaStateFile = varna.getStateInfo(model.rna);
2005 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
2006 copyFileToJar(jout, varnaStateFile, jarEntryName);
2007 rnaSessions.put(model, jarEntryName);
2009 SecondaryStructure ss = new SecondaryStructure();
2010 String annotationId = varna.getAnnotation(jds).annotationId;
2011 ss.setAnnotationId(annotationId);
2012 ss.setViewerState(jarEntryName);
2013 ss.setGapped(model.gapped);
2014 ss.setTitle(model.title);
2015 // rna.addSecondaryStructure(ss);
2016 rna.getSecondaryStructure().add(ss);
2025 * Copy the contents of a file to a new entry added to the output jar
2029 * @param jarEntryName
2031 protected void copyFileToJar(JarOutputStream jout, String infilePath,
2032 String jarEntryName)
2034 DataInputStream dis = null;
2037 File file = new File(infilePath);
2038 if (file.exists() && jout != null)
2040 dis = new DataInputStream(new FileInputStream(file));
2041 byte[] data = new byte[(int) file.length()];
2042 dis.readFully(data);
2043 writeJarEntry(jout, jarEntryName, data);
2045 } catch (Exception ex)
2047 ex.printStackTrace();
2055 } catch (IOException e)
2064 * Write the data to a new entry of given name in the output jar file
2067 * @param jarEntryName
2069 * @throws IOException
2071 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
2072 byte[] data) throws IOException
2076 System.out.println("Writing jar entry " + jarEntryName);
2077 jout.putNextEntry(new JarEntry(jarEntryName));
2078 DataOutputStream dout = new DataOutputStream(jout);
2079 dout.write(data, 0, data.length);
2086 * Save the state of a structure viewer
2091 * the archive XML element under which to save the state
2094 * @param matchedFile
2098 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
2099 Pdbids pdb, PDBEntry entry, List<String> viewIds,
2100 String matchedFile, StructureViewerBase viewFrame)
2102 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
2105 * Look for any bindings for this viewer to the PDB file of interest
2106 * (including part matches excluding chain id)
2108 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
2110 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
2111 final String pdbId = pdbentry.getId();
2112 if (!pdbId.equals(entry.getId())
2113 && !(entry.getId().length() > 4 && entry.getId().toLowerCase()
2114 .startsWith(pdbId.toLowerCase())))
2117 * not interested in a binding to a different PDB entry here
2121 if (matchedFile == null)
2123 matchedFile = pdbentry.getFile();
2125 else if (!matchedFile.equals(pdbentry.getFile()))
2127 warn("Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
2128 + pdbentry.getFile());
2132 // can get at it if the ID
2133 // match is ambiguous (e.g.
2136 for (int smap = 0; smap < viewFrame.getBinding()
2137 .getSequence()[peid].length; smap++)
2139 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
2140 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
2142 StructureState state = new StructureState();
2143 state.setVisible(true);
2144 state.setXpos(viewFrame.getX());
2145 state.setYpos(viewFrame.getY());
2146 state.setWidth(viewFrame.getWidth());
2147 state.setHeight(viewFrame.getHeight());
2148 final String viewId = viewFrame.getViewId();
2149 state.setViewId(viewId);
2150 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
2151 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
2152 state.setColourByJmol(viewFrame.isColouredByViewer());
2153 state.setType(viewFrame.getViewerType().toString());
2154 // pdb.addStructureState(state);
2155 pdb.getStructureState().add(state);
2163 * Populates the AnnotationColourScheme xml for save. This captures the
2164 * settings of the options in the 'Colour by Annotation' dialog.
2167 * @param userColours
2171 private AnnotationColourScheme constructAnnotationColours(
2172 AnnotationColourGradient acg, List<UserColourScheme> userColours,
2175 AnnotationColourScheme ac = new AnnotationColourScheme();
2176 ac.setAboveThreshold(acg.getAboveThreshold());
2177 ac.setThreshold(acg.getAnnotationThreshold());
2178 // 2.10.2 save annotationId (unique) not annotation label
2179 ac.setAnnotation(acg.getAnnotation().annotationId);
2180 if (acg.getBaseColour() instanceof UserColourScheme)
2183 setUserColourScheme(acg.getBaseColour(), userColours, jm));
2188 ColourSchemeProperty.getColourName(acg.getBaseColour()));
2191 ac.setMaxColour(acg.getMaxColour().getRGB());
2192 ac.setMinColour(acg.getMinColour().getRGB());
2193 ac.setPerSequence(acg.isSeqAssociated());
2194 ac.setPredefinedColours(acg.isPredefinedColours());
2198 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
2199 IdentityHashMap<SequenceGroup, String> groupRefs,
2200 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
2201 SequenceSet vamsasSet)
2204 for (int i = 0; i < aa.length; i++)
2206 Annotation an = new Annotation();
2208 AlignmentAnnotation annotation = aa[i];
2209 if (annotation.annotationId != null)
2211 annotationIds.put(annotation.annotationId, annotation);
2214 an.setId(annotation.annotationId);
2216 an.setVisible(annotation.visible);
2218 an.setDescription(annotation.description);
2220 if (annotation.sequenceRef != null)
2222 // 2.9 JAL-1781 xref on sequence id rather than name
2223 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
2225 if (annotation.groupRef != null)
2227 String groupIdr = groupRefs.get(annotation.groupRef);
2228 if (groupIdr == null)
2230 // make a locally unique String
2231 groupRefs.put(annotation.groupRef,
2232 groupIdr = ("" + System.currentTimeMillis()
2233 + annotation.groupRef.getName()
2234 + groupRefs.size()));
2236 an.setGroupRef(groupIdr.toString());
2239 // store all visualization attributes for annotation
2240 an.setGraphHeight(annotation.graphHeight);
2241 an.setCentreColLabels(annotation.centreColLabels);
2242 an.setScaleColLabels(annotation.scaleColLabel);
2243 an.setShowAllColLabels(annotation.showAllColLabels);
2244 an.setBelowAlignment(annotation.belowAlignment);
2246 if (annotation.graph > 0)
2249 an.setGraphType(annotation.graph);
2250 an.setGraphGroup(annotation.graphGroup);
2251 if (annotation.getThreshold() != null)
2253 ThresholdLine line = new ThresholdLine();
2254 line.setLabel(annotation.getThreshold().label);
2255 line.setValue(annotation.getThreshold().value);
2256 line.setColour(annotation.getThreshold().colour.getRGB());
2257 an.setThresholdLine(line);
2265 an.setLabel(annotation.label);
2267 if (annotation == av.getAlignmentQualityAnnot()
2268 || annotation == av.getAlignmentConservationAnnotation()
2269 || annotation == av.getAlignmentConsensusAnnotation()
2270 || annotation.autoCalculated)
2272 // new way of indicating autocalculated annotation -
2273 an.setAutoCalculated(annotation.autoCalculated);
2275 if (annotation.hasScore())
2277 an.setScore(annotation.getScore());
2280 if (annotation.getCalcId() != null)
2282 calcIdSet.add(annotation.getCalcId());
2283 an.setCalcId(annotation.getCalcId());
2285 if (annotation.hasProperties())
2287 for (String pr : annotation.getProperties())
2289 jalview.xml.binding.jalview.Annotation.Property prop = new jalview.xml.binding.jalview.Annotation.Property();
2291 prop.setValue(annotation.getProperty(pr));
2292 // an.addProperty(prop);
2293 an.getProperty().add(prop);
2297 AnnotationElement ae;
2298 if (annotation.annotations != null)
2300 an.setScoreOnly(false);
2301 for (int a = 0; a < annotation.annotations.length; a++)
2303 if ((annotation == null) || (annotation.annotations[a] == null))
2308 ae = new AnnotationElement();
2309 if (annotation.annotations[a].description != null)
2311 ae.setDescription(annotation.annotations[a].description);
2313 if (annotation.annotations[a].displayCharacter != null)
2315 ae.setDisplayCharacter(
2316 annotation.annotations[a].displayCharacter);
2319 if (!Float.isNaN(annotation.annotations[a].value))
2321 ae.setValue(annotation.annotations[a].value);
2325 if (annotation.annotations[a].secondaryStructure > ' ')
2327 ae.setSecondaryStructure(
2328 annotation.annotations[a].secondaryStructure + "");
2331 if (annotation.annotations[a].colour != null
2332 && annotation.annotations[a].colour != java.awt.Color.black)
2334 ae.setColour(annotation.annotations[a].colour.getRGB());
2337 // an.addAnnotationElement(ae);
2338 an.getAnnotationElement().add(ae);
2339 if (annotation.autoCalculated)
2341 // only write one non-null entry into the annotation row -
2342 // sufficient to get the visualization attributes necessary to
2350 an.setScoreOnly(true);
2352 if (!storeDS || (storeDS && !annotation.autoCalculated))
2354 // skip autocalculated annotation - these are only provided for
2356 // vamsasSet.addAnnotation(an);
2357 vamsasSet.getAnnotation().add(an);
2363 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
2365 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
2366 if (settings != null)
2368 CalcIdParam vCalcIdParam = new CalcIdParam();
2369 vCalcIdParam.setCalcId(calcId);
2370 // vCalcIdParam.addServiceURL(settings.getServiceURI());
2371 vCalcIdParam.getServiceURL().add(settings.getServiceURI());
2372 // generic URI allowing a third party to resolve another instance of the
2373 // service used for this calculation
2374 for (String url : settings.getServiceURLs())
2376 // vCalcIdParam.addServiceURL(urls);
2377 vCalcIdParam.getServiceURL().add(url);
2379 vCalcIdParam.setVersion("1.0");
2380 if (settings.getPreset() != null)
2382 WsParamSetI setting = settings.getPreset();
2383 vCalcIdParam.setName(setting.getName());
2384 vCalcIdParam.setDescription(setting.getDescription());
2388 vCalcIdParam.setName("");
2389 vCalcIdParam.setDescription("Last used parameters");
2391 // need to be able to recover 1) settings 2) user-defined presets or
2392 // recreate settings from preset 3) predefined settings provided by
2393 // service - or settings that can be transferred (or discarded)
2394 vCalcIdParam.setParameters(
2395 settings.getWsParamFile().replace("\n", "|\\n|"));
2396 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
2397 // todo - decide if updateImmediately is needed for any projects.
2399 return vCalcIdParam;
2404 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
2407 if (calcIdParam.getVersion().equals("1.0"))
2409 final String[] calcIds = calcIdParam.getServiceURL().toArray(new String[0]);
2410 Jws2Instance service = Jws2Discoverer.getDiscoverer()
2411 .getPreferredServiceFor(calcIds);
2412 if (service != null)
2414 WsParamSetI parmSet = null;
2417 parmSet = service.getParamStore().parseServiceParameterFile(
2418 calcIdParam.getName(), calcIdParam.getDescription(),
2420 calcIdParam.getParameters().replace("|\\n|", "\n"));
2421 } catch (IOException x)
2423 warn("Couldn't parse parameter data for "
2424 + calcIdParam.getCalcId(), x);
2427 List<ArgumentI> argList = null;
2428 if (calcIdParam.getName().length() > 0)
2430 parmSet = service.getParamStore()
2431 .getPreset(calcIdParam.getName());
2432 if (parmSet != null)
2434 // TODO : check we have a good match with settings in AACon -
2435 // otherwise we'll need to create a new preset
2440 argList = parmSet.getArguments();
2443 AAConSettings settings = new AAConSettings(
2444 calcIdParam.isAutoUpdate(), service, parmSet, argList);
2445 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
2446 calcIdParam.isNeedsUpdate());
2451 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
2455 throw new Error(MessageManager.formatMessage(
2456 "error.unsupported_version_calcIdparam", new Object[]
2457 { calcIdParam.toString() }));
2461 * External mapping between jalview objects and objects yielding a valid and
2462 * unique object ID string. This is null for normal Jalview project IO, but
2463 * non-null when a jalview project is being read or written as part of a
2466 IdentityHashMap jv2vobj = null;
2469 * Construct a unique ID for jvobj using either existing bindings or if none
2470 * exist, the result of the hashcode call for the object.
2473 * jalview data object
2474 * @return unique ID for referring to jvobj
2476 private String makeHashCode(Object jvobj, String altCode)
2478 if (jv2vobj != null)
2480 Object id = jv2vobj.get(jvobj);
2483 return id.toString();
2485 // check string ID mappings
2486 if (jvids2vobj != null && jvobj instanceof String)
2488 id = jvids2vobj.get(jvobj);
2492 return id.toString();
2494 // give up and warn that something has gone wrong
2495 warn("Cannot find ID for object in external mapping : " + jvobj);
2501 * return local jalview object mapped to ID, if it exists
2505 * @return null or object bound to idcode
2507 private Object retrieveExistingObj(String idcode)
2509 if (idcode != null && vobj2jv != null)
2511 return vobj2jv.get(idcode);
2517 * binding from ID strings from external mapping table to jalview data model
2520 private Hashtable vobj2jv;
2522 private Sequence createVamsasSequence(String id, SequenceI jds)
2524 return createVamsasSequence(true, id, jds, null);
2527 private Sequence createVamsasSequence(boolean recurse, String id,
2528 SequenceI jds, SequenceI parentseq)
2530 Sequence vamsasSeq = new Sequence();
2531 vamsasSeq.setId(id);
2532 vamsasSeq.setName(jds.getName());
2533 vamsasSeq.setSequence(jds.getSequenceAsString());
2534 vamsasSeq.setDescription(jds.getDescription());
2535 jalview.datamodel.DBRefEntry[] dbrefs = null;
2536 if (jds.getDatasetSequence() != null)
2538 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
2542 // seqId==dsseqid so we can tell which sequences really are
2543 // dataset sequences only
2544 vamsasSeq.setDsseqid(id);
2545 dbrefs = jds.getDBRefs();
2546 if (parentseq == null)
2553 for (int d = 0; d < dbrefs.length; d++)
2555 DBRef dbref = new DBRef();
2556 dbref.setSource(dbrefs[d].getSource());
2557 dbref.setVersion(dbrefs[d].getVersion());
2558 dbref.setAccessionId(dbrefs[d].getAccessionId());
2559 if (dbrefs[d].hasMap())
2561 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
2563 dbref.setMapping(mp);
2565 // vamsasSeq.addDBRef(dbref);
2566 vamsasSeq.getDBRef().add(dbref);
2572 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
2573 SequenceI parentseq, SequenceI jds, boolean recurse)
2576 if (jmp.getMap() != null)
2580 jalview.util.MapList mlst = jmp.getMap();
2581 List<int[]> r = mlst.getFromRanges();
2582 for (int[] range : r)
2584 MapListFrom mfrom = new MapListFrom();
2585 mfrom.setStart(range[0]);
2586 mfrom.setEnd(range[1]);
2587 // mp.addMapListFrom(mfrom);
2588 mp.getMapListFrom().add(mfrom);
2590 r = mlst.getToRanges();
2591 for (int[] range : r)
2593 MapListTo mto = new MapListTo();
2594 mto.setStart(range[0]);
2595 mto.setEnd(range[1]);
2596 // mp.addMapListTo(mto);
2597 mp.getMapListTo().add(mto);
2599 mp.setMapFromUnit(BigInteger.valueOf(mlst.getFromRatio()));
2600 mp.setMapToUnit(BigInteger.valueOf(mlst.getToRatio()));
2601 if (jmp.getTo() != null)
2603 // MappingChoice mpc = new MappingChoice();
2605 // check/create ID for the sequence referenced by getTo()
2608 SequenceI ps = null;
2609 if (parentseq != jmp.getTo()
2610 && parentseq.getDatasetSequence() != jmp.getTo())
2612 // chaining dbref rather than a handshaking one
2613 jmpid = seqHash(ps = jmp.getTo());
2617 jmpid = seqHash(ps = parentseq);
2619 // mpc.setDseqFor(jmpid);
2620 mp.setDseqFor(jmpid);
2621 if (!seqRefIds.containsKey(jmpid))
2623 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2624 seqRefIds.put(jmpid, ps);
2628 debug("reusing DseqFor ID");
2631 // mp.setMappingChoice(mpc);
2637 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2638 List<UserColourScheme> userColours, JalviewModel jm)
2641 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2642 boolean newucs = false;
2643 if (!userColours.contains(ucs))
2645 userColours.add(ucs);
2648 id = "ucs" + userColours.indexOf(ucs);
2651 // actually create the scheme's entry in the XML model
2652 java.awt.Color[] colours = ucs.getColours();
2653 UserColours uc = new UserColours();
2654 // UserColourScheme jbucs = new UserColourScheme();
2655 JalviewUserColours jbucs = new JalviewUserColours();
2657 for (int i = 0; i < colours.length; i++)
2659 Colour col = new Colour();
2660 col.setName(ResidueProperties.aa[i]);
2661 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2662 // jbucs.addColour(col);
2663 jbucs.getColour().add(col);
2665 if (ucs.getLowerCaseColours() != null)
2667 colours = ucs.getLowerCaseColours();
2668 for (int i = 0; i < colours.length; i++)
2670 Colour col = new Colour();
2671 col.setName(ResidueProperties.aa[i].toLowerCase());
2672 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2673 // jbucs.addColour(col);
2674 jbucs.getColour().add(col);
2679 uc.setUserColourScheme(jbucs);
2680 // jm.addUserColours(uc);
2681 jm.getUserColours().add(uc);
2687 jalview.schemes.UserColourScheme getUserColourScheme(
2688 JalviewModel jm, String id)
2690 List<UserColours> uc = jm.getUserColours();
2691 UserColours colours = null;
2693 for (int i = 0; i < uc.length; i++)
2695 if (uc[i].getId().equals(id))
2702 for (UserColours c : uc)
2704 if (c.getId().equals(id))
2711 java.awt.Color[] newColours = new java.awt.Color[24];
2713 for (int i = 0; i < 24; i++)
2715 newColours[i] = new java.awt.Color(Integer.parseInt(
2716 // colours.getUserColourScheme().getColour(i).getRGB(), 16));
2717 colours.getUserColourScheme().getColour().get(i).getRGB(),
2721 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2724 if (colours.getUserColourScheme().getColour().size()/*Count()*/ > 24)
2726 newColours = new java.awt.Color[23];
2727 for (int i = 0; i < 23; i++)
2729 newColours[i] = new java.awt.Color(Integer.parseInt(
2730 colours.getUserColourScheme().getColour().get(i + 24)
2734 ucs.setLowerCaseColours(newColours);
2741 * contains last error message (if any) encountered by XML loader.
2743 String errorMessage = null;
2746 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2747 * exceptions are raised during project XML parsing
2749 public boolean attemptversion1parse = false;
2752 * Load a jalview project archive from a jar file
2755 * - HTTP URL or filename
2757 public AlignFrame loadJalviewAlign(final String file)
2760 jalview.gui.AlignFrame af = null;
2764 // create list to store references for any new Jmol viewers created
2765 newStructureViewers = new Vector<>();
2766 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2767 // Workaround is to make sure caller implements the JarInputStreamProvider
2769 // so we can re-open the jar input stream for each entry.
2771 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2772 af = loadJalviewAlign(jprovider);
2775 af.setMenusForViewport();
2777 } catch (MalformedURLException e)
2779 errorMessage = "Invalid URL format for '" + file + "'";
2785 SwingUtilities.invokeAndWait(new Runnable()
2790 setLoadingFinishedForNewStructureViewers();
2793 } catch (Exception x)
2795 System.err.println("Error loading alignment: " + x.getMessage());
2801 private jarInputStreamProvider createjarInputStreamProvider(
2802 final String file) throws MalformedURLException
2805 errorMessage = null;
2806 uniqueSetSuffix = null;
2808 viewportsAdded.clear();
2809 frefedSequence = null;
2811 if (file.startsWith("http://"))
2813 url = new URL(file);
2815 final URL _url = url;
2816 return new jarInputStreamProvider()
2820 public JarInputStream getJarInputStream() throws IOException
2824 return new JarInputStream(_url.openStream());
2828 return new JarInputStream(new FileInputStream(file));
2833 public String getFilename()
2841 * Recover jalview session from a jalview project archive. Caller may
2842 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2843 * themselves. Any null fields will be initialised with default values,
2844 * non-null fields are left alone.
2849 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2851 errorMessage = null;
2852 if (uniqueSetSuffix == null)
2854 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2856 if (seqRefIds == null)
2860 AlignFrame af = null, _af = null;
2861 IdentityHashMap<AlignmentI, AlignmentI> importedDatasets = new IdentityHashMap<>();
2862 Map<String, AlignFrame> gatherToThisFrame = new HashMap<>();
2863 final String file = jprovider.getFilename();
2866 JarInputStream jin = null;
2867 JarEntry jarentry = null;
2872 jin = jprovider.getJarInputStream();
2873 for (int i = 0; i < entryCount; i++)
2875 jarentry = jin.getNextJarEntry();
2878 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2880 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2881 // JalviewModel object = new JalviewModel();
2883 JAXBContext jc = JAXBContext
2884 .newInstance("jalview.xml.binding.jalview");
2885 XMLStreamReader streamReader = XMLInputFactory.newInstance()
2886 .createXMLStreamReader(jin);
2887 javax.xml.bind.Unmarshaller um = jc.createUnmarshaller();
2888 JAXBElement<JalviewModel> jbe = um
2889 .unmarshal(streamReader, JalviewModel.class);
2890 JalviewModel object = jbe.getValue();
2893 Unmarshaller unmar = new Unmarshaller(object);
2894 unmar.setValidation(false);
2895 object = (JalviewModel) unmar.unmarshal(in);
2897 if (true) // !skipViewport(object))
2899 _af = loadFromObject(object, file, true, jprovider);
2900 if (_af != null && object.getViewport().size() > 0)
2901 // getJalviewModelSequence().getViewportCount() > 0)
2905 // store a reference to the first view
2908 if (_af.getViewport().isGatherViewsHere())
2910 // if this is a gathered view, keep its reference since
2911 // after gathering views, only this frame will remain
2913 gatherToThisFrame.put(_af.getViewport().getSequenceSetId(),
2916 // Save dataset to register mappings once all resolved
2917 importedDatasets.put(
2918 af.getViewport().getAlignment().getDataset(),
2919 af.getViewport().getAlignment().getDataset());
2924 else if (jarentry != null)
2926 // Some other file here.
2929 } while (jarentry != null);
2930 resolveFrefedSequences();
2931 } catch (IOException ex)
2933 ex.printStackTrace();
2934 errorMessage = "Couldn't locate Jalview XML file : " + file;
2936 "Exception whilst loading jalview XML file : " + ex + "\n");
2937 } catch (Exception ex)
2939 System.err.println("Parsing as Jalview Version 2 file failed.");
2940 ex.printStackTrace(System.err);
2941 if (attemptversion1parse)
2943 // used to attempt to parse as V1 castor-generated xml
2945 if (Desktop.instance != null)
2947 Desktop.instance.stopLoading();
2951 System.out.println("Successfully loaded archive file");
2954 ex.printStackTrace();
2957 "Exception whilst loading jalview XML file : " + ex + "\n");
2958 } catch (OutOfMemoryError e)
2960 // Don't use the OOM Window here
2961 errorMessage = "Out of memory loading jalview XML file";
2962 System.err.println("Out of memory whilst loading jalview XML file");
2963 e.printStackTrace();
2967 * Regather multiple views (with the same sequence set id) to the frame (if
2968 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2969 * views instead of separate frames. Note this doesn't restore a state where
2970 * some expanded views in turn have tabbed views - the last "first tab" read
2971 * in will play the role of gatherer for all.
2973 for (AlignFrame fr : gatherToThisFrame.values())
2975 Desktop.instance.gatherViews(fr);
2978 restoreSplitFrames();
2979 for (AlignmentI ds : importedDatasets.keySet())
2981 if (ds.getCodonFrames() != null)
2983 StructureSelectionManager
2984 .getStructureSelectionManager(Desktop.instance)
2985 .registerMappings(ds.getCodonFrames());
2988 if (errorMessage != null)
2993 if (Desktop.instance != null)
2995 Desktop.instance.stopLoading();
3002 * Try to reconstruct and display SplitFrame windows, where each contains
3003 * complementary dna and protein alignments. Done by pairing up AlignFrame
3004 * objects (created earlier) which have complementary viewport ids associated.
3006 protected void restoreSplitFrames()
3008 List<SplitFrame> gatherTo = new ArrayList<>();
3009 List<AlignFrame> addedToSplitFrames = new ArrayList<>();
3010 Map<String, AlignFrame> dna = new HashMap<>();
3013 * Identify the DNA alignments
3015 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
3018 AlignFrame af = candidate.getValue();
3019 if (af.getViewport().getAlignment().isNucleotide())
3021 dna.put(candidate.getKey().getId(), af);
3026 * Try to match up the protein complements
3028 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
3031 AlignFrame af = candidate.getValue();
3032 if (!af.getViewport().getAlignment().isNucleotide())
3034 String complementId = candidate.getKey().getComplementId();
3035 // only non-null complements should be in the Map
3036 if (complementId != null && dna.containsKey(complementId))
3038 final AlignFrame dnaFrame = dna.get(complementId);
3039 SplitFrame sf = createSplitFrame(dnaFrame, af);
3040 addedToSplitFrames.add(dnaFrame);
3041 addedToSplitFrames.add(af);
3042 dnaFrame.setMenusForViewport();
3043 af.setMenusForViewport();
3044 if (af.getViewport().isGatherViewsHere())
3053 * Open any that we failed to pair up (which shouldn't happen!) as
3054 * standalone AlignFrame's.
3056 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
3059 AlignFrame af = candidate.getValue();
3060 if (!addedToSplitFrames.contains(af))
3062 Viewport view = candidate.getKey();
3063 Desktop.addInternalFrame(af, view.getTitle(),
3064 safeInt(view.getWidth()), safeInt(view.getHeight()));
3065 af.setMenusForViewport();
3066 System.err.println("Failed to restore view " + view.getTitle()
3067 + " to split frame");
3072 * Gather back into tabbed views as flagged.
3074 for (SplitFrame sf : gatherTo)
3076 Desktop.instance.gatherViews(sf);
3079 splitFrameCandidates.clear();
3083 * Construct and display one SplitFrame holding DNA and protein alignments.
3086 * @param proteinFrame
3089 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
3090 AlignFrame proteinFrame)
3092 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
3093 String title = MessageManager.getString("label.linked_view_title");
3094 int width = (int) dnaFrame.getBounds().getWidth();
3095 int height = (int) (dnaFrame.getBounds().getHeight()
3096 + proteinFrame.getBounds().getHeight() + 50);
3099 * SplitFrame location is saved to both enclosed frames
3101 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
3102 Desktop.addInternalFrame(splitFrame, title, width, height);
3105 * And compute cDNA consensus (couldn't do earlier with consensus as
3106 * mappings were not yet present)
3108 proteinFrame.getViewport().alignmentChanged(proteinFrame.alignPanel);
3114 * check errorMessage for a valid error message and raise an error box in the
3115 * GUI or write the current errorMessage to stderr and then clear the error
3118 protected void reportErrors()
3120 reportErrors(false);
3123 protected void reportErrors(final boolean saving)
3125 if (errorMessage != null)
3127 final String finalErrorMessage = errorMessage;
3130 javax.swing.SwingUtilities.invokeLater(new Runnable()
3135 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
3137 "Error " + (saving ? "saving" : "loading")
3139 JvOptionPane.WARNING_MESSAGE);
3145 System.err.println("Problem loading Jalview file: " + errorMessage);
3148 errorMessage = null;
3151 Map<String, String> alreadyLoadedPDB = new HashMap<>();
3154 * when set, local views will be updated from view stored in JalviewXML
3155 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
3156 * sync if this is set to true.
3158 private final boolean updateLocalViews = false;
3161 * Returns the path to a temporary file holding the PDB file for the given PDB
3162 * id. The first time of asking, searches for a file of that name in the
3163 * Jalview project jar, and copies it to a new temporary file. Any repeat
3164 * requests just return the path to the file previously created.
3170 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId,
3173 if (alreadyLoadedPDB.containsKey(pdbId))
3175 return alreadyLoadedPDB.get(pdbId).toString();
3178 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb",
3180 if (tempFile != null)
3182 alreadyLoadedPDB.put(pdbId, tempFile);
3188 * Copies the jar entry of given name to a new temporary file and returns the
3189 * path to the file, or null if the entry is not found.
3192 * @param jarEntryName
3194 * a prefix for the temporary file name, must be at least three
3197 * null or original file - so new file can be given the same suffix
3201 protected String copyJarEntry(jarInputStreamProvider jprovider,
3202 String jarEntryName, String prefix, String origFile)
3204 BufferedReader in = null;
3205 PrintWriter out = null;
3206 String suffix = ".tmp";
3207 if (origFile == null)
3209 origFile = jarEntryName;
3211 int sfpos = origFile.lastIndexOf(".");
3212 if (sfpos > -1 && sfpos < (origFile.length() - 3))
3214 suffix = "." + origFile.substring(sfpos + 1);
3218 JarInputStream jin = jprovider.getJarInputStream();
3220 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
3221 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
3222 * FileInputStream(jprovider)); }
3225 JarEntry entry = null;
3228 entry = jin.getNextJarEntry();
3229 } while (entry != null && !entry.getName().equals(jarEntryName));
3232 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
3233 File outFile = File.createTempFile(prefix, suffix);
3234 outFile.deleteOnExit();
3235 out = new PrintWriter(new FileOutputStream(outFile));
3238 while ((data = in.readLine()) != null)
3243 String t = outFile.getAbsolutePath();
3248 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
3250 } catch (Exception ex)
3252 ex.printStackTrace();
3260 } catch (IOException e)
3274 private class JvAnnotRow
3276 public JvAnnotRow(int i, AlignmentAnnotation jaa)
3283 * persisted version of annotation row from which to take vis properties
3285 public jalview.datamodel.AlignmentAnnotation template;
3288 * original position of the annotation row in the alignment
3294 * Load alignment frame from jalview XML DOM object
3296 * @param jalviewModel
3299 * filename source string
3300 * @param loadTreesAndStructures
3301 * when false only create Viewport
3303 * data source provider
3304 * @return alignment frame created from view stored in DOM
3306 AlignFrame loadFromObject(JalviewModel jalviewModel, String file,
3307 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
3309 SequenceSet vamsasSet = jalviewModel.getVamsasModel().getSequenceSet().get(0);
3310 List<Sequence> vamsasSeqs = vamsasSet.getSequence();
3312 // JalviewModelSequence jms = object.getJalviewModelSequence();
3314 // Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
3316 Viewport view = (jalviewModel.getViewport().size() > 0)
3317 ? jalviewModel.getViewport().get(0)
3320 // ////////////////////////////////
3321 // INITIALISE ALIGNMENT SEQUENCESETID AND VIEWID
3324 // If we just load in the same jar file again, the sequenceSetId
3325 // will be the same, and we end up with multiple references
3326 // to the same sequenceSet. We must modify this id on load
3327 // so that each load of the file gives a unique id
3330 * used to resolve correct alignment dataset for alignments with multiple
3333 String uniqueSeqSetId = null;
3334 String viewId = null;
3337 uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3338 viewId = (view.getId() == null ? null
3339 : view.getId() + uniqueSetSuffix);
3342 // ////////////////////////////////
3345 List<SequenceI> hiddenSeqs = null;
3347 List<SequenceI> tmpseqs = new ArrayList<>();
3349 boolean multipleView = false;
3350 SequenceI referenceseqForView = null;
3351 // JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
3352 List<JSeq> jseqs = jalviewModel.getJSeq();
3353 int vi = 0; // counter in vamsasSeq array
3354 for (int i = 0; i < jseqs.size(); i++)
3356 JSeq jseq = jseqs.get(i);
3357 String seqId = jseq.getId();
3359 SequenceI tmpSeq = seqRefIds.get(seqId);
3362 if (!incompleteSeqs.containsKey(seqId))
3364 // may not need this check, but keep it for at least 2.9,1 release
3365 if (tmpSeq.getStart() != jseq.getStart()
3366 || tmpSeq.getEnd() != jseq.getEnd())
3369 "Warning JAL-2154 regression: updating start/end for sequence "
3370 + tmpSeq.toString() + " to " + jseq);
3375 incompleteSeqs.remove(seqId);
3377 if (vamsasSeqs.size() > vi
3378 && vamsasSeqs.get(vi).getId().equals(seqId))
3380 // most likely we are reading a dataset XML document so
3381 // update from vamsasSeq section of XML for this sequence
3382 tmpSeq.setName(vamsasSeqs.get(vi).getName());
3383 tmpSeq.setDescription(vamsasSeqs.get(vi).getDescription());
3384 tmpSeq.setSequence(vamsasSeqs.get(vi).getSequence());
3389 // reading multiple views, so vamsasSeq set is a subset of JSeq
3390 multipleView = true;
3392 tmpSeq.setStart(jseq.getStart());
3393 tmpSeq.setEnd(jseq.getEnd());
3394 tmpseqs.add(tmpSeq);
3398 Sequence vamsasSeq = vamsasSeqs.get(vi);
3399 tmpSeq = new jalview.datamodel.Sequence(vamsasSeq.getName(),
3400 vamsasSeq.getSequence());
3401 tmpSeq.setDescription(vamsasSeq.getDescription());
3402 tmpSeq.setStart(jseq.getStart());
3403 tmpSeq.setEnd(jseq.getEnd());
3404 tmpSeq.setVamsasId(uniqueSetSuffix + seqId);
3405 seqRefIds.put(vamsasSeq.getId(), tmpSeq);
3406 tmpseqs.add(tmpSeq);
3410 if (safeBoolean(jseq.isViewreference()))
3412 referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
3415 if (jseq.isHidden() != null && jseq.isHidden().booleanValue())
3417 if (hiddenSeqs == null)
3419 hiddenSeqs = new ArrayList<>();
3422 hiddenSeqs.add(tmpSeq);
3427 // Create the alignment object from the sequence set
3428 // ///////////////////////////////
3429 SequenceI[] orderedSeqs = tmpseqs
3430 .toArray(new SequenceI[tmpseqs.size()]);
3432 AlignmentI al = null;
3433 // so we must create or recover the dataset alignment before going further
3434 // ///////////////////////////////
3435 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
3437 // older jalview projects do not have a dataset - so creat alignment and
3439 al = new Alignment(orderedSeqs);
3440 al.setDataset(null);
3444 boolean isdsal = jalviewModel.getViewport().isEmpty();
3447 // we are importing a dataset record, so
3448 // recover reference to an alignment already materialsed as dataset
3449 al = getDatasetFor(vamsasSet.getDatasetId());
3453 // materialse the alignment
3454 al = new Alignment(orderedSeqs);
3458 addDatasetRef(vamsasSet.getDatasetId(), al);
3461 // finally, verify all data in vamsasSet is actually present in al
3462 // passing on flag indicating if it is actually a stored dataset
3463 recoverDatasetFor(vamsasSet, al, isdsal, uniqueSeqSetId);
3466 if (referenceseqForView != null)
3468 al.setSeqrep(referenceseqForView);
3470 // / Add the alignment properties
3471 for (int i = 0; i < vamsasSet.getSequenceSetProperties().size(); i++)
3473 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties()
3475 al.setProperty(ssp.getKey(), ssp.getValue());
3478 // ///////////////////////////////
3480 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
3483 // load sequence features, database references and any associated PDB
3484 // structures for the alignment
3486 // prior to 2.10, this part would only be executed the first time a
3487 // sequence was encountered, but not afterwards.
3488 // now, for 2.10 projects, this is also done if the xml doc includes
3489 // dataset sequences not actually present in any particular view.
3491 for (int i = 0; i < vamsasSeqs.size(); i++)
3493 JSeq jseq = jseqs.get(i);
3494 if (jseq.getFeatures().size() > 0)
3496 List<Feature> features = jseq.getFeatures();
3497 for (int f = 0; f < features.size(); f++)
3499 Feature feat = features.get(f);
3500 SequenceFeature sf = new SequenceFeature(feat.getType(),
3501 feat.getDescription(), feat.getBegin(), feat.getEnd(),
3502 safeFloat(feat.getScore()), feat.getFeatureGroup());
3503 sf.setStatus(feat.getStatus());
3506 * load any feature attributes - include map-valued attributes
3508 Map<String, Map<String, String>> mapAttributes = new HashMap<>();
3509 for (int od = 0; od < feat.getOtherData().size(); od++)
3511 OtherData keyValue = feat.getOtherData().get(od);
3512 String attributeName = keyValue.getKey();
3513 String attributeValue = keyValue.getValue();
3514 if (attributeName.startsWith("LINK"))
3516 sf.addLink(attributeValue);
3520 String subAttribute = keyValue.getKey2();
3521 if (subAttribute == null)
3523 // simple string-valued attribute
3524 sf.setValue(attributeName, attributeValue);
3528 // attribute 'key' has sub-attribute 'key2'
3529 if (!mapAttributes.containsKey(attributeName))
3531 mapAttributes.put(attributeName, new HashMap<>());
3533 mapAttributes.get(attributeName).put(subAttribute,
3538 for (Entry<String, Map<String, String>> mapAttribute : mapAttributes
3541 sf.setValue(mapAttribute.getKey(), mapAttribute.getValue());
3544 // adds feature to datasequence's feature set (since Jalview 2.10)
3545 alignmentSeq.addSequenceFeature(sf);
3548 if (vamsasSeqs.get(i).getDBRef().size() > 0)
3550 // adds dbrefs to datasequence's set (since Jalview 2.10)
3552 al.getSequenceAt(i).getDatasetSequence() == null
3553 ? al.getSequenceAt(i)
3554 : al.getSequenceAt(i).getDatasetSequence(),
3557 if (jseq.getPdbids().size() > 0)
3559 List<Pdbids> ids = jseq.getPdbids();
3560 for (int p = 0; p < ids.size(); p++)
3562 Pdbids pdbid = ids.get(p);
3563 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
3564 entry.setId(pdbid.getId());
3565 if (pdbid.getType() != null)
3567 if (PDBEntry.Type.getType(pdbid.getType()) != null)
3569 entry.setType(PDBEntry.Type.getType(pdbid.getType()));
3573 entry.setType(PDBEntry.Type.FILE);
3576 // jprovider is null when executing 'New View'
3577 if (pdbid.getFile() != null && jprovider != null)
3579 if (!pdbloaded.containsKey(pdbid.getFile()))
3581 entry.setFile(loadPDBFile(jprovider, pdbid.getId(),
3586 entry.setFile(pdbloaded.get(pdbid.getId()).toString());
3590 if (pdbid.getPdbentryItem() != null)
3592 for (PdbentryItem item : pdbid.getPdbentryItem())
3594 for (Property pr : item.getProperty())
3596 entry.setProperty(pr.getName(), pr.getValue());
3601 for (Property prop : pdbid.getProperty())
3603 entry.setProperty(prop.getName(), prop.getValue());
3605 StructureSelectionManager
3606 .getStructureSelectionManager(Desktop.instance)
3607 .registerPDBEntry(entry);
3608 // adds PDBEntry to datasequence's set (since Jalview 2.10)
3609 if (alignmentSeq.getDatasetSequence() != null)
3611 alignmentSeq.getDatasetSequence().addPDBId(entry);
3615 alignmentSeq.addPDBId(entry);
3621 * load any HMMER profile
3623 String hmmJarFile = jseqs[i].getHmmerProfile();
3624 if (hmmJarFile != null && jprovider != null)
3626 loadHmmerProfile(jprovider, hmmJarFile, alignmentSeq);
3629 } // end !multipleview
3631 // ///////////////////////////////
3632 // LOAD SEQUENCE MAPPINGS
3634 if (vamsasSet.getAlcodonFrame().size() > 0)
3636 // TODO Potentially this should only be done once for all views of an
3638 List<AlcodonFrame> alc = vamsasSet.getAlcodonFrame();
3639 for (int i = 0; i < alc.size(); i++)
3641 AlignedCodonFrame cf = new AlignedCodonFrame();
3642 if (alc.get(i).getAlcodMap().size() > 0)
3644 List<AlcodMap> maps = alc.get(i).getAlcodMap();
3645 for (int m = 0; m < maps.size(); m++)
3647 AlcodMap map = maps.get(m);
3648 SequenceI dnaseq = seqRefIds.get(map.getDnasq());
3650 jalview.datamodel.Mapping mapping = null;
3651 // attach to dna sequence reference.
3652 if (map.getMapping() != null)
3654 mapping = addMapping(map.getMapping());
3655 if (dnaseq != null && mapping.getTo() != null)
3657 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
3663 newAlcodMapRef(map.getDnasq(), cf, mapping));
3667 al.addCodonFrame(cf);
3672 // ////////////////////////////////
3674 List<JvAnnotRow> autoAlan = new ArrayList<>();
3677 * store any annotations which forward reference a group's ID
3679 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<>();
3681 if (vamsasSet.getAnnotation().size()/*Count()*/ > 0)
3683 List<Annotation> an = vamsasSet.getAnnotation();
3685 for (int i = 0; i < an.size(); i++)
3687 Annotation annotation = an.get(i);
3690 * test if annotation is automatically calculated for this view only
3692 boolean autoForView = false;
3693 if (annotation.getLabel().equals("Quality")
3694 || annotation.getLabel().equals("Conservation")
3695 || annotation.getLabel().equals("Consensus"))
3697 // Kludge for pre 2.5 projects which lacked the autocalculated flag
3699 // JAXB has no has() test; schema defaults value to false
3700 // if (!annotation.hasAutoCalculated())
3702 // annotation.setAutoCalculated(true);
3705 if (autoForView || annotation.isAutoCalculated())
3707 // remove ID - we don't recover annotation from other views for
3708 // view-specific annotation
3709 annotation.setId(null);
3712 // set visibility for other annotation in this view
3713 String annotationId = annotation.getId();
3714 if (annotationId != null && annotationIds.containsKey(annotationId))
3716 AlignmentAnnotation jda = annotationIds.get(annotationId);
3717 // in principle Visible should always be true for annotation displayed
3718 // in multiple views
3719 if (annotation.isVisible() != null)
3721 jda.visible = annotation.isVisible();
3724 al.addAnnotation(jda);
3728 // Construct new annotation from model.
3729 List<AnnotationElement> ae = annotation.getAnnotationElement();
3730 jalview.datamodel.Annotation[] anot = null;
3731 java.awt.Color firstColour = null;
3733 if (!annotation.isScoreOnly())
3735 anot = new jalview.datamodel.Annotation[al.getWidth()];
3736 for (int aa = 0; aa < ae.size() && aa < anot.length; aa++)
3738 AnnotationElement annElement = ae.get(aa);
3739 anpos = annElement.getPosition();
3741 if (anpos >= anot.length)
3746 float value = safeFloat(annElement.getValue());
3747 anot[anpos] = new jalview.datamodel.Annotation(
3748 annElement.getDisplayCharacter(),
3749 annElement.getDescription(),
3750 (annElement.getSecondaryStructure() == null
3751 || annElement.getSecondaryStructure()
3755 .getSecondaryStructure()
3758 anot[anpos].colour = new Color(safeInt(annElement.getColour()));
3759 if (firstColour == null)
3761 firstColour = anot[anpos].colour;
3765 jalview.datamodel.AlignmentAnnotation jaa = null;
3767 if (annotation.isGraph())
3769 float llim = 0, hlim = 0;
3770 // if (autoForView || an[i].isAutoCalculated()) {
3773 jaa = new jalview.datamodel.AlignmentAnnotation(
3774 annotation.getLabel(), annotation.getDescription(), anot,
3775 llim, hlim, safeInt(annotation.getGraphType()));
3777 jaa.graphGroup = safeInt(annotation.getGraphGroup());
3778 jaa._linecolour = firstColour;
3779 if (annotation.getThresholdLine() != null)
3781 jaa.setThreshold(new jalview.datamodel.GraphLine(
3782 safeFloat(annotation.getThresholdLine().getValue()),
3783 annotation.getThresholdLine().getLabel(),
3784 new java.awt.Color(safeInt(
3785 annotation.getThresholdLine().getColour()))));
3787 if (autoForView || annotation.isAutoCalculated())
3789 // Hardwire the symbol display line to ensure that labels for
3790 // histograms are displayed
3796 jaa = new jalview.datamodel.AlignmentAnnotation(
3797 annotation.getLabel(), annotation.getDescription(), anot);
3798 jaa._linecolour = firstColour;
3800 // register new annotation
3801 if (annotation.getId() != null)
3803 annotationIds.put(annotation.getId(), jaa);
3804 jaa.annotationId = annotation.getId();
3806 // recover sequence association
3807 String sequenceRef = annotation.getSequenceRef();
3808 if (sequenceRef != null)
3810 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3811 SequenceI sequence = seqRefIds.get(sequenceRef);
3812 if (sequence == null)
3814 // in pre-2.9 projects sequence ref is to sequence name
3815 sequence = al.findName(sequenceRef);
3817 if (sequence != null)
3819 jaa.createSequenceMapping(sequence, 1, true);
3820 sequence.addAlignmentAnnotation(jaa);
3823 // and make a note of any group association
3824 if (annotation.getGroupRef() != null
3825 && annotation.getGroupRef().length() > 0)
3827 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3828 .get(annotation.getGroupRef());
3831 aal = new ArrayList<>();
3832 groupAnnotRefs.put(annotation.getGroupRef(), aal);
3837 if (annotation.getScore() != null)
3839 jaa.setScore(annotation.getScore().doubleValue());
3841 if (annotation.isVisible() != null)
3843 jaa.visible = annotation.isVisible().booleanValue();
3846 if (annotation.isCentreColLabels() != null)
3848 jaa.centreColLabels = annotation.isCentreColLabels()
3852 if (annotation.isScaleColLabels() != null)
3854 jaa.scaleColLabel = annotation.isScaleColLabels().booleanValue();
3856 if (annotation.isAutoCalculated())
3858 // newer files have an 'autoCalculated' flag and store calculation
3859 // state in viewport properties
3860 jaa.autoCalculated = true; // means annotation will be marked for
3861 // update at end of load.
3863 if (annotation.getGraphHeight() != null)
3865 jaa.graphHeight = annotation.getGraphHeight().intValue();
3867 jaa.belowAlignment = annotation.isBelowAlignment();
3868 jaa.setCalcId(annotation.getCalcId());
3869 if (annotation.getProperty().size() > 0)
3871 for (Annotation.Property prop : annotation
3874 jaa.setProperty(prop.getName(), prop.getValue());
3877 if (jaa.autoCalculated)
3879 autoAlan.add(new JvAnnotRow(i, jaa));
3882 // if (!autoForView)
3884 // add autocalculated group annotation and any user created annotation
3886 al.addAnnotation(jaa);
3890 // ///////////////////////
3892 // Create alignment markup and styles for this view
3893 if (jalviewModel.getJGroup().size() > 0)
3895 List<JGroup> groups = jalviewModel.getJGroup();
3896 boolean addAnnotSchemeGroup = false;
3897 for (int i = 0; i < groups.size(); i++)
3899 JGroup jGroup = groups.get(i);
3900 ColourSchemeI cs = null;
3901 if (jGroup.getColour() != null)
3903 if (jGroup.getColour().startsWith("ucs"))
3905 cs = getUserColourScheme(jalviewModel, jGroup.getColour());
3907 else if (jGroup.getColour().equals("AnnotationColourGradient")
3908 && jGroup.getAnnotationColours() != null)
3910 addAnnotSchemeGroup = true;
3914 cs = ColourSchemeProperty.getColourScheme(null, al,
3915 jGroup.getColour());
3918 int pidThreshold = safeInt(jGroup.getPidThreshold());
3920 Vector<SequenceI> seqs = new Vector<>();
3922 for (int s = 0; s < jGroup.getSeq().size(); s++)
3924 String seqId = jGroup.getSeq().get(s);
3925 SequenceI ts = seqRefIds.get(seqId);
3929 seqs.addElement(ts);
3933 if (seqs.size() < 1)
3938 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3939 safeBoolean(jGroup.isDisplayBoxes()),
3940 safeBoolean(jGroup.isDisplayText()),
3941 safeBoolean(jGroup.isColourText()),
3942 safeInt(jGroup.getStart()), safeInt(jGroup.getEnd()));
3943 sg.getGroupColourScheme().setThreshold(pidThreshold, true);
3944 sg.getGroupColourScheme()
3945 .setConservationInc(safeInt(jGroup.getConsThreshold()));
3946 sg.setOutlineColour(new Color(safeInt(jGroup.getOutlineColour())));
3948 sg.textColour = new Color(safeInt(jGroup.getTextCol1()));
3949 sg.textColour2 = new Color(safeInt(jGroup.getTextCol2()));
3950 sg.setShowNonconserved(safeBoolean(jGroup.isShowUnconserved()));
3951 sg.thresholdTextColour = safeInt(jGroup.getTextColThreshold());
3952 // attributes with a default in the schema are never null
3953 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3954 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3955 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3956 sg.setIgnoreGapsConsensus(jGroup.isIgnoreGapsinConsensus());
3957 if (jGroup.getConsThreshold() != null
3958 && jGroup.getConsThreshold().intValue() != 0)
3960 Conservation c = new Conservation("All", sg.getSequences(null), 0,
3963 c.verdict(false, 25);
3964 sg.cs.setConservation(c);
3967 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3969 // re-instate unique group/annotation row reference
3970 List<AlignmentAnnotation> jaal = groupAnnotRefs
3971 .get(jGroup.getId());
3974 for (AlignmentAnnotation jaa : jaal)
3977 if (jaa.autoCalculated)
3979 // match up and try to set group autocalc alignment row for this
3981 if (jaa.label.startsWith("Consensus for "))
3983 sg.setConsensus(jaa);
3985 // match up and try to set group autocalc alignment row for this
3987 if (jaa.label.startsWith("Conservation for "))
3989 sg.setConservationRow(jaa);
3996 if (addAnnotSchemeGroup)
3998 // reconstruct the annotation colourscheme
3999 sg.setColourScheme(constructAnnotationColour(
4000 jGroup.getAnnotationColours(), null, al, jalviewModel, false));
4006 // only dataset in this model, so just return.
4009 // ///////////////////////////////
4012 AlignFrame af = null;
4013 AlignViewport av = null;
4014 // now check to see if we really need to create a new viewport.
4015 if (multipleView && viewportsAdded.size() == 0)
4017 // We recovered an alignment for which a viewport already exists.
4018 // TODO: fix up any settings necessary for overlaying stored state onto
4019 // state recovered from another document. (may not be necessary).
4020 // we may need a binding from a viewport in memory to one recovered from
4022 // and then recover its containing af to allow the settings to be applied.
4023 // TODO: fix for vamsas demo
4025 "About to recover a viewport for existing alignment: Sequence set ID is "
4027 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
4028 if (seqsetobj != null)
4030 if (seqsetobj instanceof String)
4032 uniqueSeqSetId = (String) seqsetobj;
4034 "Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
4040 "Warning : Collision between sequence set ID string and existing jalview object mapping.");
4046 * indicate that annotation colours are applied across all groups (pre
4047 * Jalview 2.8.1 behaviour)
4049 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan("2.8.1",
4050 jalviewModel.getVersion());
4052 AlignmentPanel ap = null;
4053 boolean isnewview = true;
4056 // Check to see if this alignment already has a view id == viewId
4057 jalview.gui.AlignmentPanel views[] = Desktop
4058 .getAlignmentPanels(uniqueSeqSetId);
4059 if (views != null && views.length > 0)
4061 for (int v = 0; v < views.length; v++)
4063 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
4065 // recover the existing alignpanel, alignframe, viewport
4066 af = views[v].alignFrame;
4069 // TODO: could even skip resetting view settings if we don't want to
4070 // change the local settings from other jalview processes
4079 af = loadViewport(file, jseqs, hiddenSeqs, al, jalviewModel, view,
4080 uniqueSeqSetId, viewId, autoAlan);
4081 av = af.getViewport();
4086 * Load any trees, PDB structures and viewers
4088 * Not done if flag is false (when this method is used for New View)
4090 if (loadTreesAndStructures)
4092 loadTrees(jalviewModel, view, af, av, ap);
4093 loadPCAViewers(jalviewModel, ap);
4094 loadPDBStructures(jprovider, jseqs, af, ap);
4095 loadRnaViewers(jprovider, jseqs, ap);
4097 // and finally return.
4102 * Loads a HMMER profile from a file stored in the project, and associates it
4103 * with the specified sequence
4109 protected void loadHmmerProfile(jarInputStreamProvider jprovider,
4110 String hmmJarFile, SequenceI seq)
4114 String hmmFile = copyJarEntry(jprovider, hmmJarFile, "hmm", null);
4115 HMMFile parser = new HMMFile(hmmFile, DataSourceType.FILE);
4116 HiddenMarkovModel hmmModel = parser.getHMM();
4117 hmmModel = new HiddenMarkovModel(hmmModel, seq);
4118 seq.setHMM(hmmModel);
4119 } catch (IOException e)
4121 warn("Error loading HMM profile for " + seq.getName() + ": "
4127 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
4128 * panel is restored from separate jar entries, two (gapped and trimmed) per
4129 * sequence and secondary structure.
4131 * Currently each viewer shows just one sequence and structure (gapped and
4132 * trimmed), however this method is designed to support multiple sequences or
4133 * structures in viewers if wanted in future.
4139 private void loadRnaViewers(jarInputStreamProvider jprovider,
4140 List<JSeq> jseqs, AlignmentPanel ap)
4143 * scan the sequences for references to viewers; create each one the first
4144 * time it is referenced, add Rna models to existing viewers
4146 for (JSeq jseq : jseqs)
4148 for (int i = 0; i < jseq.getRnaViewer().size(); i++)
4150 RnaViewer viewer = jseq.getRnaViewer().get(i);
4151 AppVarna appVarna = findOrCreateVarnaViewer(viewer, uniqueSetSuffix,
4154 for (int j = 0; j < viewer.getSecondaryStructure().size(); j++)
4156 SecondaryStructure ss = viewer.getSecondaryStructure().get(j);
4157 SequenceI seq = seqRefIds.get(jseq.getId());
4158 AlignmentAnnotation ann = this.annotationIds
4159 .get(ss.getAnnotationId());
4162 * add the structure to the Varna display (with session state copied
4163 * from the jar to a temporary file)
4165 boolean gapped = safeBoolean(ss.isGapped());
4166 String rnaTitle = ss.getTitle();
4167 String sessionState = ss.getViewerState();
4168 String tempStateFile = copyJarEntry(jprovider, sessionState,
4170 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
4171 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
4173 appVarna.setInitialSelection(safeInt(viewer.getSelectedRna()));
4179 * Locate and return an already instantiated matching AppVarna, or create one
4183 * @param viewIdSuffix
4187 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
4188 String viewIdSuffix, AlignmentPanel ap)
4191 * on each load a suffix is appended to the saved viewId, to avoid conflicts
4192 * if load is repeated
4194 String postLoadId = viewer.getViewId() + viewIdSuffix;
4195 for (JInternalFrame frame : getAllFrames())
4197 if (frame instanceof AppVarna)
4199 AppVarna varna = (AppVarna) frame;
4200 if (postLoadId.equals(varna.getViewId()))
4202 // this viewer is already instantiated
4203 // could in future here add ap as another 'parent' of the
4204 // AppVarna window; currently just 1-to-many
4211 * viewer not found - make it
4213 RnaViewerModel model = new RnaViewerModel(postLoadId, viewer.getTitle(),
4214 safeInt(viewer.getXpos()), safeInt(viewer.getYpos()),
4215 safeInt(viewer.getWidth()), safeInt(viewer.getHeight()),
4216 safeInt(viewer.getDividerLocation()));
4217 AppVarna varna = new AppVarna(model, ap);
4223 * Load any saved trees
4231 protected void loadTrees(JalviewModel jm, Viewport view,
4232 AlignFrame af, AlignViewport av, AlignmentPanel ap)
4234 // TODO result of automated refactoring - are all these parameters needed?
4237 for (int t = 0; t < jm.getTree().size(); t++)
4240 Tree tree = jm.getTree().get(t);
4242 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
4245 tp = af.showNewickTree(new NewickFile(tree.getNewick()),
4246 tree.getTitle(), safeInt(tree.getWidth()),
4247 safeInt(tree.getHeight()), safeInt(tree.getXpos()),
4248 safeInt(tree.getYpos()));
4249 if (tree.getId() != null)
4251 // perhaps bind the tree id to something ?
4256 // update local tree attributes ?
4257 // TODO: should check if tp has been manipulated by user - if so its
4258 // settings shouldn't be modified
4259 tp.setTitle(tree.getTitle());
4260 tp.setBounds(new Rectangle(safeInt(tree.getXpos()),
4261 safeInt(tree.getYpos()), safeInt(tree.getWidth()),
4262 safeInt(tree.getHeight())));
4263 tp.setViewport(av); // af.viewport;
4264 // TODO: verify 'associate with all views' works still
4265 tp.getTreeCanvas().setViewport(av); // af.viewport;
4266 tp.getTreeCanvas().setAssociatedPanel(ap); // af.alignPanel;
4268 tp.getTreeCanvas().setApplyToAllViews(tree.isLinkToAllViews());
4271 warn("There was a problem recovering stored Newick tree: \n"
4272 + tree.getNewick());
4276 tp.fitToWindow.setState(safeBoolean(tree.isFitToWindow()));
4277 tp.fitToWindow_actionPerformed(null);
4279 if (tree.getFontName() != null)
4282 new Font(tree.getFontName(), safeInt(tree.getFontStyle()),
4283 safeInt(tree.getFontSize())));
4288 new Font(view.getFontName(), safeInt(view.getFontStyle()),
4289 safeInt(view.getFontSize())));
4292 tp.showPlaceholders(safeBoolean(tree.isMarkUnlinked()));
4293 tp.showBootstrap(safeBoolean(tree.isShowBootstrap()));
4294 tp.showDistances(safeBoolean(tree.isShowDistances()));
4296 tp.getTreeCanvas().setThreshold(safeFloat(tree.getThreshold()));
4298 if (safeBoolean(tree.isCurrentTree()))
4300 af.getViewport().setCurrentTree(tp.getTree());
4304 } catch (Exception ex)
4306 ex.printStackTrace();
4311 * Load and link any saved structure viewers.
4318 protected void loadPDBStructures(jarInputStreamProvider jprovider,
4319 List<JSeq> jseqs, AlignFrame af, AlignmentPanel ap)
4322 * Run through all PDB ids on the alignment, and collect mappings between
4323 * distinct view ids and all sequences referring to that view.
4325 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<>();
4327 for (int i = 0; i < jseqs.size(); i++)
4329 JSeq jseq = jseqs.get(i);
4330 if (jseq.getPdbids().size() > 0)
4332 List<Pdbids> ids = jseq.getPdbids();
4333 for (int p = 0; p < ids.size(); p++)
4335 Pdbids pdbid = ids.get(p);
4336 final int structureStateCount = pdbid.getStructureState().size();
4337 for (int s = 0; s < structureStateCount; s++)
4339 // check to see if we haven't already created this structure view
4340 final StructureState structureState = pdbid
4341 .getStructureState().get(s);
4342 String sviewid = (structureState.getViewId() == null) ? null
4343 : structureState.getViewId() + uniqueSetSuffix;
4344 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
4345 // Originally : pdbid.getFile()
4346 // : TODO: verify external PDB file recovery still works in normal
4347 // jalview project load
4349 loadPDBFile(jprovider, pdbid.getId(), pdbid.getFile()));
4350 jpdb.setId(pdbid.getId());
4352 int x = safeInt(structureState.getXpos());
4353 int y = safeInt(structureState.getYpos());
4354 int width = safeInt(structureState.getWidth());
4355 int height = safeInt(structureState.getHeight());
4357 // Probably don't need to do this anymore...
4358 // Desktop.desktop.getComponentAt(x, y);
4359 // TODO: NOW: check that this recovers the PDB file correctly.
4360 String pdbFile = loadPDBFile(jprovider, pdbid.getId(),
4362 jalview.datamodel.SequenceI seq = seqRefIds
4363 .get(jseq.getId() + "");
4364 if (sviewid == null)
4366 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width + ","
4369 if (!structureViewers.containsKey(sviewid))
4371 structureViewers.put(sviewid,
4372 new StructureViewerModel(x, y, width, height, false,
4373 false, true, structureState.getViewId(),
4374 structureState.getType()));
4375 // Legacy pre-2.7 conversion JAL-823 :
4376 // do not assume any view has to be linked for colour by
4380 // assemble String[] { pdb files }, String[] { id for each
4381 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
4382 // seqs_file 2}, boolean[] {
4383 // linkAlignPanel,superposeWithAlignpanel}} from hash
4384 StructureViewerModel jmoldat = structureViewers.get(sviewid);
4385 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
4386 || structureState.isAlignwithAlignPanel());
4389 * Default colour by linked panel to false if not specified (e.g.
4390 * for pre-2.7 projects)
4392 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
4393 colourWithAlignPanel |= structureState.isColourwithAlignPanel();
4394 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
4397 * Default colour by viewer to true if not specified (e.g. for
4400 boolean colourByViewer = jmoldat.isColourByViewer();
4401 colourByViewer &= structureState.isColourByJmol();
4402 jmoldat.setColourByViewer(colourByViewer);
4404 if (jmoldat.getStateData().length() < structureState
4405 .getValue()/*Content()*/.length())
4407 jmoldat.setStateData(structureState.getValue());// Content());
4409 if (pdbid.getFile() != null)
4411 File mapkey = new File(pdbid.getFile());
4412 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
4413 if (seqstrmaps == null)
4415 jmoldat.getFileData().put(mapkey,
4416 seqstrmaps = jmoldat.new StructureData(pdbFile,
4419 if (!seqstrmaps.getSeqList().contains(seq))
4421 seqstrmaps.getSeqList().add(seq);
4427 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");
4434 // Instantiate the associated structure views
4435 for (Entry<String, StructureViewerModel> entry : structureViewers
4440 createOrLinkStructureViewer(entry, af, ap, jprovider);
4441 } catch (Exception e)
4444 "Error loading structure viewer: " + e.getMessage());
4445 // failed - try the next one
4457 protected void createOrLinkStructureViewer(
4458 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4459 AlignmentPanel ap, jarInputStreamProvider jprovider)
4461 final StructureViewerModel stateData = viewerData.getValue();
4464 * Search for any viewer windows already open from other alignment views
4465 * that exactly match the stored structure state
4467 StructureViewerBase comp = findMatchingViewer(viewerData);
4471 linkStructureViewer(ap, comp, stateData);
4476 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
4477 * "viewer_"+stateData.viewId
4479 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
4481 createChimeraViewer(viewerData, af, jprovider);
4486 * else Jmol (if pre-2.9, stateData contains JMOL state string)
4488 createJmolViewer(viewerData, af, jprovider);
4493 * Create a new Chimera viewer.
4499 protected void createChimeraViewer(
4500 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4501 jarInputStreamProvider jprovider)
4503 StructureViewerModel data = viewerData.getValue();
4504 String chimeraSessionFile = data.getStateData();
4507 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
4509 * NB this is the 'saved' viewId as in the project file XML, _not_ the
4510 * 'uniquified' sviewid used to reconstruct the viewer here
4512 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
4513 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
4516 Set<Entry<File, StructureData>> fileData = data.getFileData()
4518 List<PDBEntry> pdbs = new ArrayList<>();
4519 List<SequenceI[]> allseqs = new ArrayList<>();
4520 for (Entry<File, StructureData> pdb : fileData)
4522 String filePath = pdb.getValue().getFilePath();
4523 String pdbId = pdb.getValue().getPdbId();
4524 // pdbs.add(new PDBEntry(filePath, pdbId));
4525 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
4526 final List<SequenceI> seqList = pdb.getValue().getSeqList();
4527 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
4531 boolean colourByChimera = data.isColourByViewer();
4532 boolean colourBySequence = data.isColourWithAlignPanel();
4534 // TODO use StructureViewer as a factory here, see JAL-1761
4535 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
4536 final SequenceI[][] seqsArray = allseqs
4537 .toArray(new SequenceI[allseqs.size()][]);
4538 String newViewId = viewerData.getKey();
4540 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
4541 af.alignPanel, pdbArray, seqsArray, colourByChimera,
4542 colourBySequence, newViewId);
4543 cvf.setSize(data.getWidth(), data.getHeight());
4544 cvf.setLocation(data.getX(), data.getY());
4548 * Create a new Jmol window. First parse the Jmol state to translate filenames
4549 * loaded into the view, and record the order in which files are shown in the
4550 * Jmol view, so we can add the sequence mappings in same order.
4556 protected void createJmolViewer(
4557 final Entry<String, StructureViewerModel> viewerData,
4558 AlignFrame af, jarInputStreamProvider jprovider)
4560 final StructureViewerModel svattrib = viewerData.getValue();
4561 String state = svattrib.getStateData();
4564 * Pre-2.9: state element value is the Jmol state string
4566 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
4569 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
4571 state = readJarEntry(jprovider,
4572 getViewerJarEntryName(svattrib.getViewId()));
4575 List<String> pdbfilenames = new ArrayList<>();
4576 List<SequenceI[]> seqmaps = new ArrayList<>();
4577 List<String> pdbids = new ArrayList<>();
4578 StringBuilder newFileLoc = new StringBuilder(64);
4579 int cp = 0, ncp, ecp;
4580 Map<File, StructureData> oldFiles = svattrib.getFileData();
4581 while ((ncp = state.indexOf("load ", cp)) > -1)
4585 // look for next filename in load statement
4586 newFileLoc.append(state.substring(cp,
4587 ncp = (state.indexOf("\"", ncp + 1) + 1)));
4588 String oldfilenam = state.substring(ncp,
4589 ecp = state.indexOf("\"", ncp));
4590 // recover the new mapping data for this old filename
4591 // have to normalize filename - since Jmol and jalview do
4593 // translation differently.
4594 StructureData filedat = oldFiles.get(new File(oldfilenam));
4595 if (filedat == null)
4597 String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\");
4598 filedat = oldFiles.get(new File(reformatedOldFilename));
4600 newFileLoc.append(Platform.escapeBackslashes(filedat.getFilePath()));
4601 pdbfilenames.add(filedat.getFilePath());
4602 pdbids.add(filedat.getPdbId());
4603 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4604 newFileLoc.append("\"");
4605 cp = ecp + 1; // advance beyond last \" and set cursor so we can
4606 // look for next file statement.
4607 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
4611 // just append rest of state
4612 newFileLoc.append(state.substring(cp));
4616 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
4617 newFileLoc = new StringBuilder(state);
4618 newFileLoc.append("; load append ");
4619 for (File id : oldFiles.keySet())
4621 // add this and any other pdb files that should be present in
4623 StructureData filedat = oldFiles.get(id);
4624 newFileLoc.append(filedat.getFilePath());
4625 pdbfilenames.add(filedat.getFilePath());
4626 pdbids.add(filedat.getPdbId());
4627 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4628 newFileLoc.append(" \"");
4629 newFileLoc.append(filedat.getFilePath());
4630 newFileLoc.append("\"");
4633 newFileLoc.append(";");
4636 if (newFileLoc.length() == 0)
4640 int histbug = newFileLoc.indexOf("history = ");
4644 * change "history = [true|false];" to "history = [1|0];"
4647 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
4648 String val = (diff == -1) ? null
4649 : newFileLoc.substring(histbug, diff);
4650 if (val != null && val.length() >= 4)
4652 if (val.contains("e")) // eh? what can it be?
4654 if (val.trim().equals("true"))
4662 newFileLoc.replace(histbug, diff, val);
4667 final String[] pdbf = pdbfilenames
4668 .toArray(new String[pdbfilenames.size()]);
4669 final String[] id = pdbids.toArray(new String[pdbids.size()]);
4670 final SequenceI[][] sq = seqmaps
4671 .toArray(new SequenceI[seqmaps.size()][]);
4672 final String fileloc = newFileLoc.toString();
4673 final String sviewid = viewerData.getKey();
4674 final AlignFrame alf = af;
4675 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
4676 svattrib.getWidth(), svattrib.getHeight());
4679 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
4684 JalviewStructureDisplayI sview = null;
4687 sview = new StructureViewer(
4688 alf.alignPanel.getStructureSelectionManager())
4689 .createView(StructureViewer.ViewerType.JMOL,
4690 pdbf, id, sq, alf.alignPanel, svattrib,
4691 fileloc, rect, sviewid);
4692 addNewStructureViewer(sview);
4693 } catch (OutOfMemoryError ex)
4695 new OOMWarning("restoring structure view for PDB id " + id,
4696 (OutOfMemoryError) ex.getCause());
4697 if (sview != null && sview.isVisible())
4699 sview.closeViewer(false);
4700 sview.setVisible(false);
4706 } catch (InvocationTargetException ex)
4708 warn("Unexpected error when opening Jmol view.", ex);
4710 } catch (InterruptedException e)
4712 // e.printStackTrace();
4718 * Generates a name for the entry in the project jar file to hold state
4719 * information for a structure viewer
4724 protected String getViewerJarEntryName(String viewId)
4726 return VIEWER_PREFIX + viewId;
4730 * Returns any open frame that matches given structure viewer data. The match
4731 * is based on the unique viewId, or (for older project versions) the frame's
4737 protected StructureViewerBase findMatchingViewer(
4738 Entry<String, StructureViewerModel> viewerData)
4740 final String sviewid = viewerData.getKey();
4741 final StructureViewerModel svattrib = viewerData.getValue();
4742 StructureViewerBase comp = null;
4743 JInternalFrame[] frames = getAllFrames();
4744 for (JInternalFrame frame : frames)
4746 if (frame instanceof StructureViewerBase)
4749 * Post jalview 2.4 schema includes structure view id
4751 if (sviewid != null && ((StructureViewerBase) frame).getViewId()
4754 comp = (StructureViewerBase) frame;
4755 break; // break added in 2.9
4758 * Otherwise test for matching position and size of viewer frame
4760 else if (frame.getX() == svattrib.getX()
4761 && frame.getY() == svattrib.getY()
4762 && frame.getHeight() == svattrib.getHeight()
4763 && frame.getWidth() == svattrib.getWidth())
4765 comp = (StructureViewerBase) frame;
4766 // no break in faint hope of an exact match on viewId
4774 * Link an AlignmentPanel to an existing structure viewer.
4779 * @param useinViewerSuperpos
4780 * @param usetoColourbyseq
4781 * @param viewerColouring
4783 protected void linkStructureViewer(AlignmentPanel ap,
4784 StructureViewerBase viewer, StructureViewerModel stateData)
4786 // NOTE: if the jalview project is part of a shared session then
4787 // view synchronization should/could be done here.
4789 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4790 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4791 final boolean viewerColouring = stateData.isColourByViewer();
4792 Map<File, StructureData> oldFiles = stateData.getFileData();
4795 * Add mapping for sequences in this view to an already open viewer
4797 final AAStructureBindingModel binding = viewer.getBinding();
4798 for (File id : oldFiles.keySet())
4800 // add this and any other pdb files that should be present in the
4802 StructureData filedat = oldFiles.get(id);
4803 String pdbFile = filedat.getFilePath();
4804 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4805 binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE,
4807 binding.addSequenceForStructFile(pdbFile, seq);
4809 // and add the AlignmentPanel's reference to the view panel
4810 viewer.addAlignmentPanel(ap);
4811 if (useinViewerSuperpos)
4813 viewer.useAlignmentPanelForSuperposition(ap);
4817 viewer.excludeAlignmentPanelForSuperposition(ap);
4819 if (usetoColourbyseq)
4821 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4825 viewer.excludeAlignmentPanelForColourbyseq(ap);
4830 * Get all frames within the Desktop.
4834 protected JInternalFrame[] getAllFrames()
4836 JInternalFrame[] frames = null;
4837 // TODO is this necessary - is it safe - risk of hanging?
4842 frames = Desktop.desktop.getAllFrames();
4843 } catch (ArrayIndexOutOfBoundsException e)
4845 // occasional No such child exceptions are thrown here...
4849 } catch (InterruptedException f)
4853 } while (frames == null);
4858 * Answers true if 'version' is equal to or later than 'supported', where each
4859 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4860 * changes. Development and test values for 'version' are leniently treated
4864 * - minimum version we are comparing against
4866 * - version of data being processsed
4869 public static boolean isVersionStringLaterThan(String supported,
4872 if (supported == null || version == null
4873 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4874 || version.equalsIgnoreCase("Test")
4875 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4877 System.err.println("Assuming project file with "
4878 + (version == null ? "null" : version)
4879 + " is compatible with Jalview version " + supported);
4884 return StringUtils.compareVersions(version, supported, "b") >= 0;
4888 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4890 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4892 if (newStructureViewers != null)
4894 sview.getBinding().setFinishedLoadingFromArchive(false);
4895 newStructureViewers.add(sview);
4899 protected void setLoadingFinishedForNewStructureViewers()
4901 if (newStructureViewers != null)
4903 for (JalviewStructureDisplayI sview : newStructureViewers)
4905 sview.getBinding().setFinishedLoadingFromArchive(true);
4907 newStructureViewers.clear();
4908 newStructureViewers = null;
4912 AlignFrame loadViewport(String file, List<JSeq> JSEQ,
4913 List<SequenceI> hiddenSeqs, AlignmentI al,
4914 JalviewModel jm, Viewport view, String uniqueSeqSetId,
4915 String viewId, List<JvAnnotRow> autoAlan)
4917 AlignFrame af = null;
4918 af = new AlignFrame(al, safeInt(view.getWidth()),
4919 safeInt(view.getHeight()), uniqueSeqSetId, viewId);
4921 af.setFileName(file, FileFormat.Jalview);
4923 final AlignViewport viewport = af.getViewport();
4924 for (int i = 0; i < JSEQ.size(); i++)
4926 int colour = safeInt(JSEQ.get(i).getColour());
4927 viewport.setSequenceColour(viewport.getAlignment().getSequenceAt(i),
4933 viewport.setColourByReferenceSeq(true);
4934 viewport.setDisplayReferenceSeq(true);
4937 viewport.setGatherViewsHere(safeBoolean(view.isGatheredViews()));
4939 if (view.getSequenceSetId() != null)
4941 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4943 viewport.setSequenceSetId(uniqueSeqSetId);
4946 // propagate shared settings to this new view
4947 viewport.setHistoryList(av.getHistoryList());
4948 viewport.setRedoList(av.getRedoList());
4952 viewportsAdded.put(uniqueSeqSetId, viewport);
4954 // TODO: check if this method can be called repeatedly without
4955 // side-effects if alignpanel already registered.
4956 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4958 // apply Hidden regions to view.
4959 if (hiddenSeqs != null)
4961 for (int s = 0; s < JSEQ.size(); s++)
4963 SequenceGroup hidden = new SequenceGroup();
4964 boolean isRepresentative = false;
4965 for (int r = 0; r < JSEQ.get(s).getHiddenSequences().size(); r++)
4967 isRepresentative = true;
4968 SequenceI sequenceToHide = al
4969 .getSequenceAt(JSEQ.get(s).getHiddenSequences().get(r));
4970 hidden.addSequence(sequenceToHide, false);
4971 // remove from hiddenSeqs list so we don't try to hide it twice
4972 hiddenSeqs.remove(sequenceToHide);
4974 if (isRepresentative)
4976 SequenceI representativeSequence = al.getSequenceAt(s);
4977 hidden.addSequence(representativeSequence, false);
4978 viewport.hideRepSequences(representativeSequence, hidden);
4982 SequenceI[] hseqs = hiddenSeqs
4983 .toArray(new SequenceI[hiddenSeqs.size()]);
4984 viewport.hideSequence(hseqs);
4987 // recover view properties and display parameters
4989 viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
4990 viewport.setAbovePIDThreshold(safeBoolean(view.isPidSelected()));
4991 final int pidThreshold = safeInt(view.getPidThreshold());
4992 viewport.setThreshold(pidThreshold);
4994 viewport.setColourText(safeBoolean(view.isShowColourText()));
4997 .setConservationSelected(
4998 safeBoolean(view.isConservationSelected()));
4999 viewport.setIncrement(safeInt(view.getConsThreshold()));
5000 viewport.setShowJVSuffix(safeBoolean(view.isShowFullId()));
5001 viewport.setRightAlignIds(safeBoolean(view.isRightAlignIds()));
5002 viewport.setFont(new Font(view.getFontName(),
5003 safeInt(view.getFontStyle()), safeInt(view.getFontSize())),
5005 ViewStyleI vs = viewport.getViewStyle();
5006 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
5007 viewport.setViewStyle(vs);
5008 // TODO: allow custom charWidth/Heights to be restored by updating them
5009 // after setting font - which means set above to false
5010 viewport.setRenderGaps(safeBoolean(view.isRenderGaps()));
5011 viewport.setWrapAlignment(safeBoolean(view.isWrapAlignment()));
5012 viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
5014 viewport.setShowBoxes(safeBoolean(view.isShowBoxes()));
5016 viewport.setShowText(safeBoolean(view.isShowText()));
5018 viewport.setTextColour(new Color(safeInt(view.getTextCol1())));
5019 viewport.setTextColour2(new Color(safeInt(view.getTextCol2())));
5020 viewport.setThresholdTextColour(safeInt(view.getTextColThreshold()));
5021 viewport.setShowUnconserved(view.isShowUnconserved());
5022 viewport.getRanges().setStartRes(safeInt(view.getStartRes()));
5024 if (view.getViewName() != null)
5026 viewport.setViewName(view.getViewName());
5027 af.setInitialTabVisible();
5029 af.setBounds(safeInt(view.getXpos()), safeInt(view.getYpos()),
5030 safeInt(view.getWidth()), safeInt(view.getHeight()));
5031 // startSeq set in af.alignPanel.updateLayout below
5032 af.alignPanel.updateLayout();
5033 ColourSchemeI cs = null;
5034 // apply colourschemes
5035 if (view.getBgColour() != null)
5037 if (view.getBgColour().startsWith("ucs"))
5039 cs = getUserColourScheme(jm, view.getBgColour());
5041 else if (view.getBgColour().startsWith("Annotation"))
5043 AnnotationColourScheme viewAnnColour = view.getAnnotationColours();
5044 cs = constructAnnotationColour(viewAnnColour, af, al, jm, true);
5051 cs = ColourSchemeProperty.getColourScheme(af.getViewport(), al,
5052 view.getBgColour());
5057 * turn off 'alignment colour applies to all groups'
5058 * while restoring global colour scheme
5060 viewport.setColourAppliesToAllGroups(false);
5061 viewport.setGlobalColourScheme(cs);
5062 viewport.getResidueShading().setThreshold(pidThreshold,
5063 view.isIgnoreGapsinConsensus());
5064 viewport.getResidueShading()
5065 .setConsensus(viewport.getSequenceConsensusHash());
5066 if (safeBoolean(view.isConservationSelected()) && cs != null)
5068 viewport.getResidueShading()
5069 .setConservationInc(safeInt(view.getConsThreshold()));
5071 af.changeColour(cs);
5072 viewport.setColourAppliesToAllGroups(true);
5075 .setShowSequenceFeatures(
5076 safeBoolean(view.isShowSequenceFeatures()));
5078 viewport.setCentreColumnLabels(view.isCentreColumnLabels());
5079 viewport.setIgnoreGapsConsensus(view.isIgnoreGapsinConsensus(), null);
5080 viewport.setFollowHighlight(view.isFollowHighlight());
5081 viewport.followSelection = view.isFollowSelection();
5082 viewport.setShowConsensusHistogram(view.isShowConsensusHistogram());
5083 viewport.setShowSequenceLogo(view.isShowSequenceLogo());
5084 viewport.setNormaliseSequenceLogo(view.isNormaliseSequenceLogo());
5085 viewport.setShowDBRefs(safeBoolean(view.isShowDbRefTooltip()));
5086 viewport.setShowNPFeats(safeBoolean(view.isShowNPfeatureTooltip()));
5087 viewport.setShowGroupConsensus(view.isShowGroupConsensus());
5088 viewport.setShowGroupConservation(view.isShowGroupConservation());
5090 // recover feature settings
5091 if (jm.getFeatureSettings() != null)
5093 FeatureRenderer fr = af.alignPanel.getSeqPanel().seqCanvas
5094 .getFeatureRenderer();
5095 FeaturesDisplayed fdi;
5096 viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
5097 String[] renderOrder = new String[jm.getFeatureSettings()
5098 .getSetting().size()];
5099 Map<String, FeatureColourI> featureColours = new Hashtable<>();
5100 Map<String, Float> featureOrder = new Hashtable<>();
5102 for (int fs = 0; fs < jm.getFeatureSettings()
5103 .getSetting().size(); fs++)
5105 Setting setting = jm.getFeatureSettings().getSetting().get(fs);
5106 String featureType = setting.getType();
5109 * restore feature filters (if any)
5111 jalview.xml.binding.jalview.FeatureMatcherSet filters = setting
5113 if (filters != null)
5115 FeatureMatcherSetI filter = Jalview2XML
5116 .parseFilter(featureType, filters);
5117 if (!filter.isEmpty())
5119 fr.setFeatureFilter(featureType, filter);
5124 * restore feature colour scheme
5126 Color maxColour = new Color(setting.getColour());
5127 if (setting.getMincolour() != null)
5130 * minColour is always set unless a simple colour
5131 * (including for colour by label though it doesn't use it)
5133 Color minColour = new Color(setting.getMincolour().intValue());
5134 Color noValueColour = minColour;
5135 NoValueColour noColour = setting.getNoValueColour();
5136 if (noColour == NoValueColour.NONE)
5138 noValueColour = null;
5140 else if (noColour == NoValueColour.MAX)
5142 noValueColour = maxColour;
5144 float min = safeFloat(safeFloat(setting.getMin()));
5145 float max = setting.getMax() == null ? 1f
5146 : setting.getMax().floatValue();
5147 FeatureColourI gc = new FeatureColour(maxColour, minColour,
5149 noValueColour, min, max);
5150 if (setting.getAttributeName().size() > 0)
5152 gc.setAttributeName(setting.getAttributeName().toArray(
5153 new String[setting.getAttributeName().size()]));
5155 if (setting.getThreshold() != null)
5157 gc.setThreshold(setting.getThreshold().floatValue());
5158 int threshstate = safeInt(setting.getThreshstate());
5159 // -1 = None, 0 = Below, 1 = Above threshold
5160 if (threshstate == 0)
5162 gc.setBelowThreshold(true);
5164 else if (threshstate == 1)
5166 gc.setAboveThreshold(true);
5169 gc.setAutoScaled(true); // default
5170 if (setting.isAutoScale() != null)
5172 gc.setAutoScaled(setting.isAutoScale());
5174 if (setting.isColourByLabel() != null)
5176 gc.setColourByLabel(setting.isColourByLabel());
5178 // and put in the feature colour table.
5179 featureColours.put(featureType, gc);
5183 featureColours.put(featureType,
5184 new FeatureColour(maxColour));
5186 renderOrder[fs] = featureType;
5187 if (setting.getOrder() != null)
5189 featureOrder.put(featureType, setting.getOrder().floatValue());
5193 featureOrder.put(featureType, Float.valueOf(
5194 fs / jm.getFeatureSettings().getSetting().size()));
5196 if (safeBoolean(setting.isDisplay()))
5198 fdi.setVisible(featureType);
5201 Map<String, Boolean> fgtable = new Hashtable<>();
5202 for (int gs = 0; gs < jm.getFeatureSettings().getGroup().size(); gs++)
5204 Group grp = jm.getFeatureSettings().getGroup().get(gs);
5205 fgtable.put(grp.getName(), Boolean.valueOf(grp.isDisplay()));
5207 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
5208 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
5209 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
5210 FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
5211 fgtable, featureColours, 1.0f, featureOrder);
5212 fr.transferSettings(frs);
5215 if (view.getHiddenColumns().size() > 0)
5217 for (int c = 0; c < view.getHiddenColumns().size(); c++)
5219 final HiddenColumns hc = view.getHiddenColumns().get(c);
5220 viewport.hideColumns(safeInt(hc.getStart()),
5221 safeInt(hc.getEnd()) /* +1 */);
5224 if (view.getCalcIdParam() != null)
5226 for (CalcIdParam calcIdParam : view.getCalcIdParam())
5228 if (calcIdParam != null)
5230 if (recoverCalcIdParam(calcIdParam, viewport))
5235 warn("Couldn't recover parameters for "
5236 + calcIdParam.getCalcId());
5241 af.setMenusFromViewport(viewport);
5242 af.setTitle(view.getTitle());
5243 // TODO: we don't need to do this if the viewport is aready visible.
5245 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
5246 * has a 'cdna/protein complement' view, in which case save it in order to
5247 * populate a SplitFrame once all views have been read in.
5249 String complementaryViewId = view.getComplementId();
5250 if (complementaryViewId == null)
5252 Desktop.addInternalFrame(af, view.getTitle(),
5253 safeInt(view.getWidth()), safeInt(view.getHeight()));
5254 // recompute any autoannotation
5255 af.alignPanel.updateAnnotation(false, true);
5256 reorderAutoannotation(af, al, autoAlan);
5257 af.alignPanel.alignmentChanged();
5261 splitFrameCandidates.put(view, af);
5267 * Reads saved data to restore Colour by Annotation settings
5269 * @param viewAnnColour
5273 * @param checkGroupAnnColour
5276 private ColourSchemeI constructAnnotationColour(
5277 AnnotationColourScheme viewAnnColour, AlignFrame af,
5278 AlignmentI al, JalviewModel model, boolean checkGroupAnnColour)
5280 boolean propagateAnnColour = false;
5281 AlignmentI annAlignment = af != null ? af.getViewport().getAlignment()
5283 if (checkGroupAnnColour && al.getGroups() != null
5284 && al.getGroups().size() > 0)
5286 // pre 2.8.1 behaviour
5287 // check to see if we should transfer annotation colours
5288 propagateAnnColour = true;
5289 for (SequenceGroup sg : al.getGroups())
5291 if (sg.getColourScheme() instanceof AnnotationColourGradient)
5293 propagateAnnColour = false;
5299 * 2.10.2- : saved annotationId is AlignmentAnnotation.annotationId
5301 String annotationId = viewAnnColour.getAnnotation();
5302 AlignmentAnnotation matchedAnnotation = annotationIds.get(annotationId);
5305 * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
5307 if (matchedAnnotation == null
5308 && annAlignment.getAlignmentAnnotation() != null)
5310 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
5313 .equals(annAlignment.getAlignmentAnnotation()[i].label))
5315 matchedAnnotation = annAlignment.getAlignmentAnnotation()[i];
5320 if (matchedAnnotation == null)
5322 System.err.println("Failed to match annotation colour scheme for "
5326 if (matchedAnnotation.getThreshold() == null)
5328 matchedAnnotation.setThreshold(
5329 new GraphLine(safeFloat(viewAnnColour.getThreshold()),
5330 "Threshold", Color.black));
5333 AnnotationColourGradient cs = null;
5334 if (viewAnnColour.getColourScheme().equals("None"))
5336 cs = new AnnotationColourGradient(matchedAnnotation,
5337 new Color(safeInt(viewAnnColour.getMinColour())),
5338 new Color(safeInt(viewAnnColour.getMaxColour())),
5339 safeInt(viewAnnColour.getAboveThreshold()));
5341 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
5343 cs = new AnnotationColourGradient(matchedAnnotation,
5344 getUserColourScheme(model, viewAnnColour.getColourScheme()),
5345 safeInt(viewAnnColour.getAboveThreshold()));
5349 cs = new AnnotationColourGradient(matchedAnnotation,
5350 ColourSchemeProperty.getColourScheme(af.getViewport(), al,
5351 viewAnnColour.getColourScheme()),
5352 safeInt(viewAnnColour.getAboveThreshold()));
5355 boolean perSequenceOnly = safeBoolean(viewAnnColour.isPerSequence());
5356 boolean useOriginalColours = safeBoolean(
5357 viewAnnColour.isPredefinedColours());
5358 cs.setSeqAssociated(perSequenceOnly);
5359 cs.setPredefinedColours(useOriginalColours);
5361 if (propagateAnnColour && al.getGroups() != null)
5363 // Also use these settings for all the groups
5364 for (int g = 0; g < al.getGroups().size(); g++)
5366 SequenceGroup sg = al.getGroups().get(g);
5367 if (sg.getGroupColourScheme() == null)
5372 AnnotationColourGradient groupScheme = new AnnotationColourGradient(
5373 matchedAnnotation, sg.getColourScheme(),
5374 safeInt(viewAnnColour.getAboveThreshold()));
5375 sg.setColourScheme(groupScheme);
5376 groupScheme.setSeqAssociated(perSequenceOnly);
5377 groupScheme.setPredefinedColours(useOriginalColours);
5383 private void reorderAutoannotation(AlignFrame af, AlignmentI al,
5384 List<JvAnnotRow> autoAlan)
5386 // copy over visualization settings for autocalculated annotation in the
5388 if (al.getAlignmentAnnotation() != null)
5391 * Kludge for magic autoannotation names (see JAL-811)
5393 String[] magicNames = new String[] { "Consensus", "Quality",
5395 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
5396 Hashtable<String, JvAnnotRow> visan = new Hashtable<>();
5397 for (String nm : magicNames)
5399 visan.put(nm, nullAnnot);
5401 for (JvAnnotRow auan : autoAlan)
5403 visan.put(auan.template.label
5404 + (auan.template.getCalcId() == null ? ""
5405 : "\t" + auan.template.getCalcId()),
5408 int hSize = al.getAlignmentAnnotation().length;
5409 List<JvAnnotRow> reorder = new ArrayList<>();
5410 // work through any autoCalculated annotation already on the view
5411 // removing it if it should be placed in a different location on the
5412 // annotation panel.
5413 List<String> remains = new ArrayList<>(visan.keySet());
5414 for (int h = 0; h < hSize; h++)
5416 jalview.datamodel.AlignmentAnnotation jalan = al
5417 .getAlignmentAnnotation()[h];
5418 if (jalan.autoCalculated)
5421 JvAnnotRow valan = visan.get(k = jalan.label);
5422 if (jalan.getCalcId() != null)
5424 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
5429 // delete the auto calculated row from the alignment
5430 al.deleteAnnotation(jalan, false);
5434 if (valan != nullAnnot)
5436 if (jalan != valan.template)
5438 // newly created autoannotation row instance
5439 // so keep a reference to the visible annotation row
5440 // and copy over all relevant attributes
5441 if (valan.template.graphHeight >= 0)
5444 jalan.graphHeight = valan.template.graphHeight;
5446 jalan.visible = valan.template.visible;
5448 reorder.add(new JvAnnotRow(valan.order, jalan));
5453 // Add any (possibly stale) autocalculated rows that were not appended to
5454 // the view during construction
5455 for (String other : remains)
5457 JvAnnotRow othera = visan.get(other);
5458 if (othera != nullAnnot && othera.template.getCalcId() != null
5459 && othera.template.getCalcId().length() > 0)
5461 reorder.add(othera);
5464 // now put the automatic annotation in its correct place
5465 int s = 0, srt[] = new int[reorder.size()];
5466 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
5467 for (JvAnnotRow jvar : reorder)
5470 srt[s++] = jvar.order;
5473 jalview.util.QuickSort.sort(srt, rws);
5474 // and re-insert the annotation at its correct position
5475 for (JvAnnotRow jvar : rws)
5477 al.addAnnotation(jvar.template, jvar.order);
5479 af.alignPanel.adjustAnnotationHeight();
5483 Hashtable skipList = null;
5486 * TODO remove this method
5489 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
5490 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
5491 * throw new Error("Implementation Error. No skipList defined for this
5492 * Jalview2XML instance."); } return (AlignFrame)
5493 * skipList.get(view.getSequenceSetId()); }
5497 * Check if the Jalview view contained in object should be skipped or not.
5500 * @return true if view's sequenceSetId is a key in skipList
5502 private boolean skipViewport(JalviewModel object)
5504 if (skipList == null)
5508 String id = object.getViewport().get(0).getSequenceSetId();
5509 if (skipList.containsKey(id))
5511 debug("Skipping sequence set id " + id);
5517 public void addToSkipList(AlignFrame af)
5519 if (skipList == null)
5521 skipList = new Hashtable();
5523 skipList.put(af.getViewport().getSequenceSetId(), af);
5526 public void clearSkipList()
5528 if (skipList != null)
5535 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
5536 boolean ignoreUnrefed, String uniqueSeqSetId)
5538 jalview.datamodel.AlignmentI ds = getDatasetFor(
5539 vamsasSet.getDatasetId());
5540 AlignmentI xtant_ds = ds;
5541 if (xtant_ds == null)
5543 // good chance we are about to create a new dataset, but check if we've
5544 // seen some of the dataset sequence IDs before.
5545 // TODO: skip this check if we are working with project generated by
5546 // version 2.11 or later
5547 xtant_ds = checkIfHasDataset(vamsasSet.getSequence());
5548 if (xtant_ds != null)
5551 addDatasetRef(vamsasSet.getDatasetId(), ds);
5554 Vector dseqs = null;
5557 // recovering an alignment View
5558 AlignmentI seqSetDS = getDatasetFor(UNIQSEQSETID + uniqueSeqSetId);
5559 if (seqSetDS != null)
5561 if (ds != null && ds != seqSetDS)
5563 warn("JAL-3171 regression: Overwriting a dataset reference for an alignment"
5564 + " - CDS/Protein crossreference data may be lost");
5565 if (xtant_ds != null)
5567 // This can only happen if the unique sequence set ID was bound to a
5568 // dataset that did not contain any of the sequences in the view
5569 // currently being restored.
5570 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.");
5574 addDatasetRef(vamsasSet.getDatasetId(), ds);
5579 // try even harder to restore dataset
5580 AlignmentI xtantDS = checkIfHasDataset(vamsasSet.getSequence());
5581 // create a list of new dataset sequences
5582 dseqs = new Vector();
5584 for (int i = 0, iSize = vamsasSet.getSequence().size(); i < iSize; i++)
5586 Sequence vamsasSeq = vamsasSet.getSequence().get(i);
5587 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
5589 // create a new dataset
5592 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
5593 dseqs.copyInto(dsseqs);
5594 ds = new jalview.datamodel.Alignment(dsseqs);
5595 debug("Created new dataset " + vamsasSet.getDatasetId()
5596 + " for alignment " + System.identityHashCode(al));
5597 addDatasetRef(vamsasSet.getDatasetId(), ds);
5599 // set the dataset for the newly imported alignment.
5600 if (al.getDataset() == null && !ignoreUnrefed)
5603 // register dataset for the alignment's uniqueSeqSetId for legacy projects
5604 addDatasetRef(UNIQSEQSETID + uniqueSeqSetId, ds);
5606 updateSeqDatasetBinding(vamsasSet.getSequence(), ds);
5610 * XML dataset sequence ID to materialised dataset reference
5612 HashMap<String, AlignmentI> seqToDataset = new HashMap<>();
5615 * @return the first materialised dataset reference containing a dataset
5616 * sequence referenced in the given view
5618 * - sequences from the view
5620 AlignmentI checkIfHasDataset(List<Sequence> list)
5622 for (Sequence restoredSeq : list)
5624 AlignmentI datasetFor = seqToDataset.get(restoredSeq.getDsseqid());
5625 if (datasetFor != null)
5634 * Register ds as the containing dataset for the dataset sequences referenced
5635 * by sequences in list
5638 * - sequences in a view
5641 void updateSeqDatasetBinding(List<Sequence> list, AlignmentI ds)
5643 for (Sequence restoredSeq : list)
5645 AlignmentI prevDS = seqToDataset.put(restoredSeq.getDsseqid(), ds);
5646 if (prevDS != null && prevDS != ds)
5648 warn("Dataset sequence appears in many datasets: "
5649 + restoredSeq.getDsseqid());
5650 // TODO: try to merge!
5657 * sequence definition to create/merge dataset sequence for
5661 * vector to add new dataset sequence to
5662 * @param ignoreUnrefed
5663 * - when true, don't create new sequences from vamsasSeq if it's id
5664 * doesn't already have an asssociated Jalview sequence.
5666 * - used to reorder the sequence in the alignment according to the
5667 * vamsasSeq array ordering, to preserve ordering of dataset
5669 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
5670 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed, int vseqpos)
5672 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
5674 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
5675 boolean reorder = false;
5676 SequenceI dsq = null;
5677 if (sq != null && sq.getDatasetSequence() != null)
5679 dsq = sq.getDatasetSequence();
5685 if (sq == null && ignoreUnrefed)
5689 String sqid = vamsasSeq.getDsseqid();
5692 // need to create or add a new dataset sequence reference to this sequence
5695 dsq = seqRefIds.get(sqid);
5700 // make a new dataset sequence
5701 dsq = sq.createDatasetSequence();
5704 // make up a new dataset reference for this sequence
5705 sqid = seqHash(dsq);
5707 dsq.setVamsasId(uniqueSetSuffix + sqid);
5708 seqRefIds.put(sqid, dsq);
5713 dseqs.addElement(dsq);
5718 ds.addSequence(dsq);
5724 { // make this dataset sequence sq's dataset sequence
5725 sq.setDatasetSequence(dsq);
5726 // and update the current dataset alignment
5731 if (!dseqs.contains(dsq))
5738 if (ds.findIndex(dsq) < 0)
5740 ds.addSequence(dsq);
5747 // TODO: refactor this as a merge dataset sequence function
5748 // now check that sq (the dataset sequence) sequence really is the union of
5749 // all references to it
5750 // boolean pre = sq.getStart() < dsq.getStart();
5751 // boolean post = sq.getEnd() > dsq.getEnd();
5755 // StringBuffer sb = new StringBuffer();
5756 String newres = jalview.analysis.AlignSeq.extractGaps(
5757 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
5758 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
5759 && newres.length() > dsq.getLength())
5761 // Update with the longer sequence.
5765 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
5766 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
5767 * sb.append(newres.substring(newres.length() - sq.getEnd() -
5768 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
5770 dsq.setSequence(newres);
5772 // TODO: merges will never happen if we 'know' we have the real dataset
5773 // sequence - this should be detected when id==dssid
5775 "DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
5776 // + (pre ? "prepended" : "") + " "
5777 // + (post ? "appended" : ""));
5782 // sequence refs are identical. We may need to update the existing dataset
5783 // alignment with this one, though.
5784 if (ds != null && dseqs == null)
5786 int opos = ds.findIndex(dsq);
5787 SequenceI tseq = null;
5788 if (opos != -1 && vseqpos != opos)
5790 // remove from old position
5791 ds.deleteSequence(dsq);
5793 if (vseqpos < ds.getHeight())
5795 if (vseqpos != opos)
5797 // save sequence at destination position
5798 tseq = ds.getSequenceAt(vseqpos);
5799 ds.replaceSequenceAt(vseqpos, dsq);
5800 ds.addSequence(tseq);
5805 ds.addSequence(dsq);
5812 * TODO use AlignmentI here and in related methods - needs
5813 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
5815 Hashtable<String, AlignmentI> datasetIds = null;
5817 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
5819 private AlignmentI getDatasetFor(String datasetId)
5821 if (datasetIds == null)
5823 datasetIds = new Hashtable<>();
5826 if (datasetIds.containsKey(datasetId))
5828 return datasetIds.get(datasetId);
5833 private void addDatasetRef(String datasetId, AlignmentI dataset)
5835 if (datasetIds == null)
5837 datasetIds = new Hashtable<>();
5839 datasetIds.put(datasetId, dataset);
5843 * make a new dataset ID for this jalview dataset alignment
5848 private String getDatasetIdRef(AlignmentI dataset)
5850 if (dataset.getDataset() != null)
5852 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
5854 String datasetId = makeHashCode(dataset, null);
5855 if (datasetId == null)
5857 // make a new datasetId and record it
5858 if (dataset2Ids == null)
5860 dataset2Ids = new IdentityHashMap<>();
5864 datasetId = dataset2Ids.get(dataset);
5866 if (datasetId == null)
5868 datasetId = "ds" + dataset2Ids.size() + 1;
5869 dataset2Ids.put(dataset, datasetId);
5875 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5877 for (int d = 0; d < sequence.getDBRef().size(); d++)
5879 DBRef dr = sequence.getDBRef().get(d);
5880 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
5881 dr.getSource(), dr.getVersion(), dr.getAccessionId());
5882 if (dr.getMapping() != null)
5884 entry.setMap(addMapping(dr.getMapping()));
5886 datasetSequence.addDBRef(entry);
5890 private jalview.datamodel.Mapping addMapping(Mapping m)
5892 SequenceI dsto = null;
5893 // Mapping m = dr.getMapping();
5894 int fr[] = new int[m.getMapListFrom().size() * 2];
5895 Iterator<MapListFrom> from = m.getMapListFrom().iterator();// enumerateMapListFrom();
5896 for (int _i = 0; from.hasNext(); _i += 2)
5898 MapListFrom mf = from.next();
5899 fr[_i] = mf.getStart();
5900 fr[_i + 1] = mf.getEnd();
5902 int fto[] = new int[m.getMapListTo().size() * 2];
5903 Iterator<MapListTo> to = m.getMapListTo().iterator();// enumerateMapListTo();
5904 for (int _i = 0; to.hasNext(); _i += 2)
5906 MapListTo mf = to.next();
5907 fto[_i] = mf.getStart();
5908 fto[_i + 1] = mf.getEnd();
5910 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto, fr,
5911 fto, m.getMapFromUnit().intValue(),
5912 m.getMapToUnit().intValue());
5915 * (optional) choice of dseqFor or Sequence
5917 if (m.getDseqFor() != null)
5919 String dsfor = m.getDseqFor();
5920 if (seqRefIds.containsKey(dsfor))
5925 jmap.setTo(seqRefIds.get(dsfor));
5929 frefedSequence.add(newMappingRef(dsfor, jmap));
5932 else if (m.getSequence() != null)
5935 * local sequence definition
5937 Sequence ms = m.getSequence();
5938 SequenceI djs = null;
5939 String sqid = ms.getDsseqid();
5940 if (sqid != null && sqid.length() > 0)
5943 * recover dataset sequence
5945 djs = seqRefIds.get(sqid);
5950 "Warning - making up dataset sequence id for DbRef sequence map reference");
5951 sqid = ((Object) ms).toString(); // make up a new hascode for
5952 // undefined dataset sequence hash
5953 // (unlikely to happen)
5959 * make a new dataset sequence and add it to refIds hash
5961 djs = new jalview.datamodel.Sequence(ms.getName(),
5963 djs.setStart(jmap.getMap().getToLowest());
5964 djs.setEnd(jmap.getMap().getToHighest());
5965 djs.setVamsasId(uniqueSetSuffix + sqid);
5967 incompleteSeqs.put(sqid, djs);
5968 seqRefIds.put(sqid, djs);
5970 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5979 * Provides a 'copy' of an alignment view (on action New View) by 'saving' the
5980 * view as XML (but not to file), and then reloading it
5985 public AlignmentPanel copyAlignPanel(AlignmentPanel ap)
5988 JalviewModel jm = saveState(ap, null, null, null);
5991 jm.getVamsasModel().getSequenceSet().get(0).getDatasetId(),
5992 ap.getAlignment().getDataset());
5994 uniqueSetSuffix = "";
5995 // jm.getJalviewModelSequence().getViewport(0).setId(null);
5996 jm.getViewport().get(0).setId(null);
5997 // we don't overwrite the view we just copied
5999 if (this.frefedSequence == null)
6001 frefedSequence = new Vector<>();
6004 viewportsAdded.clear();
6006 AlignFrame af = loadFromObject(jm, null, false, null);
6007 af.getAlignPanels().clear();
6008 af.closeMenuItem_actionPerformed(true);
6011 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
6012 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
6013 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
6014 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
6015 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
6018 return af.alignPanel;
6021 private Hashtable jvids2vobj;
6023 private void warn(String msg)
6028 private void warn(String msg, Exception e)
6030 if (Cache.log != null)
6034 Cache.log.warn(msg, e);
6038 Cache.log.warn(msg);
6043 System.err.println("Warning: " + msg);
6046 e.printStackTrace();
6051 private void debug(String string)
6053 debug(string, null);
6056 private void debug(String msg, Exception e)
6058 if (Cache.log != null)
6062 Cache.log.debug(msg, e);
6066 Cache.log.debug(msg);
6071 System.err.println("Warning: " + msg);
6074 e.printStackTrace();
6080 * set the object to ID mapping tables used to write/recover objects and XML
6081 * ID strings for the jalview project. If external tables are provided then
6082 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
6083 * object goes out of scope. - also populates the datasetIds hashtable with
6084 * alignment objects containing dataset sequences
6087 * Map from ID strings to jalview datamodel
6089 * Map from jalview datamodel to ID strings
6093 public void setObjectMappingTables(Hashtable vobj2jv,
6094 IdentityHashMap jv2vobj)
6096 this.jv2vobj = jv2vobj;
6097 this.vobj2jv = vobj2jv;
6098 Iterator ds = jv2vobj.keySet().iterator();
6100 while (ds.hasNext())
6102 Object jvobj = ds.next();
6103 id = jv2vobj.get(jvobj).toString();
6104 if (jvobj instanceof jalview.datamodel.Alignment)
6106 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
6108 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
6111 else if (jvobj instanceof jalview.datamodel.Sequence)
6113 // register sequence object so the XML parser can recover it.
6114 if (seqRefIds == null)
6116 seqRefIds = new HashMap<>();
6118 if (seqsToIds == null)
6120 seqsToIds = new IdentityHashMap<>();
6122 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
6123 seqsToIds.put((SequenceI) jvobj, id);
6125 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
6128 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
6129 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
6130 if (jvann.annotationId == null)
6132 jvann.annotationId = anid;
6134 if (!jvann.annotationId.equals(anid))
6136 // TODO verify that this is the correct behaviour
6137 this.warn("Overriding Annotation ID for " + anid
6138 + " from different id : " + jvann.annotationId);
6139 jvann.annotationId = anid;
6142 else if (jvobj instanceof String)
6144 if (jvids2vobj == null)
6146 jvids2vobj = new Hashtable();
6147 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
6152 debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
6158 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
6159 * objects created from the project archive. If string is null (default for
6160 * construction) then suffix will be set automatically.
6164 public void setUniqueSetSuffix(String string)
6166 uniqueSetSuffix = string;
6171 * uses skipList2 as the skipList for skipping views on sequence sets
6172 * associated with keys in the skipList
6176 public void setSkipList(Hashtable skipList2)
6178 skipList = skipList2;
6182 * Reads the jar entry of given name and returns its contents, or null if the
6183 * entry is not found.
6186 * @param jarEntryName
6189 protected String readJarEntry(jarInputStreamProvider jprovider,
6190 String jarEntryName)
6192 String result = null;
6193 BufferedReader in = null;
6198 * Reopen the jar input stream and traverse its entries to find a matching
6201 JarInputStream jin = jprovider.getJarInputStream();
6202 JarEntry entry = null;
6205 entry = jin.getNextJarEntry();
6206 } while (entry != null && !entry.getName().equals(jarEntryName));
6210 StringBuilder out = new StringBuilder(256);
6211 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
6214 while ((data = in.readLine()) != null)
6218 result = out.toString();
6222 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
6224 } catch (Exception ex)
6226 ex.printStackTrace();
6234 } catch (IOException e)
6245 * Returns an incrementing counter (0, 1, 2...)
6249 private synchronized int nextCounter()
6255 * Loads any saved PCA viewers
6260 protected void loadPCAViewers(JalviewModel model, AlignmentPanel ap)
6264 List<PcaViewer> pcaviewers = model.getPcaViewer();
6265 for (PcaViewer viewer : pcaviewers)
6267 String modelName = viewer.getScoreModelName();
6268 SimilarityParamsI params = new SimilarityParams(
6269 viewer.isIncludeGappedColumns(), viewer.isMatchGaps(),
6270 viewer.isIncludeGaps(),
6271 viewer.isDenominateByShortestLength());
6274 * create the panel (without computing the PCA)
6276 PCAPanel panel = new PCAPanel(ap, modelName, params);
6278 panel.setTitle(viewer.getTitle());
6279 panel.setBounds(new Rectangle(viewer.getXpos(), viewer.getYpos(),
6280 viewer.getWidth(), viewer.getHeight()));
6282 boolean showLabels = viewer.isShowLabels();
6283 panel.setShowLabels(showLabels);
6284 panel.getRotatableCanvas().setShowLabels(showLabels);
6285 panel.getRotatableCanvas()
6286 .setBgColour(new Color(viewer.getBgColour()));
6287 panel.getRotatableCanvas()
6288 .setApplyToAllViews(viewer.isLinkToAllViews());
6291 * load PCA output data
6293 ScoreModelI scoreModel = ScoreModels.getInstance()
6294 .getScoreModel(modelName, ap);
6295 PCA pca = new PCA(null, scoreModel, params);
6296 PcaDataType pcaData = viewer.getPcaData();
6298 MatrixI pairwise = loadDoubleMatrix(pcaData.getPairwiseMatrix());
6299 pca.setPairwiseScores(pairwise);
6301 MatrixI triDiag = loadDoubleMatrix(pcaData.getTridiagonalMatrix());
6302 pca.setTridiagonal(triDiag);
6304 MatrixI result = loadDoubleMatrix(pcaData.getEigenMatrix());
6305 pca.setEigenmatrix(result);
6307 panel.getPcaModel().setPCA(pca);
6310 * we haven't saved the input data! (JAL-2647 to do)
6312 panel.setInputData(null);
6315 * add the sequence points for the PCA display
6317 List<jalview.datamodel.SequencePoint> seqPoints = new ArrayList<>();
6318 for (SequencePoint sp : viewer.getSequencePoint())
6320 String seqId = sp.getSequenceRef();
6321 SequenceI seq = seqRefIds.get(seqId);
6324 throw new IllegalStateException(
6325 "Unmatched seqref for PCA: " + seqId);
6327 Point pt = new Point(sp.getXPos(), sp.getYPos(), sp.getZPos());
6328 jalview.datamodel.SequencePoint seqPoint = new jalview.datamodel.SequencePoint(
6330 seqPoints.add(seqPoint);
6332 panel.getRotatableCanvas().setPoints(seqPoints, seqPoints.size());
6335 * set min-max ranges and scale after setPoints (which recomputes them)
6337 panel.getRotatableCanvas().setScaleFactor(viewer.getScaleFactor());
6338 SeqPointMin spMin = viewer.getSeqPointMin();
6339 float[] min = new float[] { spMin.getXPos(), spMin.getYPos(),
6341 SeqPointMax spMax = viewer.getSeqPointMax();
6342 float[] max = new float[] { spMax.getXPos(), spMax.getYPos(),
6344 panel.getRotatableCanvas().setSeqMinMax(min, max);
6346 // todo: hold points list in PCAModel only
6347 panel.getPcaModel().setSequencePoints(seqPoints);
6349 panel.setSelectedDimensionIndex(viewer.getXDim(), X);
6350 panel.setSelectedDimensionIndex(viewer.getYDim(), Y);
6351 panel.setSelectedDimensionIndex(viewer.getZDim(), Z);
6353 // is this duplication needed?
6354 panel.setTop(seqPoints.size() - 1);
6355 panel.getPcaModel().setTop(seqPoints.size() - 1);
6358 * add the axes' end points for the display
6360 for (int i = 0; i < 3; i++)
6362 Axis axis = viewer.getAxis().get(i);
6363 panel.getRotatableCanvas().getAxisEndPoints()[i] = new Point(
6364 axis.getXPos(), axis.getYPos(), axis.getZPos());
6367 Desktop.addInternalFrame(panel, MessageManager.formatMessage(
6368 "label.calc_title", "PCA", modelName), 475, 450);
6370 } catch (Exception ex)
6372 Cache.log.error("Error loading PCA: " + ex.toString());
6377 * Populates an XML model of the feature colour scheme for one feature type
6379 * @param featureType
6383 public static Colour marshalColour(
6384 String featureType, FeatureColourI fcol)
6386 Colour col = new Colour();
6387 if (fcol.isSimpleColour())
6389 col.setRGB(Format.getHexString(fcol.getColour()));
6393 col.setRGB(Format.getHexString(fcol.getMaxColour()));
6394 col.setMin(fcol.getMin());
6395 col.setMax(fcol.getMax());
6396 col.setMinRGB(jalview.util.Format.getHexString(fcol.getMinColour()));
6397 col.setAutoScale(fcol.isAutoScaled());
6398 col.setThreshold(fcol.getThreshold());
6399 col.setColourByLabel(fcol.isColourByLabel());
6400 col.setThreshType(fcol.isAboveThreshold() ? ThresholdType.ABOVE
6401 : (fcol.isBelowThreshold() ? ThresholdType.BELOW
6402 : ThresholdType.NONE));
6403 if (fcol.isColourByAttribute())
6405 final String[] attName = fcol.getAttributeName();
6406 col.getAttributeName().add(attName[0]);
6407 if (attName.length > 1)
6409 col.getAttributeName().add(attName[1]);
6412 Color noColour = fcol.getNoColour();
6413 if (noColour == null)
6415 col.setNoValueColour(NoValueColour.NONE);
6417 else if (noColour == fcol.getMaxColour())
6419 col.setNoValueColour(NoValueColour.MAX);
6423 col.setNoValueColour(NoValueColour.MIN);
6426 col.setName(featureType);
6431 * Populates an XML model of the feature filter(s) for one feature type
6433 * @param firstMatcher
6434 * the first (or only) match condition)
6436 * remaining match conditions (if any)
6438 * if true, conditions are and-ed, else or-ed
6440 public static jalview.xml.binding.jalview.FeatureMatcherSet marshalFilter(
6441 FeatureMatcherI firstMatcher, Iterator<FeatureMatcherI> filters,
6444 jalview.xml.binding.jalview.FeatureMatcherSet result = new jalview.xml.binding.jalview.FeatureMatcherSet();
6446 if (filters.hasNext())
6451 CompoundMatcher compound = new CompoundMatcher();
6452 compound.setAnd(and);
6453 jalview.xml.binding.jalview.FeatureMatcherSet matcher1 = marshalFilter(
6454 firstMatcher, Collections.emptyIterator(), and);
6455 // compound.addMatcherSet(matcher1);
6456 compound.getMatcherSet().add(matcher1);
6457 FeatureMatcherI nextMatcher = filters.next();
6458 jalview.xml.binding.jalview.FeatureMatcherSet matcher2 = marshalFilter(
6459 nextMatcher, filters, and);
6460 // compound.addMatcherSet(matcher2);
6461 compound.getMatcherSet().add(matcher2);
6462 result.setCompoundMatcher(compound);
6467 * single condition matcher
6469 // MatchCondition matcherModel = new MatchCondition();
6470 jalview.xml.binding.jalview.FeatureMatcher matcherModel = new jalview.xml.binding.jalview.FeatureMatcher();
6471 matcherModel.setCondition(
6472 firstMatcher.getMatcher().getCondition().getStableName());
6473 matcherModel.setValue(firstMatcher.getMatcher().getPattern());
6474 if (firstMatcher.isByAttribute())
6476 matcherModel.setBy(FilterBy.BY_ATTRIBUTE);
6477 // matcherModel.setAttributeName(firstMatcher.getAttribute());
6478 String[] attName = firstMatcher.getAttribute();
6479 matcherModel.getAttributeName().add(attName[0]); // attribute
6480 if (attName.length > 1)
6482 matcherModel.getAttributeName().add(attName[1]); // sub-attribute
6485 else if (firstMatcher.isByLabel())
6487 matcherModel.setBy(FilterBy.BY_LABEL);
6489 else if (firstMatcher.isByScore())
6491 matcherModel.setBy(FilterBy.BY_SCORE);
6493 result.setMatchCondition(matcherModel);
6500 * Loads one XML model of a feature filter to a Jalview object
6502 * @param featureType
6503 * @param matcherSetModel
6506 public static FeatureMatcherSetI parseFilter(
6508 jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel)
6510 FeatureMatcherSetI result = new FeatureMatcherSet();
6513 parseFilterConditions(result, matcherSetModel, true);
6514 } catch (IllegalStateException e)
6516 // mixing AND and OR conditions perhaps
6518 String.format("Error reading filter conditions for '%s': %s",
6519 featureType, e.getMessage()));
6520 // return as much as was parsed up to the error
6527 * Adds feature match conditions to matcherSet as unmarshalled from XML
6528 * (possibly recursively for compound conditions)
6531 * @param matcherSetModel
6533 * if true, multiple conditions are AND-ed, else they are OR-ed
6534 * @throws IllegalStateException
6535 * if AND and OR conditions are mixed
6537 protected static void parseFilterConditions(
6538 FeatureMatcherSetI matcherSet,
6539 jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel,
6542 jalview.xml.binding.jalview.FeatureMatcher mc = matcherSetModel
6543 .getMatchCondition();
6549 FilterBy filterBy = mc.getBy();
6550 Condition cond = Condition.fromString(mc.getCondition());
6551 String pattern = mc.getValue();
6552 FeatureMatcherI matchCondition = null;
6553 if (filterBy == FilterBy.BY_LABEL)
6555 matchCondition = FeatureMatcher.byLabel(cond, pattern);
6557 else if (filterBy == FilterBy.BY_SCORE)
6559 matchCondition = FeatureMatcher.byScore(cond, pattern);
6562 else if (filterBy == FilterBy.BY_ATTRIBUTE)
6564 final List<String> attributeName = mc.getAttributeName();
6565 String[] attNames = attributeName
6566 .toArray(new String[attributeName.size()]);
6567 matchCondition = FeatureMatcher.byAttribute(cond, pattern,
6572 * note this throws IllegalStateException if AND-ing to a
6573 * previously OR-ed compound condition, or vice versa
6577 matcherSet.and(matchCondition);
6581 matcherSet.or(matchCondition);
6587 * compound condition
6589 List<jalview.xml.binding.jalview.FeatureMatcherSet> matchers = matcherSetModel
6590 .getCompoundMatcher().getMatcherSet();
6591 boolean anded = matcherSetModel.getCompoundMatcher().isAnd();
6592 if (matchers.size() == 2)
6594 parseFilterConditions(matcherSet, matchers.get(0), anded);
6595 parseFilterConditions(matcherSet, matchers.get(1), anded);
6599 System.err.println("Malformed compound filter condition");
6605 * Loads one XML model of a feature colour to a Jalview object
6607 * @param colourModel
6610 public static FeatureColourI parseColour(Colour colourModel)
6612 FeatureColourI colour = null;
6614 if (colourModel.getMax() != null)
6616 Color mincol = null;
6617 Color maxcol = null;
6618 Color noValueColour = null;
6622 mincol = new Color(Integer.parseInt(colourModel.getMinRGB(), 16));
6623 maxcol = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6624 } catch (Exception e)
6626 if (Cache.log != null)
6628 Cache.log.warn("Couldn't parse out graduated feature color.", e);
6632 NoValueColour noCol = colourModel.getNoValueColour();
6633 if (noCol == NoValueColour.MIN)
6635 noValueColour = mincol;
6637 else if (noCol == NoValueColour.MAX)
6639 noValueColour = maxcol;
6642 colour = new FeatureColour(maxcol, mincol, maxcol, noValueColour,
6643 safeFloat(colourModel.getMin()),
6644 safeFloat(colourModel.getMax()));
6645 final List<String> attributeName = colourModel.getAttributeName();
6646 String[] attributes = attributeName
6647 .toArray(new String[attributeName.size()]);
6648 if (attributes != null && attributes.length > 0)
6650 colour.setAttributeName(attributes);
6652 if (colourModel.isAutoScale() != null)
6654 colour.setAutoScaled(colourModel.isAutoScale().booleanValue());
6656 if (colourModel.isColourByLabel() != null)
6658 colour.setColourByLabel(
6659 colourModel.isColourByLabel().booleanValue());
6661 if (colourModel.getThreshold() != null)
6663 colour.setThreshold(colourModel.getThreshold().floatValue());
6665 ThresholdType ttyp = colourModel.getThreshType();
6666 if (ttyp == ThresholdType.ABOVE)
6668 colour.setAboveThreshold(true);
6670 else if (ttyp == ThresholdType.BELOW)
6672 colour.setBelowThreshold(true);
6677 Color color = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6678 colour = new FeatureColour(color);