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.getIgnoreGapsConsensus());
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()))
2128 "Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
2129 + pdbentry.getFile());
2133 // can get at it if the ID
2134 // match is ambiguous (e.g.
2137 for (int smap = 0; smap < viewFrame.getBinding()
2138 .getSequence()[peid].length; smap++)
2140 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
2141 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
2143 StructureState state = new StructureState();
2144 state.setVisible(true);
2145 state.setXpos(viewFrame.getX());
2146 state.setYpos(viewFrame.getY());
2147 state.setWidth(viewFrame.getWidth());
2148 state.setHeight(viewFrame.getHeight());
2149 final String viewId = viewFrame.getViewId();
2150 state.setViewId(viewId);
2151 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
2152 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
2153 state.setColourByJmol(viewFrame.isColouredByViewer());
2154 state.setType(viewFrame.getViewerType().toString());
2155 // pdb.addStructureState(state);
2156 pdb.getStructureState().add(state);
2164 * Populates the AnnotationColourScheme xml for save. This captures the
2165 * settings of the options in the 'Colour by Annotation' dialog.
2168 * @param userColours
2172 private AnnotationColourScheme constructAnnotationColours(
2173 AnnotationColourGradient acg, List<UserColourScheme> userColours,
2176 AnnotationColourScheme ac = new AnnotationColourScheme();
2177 ac.setAboveThreshold(acg.getAboveThreshold());
2178 ac.setThreshold(acg.getAnnotationThreshold());
2179 // 2.10.2 save annotationId (unique) not annotation label
2180 ac.setAnnotation(acg.getAnnotation().annotationId);
2181 if (acg.getBaseColour() instanceof UserColourScheme)
2184 setUserColourScheme(acg.getBaseColour(), userColours, jm));
2189 ColourSchemeProperty.getColourName(acg.getBaseColour()));
2192 ac.setMaxColour(acg.getMaxColour().getRGB());
2193 ac.setMinColour(acg.getMinColour().getRGB());
2194 ac.setPerSequence(acg.isSeqAssociated());
2195 ac.setPredefinedColours(acg.isPredefinedColours());
2199 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
2200 IdentityHashMap<SequenceGroup, String> groupRefs,
2201 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
2202 SequenceSet vamsasSet)
2205 for (int i = 0; i < aa.length; i++)
2207 Annotation an = new Annotation();
2209 AlignmentAnnotation annotation = aa[i];
2210 if (annotation.annotationId != null)
2212 annotationIds.put(annotation.annotationId, annotation);
2215 an.setId(annotation.annotationId);
2217 an.setVisible(annotation.visible);
2219 an.setDescription(annotation.description);
2221 if (annotation.sequenceRef != null)
2223 // 2.9 JAL-1781 xref on sequence id rather than name
2224 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
2226 if (annotation.groupRef != null)
2228 String groupIdr = groupRefs.get(annotation.groupRef);
2229 if (groupIdr == null)
2231 // make a locally unique String
2232 groupRefs.put(annotation.groupRef,
2233 groupIdr = ("" + System.currentTimeMillis()
2234 + annotation.groupRef.getName()
2235 + groupRefs.size()));
2237 an.setGroupRef(groupIdr.toString());
2240 // store all visualization attributes for annotation
2241 an.setGraphHeight(annotation.graphHeight);
2242 an.setCentreColLabels(annotation.centreColLabels);
2243 an.setScaleColLabels(annotation.scaleColLabel);
2244 an.setShowAllColLabels(annotation.showAllColLabels);
2245 an.setBelowAlignment(annotation.belowAlignment);
2247 if (annotation.graph > 0)
2250 an.setGraphType(annotation.graph);
2251 an.setGraphGroup(annotation.graphGroup);
2252 if (annotation.getThreshold() != null)
2254 ThresholdLine line = new ThresholdLine();
2255 line.setLabel(annotation.getThreshold().label);
2256 line.setValue(annotation.getThreshold().value);
2257 line.setColour(annotation.getThreshold().colour.getRGB());
2258 an.setThresholdLine(line);
2266 an.setLabel(annotation.label);
2268 if (annotation == av.getAlignmentQualityAnnot()
2269 || annotation == av.getAlignmentConservationAnnotation()
2270 || annotation == av.getAlignmentConsensusAnnotation()
2271 || annotation.autoCalculated)
2273 // new way of indicating autocalculated annotation -
2274 an.setAutoCalculated(annotation.autoCalculated);
2276 if (annotation.hasScore())
2278 an.setScore(annotation.getScore());
2281 if (annotation.getCalcId() != null)
2283 calcIdSet.add(annotation.getCalcId());
2284 an.setCalcId(annotation.getCalcId());
2286 if (annotation.hasProperties())
2288 for (String pr : annotation.getProperties())
2290 jalview.xml.binding.jalview.Annotation.Property prop = new jalview.xml.binding.jalview.Annotation.Property();
2292 prop.setValue(annotation.getProperty(pr));
2293 // an.addProperty(prop);
2294 an.getProperty().add(prop);
2298 AnnotationElement ae;
2299 if (annotation.annotations != null)
2301 an.setScoreOnly(false);
2302 for (int a = 0; a < annotation.annotations.length; a++)
2304 if ((annotation == null) || (annotation.annotations[a] == null))
2309 ae = new AnnotationElement();
2310 if (annotation.annotations[a].description != null)
2312 ae.setDescription(annotation.annotations[a].description);
2314 if (annotation.annotations[a].displayCharacter != null)
2316 ae.setDisplayCharacter(
2317 annotation.annotations[a].displayCharacter);
2320 if (!Float.isNaN(annotation.annotations[a].value))
2322 ae.setValue(annotation.annotations[a].value);
2326 if (annotation.annotations[a].secondaryStructure > ' ')
2328 ae.setSecondaryStructure(
2329 annotation.annotations[a].secondaryStructure + "");
2332 if (annotation.annotations[a].colour != null
2333 && annotation.annotations[a].colour != java.awt.Color.black)
2335 ae.setColour(annotation.annotations[a].colour.getRGB());
2338 // an.addAnnotationElement(ae);
2339 an.getAnnotationElement().add(ae);
2340 if (annotation.autoCalculated)
2342 // only write one non-null entry into the annotation row -
2343 // sufficient to get the visualization attributes necessary to
2351 an.setScoreOnly(true);
2353 if (!storeDS || (storeDS && !annotation.autoCalculated))
2355 // skip autocalculated annotation - these are only provided for
2357 // vamsasSet.addAnnotation(an);
2358 vamsasSet.getAnnotation().add(an);
2364 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
2366 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
2367 if (settings != null)
2369 CalcIdParam vCalcIdParam = new CalcIdParam();
2370 vCalcIdParam.setCalcId(calcId);
2371 // vCalcIdParam.addServiceURL(settings.getServiceURI());
2372 vCalcIdParam.getServiceURL().add(settings.getServiceURI());
2373 // generic URI allowing a third party to resolve another instance of the
2374 // service used for this calculation
2375 for (String url : settings.getServiceURLs())
2377 // vCalcIdParam.addServiceURL(urls);
2378 vCalcIdParam.getServiceURL().add(url);
2380 vCalcIdParam.setVersion("1.0");
2381 if (settings.getPreset() != null)
2383 WsParamSetI setting = settings.getPreset();
2384 vCalcIdParam.setName(setting.getName());
2385 vCalcIdParam.setDescription(setting.getDescription());
2389 vCalcIdParam.setName("");
2390 vCalcIdParam.setDescription("Last used parameters");
2392 // need to be able to recover 1) settings 2) user-defined presets or
2393 // recreate settings from preset 3) predefined settings provided by
2394 // service - or settings that can be transferred (or discarded)
2395 vCalcIdParam.setParameters(
2396 settings.getWsParamFile().replace("\n", "|\\n|"));
2397 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
2398 // todo - decide if updateImmediately is needed for any projects.
2400 return vCalcIdParam;
2405 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
2408 if (calcIdParam.getVersion().equals("1.0"))
2410 final String[] calcIds = calcIdParam.getServiceURL().toArray(new String[0]);
2411 Jws2Instance service = Jws2Discoverer.getDiscoverer()
2412 .getPreferredServiceFor(calcIds);
2413 if (service != null)
2415 WsParamSetI parmSet = null;
2418 parmSet = service.getParamStore().parseServiceParameterFile(
2419 calcIdParam.getName(), calcIdParam.getDescription(),
2421 calcIdParam.getParameters().replace("|\\n|", "\n"));
2422 } catch (IOException x)
2424 warn("Couldn't parse parameter data for "
2425 + calcIdParam.getCalcId(), x);
2428 List<ArgumentI> argList = null;
2429 if (calcIdParam.getName().length() > 0)
2431 parmSet = service.getParamStore()
2432 .getPreset(calcIdParam.getName());
2433 if (parmSet != null)
2435 // TODO : check we have a good match with settings in AACon -
2436 // otherwise we'll need to create a new preset
2441 argList = parmSet.getArguments();
2444 AAConSettings settings = new AAConSettings(
2445 calcIdParam.isAutoUpdate(), service, parmSet, argList);
2446 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
2447 calcIdParam.isNeedsUpdate());
2452 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
2456 throw new Error(MessageManager.formatMessage(
2457 "error.unsupported_version_calcIdparam", new Object[]
2458 { calcIdParam.toString() }));
2462 * External mapping between jalview objects and objects yielding a valid and
2463 * unique object ID string. This is null for normal Jalview project IO, but
2464 * non-null when a jalview project is being read or written as part of a
2467 IdentityHashMap jv2vobj = null;
2470 * Construct a unique ID for jvobj using either existing bindings or if none
2471 * exist, the result of the hashcode call for the object.
2474 * jalview data object
2475 * @return unique ID for referring to jvobj
2477 private String makeHashCode(Object jvobj, String altCode)
2479 if (jv2vobj != null)
2481 Object id = jv2vobj.get(jvobj);
2484 return id.toString();
2486 // check string ID mappings
2487 if (jvids2vobj != null && jvobj instanceof String)
2489 id = jvids2vobj.get(jvobj);
2493 return id.toString();
2495 // give up and warn that something has gone wrong
2496 warn("Cannot find ID for object in external mapping : " + jvobj);
2502 * return local jalview object mapped to ID, if it exists
2506 * @return null or object bound to idcode
2508 private Object retrieveExistingObj(String idcode)
2510 if (idcode != null && vobj2jv != null)
2512 return vobj2jv.get(idcode);
2518 * binding from ID strings from external mapping table to jalview data model
2521 private Hashtable vobj2jv;
2523 private Sequence createVamsasSequence(String id, SequenceI jds)
2525 return createVamsasSequence(true, id, jds, null);
2528 private Sequence createVamsasSequence(boolean recurse, String id,
2529 SequenceI jds, SequenceI parentseq)
2531 Sequence vamsasSeq = new Sequence();
2532 vamsasSeq.setId(id);
2533 vamsasSeq.setName(jds.getName());
2534 vamsasSeq.setSequence(jds.getSequenceAsString());
2535 vamsasSeq.setDescription(jds.getDescription());
2536 jalview.datamodel.DBRefEntry[] dbrefs = null;
2537 if (jds.getDatasetSequence() != null)
2539 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
2543 // seqId==dsseqid so we can tell which sequences really are
2544 // dataset sequences only
2545 vamsasSeq.setDsseqid(id);
2546 dbrefs = jds.getDBRefs();
2547 if (parentseq == null)
2554 for (int d = 0; d < dbrefs.length; d++)
2556 DBRef dbref = new DBRef();
2557 dbref.setSource(dbrefs[d].getSource());
2558 dbref.setVersion(dbrefs[d].getVersion());
2559 dbref.setAccessionId(dbrefs[d].getAccessionId());
2560 if (dbrefs[d].hasMap())
2562 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
2564 dbref.setMapping(mp);
2566 // vamsasSeq.addDBRef(dbref);
2567 vamsasSeq.getDBRef().add(dbref);
2573 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
2574 SequenceI parentseq, SequenceI jds, boolean recurse)
2577 if (jmp.getMap() != null)
2581 jalview.util.MapList mlst = jmp.getMap();
2582 List<int[]> r = mlst.getFromRanges();
2583 for (int[] range : r)
2585 MapListFrom mfrom = new MapListFrom();
2586 mfrom.setStart(range[0]);
2587 mfrom.setEnd(range[1]);
2588 // mp.addMapListFrom(mfrom);
2589 mp.getMapListFrom().add(mfrom);
2591 r = mlst.getToRanges();
2592 for (int[] range : r)
2594 MapListTo mto = new MapListTo();
2595 mto.setStart(range[0]);
2596 mto.setEnd(range[1]);
2597 // mp.addMapListTo(mto);
2598 mp.getMapListTo().add(mto);
2600 mp.setMapFromUnit(BigInteger.valueOf(mlst.getFromRatio()));
2601 mp.setMapToUnit(BigInteger.valueOf(mlst.getToRatio()));
2602 if (jmp.getTo() != null)
2604 // MappingChoice mpc = new MappingChoice();
2606 // check/create ID for the sequence referenced by getTo()
2609 SequenceI ps = null;
2610 if (parentseq != jmp.getTo()
2611 && parentseq.getDatasetSequence() != jmp.getTo())
2613 // chaining dbref rather than a handshaking one
2614 jmpid = seqHash(ps = jmp.getTo());
2618 jmpid = seqHash(ps = parentseq);
2620 // mpc.setDseqFor(jmpid);
2621 mp.setDseqFor(jmpid);
2622 if (!seqRefIds.containsKey(jmpid))
2624 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2625 seqRefIds.put(jmpid, ps);
2629 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2632 // mp.setMappingChoice(mpc);
2638 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2639 List<UserColourScheme> userColours, JalviewModel jm)
2642 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2643 boolean newucs = false;
2644 if (!userColours.contains(ucs))
2646 userColours.add(ucs);
2649 id = "ucs" + userColours.indexOf(ucs);
2652 // actually create the scheme's entry in the XML model
2653 java.awt.Color[] colours = ucs.getColours();
2654 UserColours uc = new UserColours();
2655 // UserColourScheme jbucs = new UserColourScheme();
2656 JalviewUserColours jbucs = new JalviewUserColours();
2658 for (int i = 0; i < colours.length; i++)
2660 Colour col = new Colour();
2661 col.setName(ResidueProperties.aa[i]);
2662 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2663 // jbucs.addColour(col);
2664 jbucs.getColour().add(col);
2666 if (ucs.getLowerCaseColours() != null)
2668 colours = ucs.getLowerCaseColours();
2669 for (int i = 0; i < colours.length; i++)
2671 Colour col = new Colour();
2672 col.setName(ResidueProperties.aa[i].toLowerCase());
2673 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2674 // jbucs.addColour(col);
2675 jbucs.getColour().add(col);
2680 uc.setUserColourScheme(jbucs);
2681 // jm.addUserColours(uc);
2682 jm.getUserColours().add(uc);
2688 jalview.schemes.UserColourScheme getUserColourScheme(
2689 JalviewModel jm, String id)
2691 List<UserColours> uc = jm.getUserColours();
2692 UserColours colours = null;
2694 for (int i = 0; i < uc.length; i++)
2696 if (uc[i].getId().equals(id))
2703 for (UserColours c : uc)
2705 if (c.getId().equals(id))
2712 java.awt.Color[] newColours = new java.awt.Color[24];
2714 for (int i = 0; i < 24; i++)
2716 newColours[i] = new java.awt.Color(Integer.parseInt(
2717 // colours.getUserColourScheme().getColour(i).getRGB(), 16));
2718 colours.getUserColourScheme().getColour().get(i).getRGB(),
2722 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2725 if (colours.getUserColourScheme().getColour().size()/*Count()*/ > 24)
2727 newColours = new java.awt.Color[23];
2728 for (int i = 0; i < 23; i++)
2730 newColours[i] = new java.awt.Color(Integer.parseInt(
2731 colours.getUserColourScheme().getColour().get(i + 24)
2735 ucs.setLowerCaseColours(newColours);
2742 * contains last error message (if any) encountered by XML loader.
2744 String errorMessage = null;
2747 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2748 * exceptions are raised during project XML parsing
2750 public boolean attemptversion1parse = false;
2753 * Load a jalview project archive from a jar file
2756 * - HTTP URL or filename
2758 public AlignFrame loadJalviewAlign(final String file)
2761 jalview.gui.AlignFrame af = null;
2765 // create list to store references for any new Jmol viewers created
2766 newStructureViewers = new Vector<>();
2767 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2768 // Workaround is to make sure caller implements the JarInputStreamProvider
2770 // so we can re-open the jar input stream for each entry.
2772 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2773 af = loadJalviewAlign(jprovider);
2776 af.setMenusForViewport();
2778 } catch (MalformedURLException e)
2780 errorMessage = "Invalid URL format for '" + file + "'";
2786 SwingUtilities.invokeAndWait(new Runnable()
2791 setLoadingFinishedForNewStructureViewers();
2794 } catch (Exception x)
2796 System.err.println("Error loading alignment: " + x.getMessage());
2802 private jarInputStreamProvider createjarInputStreamProvider(
2803 final String file) throws MalformedURLException
2806 errorMessage = null;
2807 uniqueSetSuffix = null;
2809 viewportsAdded.clear();
2810 frefedSequence = null;
2812 if (file.startsWith("http://"))
2814 url = new URL(file);
2816 final URL _url = url;
2817 return new jarInputStreamProvider()
2821 public JarInputStream getJarInputStream() throws IOException
2825 return new JarInputStream(_url.openStream());
2829 return new JarInputStream(new FileInputStream(file));
2834 public String getFilename()
2842 * Recover jalview session from a jalview project archive. Caller may
2843 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2844 * themselves. Any null fields will be initialised with default values,
2845 * non-null fields are left alone.
2850 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2852 errorMessage = null;
2853 if (uniqueSetSuffix == null)
2855 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2857 if (seqRefIds == null)
2861 AlignFrame af = null, _af = null;
2862 IdentityHashMap<AlignmentI, AlignmentI> importedDatasets = new IdentityHashMap<>();
2863 Map<String, AlignFrame> gatherToThisFrame = new HashMap<>();
2864 final String file = jprovider.getFilename();
2867 JarInputStream jin = null;
2868 JarEntry jarentry = null;
2873 jin = jprovider.getJarInputStream();
2874 for (int i = 0; i < entryCount; i++)
2876 jarentry = jin.getNextJarEntry();
2879 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2881 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2882 // JalviewModel object = new JalviewModel();
2884 JAXBContext jc = JAXBContext
2885 .newInstance("jalview.xml.binding.jalview");
2886 XMLStreamReader streamReader = XMLInputFactory.newInstance()
2887 .createXMLStreamReader(jin);
2888 javax.xml.bind.Unmarshaller um = jc.createUnmarshaller();
2889 JAXBElement<JalviewModel> jbe = um
2890 .unmarshal(streamReader, JalviewModel.class);
2891 JalviewModel object = jbe.getValue();
2894 Unmarshaller unmar = new Unmarshaller(object);
2895 unmar.setValidation(false);
2896 object = (JalviewModel) unmar.unmarshal(in);
2898 if (true) // !skipViewport(object))
2900 _af = loadFromObject(object, file, true, jprovider);
2901 if (_af != null && object.getViewport().size() > 0)
2902 // getJalviewModelSequence().getViewportCount() > 0)
2906 // store a reference to the first view
2909 if (_af.getViewport().isGatherViewsHere())
2911 // if this is a gathered view, keep its reference since
2912 // after gathering views, only this frame will remain
2914 gatherToThisFrame.put(_af.getViewport().getSequenceSetId(),
2917 // Save dataset to register mappings once all resolved
2918 importedDatasets.put(
2919 af.getViewport().getAlignment().getDataset(),
2920 af.getViewport().getAlignment().getDataset());
2925 else if (jarentry != null)
2927 // Some other file here.
2930 } while (jarentry != null);
2931 resolveFrefedSequences();
2932 } catch (IOException ex)
2934 ex.printStackTrace();
2935 errorMessage = "Couldn't locate Jalview XML file : " + file;
2937 "Exception whilst loading jalview XML file : " + ex + "\n");
2938 } catch (Exception ex)
2940 System.err.println("Parsing as Jalview Version 2 file failed.");
2941 ex.printStackTrace(System.err);
2942 if (attemptversion1parse)
2944 // used to attempt to parse as V1 castor-generated xml
2946 if (Desktop.instance != null)
2948 Desktop.instance.stopLoading();
2952 System.out.println("Successfully loaded archive file");
2955 ex.printStackTrace();
2958 "Exception whilst loading jalview XML file : " + ex + "\n");
2959 } catch (OutOfMemoryError e)
2961 // Don't use the OOM Window here
2962 errorMessage = "Out of memory loading jalview XML file";
2963 System.err.println("Out of memory whilst loading jalview XML file");
2964 e.printStackTrace();
2968 * Regather multiple views (with the same sequence set id) to the frame (if
2969 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2970 * views instead of separate frames. Note this doesn't restore a state where
2971 * some expanded views in turn have tabbed views - the last "first tab" read
2972 * in will play the role of gatherer for all.
2974 for (AlignFrame fr : gatherToThisFrame.values())
2976 Desktop.instance.gatherViews(fr);
2979 restoreSplitFrames();
2980 for (AlignmentI ds : importedDatasets.keySet())
2982 if (ds.getCodonFrames() != null)
2984 StructureSelectionManager
2985 .getStructureSelectionManager(Desktop.instance)
2986 .registerMappings(ds.getCodonFrames());
2989 if (errorMessage != null)
2994 if (Desktop.instance != null)
2996 Desktop.instance.stopLoading();
3003 * Try to reconstruct and display SplitFrame windows, where each contains
3004 * complementary dna and protein alignments. Done by pairing up AlignFrame
3005 * objects (created earlier) which have complementary viewport ids associated.
3007 protected void restoreSplitFrames()
3009 List<SplitFrame> gatherTo = new ArrayList<>();
3010 List<AlignFrame> addedToSplitFrames = new ArrayList<>();
3011 Map<String, AlignFrame> dna = new HashMap<>();
3014 * Identify the DNA alignments
3016 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
3019 AlignFrame af = candidate.getValue();
3020 if (af.getViewport().getAlignment().isNucleotide())
3022 dna.put(candidate.getKey().getId(), af);
3027 * Try to match up the protein complements
3029 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
3032 AlignFrame af = candidate.getValue();
3033 if (!af.getViewport().getAlignment().isNucleotide())
3035 String complementId = candidate.getKey().getComplementId();
3036 // only non-null complements should be in the Map
3037 if (complementId != null && dna.containsKey(complementId))
3039 final AlignFrame dnaFrame = dna.get(complementId);
3040 SplitFrame sf = createSplitFrame(dnaFrame, af);
3041 addedToSplitFrames.add(dnaFrame);
3042 addedToSplitFrames.add(af);
3043 dnaFrame.setMenusForViewport();
3044 af.setMenusForViewport();
3045 if (af.getViewport().isGatherViewsHere())
3054 * Open any that we failed to pair up (which shouldn't happen!) as
3055 * standalone AlignFrame's.
3057 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
3060 AlignFrame af = candidate.getValue();
3061 if (!addedToSplitFrames.contains(af))
3063 Viewport view = candidate.getKey();
3064 Desktop.addInternalFrame(af, view.getTitle(),
3065 safeInt(view.getWidth()), safeInt(view.getHeight()));
3066 af.setMenusForViewport();
3067 System.err.println("Failed to restore view " + view.getTitle()
3068 + " to split frame");
3073 * Gather back into tabbed views as flagged.
3075 for (SplitFrame sf : gatherTo)
3077 Desktop.instance.gatherViews(sf);
3080 splitFrameCandidates.clear();
3084 * Construct and display one SplitFrame holding DNA and protein alignments.
3087 * @param proteinFrame
3090 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
3091 AlignFrame proteinFrame)
3093 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
3094 String title = MessageManager.getString("label.linked_view_title");
3095 int width = (int) dnaFrame.getBounds().getWidth();
3096 int height = (int) (dnaFrame.getBounds().getHeight()
3097 + proteinFrame.getBounds().getHeight() + 50);
3100 * SplitFrame location is saved to both enclosed frames
3102 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
3103 Desktop.addInternalFrame(splitFrame, title, width, height);
3106 * And compute cDNA consensus (couldn't do earlier with consensus as
3107 * mappings were not yet present)
3109 proteinFrame.getViewport().alignmentChanged(proteinFrame.alignPanel);
3115 * check errorMessage for a valid error message and raise an error box in the
3116 * GUI or write the current errorMessage to stderr and then clear the error
3119 protected void reportErrors()
3121 reportErrors(false);
3124 protected void reportErrors(final boolean saving)
3126 if (errorMessage != null)
3128 final String finalErrorMessage = errorMessage;
3131 javax.swing.SwingUtilities.invokeLater(new Runnable()
3136 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
3138 "Error " + (saving ? "saving" : "loading")
3140 JvOptionPane.WARNING_MESSAGE);
3146 System.err.println("Problem loading Jalview file: " + errorMessage);
3149 errorMessage = null;
3152 Map<String, String> alreadyLoadedPDB = new HashMap<>();
3155 * when set, local views will be updated from view stored in JalviewXML
3156 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
3157 * sync if this is set to true.
3159 private final boolean updateLocalViews = false;
3162 * Returns the path to a temporary file holding the PDB file for the given PDB
3163 * id. The first time of asking, searches for a file of that name in the
3164 * Jalview project jar, and copies it to a new temporary file. Any repeat
3165 * requests just return the path to the file previously created.
3171 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId,
3174 if (alreadyLoadedPDB.containsKey(pdbId))
3176 return alreadyLoadedPDB.get(pdbId).toString();
3179 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb",
3181 if (tempFile != null)
3183 alreadyLoadedPDB.put(pdbId, tempFile);
3189 * Copies the jar entry of given name to a new temporary file and returns the
3190 * path to the file, or null if the entry is not found.
3193 * @param jarEntryName
3195 * a prefix for the temporary file name, must be at least three
3198 * null or original file - so new file can be given the same suffix
3202 protected String copyJarEntry(jarInputStreamProvider jprovider,
3203 String jarEntryName, String prefix, String origFile)
3205 BufferedReader in = null;
3206 PrintWriter out = null;
3207 String suffix = ".tmp";
3208 if (origFile == null)
3210 origFile = jarEntryName;
3212 int sfpos = origFile.lastIndexOf(".");
3213 if (sfpos > -1 && sfpos < (origFile.length() - 3))
3215 suffix = "." + origFile.substring(sfpos + 1);
3219 JarInputStream jin = jprovider.getJarInputStream();
3221 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
3222 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
3223 * FileInputStream(jprovider)); }
3226 JarEntry entry = null;
3229 entry = jin.getNextJarEntry();
3230 } while (entry != null && !entry.getName().equals(jarEntryName));
3233 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
3234 File outFile = File.createTempFile(prefix, suffix);
3235 outFile.deleteOnExit();
3236 out = new PrintWriter(new FileOutputStream(outFile));
3239 while ((data = in.readLine()) != null)
3244 String t = outFile.getAbsolutePath();
3249 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
3251 } catch (Exception ex)
3253 ex.printStackTrace();
3261 } catch (IOException e)
3275 private class JvAnnotRow
3277 public JvAnnotRow(int i, AlignmentAnnotation jaa)
3284 * persisted version of annotation row from which to take vis properties
3286 public jalview.datamodel.AlignmentAnnotation template;
3289 * original position of the annotation row in the alignment
3295 * Load alignment frame from jalview XML DOM object
3297 * @param jalviewModel
3300 * filename source string
3301 * @param loadTreesAndStructures
3302 * when false only create Viewport
3304 * data source provider
3305 * @return alignment frame created from view stored in DOM
3307 AlignFrame loadFromObject(JalviewModel jalviewModel, String file,
3308 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
3310 SequenceSet vamsasSet = jalviewModel.getVamsasModel().getSequenceSet().get(0);
3311 List<Sequence> vamsasSeqs = vamsasSet.getSequence();
3313 // JalviewModelSequence jms = object.getJalviewModelSequence();
3315 // Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
3317 Viewport view = (jalviewModel.getViewport().size() > 0)
3318 ? jalviewModel.getViewport().get(0)
3321 // ////////////////////////////////
3322 // INITIALISE ALIGNMENT SEQUENCESETID AND VIEWID
3325 // If we just load in the same jar file again, the sequenceSetId
3326 // will be the same, and we end up with multiple references
3327 // to the same sequenceSet. We must modify this id on load
3328 // so that each load of the file gives a unique id
3331 * used to resolve correct alignment dataset for alignments with multiple
3334 String uniqueSeqSetId = null;
3335 String viewId = null;
3338 uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3339 viewId = (view.getId() == null ? null
3340 : view.getId() + uniqueSetSuffix);
3343 // ////////////////////////////////
3346 List<SequenceI> hiddenSeqs = null;
3348 List<SequenceI> tmpseqs = new ArrayList<>();
3350 boolean multipleView = false;
3351 SequenceI referenceseqForView = null;
3352 // JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
3353 List<JSeq> jseqs = jalviewModel.getJSeq();
3354 int vi = 0; // counter in vamsasSeq array
3355 for (int i = 0; i < jseqs.size(); i++)
3357 JSeq jseq = jseqs.get(i);
3358 String seqId = jseq.getId();
3360 SequenceI tmpSeq = seqRefIds.get(seqId);
3363 if (!incompleteSeqs.containsKey(seqId))
3365 // may not need this check, but keep it for at least 2.9,1 release
3366 if (tmpSeq.getStart() != jseq.getStart()
3367 || tmpSeq.getEnd() != jseq.getEnd())
3370 "Warning JAL-2154 regression: updating start/end for sequence "
3371 + tmpSeq.toString() + " to " + jseq);
3376 incompleteSeqs.remove(seqId);
3378 if (vamsasSeqs.size() > vi
3379 && vamsasSeqs.get(vi).getId().equals(seqId))
3381 // most likely we are reading a dataset XML document so
3382 // update from vamsasSeq section of XML for this sequence
3383 tmpSeq.setName(vamsasSeqs.get(vi).getName());
3384 tmpSeq.setDescription(vamsasSeqs.get(vi).getDescription());
3385 tmpSeq.setSequence(vamsasSeqs.get(vi).getSequence());
3390 // reading multiple views, so vamsasSeq set is a subset of JSeq
3391 multipleView = true;
3393 tmpSeq.setStart(jseq.getStart());
3394 tmpSeq.setEnd(jseq.getEnd());
3395 tmpseqs.add(tmpSeq);
3399 Sequence vamsasSeq = vamsasSeqs.get(vi);
3400 tmpSeq = new jalview.datamodel.Sequence(vamsasSeq.getName(),
3401 vamsasSeq.getSequence());
3402 tmpSeq.setDescription(vamsasSeq.getDescription());
3403 tmpSeq.setStart(jseq.getStart());
3404 tmpSeq.setEnd(jseq.getEnd());
3405 tmpSeq.setVamsasId(uniqueSetSuffix + seqId);
3406 seqRefIds.put(vamsasSeq.getId(), tmpSeq);
3407 tmpseqs.add(tmpSeq);
3411 if (safeBoolean(jseq.isViewreference()))
3413 referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
3416 if (jseq.isHidden() != null && jseq.isHidden().booleanValue())
3418 if (hiddenSeqs == null)
3420 hiddenSeqs = new ArrayList<>();
3423 hiddenSeqs.add(tmpSeq);
3428 // Create the alignment object from the sequence set
3429 // ///////////////////////////////
3430 SequenceI[] orderedSeqs = tmpseqs
3431 .toArray(new SequenceI[tmpseqs.size()]);
3433 AlignmentI al = null;
3434 // so we must create or recover the dataset alignment before going further
3435 // ///////////////////////////////
3436 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
3438 // older jalview projects do not have a dataset - so creat alignment and
3440 al = new Alignment(orderedSeqs);
3441 al.setDataset(null);
3445 boolean isdsal = jalviewModel.getViewport().isEmpty();
3448 // we are importing a dataset record, so
3449 // recover reference to an alignment already materialsed as dataset
3450 al = getDatasetFor(vamsasSet.getDatasetId());
3454 // materialse the alignment
3455 al = new Alignment(orderedSeqs);
3459 addDatasetRef(vamsasSet.getDatasetId(), al);
3462 // finally, verify all data in vamsasSet is actually present in al
3463 // passing on flag indicating if it is actually a stored dataset
3464 recoverDatasetFor(vamsasSet, al, isdsal, uniqueSeqSetId);
3467 if (referenceseqForView != null)
3469 al.setSeqrep(referenceseqForView);
3471 // / Add the alignment properties
3472 for (int i = 0; i < vamsasSet.getSequenceSetProperties().size(); i++)
3474 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties()
3476 al.setProperty(ssp.getKey(), ssp.getValue());
3479 // ///////////////////////////////
3481 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
3484 // load sequence features, database references and any associated PDB
3485 // structures for the alignment
3487 // prior to 2.10, this part would only be executed the first time a
3488 // sequence was encountered, but not afterwards.
3489 // now, for 2.10 projects, this is also done if the xml doc includes
3490 // dataset sequences not actually present in any particular view.
3492 for (int i = 0; i < vamsasSeqs.size(); i++)
3494 JSeq jseq = jseqs.get(i);
3495 if (jseq.getFeatures().size() > 0)
3497 List<Feature> features = jseq.getFeatures();
3498 for (int f = 0; f < features.size(); f++)
3500 Feature feat = features.get(f);
3501 SequenceFeature sf = new SequenceFeature(feat.getType(),
3502 feat.getDescription(), feat.getBegin(), feat.getEnd(),
3503 safeFloat(feat.getScore()), feat.getFeatureGroup());
3504 sf.setStatus(feat.getStatus());
3507 * load any feature attributes - include map-valued attributes
3509 Map<String, Map<String, String>> mapAttributes = new HashMap<>();
3510 for (int od = 0; od < feat.getOtherData().size(); od++)
3512 OtherData keyValue = feat.getOtherData().get(od);
3513 String attributeName = keyValue.getKey();
3514 String attributeValue = keyValue.getValue();
3515 if (attributeName.startsWith("LINK"))
3517 sf.addLink(attributeValue);
3521 String subAttribute = keyValue.getKey2();
3522 if (subAttribute == null)
3524 // simple string-valued attribute
3525 sf.setValue(attributeName, attributeValue);
3529 // attribute 'key' has sub-attribute 'key2'
3530 if (!mapAttributes.containsKey(attributeName))
3532 mapAttributes.put(attributeName, new HashMap<>());
3534 mapAttributes.get(attributeName).put(subAttribute,
3539 for (Entry<String, Map<String, String>> mapAttribute : mapAttributes
3542 sf.setValue(mapAttribute.getKey(), mapAttribute.getValue());
3545 // adds feature to datasequence's feature set (since Jalview 2.10)
3546 al.getSequenceAt(i).addSequenceFeature(sf);
3549 if (vamsasSeqs.get(i).getDBRef().size() > 0)
3551 // adds dbrefs to datasequence's set (since Jalview 2.10)
3553 al.getSequenceAt(i).getDatasetSequence() == null
3554 ? al.getSequenceAt(i)
3555 : al.getSequenceAt(i).getDatasetSequence(),
3558 if (jseq.getPdbids().size() > 0)
3560 List<Pdbids> ids = jseq.getPdbids();
3561 for (int p = 0; p < ids.size(); p++)
3563 Pdbids pdbid = ids.get(p);
3564 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
3565 entry.setId(pdbid.getId());
3566 if (pdbid.getType() != null)
3568 if (PDBEntry.Type.getType(pdbid.getType()) != null)
3570 entry.setType(PDBEntry.Type.getType(pdbid.getType()));
3574 entry.setType(PDBEntry.Type.FILE);
3577 // jprovider is null when executing 'New View'
3578 if (pdbid.getFile() != null && jprovider != null)
3580 if (!pdbloaded.containsKey(pdbid.getFile()))
3582 entry.setFile(loadPDBFile(jprovider, pdbid.getId(),
3587 entry.setFile(pdbloaded.get(pdbid.getId()).toString());
3591 if (pdbid.getPdbentryItem() != null)
3593 for (PdbentryItem item : pdbid.getPdbentryItem())
3595 for (Property pr : item.getProperty())
3597 entry.setProperty(pr.getName(), pr.getValue());
3602 for (Property prop : pdbid.getProperty())
3604 entry.setProperty(prop.getName(), prop.getValue());
3606 StructureSelectionManager
3607 .getStructureSelectionManager(Desktop.instance)
3608 .registerPDBEntry(entry);
3609 // adds PDBEntry to datasequence's set (since Jalview 2.10)
3610 if (al.getSequenceAt(i).getDatasetSequence() != null)
3612 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
3616 al.getSequenceAt(i).addPDBId(entry);
3622 * load any HMMER profile
3624 String hmmJarFile = jseqs.get(i).getHmmerProfile();
3625 if (hmmJarFile != null && jprovider != null)
3627 loadHmmerProfile(jprovider, hmmJarFile, al.getSequenceAt(i));
3630 } // end !multipleview
3632 // ///////////////////////////////
3633 // LOAD SEQUENCE MAPPINGS
3635 if (vamsasSet.getAlcodonFrame().size() > 0)
3637 // TODO Potentially this should only be done once for all views of an
3639 List<AlcodonFrame> alc = vamsasSet.getAlcodonFrame();
3640 for (int i = 0; i < alc.size(); i++)
3642 AlignedCodonFrame cf = new AlignedCodonFrame();
3643 if (alc.get(i).getAlcodMap().size() > 0)
3645 List<AlcodMap> maps = alc.get(i).getAlcodMap();
3646 for (int m = 0; m < maps.size(); m++)
3648 AlcodMap map = maps.get(m);
3649 SequenceI dnaseq = seqRefIds.get(map.getDnasq());
3651 jalview.datamodel.Mapping mapping = null;
3652 // attach to dna sequence reference.
3653 if (map.getMapping() != null)
3655 mapping = addMapping(map.getMapping());
3656 if (dnaseq != null && mapping.getTo() != null)
3658 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
3664 newAlcodMapRef(map.getDnasq(), cf, mapping));
3668 al.addCodonFrame(cf);
3673 // ////////////////////////////////
3675 List<JvAnnotRow> autoAlan = new ArrayList<>();
3678 * store any annotations which forward reference a group's ID
3680 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<>();
3682 if (vamsasSet.getAnnotation().size()/*Count()*/ > 0)
3684 List<Annotation> an = vamsasSet.getAnnotation();
3686 for (int i = 0; i < an.size(); i++)
3688 Annotation annotation = an.get(i);
3691 * test if annotation is automatically calculated for this view only
3693 boolean autoForView = false;
3694 if (annotation.getLabel().equals("Quality")
3695 || annotation.getLabel().equals("Conservation")
3696 || annotation.getLabel().equals("Consensus"))
3698 // Kludge for pre 2.5 projects which lacked the autocalculated flag
3700 // JAXB has no has() test; schema defaults value to false
3701 // if (!annotation.hasAutoCalculated())
3703 // annotation.setAutoCalculated(true);
3706 if (autoForView || annotation.isAutoCalculated())
3708 // remove ID - we don't recover annotation from other views for
3709 // view-specific annotation
3710 annotation.setId(null);
3713 // set visibility for other annotation in this view
3714 String annotationId = annotation.getId();
3715 if (annotationId != null && annotationIds.containsKey(annotationId))
3717 AlignmentAnnotation jda = annotationIds.get(annotationId);
3718 // in principle Visible should always be true for annotation displayed
3719 // in multiple views
3720 if (annotation.isVisible() != null)
3722 jda.visible = annotation.isVisible();
3725 al.addAnnotation(jda);
3729 // Construct new annotation from model.
3730 List<AnnotationElement> ae = annotation.getAnnotationElement();
3731 jalview.datamodel.Annotation[] anot = null;
3732 java.awt.Color firstColour = null;
3734 if (!annotation.isScoreOnly())
3736 anot = new jalview.datamodel.Annotation[al.getWidth()];
3737 for (int aa = 0; aa < ae.size() && aa < anot.length; aa++)
3739 AnnotationElement annElement = ae.get(aa);
3740 anpos = annElement.getPosition();
3742 if (anpos >= anot.length)
3747 float value = safeFloat(annElement.getValue());
3748 anot[anpos] = new jalview.datamodel.Annotation(
3749 annElement.getDisplayCharacter(),
3750 annElement.getDescription(),
3751 (annElement.getSecondaryStructure() == null
3752 || annElement.getSecondaryStructure()
3756 .getSecondaryStructure()
3759 anot[anpos].colour = new Color(safeInt(annElement.getColour()));
3760 if (firstColour == null)
3762 firstColour = anot[anpos].colour;
3766 jalview.datamodel.AlignmentAnnotation jaa = null;
3768 if (annotation.isGraph())
3770 float llim = 0, hlim = 0;
3771 // if (autoForView || an[i].isAutoCalculated()) {
3774 jaa = new jalview.datamodel.AlignmentAnnotation(
3775 annotation.getLabel(), annotation.getDescription(), anot,
3776 llim, hlim, safeInt(annotation.getGraphType()));
3778 jaa.graphGroup = safeInt(annotation.getGraphGroup());
3779 jaa._linecolour = firstColour;
3780 if (annotation.getThresholdLine() != null)
3782 jaa.setThreshold(new jalview.datamodel.GraphLine(
3783 safeFloat(annotation.getThresholdLine().getValue()),
3784 annotation.getThresholdLine().getLabel(),
3785 new java.awt.Color(safeInt(
3786 annotation.getThresholdLine().getColour()))));
3788 if (autoForView || annotation.isAutoCalculated())
3790 // Hardwire the symbol display line to ensure that labels for
3791 // histograms are displayed
3797 jaa = new jalview.datamodel.AlignmentAnnotation(
3798 annotation.getLabel(), annotation.getDescription(), anot);
3799 jaa._linecolour = firstColour;
3801 // register new annotation
3802 if (annotation.getId() != null)
3804 annotationIds.put(annotation.getId(), jaa);
3805 jaa.annotationId = annotation.getId();
3807 // recover sequence association
3808 String sequenceRef = annotation.getSequenceRef();
3809 if (sequenceRef != null)
3811 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3812 SequenceI sequence = seqRefIds.get(sequenceRef);
3813 if (sequence == null)
3815 // in pre-2.9 projects sequence ref is to sequence name
3816 sequence = al.findName(sequenceRef);
3818 if (sequence != null)
3820 jaa.createSequenceMapping(sequence, 1, true);
3821 sequence.addAlignmentAnnotation(jaa);
3824 // and make a note of any group association
3825 if (annotation.getGroupRef() != null
3826 && annotation.getGroupRef().length() > 0)
3828 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3829 .get(annotation.getGroupRef());
3832 aal = new ArrayList<>();
3833 groupAnnotRefs.put(annotation.getGroupRef(), aal);
3838 if (annotation.getScore() != null)
3840 jaa.setScore(annotation.getScore().doubleValue());
3842 if (annotation.isVisible() != null)
3844 jaa.visible = annotation.isVisible().booleanValue();
3847 if (annotation.isCentreColLabels() != null)
3849 jaa.centreColLabels = annotation.isCentreColLabels()
3853 if (annotation.isScaleColLabels() != null)
3855 jaa.scaleColLabel = annotation.isScaleColLabels().booleanValue();
3857 if (annotation.isAutoCalculated())
3859 // newer files have an 'autoCalculated' flag and store calculation
3860 // state in viewport properties
3861 jaa.autoCalculated = true; // means annotation will be marked for
3862 // update at end of load.
3864 if (annotation.getGraphHeight() != null)
3866 jaa.graphHeight = annotation.getGraphHeight().intValue();
3868 jaa.belowAlignment = annotation.isBelowAlignment();
3869 jaa.setCalcId(annotation.getCalcId());
3870 if (annotation.getProperty().size() > 0)
3872 for (Annotation.Property prop : annotation
3875 jaa.setProperty(prop.getName(), prop.getValue());
3878 if (jaa.autoCalculated)
3880 autoAlan.add(new JvAnnotRow(i, jaa));
3883 // if (!autoForView)
3885 // add autocalculated group annotation and any user created annotation
3887 al.addAnnotation(jaa);
3891 // ///////////////////////
3893 // Create alignment markup and styles for this view
3894 if (jalviewModel.getJGroup().size() > 0)
3896 List<JGroup> groups = jalviewModel.getJGroup();
3897 boolean addAnnotSchemeGroup = false;
3898 for (int i = 0; i < groups.size(); i++)
3900 JGroup jGroup = groups.get(i);
3901 ColourSchemeI cs = null;
3902 if (jGroup.getColour() != null)
3904 if (jGroup.getColour().startsWith("ucs"))
3906 cs = getUserColourScheme(jalviewModel, jGroup.getColour());
3908 else if (jGroup.getColour().equals("AnnotationColourGradient")
3909 && jGroup.getAnnotationColours() != null)
3911 addAnnotSchemeGroup = true;
3915 cs = ColourSchemeProperty.getColourScheme(null, al,
3916 jGroup.getColour());
3919 int pidThreshold = safeInt(jGroup.getPidThreshold());
3921 Vector<SequenceI> seqs = new Vector<>();
3923 for (int s = 0; s < jGroup.getSeq().size(); s++)
3925 String seqId = jGroup.getSeq().get(s);
3926 SequenceI ts = seqRefIds.get(seqId);
3930 seqs.addElement(ts);
3934 if (seqs.size() < 1)
3939 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3940 safeBoolean(jGroup.isDisplayBoxes()),
3941 safeBoolean(jGroup.isDisplayText()),
3942 safeBoolean(jGroup.isColourText()),
3943 safeInt(jGroup.getStart()), safeInt(jGroup.getEnd()));
3944 sg.getGroupColourScheme().setThreshold(pidThreshold, true);
3945 sg.getGroupColourScheme()
3946 .setConservationInc(safeInt(jGroup.getConsThreshold()));
3947 sg.setOutlineColour(new Color(safeInt(jGroup.getOutlineColour())));
3949 sg.textColour = new Color(safeInt(jGroup.getTextCol1()));
3950 sg.textColour2 = new Color(safeInt(jGroup.getTextCol2()));
3951 sg.setShowNonconserved(safeBoolean(jGroup.isShowUnconserved()));
3952 sg.thresholdTextColour = safeInt(jGroup.getTextColThreshold());
3953 // attributes with a default in the schema are never null
3954 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3955 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3956 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3957 sg.setIgnoreGapsConsensus(jGroup.isIgnoreGapsinConsensus());
3958 if (jGroup.getConsThreshold() != null
3959 && jGroup.getConsThreshold().intValue() != 0)
3961 Conservation c = new Conservation("All", sg.getSequences(null), 0,
3964 c.verdict(false, 25);
3965 sg.cs.setConservation(c);
3968 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3970 // re-instate unique group/annotation row reference
3971 List<AlignmentAnnotation> jaal = groupAnnotRefs
3972 .get(jGroup.getId());
3975 for (AlignmentAnnotation jaa : jaal)
3978 if (jaa.autoCalculated)
3980 // match up and try to set group autocalc alignment row for this
3982 if (jaa.label.startsWith("Consensus for "))
3984 sg.setConsensus(jaa);
3986 // match up and try to set group autocalc alignment row for this
3988 if (jaa.label.startsWith("Conservation for "))
3990 sg.setConservationRow(jaa);
3997 if (addAnnotSchemeGroup)
3999 // reconstruct the annotation colourscheme
4000 sg.setColourScheme(constructAnnotationColour(
4001 jGroup.getAnnotationColours(), null, al, jalviewModel, false));
4007 // only dataset in this model, so just return.
4010 // ///////////////////////////////
4013 AlignFrame af = null;
4014 AlignViewport av = null;
4015 // now check to see if we really need to create a new viewport.
4016 if (multipleView && viewportsAdded.size() == 0)
4018 // We recovered an alignment for which a viewport already exists.
4019 // TODO: fix up any settings necessary for overlaying stored state onto
4020 // state recovered from another document. (may not be necessary).
4021 // we may need a binding from a viewport in memory to one recovered from
4023 // and then recover its containing af to allow the settings to be applied.
4024 // TODO: fix for vamsas demo
4026 "About to recover a viewport for existing alignment: Sequence set ID is "
4028 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
4029 if (seqsetobj != null)
4031 if (seqsetobj instanceof String)
4033 uniqueSeqSetId = (String) seqsetobj;
4035 "Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
4041 "Warning : Collision between sequence set ID string and existing jalview object mapping.");
4047 * indicate that annotation colours are applied across all groups (pre
4048 * Jalview 2.8.1 behaviour)
4050 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan("2.8.1",
4051 jalviewModel.getVersion());
4053 AlignmentPanel ap = null;
4054 boolean isnewview = true;
4057 // Check to see if this alignment already has a view id == viewId
4058 jalview.gui.AlignmentPanel views[] = Desktop
4059 .getAlignmentPanels(uniqueSeqSetId);
4060 if (views != null && views.length > 0)
4062 for (int v = 0; v < views.length; v++)
4064 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
4066 // recover the existing alignpanel, alignframe, viewport
4067 af = views[v].alignFrame;
4070 // TODO: could even skip resetting view settings if we don't want to
4071 // change the local settings from other jalview processes
4080 af = loadViewport(file, jseqs, hiddenSeqs, al, jalviewModel, view,
4081 uniqueSeqSetId, viewId, autoAlan);
4082 av = af.getViewport();
4087 * Load any trees, PDB structures and viewers
4089 * Not done if flag is false (when this method is used for New View)
4091 if (loadTreesAndStructures)
4093 loadTrees(jalviewModel, view, af, av, ap);
4094 loadPCAViewers(jalviewModel, ap);
4095 loadPDBStructures(jprovider, jseqs, af, ap);
4096 loadRnaViewers(jprovider, jseqs, ap);
4098 // and finally return.
4103 * Loads a HMMER profile from a file stored in the project, and associates it
4104 * with the specified sequence
4110 protected void loadHmmerProfile(jarInputStreamProvider jprovider,
4111 String hmmJarFile, SequenceI seq)
4115 String hmmFile = copyJarEntry(jprovider, hmmJarFile, "hmm", null);
4116 HMMFile parser = new HMMFile(hmmFile, DataSourceType.FILE);
4117 HiddenMarkovModel hmmModel = parser.getHMM();
4118 hmmModel = new HiddenMarkovModel(hmmModel, seq);
4119 seq.setHMM(hmmModel);
4120 } catch (IOException e)
4122 warn("Error loading HMM profile for " + seq.getName() + ": "
4128 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
4129 * panel is restored from separate jar entries, two (gapped and trimmed) per
4130 * sequence and secondary structure.
4132 * Currently each viewer shows just one sequence and structure (gapped and
4133 * trimmed), however this method is designed to support multiple sequences or
4134 * structures in viewers if wanted in future.
4140 private void loadRnaViewers(jarInputStreamProvider jprovider,
4141 List<JSeq> jseqs, AlignmentPanel ap)
4144 * scan the sequences for references to viewers; create each one the first
4145 * time it is referenced, add Rna models to existing viewers
4147 for (JSeq jseq : jseqs)
4149 for (int i = 0; i < jseq.getRnaViewer().size(); i++)
4151 RnaViewer viewer = jseq.getRnaViewer().get(i);
4152 AppVarna appVarna = findOrCreateVarnaViewer(viewer, uniqueSetSuffix,
4155 for (int j = 0; j < viewer.getSecondaryStructure().size(); j++)
4157 SecondaryStructure ss = viewer.getSecondaryStructure().get(j);
4158 SequenceI seq = seqRefIds.get(jseq.getId());
4159 AlignmentAnnotation ann = this.annotationIds
4160 .get(ss.getAnnotationId());
4163 * add the structure to the Varna display (with session state copied
4164 * from the jar to a temporary file)
4166 boolean gapped = safeBoolean(ss.isGapped());
4167 String rnaTitle = ss.getTitle();
4168 String sessionState = ss.getViewerState();
4169 String tempStateFile = copyJarEntry(jprovider, sessionState,
4171 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
4172 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
4174 appVarna.setInitialSelection(safeInt(viewer.getSelectedRna()));
4180 * Locate and return an already instantiated matching AppVarna, or create one
4184 * @param viewIdSuffix
4188 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
4189 String viewIdSuffix, AlignmentPanel ap)
4192 * on each load a suffix is appended to the saved viewId, to avoid conflicts
4193 * if load is repeated
4195 String postLoadId = viewer.getViewId() + viewIdSuffix;
4196 for (JInternalFrame frame : getAllFrames())
4198 if (frame instanceof AppVarna)
4200 AppVarna varna = (AppVarna) frame;
4201 if (postLoadId.equals(varna.getViewId()))
4203 // this viewer is already instantiated
4204 // could in future here add ap as another 'parent' of the
4205 // AppVarna window; currently just 1-to-many
4212 * viewer not found - make it
4214 RnaViewerModel model = new RnaViewerModel(postLoadId, viewer.getTitle(),
4215 safeInt(viewer.getXpos()), safeInt(viewer.getYpos()),
4216 safeInt(viewer.getWidth()), safeInt(viewer.getHeight()),
4217 safeInt(viewer.getDividerLocation()));
4218 AppVarna varna = new AppVarna(model, ap);
4224 * Load any saved trees
4232 protected void loadTrees(JalviewModel jm, Viewport view,
4233 AlignFrame af, AlignViewport av, AlignmentPanel ap)
4235 // TODO result of automated refactoring - are all these parameters needed?
4238 for (int t = 0; t < jm.getTree().size(); t++)
4241 Tree tree = jm.getTree().get(t);
4243 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
4246 tp = af.showNewickTree(new NewickFile(tree.getNewick()),
4247 tree.getTitle(), safeInt(tree.getWidth()),
4248 safeInt(tree.getHeight()), safeInt(tree.getXpos()),
4249 safeInt(tree.getYpos()));
4250 if (tree.getId() != null)
4252 // perhaps bind the tree id to something ?
4257 // update local tree attributes ?
4258 // TODO: should check if tp has been manipulated by user - if so its
4259 // settings shouldn't be modified
4260 tp.setTitle(tree.getTitle());
4261 tp.setBounds(new Rectangle(safeInt(tree.getXpos()),
4262 safeInt(tree.getYpos()), safeInt(tree.getWidth()),
4263 safeInt(tree.getHeight())));
4264 tp.setViewport(av); // af.viewport;
4265 // TODO: verify 'associate with all views' works still
4266 tp.getTreeCanvas().setViewport(av); // af.viewport;
4267 tp.getTreeCanvas().setAssociatedPanel(ap); // af.alignPanel;
4269 tp.getTreeCanvas().setApplyToAllViews(tree.isLinkToAllViews());
4272 warn("There was a problem recovering stored Newick tree: \n"
4273 + tree.getNewick());
4277 tp.fitToWindow.setState(safeBoolean(tree.isFitToWindow()));
4278 tp.fitToWindow_actionPerformed(null);
4280 if (tree.getFontName() != null)
4283 new Font(tree.getFontName(), safeInt(tree.getFontStyle()),
4284 safeInt(tree.getFontSize())));
4289 new Font(view.getFontName(), safeInt(view.getFontStyle()),
4290 safeInt(view.getFontSize())));
4293 tp.showPlaceholders(safeBoolean(tree.isMarkUnlinked()));
4294 tp.showBootstrap(safeBoolean(tree.isShowBootstrap()));
4295 tp.showDistances(safeBoolean(tree.isShowDistances()));
4297 tp.getTreeCanvas().setThreshold(safeFloat(tree.getThreshold()));
4299 if (safeBoolean(tree.isCurrentTree()))
4301 af.getViewport().setCurrentTree(tp.getTree());
4305 } catch (Exception ex)
4307 ex.printStackTrace();
4312 * Load and link any saved structure viewers.
4319 protected void loadPDBStructures(jarInputStreamProvider jprovider,
4320 List<JSeq> jseqs, AlignFrame af, AlignmentPanel ap)
4323 * Run through all PDB ids on the alignment, and collect mappings between
4324 * distinct view ids and all sequences referring to that view.
4326 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<>();
4328 for (int i = 0; i < jseqs.size(); i++)
4330 JSeq jseq = jseqs.get(i);
4331 if (jseq.getPdbids().size() > 0)
4333 List<Pdbids> ids = jseq.getPdbids();
4334 for (int p = 0; p < ids.size(); p++)
4336 Pdbids pdbid = ids.get(p);
4337 final int structureStateCount = pdbid.getStructureState().size();
4338 for (int s = 0; s < structureStateCount; s++)
4340 // check to see if we haven't already created this structure view
4341 final StructureState structureState = pdbid
4342 .getStructureState().get(s);
4343 String sviewid = (structureState.getViewId() == null) ? null
4344 : structureState.getViewId() + uniqueSetSuffix;
4345 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
4346 // Originally : pdbid.getFile()
4347 // : TODO: verify external PDB file recovery still works in normal
4348 // jalview project load
4350 loadPDBFile(jprovider, pdbid.getId(), pdbid.getFile()));
4351 jpdb.setId(pdbid.getId());
4353 int x = safeInt(structureState.getXpos());
4354 int y = safeInt(structureState.getYpos());
4355 int width = safeInt(structureState.getWidth());
4356 int height = safeInt(structureState.getHeight());
4358 // Probably don't need to do this anymore...
4359 // Desktop.desktop.getComponentAt(x, y);
4360 // TODO: NOW: check that this recovers the PDB file correctly.
4361 String pdbFile = loadPDBFile(jprovider, pdbid.getId(),
4363 jalview.datamodel.SequenceI seq = seqRefIds
4364 .get(jseq.getId() + "");
4365 if (sviewid == null)
4367 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width + ","
4370 if (!structureViewers.containsKey(sviewid))
4372 structureViewers.put(sviewid,
4373 new StructureViewerModel(x, y, width, height, false,
4374 false, true, structureState.getViewId(),
4375 structureState.getType()));
4376 // Legacy pre-2.7 conversion JAL-823 :
4377 // do not assume any view has to be linked for colour by
4381 // assemble String[] { pdb files }, String[] { id for each
4382 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
4383 // seqs_file 2}, boolean[] {
4384 // linkAlignPanel,superposeWithAlignpanel}} from hash
4385 StructureViewerModel jmoldat = structureViewers.get(sviewid);
4386 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
4387 || structureState.isAlignwithAlignPanel());
4390 * Default colour by linked panel to false if not specified (e.g.
4391 * for pre-2.7 projects)
4393 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
4394 colourWithAlignPanel |= structureState.isColourwithAlignPanel();
4395 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
4398 * Default colour by viewer to true if not specified (e.g. for
4401 boolean colourByViewer = jmoldat.isColourByViewer();
4402 colourByViewer &= structureState.isColourByJmol();
4403 jmoldat.setColourByViewer(colourByViewer);
4405 if (jmoldat.getStateData().length() < structureState
4406 .getValue()/*Content()*/.length())
4408 jmoldat.setStateData(structureState.getValue());// Content());
4410 if (pdbid.getFile() != null)
4412 File mapkey = new File(pdbid.getFile());
4413 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
4414 if (seqstrmaps == null)
4416 jmoldat.getFileData().put(mapkey,
4417 seqstrmaps = jmoldat.new StructureData(pdbFile,
4420 if (!seqstrmaps.getSeqList().contains(seq))
4422 seqstrmaps.getSeqList().add(seq);
4428 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");
4435 // Instantiate the associated structure views
4436 for (Entry<String, StructureViewerModel> entry : structureViewers
4441 createOrLinkStructureViewer(entry, af, ap, jprovider);
4442 } catch (Exception e)
4445 "Error loading structure viewer: " + e.getMessage());
4446 // failed - try the next one
4458 protected void createOrLinkStructureViewer(
4459 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4460 AlignmentPanel ap, jarInputStreamProvider jprovider)
4462 final StructureViewerModel stateData = viewerData.getValue();
4465 * Search for any viewer windows already open from other alignment views
4466 * that exactly match the stored structure state
4468 StructureViewerBase comp = findMatchingViewer(viewerData);
4472 linkStructureViewer(ap, comp, stateData);
4477 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
4478 * "viewer_"+stateData.viewId
4480 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
4482 createChimeraViewer(viewerData, af, jprovider);
4487 * else Jmol (if pre-2.9, stateData contains JMOL state string)
4489 createJmolViewer(viewerData, af, jprovider);
4494 * Create a new Chimera viewer.
4500 protected void createChimeraViewer(
4501 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4502 jarInputStreamProvider jprovider)
4504 StructureViewerModel data = viewerData.getValue();
4505 String chimeraSessionFile = data.getStateData();
4508 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
4510 * NB this is the 'saved' viewId as in the project file XML, _not_ the
4511 * 'uniquified' sviewid used to reconstruct the viewer here
4513 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
4514 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
4517 Set<Entry<File, StructureData>> fileData = data.getFileData()
4519 List<PDBEntry> pdbs = new ArrayList<>();
4520 List<SequenceI[]> allseqs = new ArrayList<>();
4521 for (Entry<File, StructureData> pdb : fileData)
4523 String filePath = pdb.getValue().getFilePath();
4524 String pdbId = pdb.getValue().getPdbId();
4525 // pdbs.add(new PDBEntry(filePath, pdbId));
4526 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
4527 final List<SequenceI> seqList = pdb.getValue().getSeqList();
4528 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
4532 boolean colourByChimera = data.isColourByViewer();
4533 boolean colourBySequence = data.isColourWithAlignPanel();
4535 // TODO use StructureViewer as a factory here, see JAL-1761
4536 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
4537 final SequenceI[][] seqsArray = allseqs
4538 .toArray(new SequenceI[allseqs.size()][]);
4539 String newViewId = viewerData.getKey();
4541 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
4542 af.alignPanel, pdbArray, seqsArray, colourByChimera,
4543 colourBySequence, newViewId);
4544 cvf.setSize(data.getWidth(), data.getHeight());
4545 cvf.setLocation(data.getX(), data.getY());
4549 * Create a new Jmol window. First parse the Jmol state to translate filenames
4550 * loaded into the view, and record the order in which files are shown in the
4551 * Jmol view, so we can add the sequence mappings in same order.
4557 protected void createJmolViewer(
4558 final Entry<String, StructureViewerModel> viewerData,
4559 AlignFrame af, jarInputStreamProvider jprovider)
4561 final StructureViewerModel svattrib = viewerData.getValue();
4562 String state = svattrib.getStateData();
4565 * Pre-2.9: state element value is the Jmol state string
4567 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
4570 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
4572 state = readJarEntry(jprovider,
4573 getViewerJarEntryName(svattrib.getViewId()));
4576 List<String> pdbfilenames = new ArrayList<>();
4577 List<SequenceI[]> seqmaps = new ArrayList<>();
4578 List<String> pdbids = new ArrayList<>();
4579 StringBuilder newFileLoc = new StringBuilder(64);
4580 int cp = 0, ncp, ecp;
4581 Map<File, StructureData> oldFiles = svattrib.getFileData();
4582 while ((ncp = state.indexOf("load ", cp)) > -1)
4586 // look for next filename in load statement
4587 newFileLoc.append(state.substring(cp,
4588 ncp = (state.indexOf("\"", ncp + 1) + 1)));
4589 String oldfilenam = state.substring(ncp,
4590 ecp = state.indexOf("\"", ncp));
4591 // recover the new mapping data for this old filename
4592 // have to normalize filename - since Jmol and jalview do
4594 // translation differently.
4595 StructureData filedat = oldFiles.get(new File(oldfilenam));
4596 if (filedat == null)
4598 String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\");
4599 filedat = oldFiles.get(new File(reformatedOldFilename));
4601 newFileLoc.append(Platform.escapeBackslashes(filedat.getFilePath()));
4602 pdbfilenames.add(filedat.getFilePath());
4603 pdbids.add(filedat.getPdbId());
4604 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4605 newFileLoc.append("\"");
4606 cp = ecp + 1; // advance beyond last \" and set cursor so we can
4607 // look for next file statement.
4608 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
4612 // just append rest of state
4613 newFileLoc.append(state.substring(cp));
4617 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
4618 newFileLoc = new StringBuilder(state);
4619 newFileLoc.append("; load append ");
4620 for (File id : oldFiles.keySet())
4622 // add this and any other pdb files that should be present in
4624 StructureData filedat = oldFiles.get(id);
4625 newFileLoc.append(filedat.getFilePath());
4626 pdbfilenames.add(filedat.getFilePath());
4627 pdbids.add(filedat.getPdbId());
4628 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4629 newFileLoc.append(" \"");
4630 newFileLoc.append(filedat.getFilePath());
4631 newFileLoc.append("\"");
4634 newFileLoc.append(";");
4637 if (newFileLoc.length() == 0)
4641 int histbug = newFileLoc.indexOf("history = ");
4645 * change "history = [true|false];" to "history = [1|0];"
4648 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
4649 String val = (diff == -1) ? null
4650 : newFileLoc.substring(histbug, diff);
4651 if (val != null && val.length() >= 4)
4653 if (val.contains("e")) // eh? what can it be?
4655 if (val.trim().equals("true"))
4663 newFileLoc.replace(histbug, diff, val);
4668 final String[] pdbf = pdbfilenames
4669 .toArray(new String[pdbfilenames.size()]);
4670 final String[] id = pdbids.toArray(new String[pdbids.size()]);
4671 final SequenceI[][] sq = seqmaps
4672 .toArray(new SequenceI[seqmaps.size()][]);
4673 final String fileloc = newFileLoc.toString();
4674 final String sviewid = viewerData.getKey();
4675 final AlignFrame alf = af;
4676 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
4677 svattrib.getWidth(), svattrib.getHeight());
4680 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
4685 JalviewStructureDisplayI sview = null;
4688 sview = new StructureViewer(
4689 alf.alignPanel.getStructureSelectionManager())
4690 .createView(StructureViewer.ViewerType.JMOL,
4691 pdbf, id, sq, alf.alignPanel, svattrib,
4692 fileloc, rect, sviewid);
4693 addNewStructureViewer(sview);
4694 } catch (OutOfMemoryError ex)
4696 new OOMWarning("restoring structure view for PDB id " + id,
4697 (OutOfMemoryError) ex.getCause());
4698 if (sview != null && sview.isVisible())
4700 sview.closeViewer(false);
4701 sview.setVisible(false);
4707 } catch (InvocationTargetException ex)
4709 warn("Unexpected error when opening Jmol view.", ex);
4711 } catch (InterruptedException e)
4713 // e.printStackTrace();
4719 * Generates a name for the entry in the project jar file to hold state
4720 * information for a structure viewer
4725 protected String getViewerJarEntryName(String viewId)
4727 return VIEWER_PREFIX + viewId;
4731 * Returns any open frame that matches given structure viewer data. The match
4732 * is based on the unique viewId, or (for older project versions) the frame's
4738 protected StructureViewerBase findMatchingViewer(
4739 Entry<String, StructureViewerModel> viewerData)
4741 final String sviewid = viewerData.getKey();
4742 final StructureViewerModel svattrib = viewerData.getValue();
4743 StructureViewerBase comp = null;
4744 JInternalFrame[] frames = getAllFrames();
4745 for (JInternalFrame frame : frames)
4747 if (frame instanceof StructureViewerBase)
4750 * Post jalview 2.4 schema includes structure view id
4752 if (sviewid != null && ((StructureViewerBase) frame).getViewId()
4755 comp = (StructureViewerBase) frame;
4756 break; // break added in 2.9
4759 * Otherwise test for matching position and size of viewer frame
4761 else if (frame.getX() == svattrib.getX()
4762 && frame.getY() == svattrib.getY()
4763 && frame.getHeight() == svattrib.getHeight()
4764 && frame.getWidth() == svattrib.getWidth())
4766 comp = (StructureViewerBase) frame;
4767 // no break in faint hope of an exact match on viewId
4775 * Link an AlignmentPanel to an existing structure viewer.
4780 * @param useinViewerSuperpos
4781 * @param usetoColourbyseq
4782 * @param viewerColouring
4784 protected void linkStructureViewer(AlignmentPanel ap,
4785 StructureViewerBase viewer, StructureViewerModel stateData)
4787 // NOTE: if the jalview project is part of a shared session then
4788 // view synchronization should/could be done here.
4790 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4791 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4792 final boolean viewerColouring = stateData.isColourByViewer();
4793 Map<File, StructureData> oldFiles = stateData.getFileData();
4796 * Add mapping for sequences in this view to an already open viewer
4798 final AAStructureBindingModel binding = viewer.getBinding();
4799 for (File id : oldFiles.keySet())
4801 // add this and any other pdb files that should be present in the
4803 StructureData filedat = oldFiles.get(id);
4804 String pdbFile = filedat.getFilePath();
4805 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4806 binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE,
4808 binding.addSequenceForStructFile(pdbFile, seq);
4810 // and add the AlignmentPanel's reference to the view panel
4811 viewer.addAlignmentPanel(ap);
4812 if (useinViewerSuperpos)
4814 viewer.useAlignmentPanelForSuperposition(ap);
4818 viewer.excludeAlignmentPanelForSuperposition(ap);
4820 if (usetoColourbyseq)
4822 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4826 viewer.excludeAlignmentPanelForColourbyseq(ap);
4831 * Get all frames within the Desktop.
4835 protected JInternalFrame[] getAllFrames()
4837 JInternalFrame[] frames = null;
4838 // TODO is this necessary - is it safe - risk of hanging?
4843 frames = Desktop.desktop.getAllFrames();
4844 } catch (ArrayIndexOutOfBoundsException e)
4846 // occasional No such child exceptions are thrown here...
4850 } catch (InterruptedException f)
4854 } while (frames == null);
4859 * Answers true if 'version' is equal to or later than 'supported', where each
4860 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4861 * changes. Development and test values for 'version' are leniently treated
4865 * - minimum version we are comparing against
4867 * - version of data being processsed
4870 public static boolean isVersionStringLaterThan(String supported,
4873 if (supported == null || version == null
4874 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4875 || version.equalsIgnoreCase("Test")
4876 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4878 System.err.println("Assuming project file with "
4879 + (version == null ? "null" : version)
4880 + " is compatible with Jalview version " + supported);
4885 return StringUtils.compareVersions(version, supported, "b") >= 0;
4889 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4891 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4893 if (newStructureViewers != null)
4895 sview.getBinding().setFinishedLoadingFromArchive(false);
4896 newStructureViewers.add(sview);
4900 protected void setLoadingFinishedForNewStructureViewers()
4902 if (newStructureViewers != null)
4904 for (JalviewStructureDisplayI sview : newStructureViewers)
4906 sview.getBinding().setFinishedLoadingFromArchive(true);
4908 newStructureViewers.clear();
4909 newStructureViewers = null;
4913 AlignFrame loadViewport(String file, List<JSeq> JSEQ,
4914 List<SequenceI> hiddenSeqs, AlignmentI al,
4915 JalviewModel jm, Viewport view, String uniqueSeqSetId,
4916 String viewId, List<JvAnnotRow> autoAlan)
4918 AlignFrame af = null;
4919 af = new AlignFrame(al, safeInt(view.getWidth()),
4920 safeInt(view.getHeight()), uniqueSeqSetId, viewId);
4922 af.setFileName(file, FileFormat.Jalview);
4924 final AlignViewport viewport = af.getViewport();
4925 for (int i = 0; i < JSEQ.size(); i++)
4927 int colour = safeInt(JSEQ.get(i).getColour());
4928 viewport.setSequenceColour(viewport.getAlignment().getSequenceAt(i),
4934 viewport.setColourByReferenceSeq(true);
4935 viewport.setDisplayReferenceSeq(true);
4938 viewport.setGatherViewsHere(safeBoolean(view.isGatheredViews()));
4940 if (view.getSequenceSetId() != null)
4942 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4944 viewport.setSequenceSetId(uniqueSeqSetId);
4947 // propagate shared settings to this new view
4948 viewport.setHistoryList(av.getHistoryList());
4949 viewport.setRedoList(av.getRedoList());
4953 viewportsAdded.put(uniqueSeqSetId, viewport);
4955 // TODO: check if this method can be called repeatedly without
4956 // side-effects if alignpanel already registered.
4957 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4959 // apply Hidden regions to view.
4960 if (hiddenSeqs != null)
4962 for (int s = 0; s < JSEQ.size(); s++)
4964 SequenceGroup hidden = new SequenceGroup();
4965 boolean isRepresentative = false;
4966 for (int r = 0; r < JSEQ.get(s).getHiddenSequences().size(); r++)
4968 isRepresentative = true;
4969 SequenceI sequenceToHide = al
4970 .getSequenceAt(JSEQ.get(s).getHiddenSequences().get(r));
4971 hidden.addSequence(sequenceToHide, false);
4972 // remove from hiddenSeqs list so we don't try to hide it twice
4973 hiddenSeqs.remove(sequenceToHide);
4975 if (isRepresentative)
4977 SequenceI representativeSequence = al.getSequenceAt(s);
4978 hidden.addSequence(representativeSequence, false);
4979 viewport.hideRepSequences(representativeSequence, hidden);
4983 SequenceI[] hseqs = hiddenSeqs
4984 .toArray(new SequenceI[hiddenSeqs.size()]);
4985 viewport.hideSequence(hseqs);
4988 // recover view properties and display parameters
4990 viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
4991 viewport.setAbovePIDThreshold(safeBoolean(view.isPidSelected()));
4992 final int pidThreshold = safeInt(view.getPidThreshold());
4993 viewport.setThreshold(pidThreshold);
4995 viewport.setColourText(safeBoolean(view.isShowColourText()));
4998 .setConservationSelected(
4999 safeBoolean(view.isConservationSelected()));
5000 viewport.setIncrement(safeInt(view.getConsThreshold()));
5001 viewport.setShowJVSuffix(safeBoolean(view.isShowFullId()));
5002 viewport.setRightAlignIds(safeBoolean(view.isRightAlignIds()));
5003 viewport.setFont(new Font(view.getFontName(),
5004 safeInt(view.getFontStyle()), safeInt(view.getFontSize())),
5006 ViewStyleI vs = viewport.getViewStyle();
5007 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
5008 viewport.setViewStyle(vs);
5009 // TODO: allow custom charWidth/Heights to be restored by updating them
5010 // after setting font - which means set above to false
5011 viewport.setRenderGaps(safeBoolean(view.isRenderGaps()));
5012 viewport.setWrapAlignment(safeBoolean(view.isWrapAlignment()));
5013 viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
5015 viewport.setShowBoxes(safeBoolean(view.isShowBoxes()));
5017 viewport.setShowText(safeBoolean(view.isShowText()));
5019 viewport.setTextColour(new Color(safeInt(view.getTextCol1())));
5020 viewport.setTextColour2(new Color(safeInt(view.getTextCol2())));
5021 viewport.setThresholdTextColour(safeInt(view.getTextColThreshold()));
5022 viewport.setShowUnconserved(view.isShowUnconserved());
5023 viewport.getRanges().setStartRes(safeInt(view.getStartRes()));
5025 if (view.getViewName() != null)
5027 viewport.setViewName(view.getViewName());
5028 af.setInitialTabVisible();
5030 af.setBounds(safeInt(view.getXpos()), safeInt(view.getYpos()),
5031 safeInt(view.getWidth()), safeInt(view.getHeight()));
5032 // startSeq set in af.alignPanel.updateLayout below
5033 af.alignPanel.updateLayout();
5034 ColourSchemeI cs = null;
5035 // apply colourschemes
5036 if (view.getBgColour() != null)
5038 if (view.getBgColour().startsWith("ucs"))
5040 cs = getUserColourScheme(jm, view.getBgColour());
5042 else if (view.getBgColour().startsWith("Annotation"))
5044 AnnotationColourScheme viewAnnColour = view.getAnnotationColours();
5045 cs = constructAnnotationColour(viewAnnColour, af, al, jm, true);
5052 cs = ColourSchemeProperty.getColourScheme(af.getViewport(), al,
5053 view.getBgColour());
5058 * turn off 'alignment colour applies to all groups'
5059 * while restoring global colour scheme
5061 viewport.setColourAppliesToAllGroups(false);
5062 viewport.setGlobalColourScheme(cs);
5063 viewport.getResidueShading().setThreshold(pidThreshold,
5064 view.isIgnoreGapsinConsensus());
5065 viewport.getResidueShading()
5066 .setConsensus(viewport.getSequenceConsensusHash());
5067 if (safeBoolean(view.isConservationSelected()) && cs != null)
5069 viewport.getResidueShading()
5070 .setConservationInc(safeInt(view.getConsThreshold()));
5072 af.changeColour(cs);
5073 viewport.setColourAppliesToAllGroups(true);
5076 .setShowSequenceFeatures(
5077 safeBoolean(view.isShowSequenceFeatures()));
5079 viewport.setCentreColumnLabels(view.isCentreColumnLabels());
5080 viewport.setIgnoreGapsConsensus(view.isIgnoreGapsinConsensus(), null);
5081 viewport.setFollowHighlight(view.isFollowHighlight());
5082 viewport.followSelection = view.isFollowSelection();
5083 viewport.setShowConsensusHistogram(view.isShowConsensusHistogram());
5084 viewport.setShowSequenceLogo(view.isShowSequenceLogo());
5085 viewport.setNormaliseSequenceLogo(view.isNormaliseSequenceLogo());
5086 viewport.setShowDBRefs(safeBoolean(view.isShowDbRefTooltip()));
5087 viewport.setShowNPFeats(safeBoolean(view.isShowNPfeatureTooltip()));
5088 viewport.setShowGroupConsensus(view.isShowGroupConsensus());
5089 viewport.setShowGroupConservation(view.isShowGroupConservation());
5091 // recover feature settings
5092 if (jm.getFeatureSettings() != null)
5094 FeatureRenderer fr = af.alignPanel.getSeqPanel().seqCanvas
5095 .getFeatureRenderer();
5096 FeaturesDisplayed fdi;
5097 viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
5098 String[] renderOrder = new String[jm.getFeatureSettings()
5099 .getSetting().size()];
5100 Map<String, FeatureColourI> featureColours = new Hashtable<>();
5101 Map<String, Float> featureOrder = new Hashtable<>();
5103 for (int fs = 0; fs < jm.getFeatureSettings()
5104 .getSetting().size(); fs++)
5106 Setting setting = jm.getFeatureSettings().getSetting().get(fs);
5107 String featureType = setting.getType();
5110 * restore feature filters (if any)
5112 jalview.xml.binding.jalview.FeatureMatcherSet filters = setting
5114 if (filters != null)
5116 FeatureMatcherSetI filter = Jalview2XML
5117 .parseFilter(featureType, filters);
5118 if (!filter.isEmpty())
5120 fr.setFeatureFilter(featureType, filter);
5125 * restore feature colour scheme
5127 Color maxColour = new Color(setting.getColour());
5128 if (setting.getMincolour() != null)
5131 * minColour is always set unless a simple colour
5132 * (including for colour by label though it doesn't use it)
5134 Color minColour = new Color(setting.getMincolour().intValue());
5135 Color noValueColour = minColour;
5136 NoValueColour noColour = setting.getNoValueColour();
5137 if (noColour == NoValueColour.NONE)
5139 noValueColour = null;
5141 else if (noColour == NoValueColour.MAX)
5143 noValueColour = maxColour;
5145 float min = safeFloat(safeFloat(setting.getMin()));
5146 float max = setting.getMax() == null ? 1f
5147 : setting.getMax().floatValue();
5148 FeatureColourI gc = new FeatureColour(maxColour, minColour,
5150 noValueColour, min, max);
5151 if (setting.getAttributeName().size() > 0)
5153 gc.setAttributeName(setting.getAttributeName().toArray(
5154 new String[setting.getAttributeName().size()]));
5156 if (setting.getThreshold() != null)
5158 gc.setThreshold(setting.getThreshold().floatValue());
5159 int threshstate = safeInt(setting.getThreshstate());
5160 // -1 = None, 0 = Below, 1 = Above threshold
5161 if (threshstate == 0)
5163 gc.setBelowThreshold(true);
5165 else if (threshstate == 1)
5167 gc.setAboveThreshold(true);
5170 gc.setAutoScaled(true); // default
5171 if (setting.isAutoScale() != null)
5173 gc.setAutoScaled(setting.isAutoScale());
5175 if (setting.isColourByLabel() != null)
5177 gc.setColourByLabel(setting.isColourByLabel());
5179 // and put in the feature colour table.
5180 featureColours.put(featureType, gc);
5184 featureColours.put(featureType,
5185 new FeatureColour(maxColour));
5187 renderOrder[fs] = featureType;
5188 if (setting.getOrder() != null)
5190 featureOrder.put(featureType, setting.getOrder().floatValue());
5194 featureOrder.put(featureType, Float.valueOf(
5195 fs / jm.getFeatureSettings().getSetting().size()));
5197 if (safeBoolean(setting.isDisplay()))
5199 fdi.setVisible(featureType);
5202 Map<String, Boolean> fgtable = new Hashtable<>();
5203 for (int gs = 0; gs < jm.getFeatureSettings().getGroup().size(); gs++)
5205 Group grp = jm.getFeatureSettings().getGroup().get(gs);
5206 fgtable.put(grp.getName(), Boolean.valueOf(grp.isDisplay()));
5208 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
5209 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
5210 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
5211 FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
5212 fgtable, featureColours, 1.0f, featureOrder);
5213 fr.transferSettings(frs);
5216 if (view.getHiddenColumns().size() > 0)
5218 for (int c = 0; c < view.getHiddenColumns().size(); c++)
5220 final HiddenColumns hc = view.getHiddenColumns().get(c);
5221 viewport.hideColumns(safeInt(hc.getStart()),
5222 safeInt(hc.getEnd()) /* +1 */);
5225 if (view.getCalcIdParam() != null)
5227 for (CalcIdParam calcIdParam : view.getCalcIdParam())
5229 if (calcIdParam != null)
5231 if (recoverCalcIdParam(calcIdParam, viewport))
5236 warn("Couldn't recover parameters for "
5237 + calcIdParam.getCalcId());
5242 af.setMenusFromViewport(viewport);
5243 af.setTitle(view.getTitle());
5244 // TODO: we don't need to do this if the viewport is aready visible.
5246 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
5247 * has a 'cdna/protein complement' view, in which case save it in order to
5248 * populate a SplitFrame once all views have been read in.
5250 String complementaryViewId = view.getComplementId();
5251 if (complementaryViewId == null)
5253 Desktop.addInternalFrame(af, view.getTitle(),
5254 safeInt(view.getWidth()), safeInt(view.getHeight()));
5255 // recompute any autoannotation
5256 af.alignPanel.updateAnnotation(false, true);
5257 reorderAutoannotation(af, al, autoAlan);
5258 af.alignPanel.alignmentChanged();
5262 splitFrameCandidates.put(view, af);
5268 * Reads saved data to restore Colour by Annotation settings
5270 * @param viewAnnColour
5274 * @param checkGroupAnnColour
5277 private ColourSchemeI constructAnnotationColour(
5278 AnnotationColourScheme viewAnnColour, AlignFrame af,
5279 AlignmentI al, JalviewModel model, boolean checkGroupAnnColour)
5281 boolean propagateAnnColour = false;
5282 AlignmentI annAlignment = af != null ? af.getViewport().getAlignment()
5284 if (checkGroupAnnColour && al.getGroups() != null
5285 && al.getGroups().size() > 0)
5287 // pre 2.8.1 behaviour
5288 // check to see if we should transfer annotation colours
5289 propagateAnnColour = true;
5290 for (SequenceGroup sg : al.getGroups())
5292 if (sg.getColourScheme() instanceof AnnotationColourGradient)
5294 propagateAnnColour = false;
5300 * 2.10.2- : saved annotationId is AlignmentAnnotation.annotationId
5302 String annotationId = viewAnnColour.getAnnotation();
5303 AlignmentAnnotation matchedAnnotation = annotationIds.get(annotationId);
5306 * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
5308 if (matchedAnnotation == null
5309 && annAlignment.getAlignmentAnnotation() != null)
5311 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
5314 .equals(annAlignment.getAlignmentAnnotation()[i].label))
5316 matchedAnnotation = annAlignment.getAlignmentAnnotation()[i];
5321 if (matchedAnnotation == null)
5323 System.err.println("Failed to match annotation colour scheme for "
5327 if (matchedAnnotation.getThreshold() == null)
5329 matchedAnnotation.setThreshold(
5330 new GraphLine(safeFloat(viewAnnColour.getThreshold()),
5331 "Threshold", Color.black));
5334 AnnotationColourGradient cs = null;
5335 if (viewAnnColour.getColourScheme().equals("None"))
5337 cs = new AnnotationColourGradient(matchedAnnotation,
5338 new Color(safeInt(viewAnnColour.getMinColour())),
5339 new Color(safeInt(viewAnnColour.getMaxColour())),
5340 safeInt(viewAnnColour.getAboveThreshold()));
5342 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
5344 cs = new AnnotationColourGradient(matchedAnnotation,
5345 getUserColourScheme(model, viewAnnColour.getColourScheme()),
5346 safeInt(viewAnnColour.getAboveThreshold()));
5350 cs = new AnnotationColourGradient(matchedAnnotation,
5351 ColourSchemeProperty.getColourScheme(af.getViewport(), al,
5352 viewAnnColour.getColourScheme()),
5353 safeInt(viewAnnColour.getAboveThreshold()));
5356 boolean perSequenceOnly = safeBoolean(viewAnnColour.isPerSequence());
5357 boolean useOriginalColours = safeBoolean(
5358 viewAnnColour.isPredefinedColours());
5359 cs.setSeqAssociated(perSequenceOnly);
5360 cs.setPredefinedColours(useOriginalColours);
5362 if (propagateAnnColour && al.getGroups() != null)
5364 // Also use these settings for all the groups
5365 for (int g = 0; g < al.getGroups().size(); g++)
5367 SequenceGroup sg = al.getGroups().get(g);
5368 if (sg.getGroupColourScheme() == null)
5373 AnnotationColourGradient groupScheme = new AnnotationColourGradient(
5374 matchedAnnotation, sg.getColourScheme(),
5375 safeInt(viewAnnColour.getAboveThreshold()));
5376 sg.setColourScheme(groupScheme);
5377 groupScheme.setSeqAssociated(perSequenceOnly);
5378 groupScheme.setPredefinedColours(useOriginalColours);
5384 private void reorderAutoannotation(AlignFrame af, AlignmentI al,
5385 List<JvAnnotRow> autoAlan)
5387 // copy over visualization settings for autocalculated annotation in the
5389 if (al.getAlignmentAnnotation() != null)
5392 * Kludge for magic autoannotation names (see JAL-811)
5394 String[] magicNames = new String[] { "Consensus", "Quality",
5396 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
5397 Hashtable<String, JvAnnotRow> visan = new Hashtable<>();
5398 for (String nm : magicNames)
5400 visan.put(nm, nullAnnot);
5402 for (JvAnnotRow auan : autoAlan)
5404 visan.put(auan.template.label
5405 + (auan.template.getCalcId() == null ? ""
5406 : "\t" + auan.template.getCalcId()),
5409 int hSize = al.getAlignmentAnnotation().length;
5410 List<JvAnnotRow> reorder = new ArrayList<>();
5411 // work through any autoCalculated annotation already on the view
5412 // removing it if it should be placed in a different location on the
5413 // annotation panel.
5414 List<String> remains = new ArrayList<>(visan.keySet());
5415 for (int h = 0; h < hSize; h++)
5417 jalview.datamodel.AlignmentAnnotation jalan = al
5418 .getAlignmentAnnotation()[h];
5419 if (jalan.autoCalculated)
5422 JvAnnotRow valan = visan.get(k = jalan.label);
5423 if (jalan.getCalcId() != null)
5425 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
5430 // delete the auto calculated row from the alignment
5431 al.deleteAnnotation(jalan, false);
5435 if (valan != nullAnnot)
5437 if (jalan != valan.template)
5439 // newly created autoannotation row instance
5440 // so keep a reference to the visible annotation row
5441 // and copy over all relevant attributes
5442 if (valan.template.graphHeight >= 0)
5445 jalan.graphHeight = valan.template.graphHeight;
5447 jalan.visible = valan.template.visible;
5449 reorder.add(new JvAnnotRow(valan.order, jalan));
5454 // Add any (possibly stale) autocalculated rows that were not appended to
5455 // the view during construction
5456 for (String other : remains)
5458 JvAnnotRow othera = visan.get(other);
5459 if (othera != nullAnnot && othera.template.getCalcId() != null
5460 && othera.template.getCalcId().length() > 0)
5462 reorder.add(othera);
5465 // now put the automatic annotation in its correct place
5466 int s = 0, srt[] = new int[reorder.size()];
5467 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
5468 for (JvAnnotRow jvar : reorder)
5471 srt[s++] = jvar.order;
5474 jalview.util.QuickSort.sort(srt, rws);
5475 // and re-insert the annotation at its correct position
5476 for (JvAnnotRow jvar : rws)
5478 al.addAnnotation(jvar.template, jvar.order);
5480 af.alignPanel.adjustAnnotationHeight();
5484 Hashtable skipList = null;
5487 * TODO remove this method
5490 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
5491 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
5492 * throw new Error("Implementation Error. No skipList defined for this
5493 * Jalview2XML instance."); } return (AlignFrame)
5494 * skipList.get(view.getSequenceSetId()); }
5498 * Check if the Jalview view contained in object should be skipped or not.
5501 * @return true if view's sequenceSetId is a key in skipList
5503 private boolean skipViewport(JalviewModel object)
5505 if (skipList == null)
5509 String id = object.getViewport().get(0).getSequenceSetId();
5510 if (skipList.containsKey(id))
5512 if (Cache.log != null && Cache.log.isDebugEnabled())
5514 Cache.log.debug("Skipping seuqence set id " + id);
5521 public void addToSkipList(AlignFrame af)
5523 if (skipList == null)
5525 skipList = new Hashtable();
5527 skipList.put(af.getViewport().getSequenceSetId(), af);
5530 public void clearSkipList()
5532 if (skipList != null)
5539 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
5540 boolean ignoreUnrefed, String uniqueSeqSetId)
5542 jalview.datamodel.AlignmentI ds = getDatasetFor(
5543 vamsasSet.getDatasetId());
5544 AlignmentI xtant_ds = ds;
5545 if (xtant_ds == null)
5547 // good chance we are about to create a new dataset, but check if we've
5548 // seen some of the dataset sequence IDs before.
5549 // TODO: skip this check if we are working with project generated by
5550 // version 2.11 or later
5551 xtant_ds = checkIfHasDataset(vamsasSet.getSequence());
5552 if (xtant_ds != null)
5555 addDatasetRef(vamsasSet.getDatasetId(), ds);
5558 Vector dseqs = null;
5561 // recovering an alignment View
5562 AlignmentI seqSetDS = getDatasetFor(UNIQSEQSETID + uniqueSeqSetId);
5563 if (seqSetDS != null)
5565 if (ds != null && ds != seqSetDS)
5567 warn("JAL-3171 regression: Overwriting a dataset reference for an alignment"
5568 + " - CDS/Protein crossreference data may be lost");
5569 if (xtant_ds != null)
5571 // This can only happen if the unique sequence set ID was bound to a
5572 // dataset that did not contain any of the sequences in the view
5573 // currently being restored.
5574 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.");
5578 addDatasetRef(vamsasSet.getDatasetId(), ds);
5583 // try even harder to restore dataset
5584 AlignmentI xtantDS = checkIfHasDataset(vamsasSet.getSequence());
5585 // create a list of new dataset sequences
5586 dseqs = new Vector();
5588 for (int i = 0, iSize = vamsasSet.getSequence().size(); i < iSize; i++)
5590 Sequence vamsasSeq = vamsasSet.getSequence().get(i);
5591 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
5593 // create a new dataset
5596 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
5597 dseqs.copyInto(dsseqs);
5598 ds = new jalview.datamodel.Alignment(dsseqs);
5599 debug("Created new dataset " + vamsasSet.getDatasetId()
5600 + " for alignment " + System.identityHashCode(al));
5601 addDatasetRef(vamsasSet.getDatasetId(), ds);
5603 // set the dataset for the newly imported alignment.
5604 if (al.getDataset() == null && !ignoreUnrefed)
5607 // register dataset for the alignment's uniqueSeqSetId for legacy projects
5608 addDatasetRef(UNIQSEQSETID + uniqueSeqSetId, ds);
5610 updateSeqDatasetBinding(vamsasSet.getSequence(), ds);
5614 * XML dataset sequence ID to materialised dataset reference
5616 HashMap<String, AlignmentI> seqToDataset = new HashMap<>();
5619 * @return the first materialised dataset reference containing a dataset
5620 * sequence referenced in the given view
5622 * - sequences from the view
5624 AlignmentI checkIfHasDataset(List<Sequence> list)
5626 for (Sequence restoredSeq : list)
5628 AlignmentI datasetFor = seqToDataset.get(restoredSeq.getDsseqid());
5629 if (datasetFor != null)
5638 * Register ds as the containing dataset for the dataset sequences referenced
5639 * by sequences in list
5642 * - sequences in a view
5645 void updateSeqDatasetBinding(List<Sequence> list, AlignmentI ds)
5647 for (Sequence restoredSeq : list)
5649 AlignmentI prevDS = seqToDataset.put(restoredSeq.getDsseqid(), ds);
5650 if (prevDS != null && prevDS != ds)
5652 warn("Dataset sequence appears in many datasets: "
5653 + restoredSeq.getDsseqid());
5654 // TODO: try to merge!
5661 * sequence definition to create/merge dataset sequence for
5665 * vector to add new dataset sequence to
5666 * @param ignoreUnrefed
5667 * - when true, don't create new sequences from vamsasSeq if it's id
5668 * doesn't already have an asssociated Jalview sequence.
5670 * - used to reorder the sequence in the alignment according to the
5671 * vamsasSeq array ordering, to preserve ordering of dataset
5673 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
5674 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed, int vseqpos)
5676 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
5678 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
5679 boolean reorder = false;
5680 SequenceI dsq = null;
5681 if (sq != null && sq.getDatasetSequence() != null)
5683 dsq = sq.getDatasetSequence();
5689 if (sq == null && ignoreUnrefed)
5693 String sqid = vamsasSeq.getDsseqid();
5696 // need to create or add a new dataset sequence reference to this sequence
5699 dsq = seqRefIds.get(sqid);
5704 // make a new dataset sequence
5705 dsq = sq.createDatasetSequence();
5708 // make up a new dataset reference for this sequence
5709 sqid = seqHash(dsq);
5711 dsq.setVamsasId(uniqueSetSuffix + sqid);
5712 seqRefIds.put(sqid, dsq);
5717 dseqs.addElement(dsq);
5722 ds.addSequence(dsq);
5728 { // make this dataset sequence sq's dataset sequence
5729 sq.setDatasetSequence(dsq);
5730 // and update the current dataset alignment
5735 if (!dseqs.contains(dsq))
5742 if (ds.findIndex(dsq) < 0)
5744 ds.addSequence(dsq);
5751 // TODO: refactor this as a merge dataset sequence function
5752 // now check that sq (the dataset sequence) sequence really is the union of
5753 // all references to it
5754 // boolean pre = sq.getStart() < dsq.getStart();
5755 // boolean post = sq.getEnd() > dsq.getEnd();
5759 // StringBuffer sb = new StringBuffer();
5760 String newres = jalview.analysis.AlignSeq.extractGaps(
5761 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
5762 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
5763 && newres.length() > dsq.getLength())
5765 // Update with the longer sequence.
5769 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
5770 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
5771 * sb.append(newres.substring(newres.length() - sq.getEnd() -
5772 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
5774 dsq.setSequence(newres);
5776 // TODO: merges will never happen if we 'know' we have the real dataset
5777 // sequence - this should be detected when id==dssid
5779 "DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
5780 // + (pre ? "prepended" : "") + " "
5781 // + (post ? "appended" : ""));
5786 // sequence refs are identical. We may need to update the existing dataset
5787 // alignment with this one, though.
5788 if (ds != null && dseqs == null)
5790 int opos = ds.findIndex(dsq);
5791 SequenceI tseq = null;
5792 if (opos != -1 && vseqpos != opos)
5794 // remove from old position
5795 ds.deleteSequence(dsq);
5797 if (vseqpos < ds.getHeight())
5799 if (vseqpos != opos)
5801 // save sequence at destination position
5802 tseq = ds.getSequenceAt(vseqpos);
5803 ds.replaceSequenceAt(vseqpos, dsq);
5804 ds.addSequence(tseq);
5809 ds.addSequence(dsq);
5816 * TODO use AlignmentI here and in related methods - needs
5817 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
5819 Hashtable<String, AlignmentI> datasetIds = null;
5821 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
5823 private AlignmentI getDatasetFor(String datasetId)
5825 if (datasetIds == null)
5827 datasetIds = new Hashtable<>();
5830 if (datasetIds.containsKey(datasetId))
5832 return datasetIds.get(datasetId);
5837 private void addDatasetRef(String datasetId, AlignmentI dataset)
5839 if (datasetIds == null)
5841 datasetIds = new Hashtable<>();
5843 datasetIds.put(datasetId, dataset);
5847 * make a new dataset ID for this jalview dataset alignment
5852 private String getDatasetIdRef(AlignmentI dataset)
5854 if (dataset.getDataset() != null)
5856 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
5858 String datasetId = makeHashCode(dataset, null);
5859 if (datasetId == null)
5861 // make a new datasetId and record it
5862 if (dataset2Ids == null)
5864 dataset2Ids = new IdentityHashMap<>();
5868 datasetId = dataset2Ids.get(dataset);
5870 if (datasetId == null)
5872 datasetId = "ds" + dataset2Ids.size() + 1;
5873 dataset2Ids.put(dataset, datasetId);
5879 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5881 for (int d = 0; d < sequence.getDBRef().size(); d++)
5883 DBRef dr = sequence.getDBRef().get(d);
5884 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
5885 dr.getSource(), dr.getVersion(), dr.getAccessionId());
5886 if (dr.getMapping() != null)
5888 entry.setMap(addMapping(dr.getMapping()));
5890 datasetSequence.addDBRef(entry);
5894 private jalview.datamodel.Mapping addMapping(Mapping m)
5896 SequenceI dsto = null;
5897 // Mapping m = dr.getMapping();
5898 int fr[] = new int[m.getMapListFrom().size() * 2];
5899 Iterator<MapListFrom> from = m.getMapListFrom().iterator();// enumerateMapListFrom();
5900 for (int _i = 0; from.hasNext(); _i += 2)
5902 MapListFrom mf = from.next();
5903 fr[_i] = mf.getStart();
5904 fr[_i + 1] = mf.getEnd();
5906 int fto[] = new int[m.getMapListTo().size() * 2];
5907 Iterator<MapListTo> to = m.getMapListTo().iterator();// enumerateMapListTo();
5908 for (int _i = 0; to.hasNext(); _i += 2)
5910 MapListTo mf = to.next();
5911 fto[_i] = mf.getStart();
5912 fto[_i + 1] = mf.getEnd();
5914 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto, fr,
5915 fto, m.getMapFromUnit().intValue(),
5916 m.getMapToUnit().intValue());
5919 * (optional) choice of dseqFor or Sequence
5921 if (m.getDseqFor() != null)
5923 String dsfor = m.getDseqFor();
5924 if (seqRefIds.containsKey(dsfor))
5929 jmap.setTo(seqRefIds.get(dsfor));
5933 frefedSequence.add(newMappingRef(dsfor, jmap));
5936 else if (m.getSequence() != null)
5939 * local sequence definition
5941 Sequence ms = m.getSequence();
5942 SequenceI djs = null;
5943 String sqid = ms.getDsseqid();
5944 if (sqid != null && sqid.length() > 0)
5947 * recover dataset sequence
5949 djs = seqRefIds.get(sqid);
5954 "Warning - making up dataset sequence id for DbRef sequence map reference");
5955 sqid = ((Object) ms).toString(); // make up a new hascode for
5956 // undefined dataset sequence hash
5957 // (unlikely to happen)
5963 * make a new dataset sequence and add it to refIds hash
5965 djs = new jalview.datamodel.Sequence(ms.getName(),
5967 djs.setStart(jmap.getMap().getToLowest());
5968 djs.setEnd(jmap.getMap().getToHighest());
5969 djs.setVamsasId(uniqueSetSuffix + sqid);
5971 incompleteSeqs.put(sqid, djs);
5972 seqRefIds.put(sqid, djs);
5974 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5983 * Provides a 'copy' of an alignment view (on action New View) by 'saving' the
5984 * view as XML (but not to file), and then reloading it
5989 public AlignmentPanel copyAlignPanel(AlignmentPanel ap)
5992 JalviewModel jm = saveState(ap, null, null, null);
5995 jm.getVamsasModel().getSequenceSet().get(0).getDatasetId(),
5996 ap.getAlignment().getDataset());
5998 uniqueSetSuffix = "";
5999 // jm.getJalviewModelSequence().getViewport(0).setId(null);
6000 jm.getViewport().get(0).setId(null);
6001 // we don't overwrite the view we just copied
6003 if (this.frefedSequence == null)
6005 frefedSequence = new Vector<>();
6008 viewportsAdded.clear();
6010 AlignFrame af = loadFromObject(jm, null, false, null);
6011 af.getAlignPanels().clear();
6012 af.closeMenuItem_actionPerformed(true);
6015 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
6016 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
6017 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
6018 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
6019 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
6022 return af.alignPanel;
6025 private Hashtable jvids2vobj;
6027 private void warn(String msg)
6032 private void warn(String msg, Exception e)
6034 if (Cache.log != null)
6038 Cache.log.warn(msg, e);
6042 Cache.log.warn(msg);
6047 System.err.println("Warning: " + msg);
6050 e.printStackTrace();
6055 private void debug(String string)
6057 debug(string, null);
6060 private void debug(String msg, Exception e)
6062 if (Cache.log != null)
6066 Cache.log.debug(msg, e);
6070 Cache.log.debug(msg);
6075 System.err.println("Warning: " + msg);
6078 e.printStackTrace();
6084 * set the object to ID mapping tables used to write/recover objects and XML
6085 * ID strings for the jalview project. If external tables are provided then
6086 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
6087 * object goes out of scope. - also populates the datasetIds hashtable with
6088 * alignment objects containing dataset sequences
6091 * Map from ID strings to jalview datamodel
6093 * Map from jalview datamodel to ID strings
6097 public void setObjectMappingTables(Hashtable vobj2jv,
6098 IdentityHashMap jv2vobj)
6100 this.jv2vobj = jv2vobj;
6101 this.vobj2jv = vobj2jv;
6102 Iterator ds = jv2vobj.keySet().iterator();
6104 while (ds.hasNext())
6106 Object jvobj = ds.next();
6107 id = jv2vobj.get(jvobj).toString();
6108 if (jvobj instanceof jalview.datamodel.Alignment)
6110 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
6112 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
6115 else if (jvobj instanceof jalview.datamodel.Sequence)
6117 // register sequence object so the XML parser can recover it.
6118 if (seqRefIds == null)
6120 seqRefIds = new HashMap<>();
6122 if (seqsToIds == null)
6124 seqsToIds = new IdentityHashMap<>();
6126 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
6127 seqsToIds.put((SequenceI) jvobj, id);
6129 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
6132 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
6133 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
6134 if (jvann.annotationId == null)
6136 jvann.annotationId = anid;
6138 if (!jvann.annotationId.equals(anid))
6140 // TODO verify that this is the correct behaviour
6141 this.warn("Overriding Annotation ID for " + anid
6142 + " from different id : " + jvann.annotationId);
6143 jvann.annotationId = anid;
6146 else if (jvobj instanceof String)
6148 if (jvids2vobj == null)
6150 jvids2vobj = new Hashtable();
6151 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
6156 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
6162 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
6163 * objects created from the project archive. If string is null (default for
6164 * construction) then suffix will be set automatically.
6168 public void setUniqueSetSuffix(String string)
6170 uniqueSetSuffix = string;
6175 * uses skipList2 as the skipList for skipping views on sequence sets
6176 * associated with keys in the skipList
6180 public void setSkipList(Hashtable skipList2)
6182 skipList = skipList2;
6186 * Reads the jar entry of given name and returns its contents, or null if the
6187 * entry is not found.
6190 * @param jarEntryName
6193 protected String readJarEntry(jarInputStreamProvider jprovider,
6194 String jarEntryName)
6196 String result = null;
6197 BufferedReader in = null;
6202 * Reopen the jar input stream and traverse its entries to find a matching
6205 JarInputStream jin = jprovider.getJarInputStream();
6206 JarEntry entry = null;
6209 entry = jin.getNextJarEntry();
6210 } while (entry != null && !entry.getName().equals(jarEntryName));
6214 StringBuilder out = new StringBuilder(256);
6215 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
6218 while ((data = in.readLine()) != null)
6222 result = out.toString();
6226 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
6228 } catch (Exception ex)
6230 ex.printStackTrace();
6238 } catch (IOException e)
6249 * Returns an incrementing counter (0, 1, 2...)
6253 private synchronized int nextCounter()
6259 * Loads any saved PCA viewers
6264 protected void loadPCAViewers(JalviewModel model, AlignmentPanel ap)
6268 List<PcaViewer> pcaviewers = model.getPcaViewer();
6269 for (PcaViewer viewer : pcaviewers)
6271 String modelName = viewer.getScoreModelName();
6272 SimilarityParamsI params = new SimilarityParams(
6273 viewer.isIncludeGappedColumns(), viewer.isMatchGaps(),
6274 viewer.isIncludeGaps(),
6275 viewer.isDenominateByShortestLength());
6278 * create the panel (without computing the PCA)
6280 PCAPanel panel = new PCAPanel(ap, modelName, params);
6282 panel.setTitle(viewer.getTitle());
6283 panel.setBounds(new Rectangle(viewer.getXpos(), viewer.getYpos(),
6284 viewer.getWidth(), viewer.getHeight()));
6286 boolean showLabels = viewer.isShowLabels();
6287 panel.setShowLabels(showLabels);
6288 panel.getRotatableCanvas().setShowLabels(showLabels);
6289 panel.getRotatableCanvas()
6290 .setBgColour(new Color(viewer.getBgColour()));
6291 panel.getRotatableCanvas()
6292 .setApplyToAllViews(viewer.isLinkToAllViews());
6295 * load PCA output data
6297 ScoreModelI scoreModel = ScoreModels.getInstance()
6298 .getScoreModel(modelName, ap);
6299 PCA pca = new PCA(null, scoreModel, params);
6300 PcaDataType pcaData = viewer.getPcaData();
6302 MatrixI pairwise = loadDoubleMatrix(pcaData.getPairwiseMatrix());
6303 pca.setPairwiseScores(pairwise);
6305 MatrixI triDiag = loadDoubleMatrix(pcaData.getTridiagonalMatrix());
6306 pca.setTridiagonal(triDiag);
6308 MatrixI result = loadDoubleMatrix(pcaData.getEigenMatrix());
6309 pca.setEigenmatrix(result);
6311 panel.getPcaModel().setPCA(pca);
6314 * we haven't saved the input data! (JAL-2647 to do)
6316 panel.setInputData(null);
6319 * add the sequence points for the PCA display
6321 List<jalview.datamodel.SequencePoint> seqPoints = new ArrayList<>();
6322 for (SequencePoint sp : viewer.getSequencePoint())
6324 String seqId = sp.getSequenceRef();
6325 SequenceI seq = seqRefIds.get(seqId);
6328 throw new IllegalStateException(
6329 "Unmatched seqref for PCA: " + seqId);
6331 Point pt = new Point(sp.getXPos(), sp.getYPos(), sp.getZPos());
6332 jalview.datamodel.SequencePoint seqPoint = new jalview.datamodel.SequencePoint(
6334 seqPoints.add(seqPoint);
6336 panel.getRotatableCanvas().setPoints(seqPoints, seqPoints.size());
6339 * set min-max ranges and scale after setPoints (which recomputes them)
6341 panel.getRotatableCanvas().setScaleFactor(viewer.getScaleFactor());
6342 SeqPointMin spMin = viewer.getSeqPointMin();
6343 float[] min = new float[] { spMin.getXPos(), spMin.getYPos(),
6345 SeqPointMax spMax = viewer.getSeqPointMax();
6346 float[] max = new float[] { spMax.getXPos(), spMax.getYPos(),
6348 panel.getRotatableCanvas().setSeqMinMax(min, max);
6350 // todo: hold points list in PCAModel only
6351 panel.getPcaModel().setSequencePoints(seqPoints);
6353 panel.setSelectedDimensionIndex(viewer.getXDim(), X);
6354 panel.setSelectedDimensionIndex(viewer.getYDim(), Y);
6355 panel.setSelectedDimensionIndex(viewer.getZDim(), Z);
6357 // is this duplication needed?
6358 panel.setTop(seqPoints.size() - 1);
6359 panel.getPcaModel().setTop(seqPoints.size() - 1);
6362 * add the axes' end points for the display
6364 for (int i = 0; i < 3; i++)
6366 Axis axis = viewer.getAxis().get(i);
6367 panel.getRotatableCanvas().getAxisEndPoints()[i] = new Point(
6368 axis.getXPos(), axis.getYPos(), axis.getZPos());
6371 Desktop.addInternalFrame(panel, MessageManager.formatMessage(
6372 "label.calc_title", "PCA", modelName), 475, 450);
6374 } catch (Exception ex)
6376 Cache.log.error("Error loading PCA: " + ex.toString());
6381 * Populates an XML model of the feature colour scheme for one feature type
6383 * @param featureType
6387 public static Colour marshalColour(
6388 String featureType, FeatureColourI fcol)
6390 Colour col = new Colour();
6391 if (fcol.isSimpleColour())
6393 col.setRGB(Format.getHexString(fcol.getColour()));
6397 col.setRGB(Format.getHexString(fcol.getMaxColour()));
6398 col.setMin(fcol.getMin());
6399 col.setMax(fcol.getMax());
6400 col.setMinRGB(jalview.util.Format.getHexString(fcol.getMinColour()));
6401 col.setAutoScale(fcol.isAutoScaled());
6402 col.setThreshold(fcol.getThreshold());
6403 col.setColourByLabel(fcol.isColourByLabel());
6404 col.setThreshType(fcol.isAboveThreshold() ? ThresholdType.ABOVE
6405 : (fcol.isBelowThreshold() ? ThresholdType.BELOW
6406 : ThresholdType.NONE));
6407 if (fcol.isColourByAttribute())
6409 final String[] attName = fcol.getAttributeName();
6410 col.getAttributeName().add(attName[0]);
6411 if (attName.length > 1)
6413 col.getAttributeName().add(attName[1]);
6416 Color noColour = fcol.getNoColour();
6417 if (noColour == null)
6419 col.setNoValueColour(NoValueColour.NONE);
6421 else if (noColour == fcol.getMaxColour())
6423 col.setNoValueColour(NoValueColour.MAX);
6427 col.setNoValueColour(NoValueColour.MIN);
6430 col.setName(featureType);
6435 * Populates an XML model of the feature filter(s) for one feature type
6437 * @param firstMatcher
6438 * the first (or only) match condition)
6440 * remaining match conditions (if any)
6442 * if true, conditions are and-ed, else or-ed
6444 public static jalview.xml.binding.jalview.FeatureMatcherSet marshalFilter(
6445 FeatureMatcherI firstMatcher, Iterator<FeatureMatcherI> filters,
6448 jalview.xml.binding.jalview.FeatureMatcherSet result = new jalview.xml.binding.jalview.FeatureMatcherSet();
6450 if (filters.hasNext())
6455 CompoundMatcher compound = new CompoundMatcher();
6456 compound.setAnd(and);
6457 jalview.xml.binding.jalview.FeatureMatcherSet matcher1 = marshalFilter(
6458 firstMatcher, Collections.emptyIterator(), and);
6459 // compound.addMatcherSet(matcher1);
6460 compound.getMatcherSet().add(matcher1);
6461 FeatureMatcherI nextMatcher = filters.next();
6462 jalview.xml.binding.jalview.FeatureMatcherSet matcher2 = marshalFilter(
6463 nextMatcher, filters, and);
6464 // compound.addMatcherSet(matcher2);
6465 compound.getMatcherSet().add(matcher2);
6466 result.setCompoundMatcher(compound);
6471 * single condition matcher
6473 // MatchCondition matcherModel = new MatchCondition();
6474 jalview.xml.binding.jalview.FeatureMatcher matcherModel = new jalview.xml.binding.jalview.FeatureMatcher();
6475 matcherModel.setCondition(
6476 firstMatcher.getMatcher().getCondition().getStableName());
6477 matcherModel.setValue(firstMatcher.getMatcher().getPattern());
6478 if (firstMatcher.isByAttribute())
6480 matcherModel.setBy(FilterBy.BY_ATTRIBUTE);
6481 // matcherModel.setAttributeName(firstMatcher.getAttribute());
6482 String[] attName = firstMatcher.getAttribute();
6483 matcherModel.getAttributeName().add(attName[0]); // attribute
6484 if (attName.length > 1)
6486 matcherModel.getAttributeName().add(attName[1]); // sub-attribute
6489 else if (firstMatcher.isByLabel())
6491 matcherModel.setBy(FilterBy.BY_LABEL);
6493 else if (firstMatcher.isByScore())
6495 matcherModel.setBy(FilterBy.BY_SCORE);
6497 result.setMatchCondition(matcherModel);
6504 * Loads one XML model of a feature filter to a Jalview object
6506 * @param featureType
6507 * @param matcherSetModel
6510 public static FeatureMatcherSetI parseFilter(
6512 jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel)
6514 FeatureMatcherSetI result = new FeatureMatcherSet();
6517 parseFilterConditions(result, matcherSetModel, true);
6518 } catch (IllegalStateException e)
6520 // mixing AND and OR conditions perhaps
6522 String.format("Error reading filter conditions for '%s': %s",
6523 featureType, e.getMessage()));
6524 // return as much as was parsed up to the error
6531 * Adds feature match conditions to matcherSet as unmarshalled from XML
6532 * (possibly recursively for compound conditions)
6535 * @param matcherSetModel
6537 * if true, multiple conditions are AND-ed, else they are OR-ed
6538 * @throws IllegalStateException
6539 * if AND and OR conditions are mixed
6541 protected static void parseFilterConditions(
6542 FeatureMatcherSetI matcherSet,
6543 jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel,
6546 jalview.xml.binding.jalview.FeatureMatcher mc = matcherSetModel
6547 .getMatchCondition();
6553 FilterBy filterBy = mc.getBy();
6554 Condition cond = Condition.fromString(mc.getCondition());
6555 String pattern = mc.getValue();
6556 FeatureMatcherI matchCondition = null;
6557 if (filterBy == FilterBy.BY_LABEL)
6559 matchCondition = FeatureMatcher.byLabel(cond, pattern);
6561 else if (filterBy == FilterBy.BY_SCORE)
6563 matchCondition = FeatureMatcher.byScore(cond, pattern);
6566 else if (filterBy == FilterBy.BY_ATTRIBUTE)
6568 final List<String> attributeName = mc.getAttributeName();
6569 String[] attNames = attributeName
6570 .toArray(new String[attributeName.size()]);
6571 matchCondition = FeatureMatcher.byAttribute(cond, pattern,
6576 * note this throws IllegalStateException if AND-ing to a
6577 * previously OR-ed compound condition, or vice versa
6581 matcherSet.and(matchCondition);
6585 matcherSet.or(matchCondition);
6591 * compound condition
6593 List<jalview.xml.binding.jalview.FeatureMatcherSet> matchers = matcherSetModel
6594 .getCompoundMatcher().getMatcherSet();
6595 boolean anded = matcherSetModel.getCompoundMatcher().isAnd();
6596 if (matchers.size() == 2)
6598 parseFilterConditions(matcherSet, matchers.get(0), anded);
6599 parseFilterConditions(matcherSet, matchers.get(1), anded);
6603 System.err.println("Malformed compound filter condition");
6609 * Loads one XML model of a feature colour to a Jalview object
6611 * @param colourModel
6614 public static FeatureColourI parseColour(Colour colourModel)
6616 FeatureColourI colour = null;
6618 if (colourModel.getMax() != null)
6620 Color mincol = null;
6621 Color maxcol = null;
6622 Color noValueColour = null;
6626 mincol = new Color(Integer.parseInt(colourModel.getMinRGB(), 16));
6627 maxcol = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6628 } catch (Exception e)
6630 Cache.log.warn("Couldn't parse out graduated feature color.", e);
6633 NoValueColour noCol = colourModel.getNoValueColour();
6634 if (noCol == NoValueColour.MIN)
6636 noValueColour = mincol;
6638 else if (noCol == NoValueColour.MAX)
6640 noValueColour = maxcol;
6643 colour = new FeatureColour(maxcol, mincol, maxcol, noValueColour,
6644 safeFloat(colourModel.getMin()),
6645 safeFloat(colourModel.getMax()));
6646 final List<String> attributeName = colourModel.getAttributeName();
6647 String[] attributes = attributeName
6648 .toArray(new String[attributeName.size()]);
6649 if (attributes != null && attributes.length > 0)
6651 colour.setAttributeName(attributes);
6653 if (colourModel.isAutoScale() != null)
6655 colour.setAutoScaled(colourModel.isAutoScale().booleanValue());
6657 if (colourModel.isColourByLabel() != null)
6659 colour.setColourByLabel(
6660 colourModel.isColourByLabel().booleanValue());
6662 if (colourModel.getThreshold() != null)
6664 colour.setThreshold(colourModel.getThreshold().floatValue());
6666 ThresholdType ttyp = colourModel.getThreshType();
6667 if (ttyp == ThresholdType.ABOVE)
6669 colour.setAboveThreshold(true);
6671 else if (ttyp == ThresholdType.BELOW)
6673 colour.setBelowThreshold(true);
6678 Color color = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6679 colour = new FeatureColour(color);