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
3626 String hmmJarFile = jseqs.get(i).getHmmerProfile();
3627 if (hmmJarFile != null && jprovider != null)
3629 loadHmmerProfile(jprovider, hmmJarFile, al.getSequenceAt(i));
3633 } // end !multipleview
3635 // ///////////////////////////////
3636 // LOAD SEQUENCE MAPPINGS
3638 if (vamsasSet.getAlcodonFrame().size() > 0)
3640 // TODO Potentially this should only be done once for all views of an
3642 List<AlcodonFrame> alc = vamsasSet.getAlcodonFrame();
3643 for (int i = 0; i < alc.size(); i++)
3645 AlignedCodonFrame cf = new AlignedCodonFrame();
3646 if (alc.get(i).getAlcodMap().size() > 0)
3648 List<AlcodMap> maps = alc.get(i).getAlcodMap();
3649 for (int m = 0; m < maps.size(); m++)
3651 AlcodMap map = maps.get(m);
3652 SequenceI dnaseq = seqRefIds.get(map.getDnasq());
3654 jalview.datamodel.Mapping mapping = null;
3655 // attach to dna sequence reference.
3656 if (map.getMapping() != null)
3658 mapping = addMapping(map.getMapping());
3659 if (dnaseq != null && mapping.getTo() != null)
3661 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
3667 newAlcodMapRef(map.getDnasq(), cf, mapping));
3671 al.addCodonFrame(cf);
3676 // ////////////////////////////////
3678 List<JvAnnotRow> autoAlan = new ArrayList<>();
3681 * store any annotations which forward reference a group's ID
3683 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<>();
3685 if (vamsasSet.getAnnotation().size()/*Count()*/ > 0)
3687 List<Annotation> an = vamsasSet.getAnnotation();
3689 for (int i = 0; i < an.size(); i++)
3691 Annotation annotation = an.get(i);
3694 * test if annotation is automatically calculated for this view only
3696 boolean autoForView = false;
3697 if (annotation.getLabel().equals("Quality")
3698 || annotation.getLabel().equals("Conservation")
3699 || annotation.getLabel().equals("Consensus"))
3701 // Kludge for pre 2.5 projects which lacked the autocalculated flag
3703 // JAXB has no has() test; schema defaults value to false
3704 // if (!annotation.hasAutoCalculated())
3706 // annotation.setAutoCalculated(true);
3709 if (autoForView || annotation.isAutoCalculated())
3711 // remove ID - we don't recover annotation from other views for
3712 // view-specific annotation
3713 annotation.setId(null);
3716 // set visibility for other annotation in this view
3717 String annotationId = annotation.getId();
3718 if (annotationId != null && annotationIds.containsKey(annotationId))
3720 AlignmentAnnotation jda = annotationIds.get(annotationId);
3721 // in principle Visible should always be true for annotation displayed
3722 // in multiple views
3723 if (annotation.isVisible() != null)
3725 jda.visible = annotation.isVisible();
3728 al.addAnnotation(jda);
3732 // Construct new annotation from model.
3733 List<AnnotationElement> ae = annotation.getAnnotationElement();
3734 jalview.datamodel.Annotation[] anot = null;
3735 java.awt.Color firstColour = null;
3737 if (!annotation.isScoreOnly())
3739 anot = new jalview.datamodel.Annotation[al.getWidth()];
3740 for (int aa = 0; aa < ae.size() && aa < anot.length; aa++)
3742 AnnotationElement annElement = ae.get(aa);
3743 anpos = annElement.getPosition();
3745 if (anpos >= anot.length)
3750 float value = safeFloat(annElement.getValue());
3751 anot[anpos] = new jalview.datamodel.Annotation(
3752 annElement.getDisplayCharacter(),
3753 annElement.getDescription(),
3754 (annElement.getSecondaryStructure() == null
3755 || annElement.getSecondaryStructure()
3759 .getSecondaryStructure()
3762 anot[anpos].colour = new Color(safeInt(annElement.getColour()));
3763 if (firstColour == null)
3765 firstColour = anot[anpos].colour;
3769 jalview.datamodel.AlignmentAnnotation jaa = null;
3771 if (annotation.isGraph())
3773 float llim = 0, hlim = 0;
3774 // if (autoForView || an[i].isAutoCalculated()) {
3777 jaa = new jalview.datamodel.AlignmentAnnotation(
3778 annotation.getLabel(), annotation.getDescription(), anot,
3779 llim, hlim, safeInt(annotation.getGraphType()));
3781 jaa.graphGroup = safeInt(annotation.getGraphGroup());
3782 jaa._linecolour = firstColour;
3783 if (annotation.getThresholdLine() != null)
3785 jaa.setThreshold(new jalview.datamodel.GraphLine(
3786 safeFloat(annotation.getThresholdLine().getValue()),
3787 annotation.getThresholdLine().getLabel(),
3788 new java.awt.Color(safeInt(
3789 annotation.getThresholdLine().getColour()))));
3791 if (autoForView || annotation.isAutoCalculated())
3793 // Hardwire the symbol display line to ensure that labels for
3794 // histograms are displayed
3800 jaa = new jalview.datamodel.AlignmentAnnotation(
3801 annotation.getLabel(), annotation.getDescription(), anot);
3802 jaa._linecolour = firstColour;
3804 // register new annotation
3805 if (annotation.getId() != null)
3807 annotationIds.put(annotation.getId(), jaa);
3808 jaa.annotationId = annotation.getId();
3810 // recover sequence association
3811 String sequenceRef = annotation.getSequenceRef();
3812 if (sequenceRef != null)
3814 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3815 SequenceI sequence = seqRefIds.get(sequenceRef);
3816 if (sequence == null)
3818 // in pre-2.9 projects sequence ref is to sequence name
3819 sequence = al.findName(sequenceRef);
3821 if (sequence != null)
3823 jaa.createSequenceMapping(sequence, 1, true);
3824 sequence.addAlignmentAnnotation(jaa);
3827 // and make a note of any group association
3828 if (annotation.getGroupRef() != null
3829 && annotation.getGroupRef().length() > 0)
3831 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3832 .get(annotation.getGroupRef());
3835 aal = new ArrayList<>();
3836 groupAnnotRefs.put(annotation.getGroupRef(), aal);
3841 if (annotation.getScore() != null)
3843 jaa.setScore(annotation.getScore().doubleValue());
3845 if (annotation.isVisible() != null)
3847 jaa.visible = annotation.isVisible().booleanValue();
3850 if (annotation.isCentreColLabels() != null)
3852 jaa.centreColLabels = annotation.isCentreColLabels()
3856 if (annotation.isScaleColLabels() != null)
3858 jaa.scaleColLabel = annotation.isScaleColLabels().booleanValue();
3860 if (annotation.isAutoCalculated())
3862 // newer files have an 'autoCalculated' flag and store calculation
3863 // state in viewport properties
3864 jaa.autoCalculated = true; // means annotation will be marked for
3865 // update at end of load.
3867 if (annotation.getGraphHeight() != null)
3869 jaa.graphHeight = annotation.getGraphHeight().intValue();
3871 jaa.belowAlignment = annotation.isBelowAlignment();
3872 jaa.setCalcId(annotation.getCalcId());
3873 if (annotation.getProperty().size() > 0)
3875 for (Annotation.Property prop : annotation
3878 jaa.setProperty(prop.getName(), prop.getValue());
3881 if (jaa.autoCalculated)
3883 autoAlan.add(new JvAnnotRow(i, jaa));
3886 // if (!autoForView)
3888 // add autocalculated group annotation and any user created annotation
3890 al.addAnnotation(jaa);
3894 // ///////////////////////
3896 // Create alignment markup and styles for this view
3897 if (jalviewModel.getJGroup().size() > 0)
3899 List<JGroup> groups = jalviewModel.getJGroup();
3900 boolean addAnnotSchemeGroup = false;
3901 for (int i = 0; i < groups.size(); i++)
3903 JGroup jGroup = groups.get(i);
3904 ColourSchemeI cs = null;
3905 if (jGroup.getColour() != null)
3907 if (jGroup.getColour().startsWith("ucs"))
3909 cs = getUserColourScheme(jalviewModel, jGroup.getColour());
3911 else if (jGroup.getColour().equals("AnnotationColourGradient")
3912 && jGroup.getAnnotationColours() != null)
3914 addAnnotSchemeGroup = true;
3918 cs = ColourSchemeProperty.getColourScheme(null, al,
3919 jGroup.getColour());
3922 int pidThreshold = safeInt(jGroup.getPidThreshold());
3924 Vector<SequenceI> seqs = new Vector<>();
3926 for (int s = 0; s < jGroup.getSeq().size(); s++)
3928 String seqId = jGroup.getSeq().get(s);
3929 SequenceI ts = seqRefIds.get(seqId);
3933 seqs.addElement(ts);
3937 if (seqs.size() < 1)
3942 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3943 safeBoolean(jGroup.isDisplayBoxes()),
3944 safeBoolean(jGroup.isDisplayText()),
3945 safeBoolean(jGroup.isColourText()),
3946 safeInt(jGroup.getStart()), safeInt(jGroup.getEnd()));
3947 sg.getGroupColourScheme().setThreshold(pidThreshold, true);
3948 sg.getGroupColourScheme()
3949 .setConservationInc(safeInt(jGroup.getConsThreshold()));
3950 sg.setOutlineColour(new Color(safeInt(jGroup.getOutlineColour())));
3952 sg.textColour = new Color(safeInt(jGroup.getTextCol1()));
3953 sg.textColour2 = new Color(safeInt(jGroup.getTextCol2()));
3954 sg.setShowNonconserved(safeBoolean(jGroup.isShowUnconserved()));
3955 sg.thresholdTextColour = safeInt(jGroup.getTextColThreshold());
3956 // attributes with a default in the schema are never null
3957 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3958 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3959 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3960 sg.setIgnoreGapsConsensus(jGroup.isIgnoreGapsinConsensus());
3961 if (jGroup.getConsThreshold() != null
3962 && jGroup.getConsThreshold().intValue() != 0)
3964 Conservation c = new Conservation("All", sg.getSequences(null), 0,
3967 c.verdict(false, 25);
3968 sg.cs.setConservation(c);
3971 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3973 // re-instate unique group/annotation row reference
3974 List<AlignmentAnnotation> jaal = groupAnnotRefs
3975 .get(jGroup.getId());
3978 for (AlignmentAnnotation jaa : jaal)
3981 if (jaa.autoCalculated)
3983 // match up and try to set group autocalc alignment row for this
3985 if (jaa.label.startsWith("Consensus for "))
3987 sg.setConsensus(jaa);
3989 // match up and try to set group autocalc alignment row for this
3991 if (jaa.label.startsWith("Conservation for "))
3993 sg.setConservationRow(jaa);
4000 if (addAnnotSchemeGroup)
4002 // reconstruct the annotation colourscheme
4003 sg.setColourScheme(constructAnnotationColour(
4004 jGroup.getAnnotationColours(), null, al, jalviewModel, false));
4010 // only dataset in this model, so just return.
4013 // ///////////////////////////////
4016 AlignFrame af = null;
4017 AlignViewport av = null;
4018 // now check to see if we really need to create a new viewport.
4019 if (multipleView && viewportsAdded.size() == 0)
4021 // We recovered an alignment for which a viewport already exists.
4022 // TODO: fix up any settings necessary for overlaying stored state onto
4023 // state recovered from another document. (may not be necessary).
4024 // we may need a binding from a viewport in memory to one recovered from
4026 // and then recover its containing af to allow the settings to be applied.
4027 // TODO: fix for vamsas demo
4029 "About to recover a viewport for existing alignment: Sequence set ID is "
4031 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
4032 if (seqsetobj != null)
4034 if (seqsetobj instanceof String)
4036 uniqueSeqSetId = (String) seqsetobj;
4038 "Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
4044 "Warning : Collision between sequence set ID string and existing jalview object mapping.");
4050 * indicate that annotation colours are applied across all groups (pre
4051 * Jalview 2.8.1 behaviour)
4053 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan("2.8.1",
4054 jalviewModel.getVersion());
4056 AlignmentPanel ap = null;
4057 boolean isnewview = true;
4060 // Check to see if this alignment already has a view id == viewId
4061 jalview.gui.AlignmentPanel views[] = Desktop
4062 .getAlignmentPanels(uniqueSeqSetId);
4063 if (views != null && views.length > 0)
4065 for (int v = 0; v < views.length; v++)
4067 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
4069 // recover the existing alignpanel, alignframe, viewport
4070 af = views[v].alignFrame;
4073 // TODO: could even skip resetting view settings if we don't want to
4074 // change the local settings from other jalview processes
4083 af = loadViewport(file, jseqs, hiddenSeqs, al, jalviewModel, view,
4084 uniqueSeqSetId, viewId, autoAlan);
4085 av = af.getViewport();
4090 * Load any trees, PDB structures and viewers
4092 * Not done if flag is false (when this method is used for New View)
4094 if (loadTreesAndStructures)
4096 loadTrees(jalviewModel, view, af, av, ap);
4097 loadPCAViewers(jalviewModel, ap);
4098 loadPDBStructures(jprovider, jseqs, af, ap);
4099 loadRnaViewers(jprovider, jseqs, ap);
4101 // and finally return.
4106 * Loads a HMMER profile from a file stored in the project, and associates it
4107 * with the specified sequence
4113 protected void loadHmmerProfile(jarInputStreamProvider jprovider,
4114 String hmmJarFile, SequenceI seq)
4118 String hmmFile = copyJarEntry(jprovider, hmmJarFile, "hmm", null);
4119 HMMFile parser = new HMMFile(hmmFile, DataSourceType.FILE);
4120 HiddenMarkovModel hmmModel = parser.getHMM();
4121 hmmModel = new HiddenMarkovModel(hmmModel, seq);
4122 seq.setHMM(hmmModel);
4123 } catch (IOException e)
4125 warn("Error loading HMM profile for " + seq.getName() + ": "
4131 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
4132 * panel is restored from separate jar entries, two (gapped and trimmed) per
4133 * sequence and secondary structure.
4135 * Currently each viewer shows just one sequence and structure (gapped and
4136 * trimmed), however this method is designed to support multiple sequences or
4137 * structures in viewers if wanted in future.
4143 private void loadRnaViewers(jarInputStreamProvider jprovider,
4144 List<JSeq> jseqs, AlignmentPanel ap)
4147 * scan the sequences for references to viewers; create each one the first
4148 * time it is referenced, add Rna models to existing viewers
4150 for (JSeq jseq : jseqs)
4152 for (int i = 0; i < jseq.getRnaViewer().size(); i++)
4154 RnaViewer viewer = jseq.getRnaViewer().get(i);
4155 AppVarna appVarna = findOrCreateVarnaViewer(viewer, uniqueSetSuffix,
4158 for (int j = 0; j < viewer.getSecondaryStructure().size(); j++)
4160 SecondaryStructure ss = viewer.getSecondaryStructure().get(j);
4161 SequenceI seq = seqRefIds.get(jseq.getId());
4162 AlignmentAnnotation ann = this.annotationIds
4163 .get(ss.getAnnotationId());
4166 * add the structure to the Varna display (with session state copied
4167 * from the jar to a temporary file)
4169 boolean gapped = safeBoolean(ss.isGapped());
4170 String rnaTitle = ss.getTitle();
4171 String sessionState = ss.getViewerState();
4172 String tempStateFile = copyJarEntry(jprovider, sessionState,
4174 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
4175 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
4177 appVarna.setInitialSelection(safeInt(viewer.getSelectedRna()));
4183 * Locate and return an already instantiated matching AppVarna, or create one
4187 * @param viewIdSuffix
4191 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
4192 String viewIdSuffix, AlignmentPanel ap)
4195 * on each load a suffix is appended to the saved viewId, to avoid conflicts
4196 * if load is repeated
4198 String postLoadId = viewer.getViewId() + viewIdSuffix;
4199 for (JInternalFrame frame : getAllFrames())
4201 if (frame instanceof AppVarna)
4203 AppVarna varna = (AppVarna) frame;
4204 if (postLoadId.equals(varna.getViewId()))
4206 // this viewer is already instantiated
4207 // could in future here add ap as another 'parent' of the
4208 // AppVarna window; currently just 1-to-many
4215 * viewer not found - make it
4217 RnaViewerModel model = new RnaViewerModel(postLoadId, viewer.getTitle(),
4218 safeInt(viewer.getXpos()), safeInt(viewer.getYpos()),
4219 safeInt(viewer.getWidth()), safeInt(viewer.getHeight()),
4220 safeInt(viewer.getDividerLocation()));
4221 AppVarna varna = new AppVarna(model, ap);
4227 * Load any saved trees
4235 protected void loadTrees(JalviewModel jm, Viewport view,
4236 AlignFrame af, AlignViewport av, AlignmentPanel ap)
4238 // TODO result of automated refactoring - are all these parameters needed?
4241 for (int t = 0; t < jm.getTree().size(); t++)
4244 Tree tree = jm.getTree().get(t);
4246 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
4249 tp = af.showNewickTree(new NewickFile(tree.getNewick()),
4250 tree.getTitle(), safeInt(tree.getWidth()),
4251 safeInt(tree.getHeight()), safeInt(tree.getXpos()),
4252 safeInt(tree.getYpos()));
4253 if (tree.getId() != null)
4255 // perhaps bind the tree id to something ?
4260 // update local tree attributes ?
4261 // TODO: should check if tp has been manipulated by user - if so its
4262 // settings shouldn't be modified
4263 tp.setTitle(tree.getTitle());
4264 tp.setBounds(new Rectangle(safeInt(tree.getXpos()),
4265 safeInt(tree.getYpos()), safeInt(tree.getWidth()),
4266 safeInt(tree.getHeight())));
4267 tp.setViewport(av); // af.viewport;
4268 // TODO: verify 'associate with all views' works still
4269 tp.getTreeCanvas().setViewport(av); // af.viewport;
4270 tp.getTreeCanvas().setAssociatedPanel(ap); // af.alignPanel;
4272 tp.getTreeCanvas().setApplyToAllViews(tree.isLinkToAllViews());
4275 warn("There was a problem recovering stored Newick tree: \n"
4276 + tree.getNewick());
4280 tp.fitToWindow.setState(safeBoolean(tree.isFitToWindow()));
4281 tp.fitToWindow_actionPerformed(null);
4283 if (tree.getFontName() != null)
4286 new Font(tree.getFontName(), safeInt(tree.getFontStyle()),
4287 safeInt(tree.getFontSize())));
4292 new Font(view.getFontName(), safeInt(view.getFontStyle()),
4293 safeInt(view.getFontSize())));
4296 tp.showPlaceholders(safeBoolean(tree.isMarkUnlinked()));
4297 tp.showBootstrap(safeBoolean(tree.isShowBootstrap()));
4298 tp.showDistances(safeBoolean(tree.isShowDistances()));
4300 tp.getTreeCanvas().setThreshold(safeFloat(tree.getThreshold()));
4302 if (safeBoolean(tree.isCurrentTree()))
4304 af.getViewport().setCurrentTree(tp.getTree());
4308 } catch (Exception ex)
4310 ex.printStackTrace();
4315 * Load and link any saved structure viewers.
4322 protected void loadPDBStructures(jarInputStreamProvider jprovider,
4323 List<JSeq> jseqs, AlignFrame af, AlignmentPanel ap)
4326 * Run through all PDB ids on the alignment, and collect mappings between
4327 * distinct view ids and all sequences referring to that view.
4329 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<>();
4331 for (int i = 0; i < jseqs.size(); i++)
4333 JSeq jseq = jseqs.get(i);
4334 if (jseq.getPdbids().size() > 0)
4336 List<Pdbids> ids = jseq.getPdbids();
4337 for (int p = 0; p < ids.size(); p++)
4339 Pdbids pdbid = ids.get(p);
4340 final int structureStateCount = pdbid.getStructureState().size();
4341 for (int s = 0; s < structureStateCount; s++)
4343 // check to see if we haven't already created this structure view
4344 final StructureState structureState = pdbid
4345 .getStructureState().get(s);
4346 String sviewid = (structureState.getViewId() == null) ? null
4347 : structureState.getViewId() + uniqueSetSuffix;
4348 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
4349 // Originally : pdbid.getFile()
4350 // : TODO: verify external PDB file recovery still works in normal
4351 // jalview project load
4353 loadPDBFile(jprovider, pdbid.getId(), pdbid.getFile()));
4354 jpdb.setId(pdbid.getId());
4356 int x = safeInt(structureState.getXpos());
4357 int y = safeInt(structureState.getYpos());
4358 int width = safeInt(structureState.getWidth());
4359 int height = safeInt(structureState.getHeight());
4361 // Probably don't need to do this anymore...
4362 // Desktop.desktop.getComponentAt(x, y);
4363 // TODO: NOW: check that this recovers the PDB file correctly.
4364 String pdbFile = loadPDBFile(jprovider, pdbid.getId(),
4366 jalview.datamodel.SequenceI seq = seqRefIds
4367 .get(jseq.getId() + "");
4368 if (sviewid == null)
4370 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width + ","
4373 if (!structureViewers.containsKey(sviewid))
4375 structureViewers.put(sviewid,
4376 new StructureViewerModel(x, y, width, height, false,
4377 false, true, structureState.getViewId(),
4378 structureState.getType()));
4379 // Legacy pre-2.7 conversion JAL-823 :
4380 // do not assume any view has to be linked for colour by
4384 // assemble String[] { pdb files }, String[] { id for each
4385 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
4386 // seqs_file 2}, boolean[] {
4387 // linkAlignPanel,superposeWithAlignpanel}} from hash
4388 StructureViewerModel jmoldat = structureViewers.get(sviewid);
4389 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
4390 || structureState.isAlignwithAlignPanel());
4393 * Default colour by linked panel to false if not specified (e.g.
4394 * for pre-2.7 projects)
4396 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
4397 colourWithAlignPanel |= structureState.isColourwithAlignPanel();
4398 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
4401 * Default colour by viewer to true if not specified (e.g. for
4404 boolean colourByViewer = jmoldat.isColourByViewer();
4405 colourByViewer &= structureState.isColourByJmol();
4406 jmoldat.setColourByViewer(colourByViewer);
4408 if (jmoldat.getStateData().length() < structureState
4409 .getValue()/*Content()*/.length())
4411 jmoldat.setStateData(structureState.getValue());// Content());
4413 if (pdbid.getFile() != null)
4415 File mapkey = new File(pdbid.getFile());
4416 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
4417 if (seqstrmaps == null)
4419 jmoldat.getFileData().put(mapkey,
4420 seqstrmaps = jmoldat.new StructureData(pdbFile,
4423 if (!seqstrmaps.getSeqList().contains(seq))
4425 seqstrmaps.getSeqList().add(seq);
4431 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");
4438 // Instantiate the associated structure views
4439 for (Entry<String, StructureViewerModel> entry : structureViewers
4444 createOrLinkStructureViewer(entry, af, ap, jprovider);
4445 } catch (Exception e)
4448 "Error loading structure viewer: " + e.getMessage());
4449 // failed - try the next one
4461 protected void createOrLinkStructureViewer(
4462 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4463 AlignmentPanel ap, jarInputStreamProvider jprovider)
4465 final StructureViewerModel stateData = viewerData.getValue();
4468 * Search for any viewer windows already open from other alignment views
4469 * that exactly match the stored structure state
4471 StructureViewerBase comp = findMatchingViewer(viewerData);
4475 linkStructureViewer(ap, comp, stateData);
4480 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
4481 * "viewer_"+stateData.viewId
4483 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
4485 createChimeraViewer(viewerData, af, jprovider);
4490 * else Jmol (if pre-2.9, stateData contains JMOL state string)
4492 createJmolViewer(viewerData, af, jprovider);
4497 * Create a new Chimera viewer.
4503 protected void createChimeraViewer(
4504 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4505 jarInputStreamProvider jprovider)
4507 StructureViewerModel data = viewerData.getValue();
4508 String chimeraSessionFile = data.getStateData();
4511 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
4513 * NB this is the 'saved' viewId as in the project file XML, _not_ the
4514 * 'uniquified' sviewid used to reconstruct the viewer here
4516 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
4517 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
4520 Set<Entry<File, StructureData>> fileData = data.getFileData()
4522 List<PDBEntry> pdbs = new ArrayList<>();
4523 List<SequenceI[]> allseqs = new ArrayList<>();
4524 for (Entry<File, StructureData> pdb : fileData)
4526 String filePath = pdb.getValue().getFilePath();
4527 String pdbId = pdb.getValue().getPdbId();
4528 // pdbs.add(new PDBEntry(filePath, pdbId));
4529 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
4530 final List<SequenceI> seqList = pdb.getValue().getSeqList();
4531 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
4535 boolean colourByChimera = data.isColourByViewer();
4536 boolean colourBySequence = data.isColourWithAlignPanel();
4538 // TODO use StructureViewer as a factory here, see JAL-1761
4539 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
4540 final SequenceI[][] seqsArray = allseqs
4541 .toArray(new SequenceI[allseqs.size()][]);
4542 String newViewId = viewerData.getKey();
4544 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
4545 af.alignPanel, pdbArray, seqsArray, colourByChimera,
4546 colourBySequence, newViewId);
4547 cvf.setSize(data.getWidth(), data.getHeight());
4548 cvf.setLocation(data.getX(), data.getY());
4552 * Create a new Jmol window. First parse the Jmol state to translate filenames
4553 * loaded into the view, and record the order in which files are shown in the
4554 * Jmol view, so we can add the sequence mappings in same order.
4560 protected void createJmolViewer(
4561 final Entry<String, StructureViewerModel> viewerData,
4562 AlignFrame af, jarInputStreamProvider jprovider)
4564 final StructureViewerModel svattrib = viewerData.getValue();
4565 String state = svattrib.getStateData();
4568 * Pre-2.9: state element value is the Jmol state string
4570 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
4573 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
4575 state = readJarEntry(jprovider,
4576 getViewerJarEntryName(svattrib.getViewId()));
4579 List<String> pdbfilenames = new ArrayList<>();
4580 List<SequenceI[]> seqmaps = new ArrayList<>();
4581 List<String> pdbids = new ArrayList<>();
4582 StringBuilder newFileLoc = new StringBuilder(64);
4583 int cp = 0, ncp, ecp;
4584 Map<File, StructureData> oldFiles = svattrib.getFileData();
4585 while ((ncp = state.indexOf("load ", cp)) > -1)
4589 // look for next filename in load statement
4590 newFileLoc.append(state.substring(cp,
4591 ncp = (state.indexOf("\"", ncp + 1) + 1)));
4592 String oldfilenam = state.substring(ncp,
4593 ecp = state.indexOf("\"", ncp));
4594 // recover the new mapping data for this old filename
4595 // have to normalize filename - since Jmol and jalview do
4597 // translation differently.
4598 StructureData filedat = oldFiles.get(new File(oldfilenam));
4599 if (filedat == null)
4601 String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\");
4602 filedat = oldFiles.get(new File(reformatedOldFilename));
4604 newFileLoc.append(Platform.escapeBackslashes(filedat.getFilePath()));
4605 pdbfilenames.add(filedat.getFilePath());
4606 pdbids.add(filedat.getPdbId());
4607 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4608 newFileLoc.append("\"");
4609 cp = ecp + 1; // advance beyond last \" and set cursor so we can
4610 // look for next file statement.
4611 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
4615 // just append rest of state
4616 newFileLoc.append(state.substring(cp));
4620 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
4621 newFileLoc = new StringBuilder(state);
4622 newFileLoc.append("; load append ");
4623 for (File id : oldFiles.keySet())
4625 // add this and any other pdb files that should be present in
4627 StructureData filedat = oldFiles.get(id);
4628 newFileLoc.append(filedat.getFilePath());
4629 pdbfilenames.add(filedat.getFilePath());
4630 pdbids.add(filedat.getPdbId());
4631 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4632 newFileLoc.append(" \"");
4633 newFileLoc.append(filedat.getFilePath());
4634 newFileLoc.append("\"");
4637 newFileLoc.append(";");
4640 if (newFileLoc.length() == 0)
4644 int histbug = newFileLoc.indexOf("history = ");
4648 * change "history = [true|false];" to "history = [1|0];"
4651 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
4652 String val = (diff == -1) ? null
4653 : newFileLoc.substring(histbug, diff);
4654 if (val != null && val.length() >= 4)
4656 if (val.contains("e")) // eh? what can it be?
4658 if (val.trim().equals("true"))
4666 newFileLoc.replace(histbug, diff, val);
4671 final String[] pdbf = pdbfilenames
4672 .toArray(new String[pdbfilenames.size()]);
4673 final String[] id = pdbids.toArray(new String[pdbids.size()]);
4674 final SequenceI[][] sq = seqmaps
4675 .toArray(new SequenceI[seqmaps.size()][]);
4676 final String fileloc = newFileLoc.toString();
4677 final String sviewid = viewerData.getKey();
4678 final AlignFrame alf = af;
4679 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
4680 svattrib.getWidth(), svattrib.getHeight());
4683 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
4688 JalviewStructureDisplayI sview = null;
4691 sview = new StructureViewer(
4692 alf.alignPanel.getStructureSelectionManager())
4693 .createView(StructureViewer.ViewerType.JMOL,
4694 pdbf, id, sq, alf.alignPanel, svattrib,
4695 fileloc, rect, sviewid);
4696 addNewStructureViewer(sview);
4697 } catch (OutOfMemoryError ex)
4699 new OOMWarning("restoring structure view for PDB id " + id,
4700 (OutOfMemoryError) ex.getCause());
4701 if (sview != null && sview.isVisible())
4703 sview.closeViewer(false);
4704 sview.setVisible(false);
4710 } catch (InvocationTargetException ex)
4712 warn("Unexpected error when opening Jmol view.", ex);
4714 } catch (InterruptedException e)
4716 // e.printStackTrace();
4722 * Generates a name for the entry in the project jar file to hold state
4723 * information for a structure viewer
4728 protected String getViewerJarEntryName(String viewId)
4730 return VIEWER_PREFIX + viewId;
4734 * Returns any open frame that matches given structure viewer data. The match
4735 * is based on the unique viewId, or (for older project versions) the frame's
4741 protected StructureViewerBase findMatchingViewer(
4742 Entry<String, StructureViewerModel> viewerData)
4744 final String sviewid = viewerData.getKey();
4745 final StructureViewerModel svattrib = viewerData.getValue();
4746 StructureViewerBase comp = null;
4747 JInternalFrame[] frames = getAllFrames();
4748 for (JInternalFrame frame : frames)
4750 if (frame instanceof StructureViewerBase)
4753 * Post jalview 2.4 schema includes structure view id
4755 if (sviewid != null && ((StructureViewerBase) frame).getViewId()
4758 comp = (StructureViewerBase) frame;
4759 break; // break added in 2.9
4762 * Otherwise test for matching position and size of viewer frame
4764 else if (frame.getX() == svattrib.getX()
4765 && frame.getY() == svattrib.getY()
4766 && frame.getHeight() == svattrib.getHeight()
4767 && frame.getWidth() == svattrib.getWidth())
4769 comp = (StructureViewerBase) frame;
4770 // no break in faint hope of an exact match on viewId
4778 * Link an AlignmentPanel to an existing structure viewer.
4783 * @param useinViewerSuperpos
4784 * @param usetoColourbyseq
4785 * @param viewerColouring
4787 protected void linkStructureViewer(AlignmentPanel ap,
4788 StructureViewerBase viewer, StructureViewerModel stateData)
4790 // NOTE: if the jalview project is part of a shared session then
4791 // view synchronization should/could be done here.
4793 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4794 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4795 final boolean viewerColouring = stateData.isColourByViewer();
4796 Map<File, StructureData> oldFiles = stateData.getFileData();
4799 * Add mapping for sequences in this view to an already open viewer
4801 final AAStructureBindingModel binding = viewer.getBinding();
4802 for (File id : oldFiles.keySet())
4804 // add this and any other pdb files that should be present in the
4806 StructureData filedat = oldFiles.get(id);
4807 String pdbFile = filedat.getFilePath();
4808 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4809 binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE,
4811 binding.addSequenceForStructFile(pdbFile, seq);
4813 // and add the AlignmentPanel's reference to the view panel
4814 viewer.addAlignmentPanel(ap);
4815 if (useinViewerSuperpos)
4817 viewer.useAlignmentPanelForSuperposition(ap);
4821 viewer.excludeAlignmentPanelForSuperposition(ap);
4823 if (usetoColourbyseq)
4825 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4829 viewer.excludeAlignmentPanelForColourbyseq(ap);
4834 * Get all frames within the Desktop.
4838 protected JInternalFrame[] getAllFrames()
4840 JInternalFrame[] frames = null;
4841 // TODO is this necessary - is it safe - risk of hanging?
4846 frames = Desktop.desktop.getAllFrames();
4847 } catch (ArrayIndexOutOfBoundsException e)
4849 // occasional No such child exceptions are thrown here...
4853 } catch (InterruptedException f)
4857 } while (frames == null);
4862 * Answers true if 'version' is equal to or later than 'supported', where each
4863 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4864 * changes. Development and test values for 'version' are leniently treated
4868 * - minimum version we are comparing against
4870 * - version of data being processsed
4873 public static boolean isVersionStringLaterThan(String supported,
4876 if (supported == null || version == null
4877 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4878 || version.equalsIgnoreCase("Test")
4879 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4881 System.err.println("Assuming project file with "
4882 + (version == null ? "null" : version)
4883 + " is compatible with Jalview version " + supported);
4888 return StringUtils.compareVersions(version, supported, "b") >= 0;
4892 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4894 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4896 if (newStructureViewers != null)
4898 sview.getBinding().setFinishedLoadingFromArchive(false);
4899 newStructureViewers.add(sview);
4903 protected void setLoadingFinishedForNewStructureViewers()
4905 if (newStructureViewers != null)
4907 for (JalviewStructureDisplayI sview : newStructureViewers)
4909 sview.getBinding().setFinishedLoadingFromArchive(true);
4911 newStructureViewers.clear();
4912 newStructureViewers = null;
4916 AlignFrame loadViewport(String file, List<JSeq> JSEQ,
4917 List<SequenceI> hiddenSeqs, AlignmentI al,
4918 JalviewModel jm, Viewport view, String uniqueSeqSetId,
4919 String viewId, List<JvAnnotRow> autoAlan)
4921 AlignFrame af = null;
4922 af = new AlignFrame(al, safeInt(view.getWidth()),
4923 safeInt(view.getHeight()), uniqueSeqSetId, viewId);
4925 af.setFileName(file, FileFormat.Jalview);
4927 final AlignViewport viewport = af.getViewport();
4928 for (int i = 0; i < JSEQ.size(); i++)
4930 int colour = safeInt(JSEQ.get(i).getColour());
4931 viewport.setSequenceColour(viewport.getAlignment().getSequenceAt(i),
4937 viewport.setColourByReferenceSeq(true);
4938 viewport.setDisplayReferenceSeq(true);
4941 viewport.setGatherViewsHere(safeBoolean(view.isGatheredViews()));
4943 if (view.getSequenceSetId() != null)
4945 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4947 viewport.setSequenceSetId(uniqueSeqSetId);
4950 // propagate shared settings to this new view
4951 viewport.setHistoryList(av.getHistoryList());
4952 viewport.setRedoList(av.getRedoList());
4956 viewportsAdded.put(uniqueSeqSetId, viewport);
4958 // TODO: check if this method can be called repeatedly without
4959 // side-effects if alignpanel already registered.
4960 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4962 // apply Hidden regions to view.
4963 if (hiddenSeqs != null)
4965 for (int s = 0; s < JSEQ.size(); s++)
4967 SequenceGroup hidden = new SequenceGroup();
4968 boolean isRepresentative = false;
4969 for (int r = 0; r < JSEQ.get(s).getHiddenSequences().size(); r++)
4971 isRepresentative = true;
4972 SequenceI sequenceToHide = al
4973 .getSequenceAt(JSEQ.get(s).getHiddenSequences().get(r));
4974 hidden.addSequence(sequenceToHide, false);
4975 // remove from hiddenSeqs list so we don't try to hide it twice
4976 hiddenSeqs.remove(sequenceToHide);
4978 if (isRepresentative)
4980 SequenceI representativeSequence = al.getSequenceAt(s);
4981 hidden.addSequence(representativeSequence, false);
4982 viewport.hideRepSequences(representativeSequence, hidden);
4986 SequenceI[] hseqs = hiddenSeqs
4987 .toArray(new SequenceI[hiddenSeqs.size()]);
4988 viewport.hideSequence(hseqs);
4991 // recover view properties and display parameters
4993 viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
4994 viewport.setAbovePIDThreshold(safeBoolean(view.isPidSelected()));
4995 final int pidThreshold = safeInt(view.getPidThreshold());
4996 viewport.setThreshold(pidThreshold);
4998 viewport.setColourText(safeBoolean(view.isShowColourText()));
5001 .setConservationSelected(
5002 safeBoolean(view.isConservationSelected()));
5003 viewport.setIncrement(safeInt(view.getConsThreshold()));
5004 viewport.setShowJVSuffix(safeBoolean(view.isShowFullId()));
5005 viewport.setRightAlignIds(safeBoolean(view.isRightAlignIds()));
5006 viewport.setFont(new Font(view.getFontName(),
5007 safeInt(view.getFontStyle()), safeInt(view.getFontSize())),
5009 ViewStyleI vs = viewport.getViewStyle();
5010 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
5011 viewport.setViewStyle(vs);
5012 // TODO: allow custom charWidth/Heights to be restored by updating them
5013 // after setting font - which means set above to false
5014 viewport.setRenderGaps(safeBoolean(view.isRenderGaps()));
5015 viewport.setWrapAlignment(safeBoolean(view.isWrapAlignment()));
5016 viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
5018 viewport.setShowBoxes(safeBoolean(view.isShowBoxes()));
5020 viewport.setShowText(safeBoolean(view.isShowText()));
5022 viewport.setTextColour(new Color(safeInt(view.getTextCol1())));
5023 viewport.setTextColour2(new Color(safeInt(view.getTextCol2())));
5024 viewport.setThresholdTextColour(safeInt(view.getTextColThreshold()));
5025 viewport.setShowUnconserved(view.isShowUnconserved());
5026 viewport.getRanges().setStartRes(safeInt(view.getStartRes()));
5028 if (view.getViewName() != null)
5030 viewport.setViewName(view.getViewName());
5031 af.setInitialTabVisible();
5033 af.setBounds(safeInt(view.getXpos()), safeInt(view.getYpos()),
5034 safeInt(view.getWidth()), safeInt(view.getHeight()));
5035 // startSeq set in af.alignPanel.updateLayout below
5036 af.alignPanel.updateLayout();
5037 ColourSchemeI cs = null;
5038 // apply colourschemes
5039 if (view.getBgColour() != null)
5041 if (view.getBgColour().startsWith("ucs"))
5043 cs = getUserColourScheme(jm, view.getBgColour());
5045 else if (view.getBgColour().startsWith("Annotation"))
5047 AnnotationColourScheme viewAnnColour = view.getAnnotationColours();
5048 cs = constructAnnotationColour(viewAnnColour, af, al, jm, true);
5055 cs = ColourSchemeProperty.getColourScheme(af.getViewport(), al,
5056 view.getBgColour());
5061 * turn off 'alignment colour applies to all groups'
5062 * while restoring global colour scheme
5064 viewport.setColourAppliesToAllGroups(false);
5065 viewport.setGlobalColourScheme(cs);
5066 viewport.getResidueShading().setThreshold(pidThreshold,
5067 view.isIgnoreGapsinConsensus());
5068 viewport.getResidueShading()
5069 .setConsensus(viewport.getSequenceConsensusHash());
5070 if (safeBoolean(view.isConservationSelected()) && cs != null)
5072 viewport.getResidueShading()
5073 .setConservationInc(safeInt(view.getConsThreshold()));
5075 af.changeColour(cs);
5076 viewport.setColourAppliesToAllGroups(true);
5079 .setShowSequenceFeatures(
5080 safeBoolean(view.isShowSequenceFeatures()));
5082 viewport.setCentreColumnLabels(view.isCentreColumnLabels());
5083 viewport.setIgnoreGapsConsensus(view.isIgnoreGapsinConsensus(), null);
5084 viewport.setFollowHighlight(view.isFollowHighlight());
5085 viewport.followSelection = view.isFollowSelection();
5086 viewport.setShowConsensusHistogram(view.isShowConsensusHistogram());
5087 viewport.setShowSequenceLogo(view.isShowSequenceLogo());
5088 viewport.setNormaliseSequenceLogo(view.isNormaliseSequenceLogo());
5089 viewport.setShowDBRefs(safeBoolean(view.isShowDbRefTooltip()));
5090 viewport.setShowNPFeats(safeBoolean(view.isShowNPfeatureTooltip()));
5091 viewport.setShowGroupConsensus(view.isShowGroupConsensus());
5092 viewport.setShowGroupConservation(view.isShowGroupConservation());
5094 // recover feature settings
5095 if (jm.getFeatureSettings() != null)
5097 FeatureRenderer fr = af.alignPanel.getSeqPanel().seqCanvas
5098 .getFeatureRenderer();
5099 FeaturesDisplayed fdi;
5100 viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
5101 String[] renderOrder = new String[jm.getFeatureSettings()
5102 .getSetting().size()];
5103 Map<String, FeatureColourI> featureColours = new Hashtable<>();
5104 Map<String, Float> featureOrder = new Hashtable<>();
5106 for (int fs = 0; fs < jm.getFeatureSettings()
5107 .getSetting().size(); fs++)
5109 Setting setting = jm.getFeatureSettings().getSetting().get(fs);
5110 String featureType = setting.getType();
5113 * restore feature filters (if any)
5115 jalview.xml.binding.jalview.FeatureMatcherSet filters = setting
5117 if (filters != null)
5119 FeatureMatcherSetI filter = Jalview2XML
5120 .parseFilter(featureType, filters);
5121 if (!filter.isEmpty())
5123 fr.setFeatureFilter(featureType, filter);
5128 * restore feature colour scheme
5130 Color maxColour = new Color(setting.getColour());
5131 if (setting.getMincolour() != null)
5134 * minColour is always set unless a simple colour
5135 * (including for colour by label though it doesn't use it)
5137 Color minColour = new Color(setting.getMincolour().intValue());
5138 Color noValueColour = minColour;
5139 NoValueColour noColour = setting.getNoValueColour();
5140 if (noColour == NoValueColour.NONE)
5142 noValueColour = null;
5144 else if (noColour == NoValueColour.MAX)
5146 noValueColour = maxColour;
5148 float min = safeFloat(safeFloat(setting.getMin()));
5149 float max = setting.getMax() == null ? 1f
5150 : setting.getMax().floatValue();
5151 FeatureColourI gc = new FeatureColour(maxColour, minColour,
5153 noValueColour, min, max);
5154 if (setting.getAttributeName().size() > 0)
5156 gc.setAttributeName(setting.getAttributeName().toArray(
5157 new String[setting.getAttributeName().size()]));
5159 if (setting.getThreshold() != null)
5161 gc.setThreshold(setting.getThreshold().floatValue());
5162 int threshstate = safeInt(setting.getThreshstate());
5163 // -1 = None, 0 = Below, 1 = Above threshold
5164 if (threshstate == 0)
5166 gc.setBelowThreshold(true);
5168 else if (threshstate == 1)
5170 gc.setAboveThreshold(true);
5173 gc.setAutoScaled(true); // default
5174 if (setting.isAutoScale() != null)
5176 gc.setAutoScaled(setting.isAutoScale());
5178 if (setting.isColourByLabel() != null)
5180 gc.setColourByLabel(setting.isColourByLabel());
5182 // and put in the feature colour table.
5183 featureColours.put(featureType, gc);
5187 featureColours.put(featureType,
5188 new FeatureColour(maxColour));
5190 renderOrder[fs] = featureType;
5191 if (setting.getOrder() != null)
5193 featureOrder.put(featureType, setting.getOrder().floatValue());
5197 featureOrder.put(featureType, Float.valueOf(
5198 fs / jm.getFeatureSettings().getSetting().size()));
5200 if (safeBoolean(setting.isDisplay()))
5202 fdi.setVisible(featureType);
5205 Map<String, Boolean> fgtable = new Hashtable<>();
5206 for (int gs = 0; gs < jm.getFeatureSettings().getGroup().size(); gs++)
5208 Group grp = jm.getFeatureSettings().getGroup().get(gs);
5209 fgtable.put(grp.getName(), Boolean.valueOf(grp.isDisplay()));
5211 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
5212 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
5213 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
5214 FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
5215 fgtable, featureColours, 1.0f, featureOrder);
5216 fr.transferSettings(frs);
5219 if (view.getHiddenColumns().size() > 0)
5221 for (int c = 0; c < view.getHiddenColumns().size(); c++)
5223 final HiddenColumns hc = view.getHiddenColumns().get(c);
5224 viewport.hideColumns(safeInt(hc.getStart()),
5225 safeInt(hc.getEnd()) /* +1 */);
5228 if (view.getCalcIdParam() != null)
5230 for (CalcIdParam calcIdParam : view.getCalcIdParam())
5232 if (calcIdParam != null)
5234 if (recoverCalcIdParam(calcIdParam, viewport))
5239 warn("Couldn't recover parameters for "
5240 + calcIdParam.getCalcId());
5245 af.setMenusFromViewport(viewport);
5246 af.setTitle(view.getTitle());
5247 // TODO: we don't need to do this if the viewport is aready visible.
5249 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
5250 * has a 'cdna/protein complement' view, in which case save it in order to
5251 * populate a SplitFrame once all views have been read in.
5253 String complementaryViewId = view.getComplementId();
5254 if (complementaryViewId == null)
5256 Desktop.addInternalFrame(af, view.getTitle(),
5257 safeInt(view.getWidth()), safeInt(view.getHeight()));
5258 // recompute any autoannotation
5259 af.alignPanel.updateAnnotation(false, true);
5260 reorderAutoannotation(af, al, autoAlan);
5261 af.alignPanel.alignmentChanged();
5265 splitFrameCandidates.put(view, af);
5271 * Reads saved data to restore Colour by Annotation settings
5273 * @param viewAnnColour
5277 * @param checkGroupAnnColour
5280 private ColourSchemeI constructAnnotationColour(
5281 AnnotationColourScheme viewAnnColour, AlignFrame af,
5282 AlignmentI al, JalviewModel model, boolean checkGroupAnnColour)
5284 boolean propagateAnnColour = false;
5285 AlignmentI annAlignment = af != null ? af.getViewport().getAlignment()
5287 if (checkGroupAnnColour && al.getGroups() != null
5288 && al.getGroups().size() > 0)
5290 // pre 2.8.1 behaviour
5291 // check to see if we should transfer annotation colours
5292 propagateAnnColour = true;
5293 for (SequenceGroup sg : al.getGroups())
5295 if (sg.getColourScheme() instanceof AnnotationColourGradient)
5297 propagateAnnColour = false;
5303 * 2.10.2- : saved annotationId is AlignmentAnnotation.annotationId
5305 String annotationId = viewAnnColour.getAnnotation();
5306 AlignmentAnnotation matchedAnnotation = annotationIds.get(annotationId);
5309 * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
5311 if (matchedAnnotation == null
5312 && annAlignment.getAlignmentAnnotation() != null)
5314 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
5317 .equals(annAlignment.getAlignmentAnnotation()[i].label))
5319 matchedAnnotation = annAlignment.getAlignmentAnnotation()[i];
5324 if (matchedAnnotation == null)
5326 System.err.println("Failed to match annotation colour scheme for "
5330 if (matchedAnnotation.getThreshold() == null)
5332 matchedAnnotation.setThreshold(
5333 new GraphLine(safeFloat(viewAnnColour.getThreshold()),
5334 "Threshold", Color.black));
5337 AnnotationColourGradient cs = null;
5338 if (viewAnnColour.getColourScheme().equals("None"))
5340 cs = new AnnotationColourGradient(matchedAnnotation,
5341 new Color(safeInt(viewAnnColour.getMinColour())),
5342 new Color(safeInt(viewAnnColour.getMaxColour())),
5343 safeInt(viewAnnColour.getAboveThreshold()));
5345 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
5347 cs = new AnnotationColourGradient(matchedAnnotation,
5348 getUserColourScheme(model, viewAnnColour.getColourScheme()),
5349 safeInt(viewAnnColour.getAboveThreshold()));
5353 cs = new AnnotationColourGradient(matchedAnnotation,
5354 ColourSchemeProperty.getColourScheme(af.getViewport(), al,
5355 viewAnnColour.getColourScheme()),
5356 safeInt(viewAnnColour.getAboveThreshold()));
5359 boolean perSequenceOnly = safeBoolean(viewAnnColour.isPerSequence());
5360 boolean useOriginalColours = safeBoolean(
5361 viewAnnColour.isPredefinedColours());
5362 cs.setSeqAssociated(perSequenceOnly);
5363 cs.setPredefinedColours(useOriginalColours);
5365 if (propagateAnnColour && al.getGroups() != null)
5367 // Also use these settings for all the groups
5368 for (int g = 0; g < al.getGroups().size(); g++)
5370 SequenceGroup sg = al.getGroups().get(g);
5371 if (sg.getGroupColourScheme() == null)
5376 AnnotationColourGradient groupScheme = new AnnotationColourGradient(
5377 matchedAnnotation, sg.getColourScheme(),
5378 safeInt(viewAnnColour.getAboveThreshold()));
5379 sg.setColourScheme(groupScheme);
5380 groupScheme.setSeqAssociated(perSequenceOnly);
5381 groupScheme.setPredefinedColours(useOriginalColours);
5387 private void reorderAutoannotation(AlignFrame af, AlignmentI al,
5388 List<JvAnnotRow> autoAlan)
5390 // copy over visualization settings for autocalculated annotation in the
5392 if (al.getAlignmentAnnotation() != null)
5395 * Kludge for magic autoannotation names (see JAL-811)
5397 String[] magicNames = new String[] { "Consensus", "Quality",
5399 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
5400 Hashtable<String, JvAnnotRow> visan = new Hashtable<>();
5401 for (String nm : magicNames)
5403 visan.put(nm, nullAnnot);
5405 for (JvAnnotRow auan : autoAlan)
5407 visan.put(auan.template.label
5408 + (auan.template.getCalcId() == null ? ""
5409 : "\t" + auan.template.getCalcId()),
5412 int hSize = al.getAlignmentAnnotation().length;
5413 List<JvAnnotRow> reorder = new ArrayList<>();
5414 // work through any autoCalculated annotation already on the view
5415 // removing it if it should be placed in a different location on the
5416 // annotation panel.
5417 List<String> remains = new ArrayList<>(visan.keySet());
5418 for (int h = 0; h < hSize; h++)
5420 jalview.datamodel.AlignmentAnnotation jalan = al
5421 .getAlignmentAnnotation()[h];
5422 if (jalan.autoCalculated)
5425 JvAnnotRow valan = visan.get(k = jalan.label);
5426 if (jalan.getCalcId() != null)
5428 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
5433 // delete the auto calculated row from the alignment
5434 al.deleteAnnotation(jalan, false);
5438 if (valan != nullAnnot)
5440 if (jalan != valan.template)
5442 // newly created autoannotation row instance
5443 // so keep a reference to the visible annotation row
5444 // and copy over all relevant attributes
5445 if (valan.template.graphHeight >= 0)
5448 jalan.graphHeight = valan.template.graphHeight;
5450 jalan.visible = valan.template.visible;
5452 reorder.add(new JvAnnotRow(valan.order, jalan));
5457 // Add any (possibly stale) autocalculated rows that were not appended to
5458 // the view during construction
5459 for (String other : remains)
5461 JvAnnotRow othera = visan.get(other);
5462 if (othera != nullAnnot && othera.template.getCalcId() != null
5463 && othera.template.getCalcId().length() > 0)
5465 reorder.add(othera);
5468 // now put the automatic annotation in its correct place
5469 int s = 0, srt[] = new int[reorder.size()];
5470 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
5471 for (JvAnnotRow jvar : reorder)
5474 srt[s++] = jvar.order;
5477 jalview.util.QuickSort.sort(srt, rws);
5478 // and re-insert the annotation at its correct position
5479 for (JvAnnotRow jvar : rws)
5481 al.addAnnotation(jvar.template, jvar.order);
5483 af.alignPanel.adjustAnnotationHeight();
5487 Hashtable skipList = null;
5490 * TODO remove this method
5493 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
5494 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
5495 * throw new Error("Implementation Error. No skipList defined for this
5496 * Jalview2XML instance."); } return (AlignFrame)
5497 * skipList.get(view.getSequenceSetId()); }
5501 * Check if the Jalview view contained in object should be skipped or not.
5504 * @return true if view's sequenceSetId is a key in skipList
5506 private boolean skipViewport(JalviewModel object)
5508 if (skipList == null)
5512 String id = object.getViewport().get(0).getSequenceSetId();
5513 if (skipList.containsKey(id))
5515 if (Cache.log != null && Cache.log.isDebugEnabled())
5517 Cache.log.debug("Skipping seuqence set id " + id);
5524 public void addToSkipList(AlignFrame af)
5526 if (skipList == null)
5528 skipList = new Hashtable();
5530 skipList.put(af.getViewport().getSequenceSetId(), af);
5533 public void clearSkipList()
5535 if (skipList != null)
5542 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
5543 boolean ignoreUnrefed, String uniqueSeqSetId)
5545 jalview.datamodel.AlignmentI ds = getDatasetFor(
5546 vamsasSet.getDatasetId());
5547 AlignmentI xtant_ds = ds;
5548 if (xtant_ds == null)
5550 // good chance we are about to create a new dataset, but check if we've
5551 // seen some of the dataset sequence IDs before.
5552 // TODO: skip this check if we are working with project generated by
5553 // version 2.11 or later
5554 xtant_ds = checkIfHasDataset(vamsasSet.getSequence());
5555 if (xtant_ds != null)
5558 addDatasetRef(vamsasSet.getDatasetId(), ds);
5561 Vector dseqs = null;
5564 // recovering an alignment View
5565 AlignmentI seqSetDS = getDatasetFor(UNIQSEQSETID + uniqueSeqSetId);
5566 if (seqSetDS != null)
5568 if (ds != null && ds != seqSetDS)
5570 warn("JAL-3171 regression: Overwriting a dataset reference for an alignment"
5571 + " - CDS/Protein crossreference data may be lost");
5572 if (xtant_ds != null)
5574 // This can only happen if the unique sequence set ID was bound to a
5575 // dataset that did not contain any of the sequences in the view
5576 // currently being restored.
5577 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.");
5581 addDatasetRef(vamsasSet.getDatasetId(), ds);
5586 // try even harder to restore dataset
5587 AlignmentI xtantDS = checkIfHasDataset(vamsasSet.getSequence());
5588 // create a list of new dataset sequences
5589 dseqs = new Vector();
5591 for (int i = 0, iSize = vamsasSet.getSequence().size(); i < iSize; i++)
5593 Sequence vamsasSeq = vamsasSet.getSequence().get(i);
5594 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
5596 // create a new dataset
5599 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
5600 dseqs.copyInto(dsseqs);
5601 ds = new jalview.datamodel.Alignment(dsseqs);
5602 debug("Created new dataset " + vamsasSet.getDatasetId()
5603 + " for alignment " + System.identityHashCode(al));
5604 addDatasetRef(vamsasSet.getDatasetId(), ds);
5606 // set the dataset for the newly imported alignment.
5607 if (al.getDataset() == null && !ignoreUnrefed)
5610 // register dataset for the alignment's uniqueSeqSetId for legacy projects
5611 addDatasetRef(UNIQSEQSETID + uniqueSeqSetId, ds);
5613 updateSeqDatasetBinding(vamsasSet.getSequence(), ds);
5617 * XML dataset sequence ID to materialised dataset reference
5619 HashMap<String, AlignmentI> seqToDataset = new HashMap<>();
5622 * @return the first materialised dataset reference containing a dataset
5623 * sequence referenced in the given view
5625 * - sequences from the view
5627 AlignmentI checkIfHasDataset(List<Sequence> list)
5629 for (Sequence restoredSeq : list)
5631 AlignmentI datasetFor = seqToDataset.get(restoredSeq.getDsseqid());
5632 if (datasetFor != null)
5641 * Register ds as the containing dataset for the dataset sequences referenced
5642 * by sequences in list
5645 * - sequences in a view
5648 void updateSeqDatasetBinding(List<Sequence> list, AlignmentI ds)
5650 for (Sequence restoredSeq : list)
5652 AlignmentI prevDS = seqToDataset.put(restoredSeq.getDsseqid(), ds);
5653 if (prevDS != null && prevDS != ds)
5655 warn("Dataset sequence appears in many datasets: "
5656 + restoredSeq.getDsseqid());
5657 // TODO: try to merge!
5664 * sequence definition to create/merge dataset sequence for
5668 * vector to add new dataset sequence to
5669 * @param ignoreUnrefed
5670 * - when true, don't create new sequences from vamsasSeq if it's id
5671 * doesn't already have an asssociated Jalview sequence.
5673 * - used to reorder the sequence in the alignment according to the
5674 * vamsasSeq array ordering, to preserve ordering of dataset
5676 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
5677 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed, int vseqpos)
5679 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
5681 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
5682 boolean reorder = false;
5683 SequenceI dsq = null;
5684 if (sq != null && sq.getDatasetSequence() != null)
5686 dsq = sq.getDatasetSequence();
5692 if (sq == null && ignoreUnrefed)
5696 String sqid = vamsasSeq.getDsseqid();
5699 // need to create or add a new dataset sequence reference to this sequence
5702 dsq = seqRefIds.get(sqid);
5707 // make a new dataset sequence
5708 dsq = sq.createDatasetSequence();
5711 // make up a new dataset reference for this sequence
5712 sqid = seqHash(dsq);
5714 dsq.setVamsasId(uniqueSetSuffix + sqid);
5715 seqRefIds.put(sqid, dsq);
5720 dseqs.addElement(dsq);
5725 ds.addSequence(dsq);
5731 { // make this dataset sequence sq's dataset sequence
5732 sq.setDatasetSequence(dsq);
5733 // and update the current dataset alignment
5738 if (!dseqs.contains(dsq))
5745 if (ds.findIndex(dsq) < 0)
5747 ds.addSequence(dsq);
5754 // TODO: refactor this as a merge dataset sequence function
5755 // now check that sq (the dataset sequence) sequence really is the union of
5756 // all references to it
5757 // boolean pre = sq.getStart() < dsq.getStart();
5758 // boolean post = sq.getEnd() > dsq.getEnd();
5762 // StringBuffer sb = new StringBuffer();
5763 String newres = jalview.analysis.AlignSeq.extractGaps(
5764 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
5765 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
5766 && newres.length() > dsq.getLength())
5768 // Update with the longer sequence.
5772 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
5773 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
5774 * sb.append(newres.substring(newres.length() - sq.getEnd() -
5775 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
5777 dsq.setSequence(newres);
5779 // TODO: merges will never happen if we 'know' we have the real dataset
5780 // sequence - this should be detected when id==dssid
5782 "DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
5783 // + (pre ? "prepended" : "") + " "
5784 // + (post ? "appended" : ""));
5789 // sequence refs are identical. We may need to update the existing dataset
5790 // alignment with this one, though.
5791 if (ds != null && dseqs == null)
5793 int opos = ds.findIndex(dsq);
5794 SequenceI tseq = null;
5795 if (opos != -1 && vseqpos != opos)
5797 // remove from old position
5798 ds.deleteSequence(dsq);
5800 if (vseqpos < ds.getHeight())
5802 if (vseqpos != opos)
5804 // save sequence at destination position
5805 tseq = ds.getSequenceAt(vseqpos);
5806 ds.replaceSequenceAt(vseqpos, dsq);
5807 ds.addSequence(tseq);
5812 ds.addSequence(dsq);
5819 * TODO use AlignmentI here and in related methods - needs
5820 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
5822 Hashtable<String, AlignmentI> datasetIds = null;
5824 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
5826 private AlignmentI getDatasetFor(String datasetId)
5828 if (datasetIds == null)
5830 datasetIds = new Hashtable<>();
5833 if (datasetIds.containsKey(datasetId))
5835 return datasetIds.get(datasetId);
5840 private void addDatasetRef(String datasetId, AlignmentI dataset)
5842 if (datasetIds == null)
5844 datasetIds = new Hashtable<>();
5846 datasetIds.put(datasetId, dataset);
5850 * make a new dataset ID for this jalview dataset alignment
5855 private String getDatasetIdRef(AlignmentI dataset)
5857 if (dataset.getDataset() != null)
5859 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
5861 String datasetId = makeHashCode(dataset, null);
5862 if (datasetId == null)
5864 // make a new datasetId and record it
5865 if (dataset2Ids == null)
5867 dataset2Ids = new IdentityHashMap<>();
5871 datasetId = dataset2Ids.get(dataset);
5873 if (datasetId == null)
5875 datasetId = "ds" + dataset2Ids.size() + 1;
5876 dataset2Ids.put(dataset, datasetId);
5882 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5884 for (int d = 0; d < sequence.getDBRef().size(); d++)
5886 DBRef dr = sequence.getDBRef().get(d);
5887 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
5888 dr.getSource(), dr.getVersion(), dr.getAccessionId());
5889 if (dr.getMapping() != null)
5891 entry.setMap(addMapping(dr.getMapping()));
5893 datasetSequence.addDBRef(entry);
5897 private jalview.datamodel.Mapping addMapping(Mapping m)
5899 SequenceI dsto = null;
5900 // Mapping m = dr.getMapping();
5901 int fr[] = new int[m.getMapListFrom().size() * 2];
5902 Iterator<MapListFrom> from = m.getMapListFrom().iterator();// enumerateMapListFrom();
5903 for (int _i = 0; from.hasNext(); _i += 2)
5905 MapListFrom mf = from.next();
5906 fr[_i] = mf.getStart();
5907 fr[_i + 1] = mf.getEnd();
5909 int fto[] = new int[m.getMapListTo().size() * 2];
5910 Iterator<MapListTo> to = m.getMapListTo().iterator();// enumerateMapListTo();
5911 for (int _i = 0; to.hasNext(); _i += 2)
5913 MapListTo mf = to.next();
5914 fto[_i] = mf.getStart();
5915 fto[_i + 1] = mf.getEnd();
5917 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto, fr,
5918 fto, m.getMapFromUnit().intValue(),
5919 m.getMapToUnit().intValue());
5922 * (optional) choice of dseqFor or Sequence
5924 if (m.getDseqFor() != null)
5926 String dsfor = m.getDseqFor();
5927 if (seqRefIds.containsKey(dsfor))
5932 jmap.setTo(seqRefIds.get(dsfor));
5936 frefedSequence.add(newMappingRef(dsfor, jmap));
5939 else if (m.getSequence() != null)
5942 * local sequence definition
5944 Sequence ms = m.getSequence();
5945 SequenceI djs = null;
5946 String sqid = ms.getDsseqid();
5947 if (sqid != null && sqid.length() > 0)
5950 * recover dataset sequence
5952 djs = seqRefIds.get(sqid);
5957 "Warning - making up dataset sequence id for DbRef sequence map reference");
5958 sqid = ((Object) ms).toString(); // make up a new hascode for
5959 // undefined dataset sequence hash
5960 // (unlikely to happen)
5966 * make a new dataset sequence and add it to refIds hash
5968 djs = new jalview.datamodel.Sequence(ms.getName(),
5970 djs.setStart(jmap.getMap().getToLowest());
5971 djs.setEnd(jmap.getMap().getToHighest());
5972 djs.setVamsasId(uniqueSetSuffix + sqid);
5974 incompleteSeqs.put(sqid, djs);
5975 seqRefIds.put(sqid, djs);
5977 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5986 * Provides a 'copy' of an alignment view (on action New View) by 'saving' the
5987 * view as XML (but not to file), and then reloading it
5992 public AlignmentPanel copyAlignPanel(AlignmentPanel ap)
5995 JalviewModel jm = saveState(ap, null, null, null);
5998 jm.getVamsasModel().getSequenceSet().get(0).getDatasetId(),
5999 ap.getAlignment().getDataset());
6001 uniqueSetSuffix = "";
6002 // jm.getJalviewModelSequence().getViewport(0).setId(null);
6003 jm.getViewport().get(0).setId(null);
6004 // we don't overwrite the view we just copied
6006 if (this.frefedSequence == null)
6008 frefedSequence = new Vector<>();
6011 viewportsAdded.clear();
6013 AlignFrame af = loadFromObject(jm, null, false, null);
6014 af.getAlignPanels().clear();
6015 af.closeMenuItem_actionPerformed(true);
6018 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
6019 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
6020 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
6021 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
6022 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
6025 return af.alignPanel;
6028 private Hashtable jvids2vobj;
6030 private void warn(String msg)
6035 private void warn(String msg, Exception e)
6037 if (Cache.log != null)
6041 Cache.log.warn(msg, e);
6045 Cache.log.warn(msg);
6050 System.err.println("Warning: " + msg);
6053 e.printStackTrace();
6058 private void debug(String string)
6060 debug(string, null);
6063 private void debug(String msg, Exception e)
6065 if (Cache.log != null)
6069 Cache.log.debug(msg, e);
6073 Cache.log.debug(msg);
6078 System.err.println("Warning: " + msg);
6081 e.printStackTrace();
6087 * set the object to ID mapping tables used to write/recover objects and XML
6088 * ID strings for the jalview project. If external tables are provided then
6089 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
6090 * object goes out of scope. - also populates the datasetIds hashtable with
6091 * alignment objects containing dataset sequences
6094 * Map from ID strings to jalview datamodel
6096 * Map from jalview datamodel to ID strings
6100 public void setObjectMappingTables(Hashtable vobj2jv,
6101 IdentityHashMap jv2vobj)
6103 this.jv2vobj = jv2vobj;
6104 this.vobj2jv = vobj2jv;
6105 Iterator ds = jv2vobj.keySet().iterator();
6107 while (ds.hasNext())
6109 Object jvobj = ds.next();
6110 id = jv2vobj.get(jvobj).toString();
6111 if (jvobj instanceof jalview.datamodel.Alignment)
6113 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
6115 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
6118 else if (jvobj instanceof jalview.datamodel.Sequence)
6120 // register sequence object so the XML parser can recover it.
6121 if (seqRefIds == null)
6123 seqRefIds = new HashMap<>();
6125 if (seqsToIds == null)
6127 seqsToIds = new IdentityHashMap<>();
6129 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
6130 seqsToIds.put((SequenceI) jvobj, id);
6132 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
6135 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
6136 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
6137 if (jvann.annotationId == null)
6139 jvann.annotationId = anid;
6141 if (!jvann.annotationId.equals(anid))
6143 // TODO verify that this is the correct behaviour
6144 this.warn("Overriding Annotation ID for " + anid
6145 + " from different id : " + jvann.annotationId);
6146 jvann.annotationId = anid;
6149 else if (jvobj instanceof String)
6151 if (jvids2vobj == null)
6153 jvids2vobj = new Hashtable();
6154 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
6159 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
6165 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
6166 * objects created from the project archive. If string is null (default for
6167 * construction) then suffix will be set automatically.
6171 public void setUniqueSetSuffix(String string)
6173 uniqueSetSuffix = string;
6178 * uses skipList2 as the skipList for skipping views on sequence sets
6179 * associated with keys in the skipList
6183 public void setSkipList(Hashtable skipList2)
6185 skipList = skipList2;
6189 * Reads the jar entry of given name and returns its contents, or null if the
6190 * entry is not found.
6193 * @param jarEntryName
6196 protected String readJarEntry(jarInputStreamProvider jprovider,
6197 String jarEntryName)
6199 String result = null;
6200 BufferedReader in = null;
6205 * Reopen the jar input stream and traverse its entries to find a matching
6208 JarInputStream jin = jprovider.getJarInputStream();
6209 JarEntry entry = null;
6212 entry = jin.getNextJarEntry();
6213 } while (entry != null && !entry.getName().equals(jarEntryName));
6217 StringBuilder out = new StringBuilder(256);
6218 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
6221 while ((data = in.readLine()) != null)
6225 result = out.toString();
6229 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
6231 } catch (Exception ex)
6233 ex.printStackTrace();
6241 } catch (IOException e)
6252 * Returns an incrementing counter (0, 1, 2...)
6256 private synchronized int nextCounter()
6262 * Loads any saved PCA viewers
6267 protected void loadPCAViewers(JalviewModel model, AlignmentPanel ap)
6271 List<PcaViewer> pcaviewers = model.getPcaViewer();
6272 for (PcaViewer viewer : pcaviewers)
6274 String modelName = viewer.getScoreModelName();
6275 SimilarityParamsI params = new SimilarityParams(
6276 viewer.isIncludeGappedColumns(), viewer.isMatchGaps(),
6277 viewer.isIncludeGaps(),
6278 viewer.isDenominateByShortestLength());
6281 * create the panel (without computing the PCA)
6283 PCAPanel panel = new PCAPanel(ap, modelName, params);
6285 panel.setTitle(viewer.getTitle());
6286 panel.setBounds(new Rectangle(viewer.getXpos(), viewer.getYpos(),
6287 viewer.getWidth(), viewer.getHeight()));
6289 boolean showLabels = viewer.isShowLabels();
6290 panel.setShowLabels(showLabels);
6291 panel.getRotatableCanvas().setShowLabels(showLabels);
6292 panel.getRotatableCanvas()
6293 .setBgColour(new Color(viewer.getBgColour()));
6294 panel.getRotatableCanvas()
6295 .setApplyToAllViews(viewer.isLinkToAllViews());
6298 * load PCA output data
6300 ScoreModelI scoreModel = ScoreModels.getInstance()
6301 .getScoreModel(modelName, ap);
6302 PCA pca = new PCA(null, scoreModel, params);
6303 PcaDataType pcaData = viewer.getPcaData();
6305 MatrixI pairwise = loadDoubleMatrix(pcaData.getPairwiseMatrix());
6306 pca.setPairwiseScores(pairwise);
6308 MatrixI triDiag = loadDoubleMatrix(pcaData.getTridiagonalMatrix());
6309 pca.setTridiagonal(triDiag);
6311 MatrixI result = loadDoubleMatrix(pcaData.getEigenMatrix());
6312 pca.setEigenmatrix(result);
6314 panel.getPcaModel().setPCA(pca);
6317 * we haven't saved the input data! (JAL-2647 to do)
6319 panel.setInputData(null);
6322 * add the sequence points for the PCA display
6324 List<jalview.datamodel.SequencePoint> seqPoints = new ArrayList<>();
6325 for (SequencePoint sp : viewer.getSequencePoint())
6327 String seqId = sp.getSequenceRef();
6328 SequenceI seq = seqRefIds.get(seqId);
6331 throw new IllegalStateException(
6332 "Unmatched seqref for PCA: " + seqId);
6334 Point pt = new Point(sp.getXPos(), sp.getYPos(), sp.getZPos());
6335 jalview.datamodel.SequencePoint seqPoint = new jalview.datamodel.SequencePoint(
6337 seqPoints.add(seqPoint);
6339 panel.getRotatableCanvas().setPoints(seqPoints, seqPoints.size());
6342 * set min-max ranges and scale after setPoints (which recomputes them)
6344 panel.getRotatableCanvas().setScaleFactor(viewer.getScaleFactor());
6345 SeqPointMin spMin = viewer.getSeqPointMin();
6346 float[] min = new float[] { spMin.getXPos(), spMin.getYPos(),
6348 SeqPointMax spMax = viewer.getSeqPointMax();
6349 float[] max = new float[] { spMax.getXPos(), spMax.getYPos(),
6351 panel.getRotatableCanvas().setSeqMinMax(min, max);
6353 // todo: hold points list in PCAModel only
6354 panel.getPcaModel().setSequencePoints(seqPoints);
6356 panel.setSelectedDimensionIndex(viewer.getXDim(), X);
6357 panel.setSelectedDimensionIndex(viewer.getYDim(), Y);
6358 panel.setSelectedDimensionIndex(viewer.getZDim(), Z);
6360 // is this duplication needed?
6361 panel.setTop(seqPoints.size() - 1);
6362 panel.getPcaModel().setTop(seqPoints.size() - 1);
6365 * add the axes' end points for the display
6367 for (int i = 0; i < 3; i++)
6369 Axis axis = viewer.getAxis().get(i);
6370 panel.getRotatableCanvas().getAxisEndPoints()[i] = new Point(
6371 axis.getXPos(), axis.getYPos(), axis.getZPos());
6374 Desktop.addInternalFrame(panel, MessageManager.formatMessage(
6375 "label.calc_title", "PCA", modelName), 475, 450);
6377 } catch (Exception ex)
6379 Cache.log.error("Error loading PCA: " + ex.toString());
6384 * Populates an XML model of the feature colour scheme for one feature type
6386 * @param featureType
6390 public static Colour marshalColour(
6391 String featureType, FeatureColourI fcol)
6393 Colour col = new Colour();
6394 if (fcol.isSimpleColour())
6396 col.setRGB(Format.getHexString(fcol.getColour()));
6400 col.setRGB(Format.getHexString(fcol.getMaxColour()));
6401 col.setMin(fcol.getMin());
6402 col.setMax(fcol.getMax());
6403 col.setMinRGB(jalview.util.Format.getHexString(fcol.getMinColour()));
6404 col.setAutoScale(fcol.isAutoScaled());
6405 col.setThreshold(fcol.getThreshold());
6406 col.setColourByLabel(fcol.isColourByLabel());
6407 col.setThreshType(fcol.isAboveThreshold() ? ThresholdType.ABOVE
6408 : (fcol.isBelowThreshold() ? ThresholdType.BELOW
6409 : ThresholdType.NONE));
6410 if (fcol.isColourByAttribute())
6412 final String[] attName = fcol.getAttributeName();
6413 col.getAttributeName().add(attName[0]);
6414 if (attName.length > 1)
6416 col.getAttributeName().add(attName[1]);
6419 Color noColour = fcol.getNoColour();
6420 if (noColour == null)
6422 col.setNoValueColour(NoValueColour.NONE);
6424 else if (noColour == fcol.getMaxColour())
6426 col.setNoValueColour(NoValueColour.MAX);
6430 col.setNoValueColour(NoValueColour.MIN);
6433 col.setName(featureType);
6438 * Populates an XML model of the feature filter(s) for one feature type
6440 * @param firstMatcher
6441 * the first (or only) match condition)
6443 * remaining match conditions (if any)
6445 * if true, conditions are and-ed, else or-ed
6447 public static jalview.xml.binding.jalview.FeatureMatcherSet marshalFilter(
6448 FeatureMatcherI firstMatcher, Iterator<FeatureMatcherI> filters,
6451 jalview.xml.binding.jalview.FeatureMatcherSet result = new jalview.xml.binding.jalview.FeatureMatcherSet();
6453 if (filters.hasNext())
6458 CompoundMatcher compound = new CompoundMatcher();
6459 compound.setAnd(and);
6460 jalview.xml.binding.jalview.FeatureMatcherSet matcher1 = marshalFilter(
6461 firstMatcher, Collections.emptyIterator(), and);
6462 // compound.addMatcherSet(matcher1);
6463 compound.getMatcherSet().add(matcher1);
6464 FeatureMatcherI nextMatcher = filters.next();
6465 jalview.xml.binding.jalview.FeatureMatcherSet matcher2 = marshalFilter(
6466 nextMatcher, filters, and);
6467 // compound.addMatcherSet(matcher2);
6468 compound.getMatcherSet().add(matcher2);
6469 result.setCompoundMatcher(compound);
6474 * single condition matcher
6476 // MatchCondition matcherModel = new MatchCondition();
6477 jalview.xml.binding.jalview.FeatureMatcher matcherModel = new jalview.xml.binding.jalview.FeatureMatcher();
6478 matcherModel.setCondition(
6479 firstMatcher.getMatcher().getCondition().getStableName());
6480 matcherModel.setValue(firstMatcher.getMatcher().getPattern());
6481 if (firstMatcher.isByAttribute())
6483 matcherModel.setBy(FilterBy.BY_ATTRIBUTE);
6484 // matcherModel.setAttributeName(firstMatcher.getAttribute());
6485 String[] attName = firstMatcher.getAttribute();
6486 matcherModel.getAttributeName().add(attName[0]); // attribute
6487 if (attName.length > 1)
6489 matcherModel.getAttributeName().add(attName[1]); // sub-attribute
6492 else if (firstMatcher.isByLabel())
6494 matcherModel.setBy(FilterBy.BY_LABEL);
6496 else if (firstMatcher.isByScore())
6498 matcherModel.setBy(FilterBy.BY_SCORE);
6500 result.setMatchCondition(matcherModel);
6507 * Loads one XML model of a feature filter to a Jalview object
6509 * @param featureType
6510 * @param matcherSetModel
6513 public static FeatureMatcherSetI parseFilter(
6515 jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel)
6517 FeatureMatcherSetI result = new FeatureMatcherSet();
6520 parseFilterConditions(result, matcherSetModel, true);
6521 } catch (IllegalStateException e)
6523 // mixing AND and OR conditions perhaps
6525 String.format("Error reading filter conditions for '%s': %s",
6526 featureType, e.getMessage()));
6527 // return as much as was parsed up to the error
6534 * Adds feature match conditions to matcherSet as unmarshalled from XML
6535 * (possibly recursively for compound conditions)
6538 * @param matcherSetModel
6540 * if true, multiple conditions are AND-ed, else they are OR-ed
6541 * @throws IllegalStateException
6542 * if AND and OR conditions are mixed
6544 protected static void parseFilterConditions(
6545 FeatureMatcherSetI matcherSet,
6546 jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel,
6549 jalview.xml.binding.jalview.FeatureMatcher mc = matcherSetModel
6550 .getMatchCondition();
6556 FilterBy filterBy = mc.getBy();
6557 Condition cond = Condition.fromString(mc.getCondition());
6558 String pattern = mc.getValue();
6559 FeatureMatcherI matchCondition = null;
6560 if (filterBy == FilterBy.BY_LABEL)
6562 matchCondition = FeatureMatcher.byLabel(cond, pattern);
6564 else if (filterBy == FilterBy.BY_SCORE)
6566 matchCondition = FeatureMatcher.byScore(cond, pattern);
6569 else if (filterBy == FilterBy.BY_ATTRIBUTE)
6571 final List<String> attributeName = mc.getAttributeName();
6572 String[] attNames = attributeName
6573 .toArray(new String[attributeName.size()]);
6574 matchCondition = FeatureMatcher.byAttribute(cond, pattern,
6579 * note this throws IllegalStateException if AND-ing to a
6580 * previously OR-ed compound condition, or vice versa
6584 matcherSet.and(matchCondition);
6588 matcherSet.or(matchCondition);
6594 * compound condition
6596 List<jalview.xml.binding.jalview.FeatureMatcherSet> matchers = matcherSetModel
6597 .getCompoundMatcher().getMatcherSet();
6598 boolean anded = matcherSetModel.getCompoundMatcher().isAnd();
6599 if (matchers.size() == 2)
6601 parseFilterConditions(matcherSet, matchers.get(0), anded);
6602 parseFilterConditions(matcherSet, matchers.get(1), anded);
6606 System.err.println("Malformed compound filter condition");
6612 * Loads one XML model of a feature colour to a Jalview object
6614 * @param colourModel
6617 public static FeatureColourI parseColour(Colour colourModel)
6619 FeatureColourI colour = null;
6621 if (colourModel.getMax() != null)
6623 Color mincol = null;
6624 Color maxcol = null;
6625 Color noValueColour = null;
6629 mincol = new Color(Integer.parseInt(colourModel.getMinRGB(), 16));
6630 maxcol = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6631 } catch (Exception e)
6633 Cache.log.warn("Couldn't parse out graduated feature color.", e);
6636 NoValueColour noCol = colourModel.getNoValueColour();
6637 if (noCol == NoValueColour.MIN)
6639 noValueColour = mincol;
6641 else if (noCol == NoValueColour.MAX)
6643 noValueColour = maxcol;
6646 colour = new FeatureColour(maxcol, mincol, maxcol, noValueColour,
6647 safeFloat(colourModel.getMin()),
6648 safeFloat(colourModel.getMax()));
6649 final List<String> attributeName = colourModel.getAttributeName();
6650 String[] attributes = attributeName
6651 .toArray(new String[attributeName.size()]);
6652 if (attributes != null && attributes.length > 0)
6654 colour.setAttributeName(attributes);
6656 if (colourModel.isAutoScale() != null)
6658 colour.setAutoScaled(colourModel.isAutoScale().booleanValue());
6660 if (colourModel.isColourByLabel() != null)
6662 colour.setColourByLabel(
6663 colourModel.isColourByLabel().booleanValue());
6665 if (colourModel.getThreshold() != null)
6667 colour.setThreshold(colourModel.getThreshold().floatValue());
6669 ThresholdType ttyp = colourModel.getThreshType();
6670 if (ttyp == ThresholdType.ABOVE)
6672 colour.setAboveThreshold(true);
6674 else if (ttyp == ThresholdType.BELOW)
6676 colour.setBelowThreshold(true);
6681 Color color = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6682 colour = new FeatureColour(color);