2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
21 package jalview.project;
23 import static jalview.math.RotatableMatrix.Axis.X;
24 import static jalview.math.RotatableMatrix.Axis.Y;
25 import static jalview.math.RotatableMatrix.Axis.Z;
27 import jalview.analysis.AnnotationSorter;
28 import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
29 import jalview.analysis.Conservation;
30 import jalview.analysis.PCA;
31 import jalview.analysis.scoremodels.ScoreModels;
32 import jalview.analysis.scoremodels.SimilarityParams;
33 import jalview.api.FeatureColourI;
34 import jalview.api.ViewStyleI;
35 import jalview.api.analysis.ScoreModelI;
36 import jalview.api.analysis.SimilarityParamsI;
37 import jalview.api.structures.JalviewStructureDisplayI;
38 import jalview.bin.Cache;
39 import jalview.datamodel.AlignedCodonFrame;
40 import jalview.datamodel.Alignment;
41 import jalview.datamodel.AlignmentAnnotation;
42 import jalview.datamodel.AlignmentI;
43 import jalview.datamodel.GraphLine;
44 import jalview.datamodel.PDBEntry;
45 import jalview.datamodel.Point;
46 import jalview.datamodel.RnaViewerModel;
47 import jalview.datamodel.SequenceFeature;
48 import jalview.datamodel.SequenceGroup;
49 import jalview.datamodel.SequenceI;
50 import jalview.datamodel.StructureViewerModel;
51 import jalview.datamodel.StructureViewerModel.StructureData;
52 import jalview.datamodel.features.FeatureMatcher;
53 import jalview.datamodel.features.FeatureMatcherI;
54 import jalview.datamodel.features.FeatureMatcherSet;
55 import jalview.datamodel.features.FeatureMatcherSetI;
56 import jalview.ext.varna.RnaModel;
57 import jalview.gui.AlignFrame;
58 import jalview.gui.AlignViewport;
59 import jalview.gui.AlignmentPanel;
60 import jalview.gui.AppVarna;
61 import jalview.gui.ChimeraViewFrame;
62 import jalview.gui.Desktop;
63 import jalview.gui.FeatureRenderer;
64 import jalview.gui.JvOptionPane;
65 import jalview.gui.OOMWarning;
66 import jalview.gui.PCAPanel;
67 import jalview.gui.PaintRefresher;
68 import jalview.gui.SplitFrame;
69 import jalview.gui.StructureViewer;
70 import jalview.gui.StructureViewer.ViewerType;
71 import jalview.gui.StructureViewerBase;
72 import jalview.gui.TreePanel;
73 import jalview.io.BackupFiles;
74 import jalview.io.DataSourceType;
75 import jalview.io.FileFormat;
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 UTF_8 = "UTF-8";
220 * prefix for recovering datasets for alignments with multiple views where
221 * non-existent dataset IDs were written for some views
223 private static final String UNIQSEQSETID = "uniqueSeqSetId.";
225 // use this with nextCounter() to make unique names for entities
226 private int counter = 0;
229 * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
230 * of sequence objects are created.
232 IdentityHashMap<SequenceI, String> seqsToIds = null;
235 * jalview XML Sequence ID to jalview sequence object reference (both dataset
236 * and alignment sequences. Populated as XML reps of sequence objects are
239 Map<String, SequenceI> seqRefIds = null;
241 Map<String, SequenceI> incompleteSeqs = null;
243 List<SeqFref> frefedSequence = null;
245 boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
248 * Map of reconstructed AlignFrame objects that appear to have come from
249 * SplitFrame objects (have a dna/protein complement view).
251 private Map<Viewport, AlignFrame> splitFrameCandidates = new HashMap<>();
254 * Map from displayed rna structure models to their saved session state jar
257 private Map<RnaModel, String> rnaSessions = new HashMap<>();
260 * A helper method for safely using the value of an optional attribute that
261 * may be null if not present in the XML. Answers the boolean value, or false
267 public static boolean safeBoolean(Boolean b)
269 return b == null ? false : b.booleanValue();
273 * A helper method for safely using the value of an optional attribute that
274 * may be null if not present in the XML. Answers the integer value, or zero
280 public static int safeInt(Integer i)
282 return i == null ? 0 : i.intValue();
286 * A helper method for safely using the value of an optional attribute that
287 * may be null if not present in the XML. Answers the float value, or zero if
293 public static float safeFloat(Float f)
295 return f == null ? 0f : f.floatValue();
299 * create/return unique hash string for sq
302 * @return new or existing unique string for sq
304 String seqHash(SequenceI sq)
306 if (seqsToIds == null)
310 if (seqsToIds.containsKey(sq))
312 return seqsToIds.get(sq);
316 // create sequential key
317 String key = "sq" + (seqsToIds.size() + 1);
318 key = makeHashCode(sq, key); // check we don't have an external reference
320 seqsToIds.put(sq, key);
327 if (seqsToIds == null)
329 seqsToIds = new IdentityHashMap<>();
331 if (seqRefIds == null)
333 seqRefIds = new HashMap<>();
335 if (incompleteSeqs == null)
337 incompleteSeqs = new HashMap<>();
339 if (frefedSequence == null)
341 frefedSequence = new ArrayList<>();
349 public Jalview2XML(boolean raiseGUI)
351 this.raiseGUI = raiseGUI;
355 * base class for resolving forward references to sequences by their ID
360 abstract class SeqFref
366 public SeqFref(String _sref, String type)
372 public String getSref()
377 public SequenceI getSrefSeq()
379 return seqRefIds.get(sref);
382 public boolean isResolvable()
384 return seqRefIds.get(sref) != null;
387 public SequenceI getSrefDatasetSeq()
389 SequenceI sq = seqRefIds.get(sref);
392 while (sq.getDatasetSequence() != null)
394 sq = sq.getDatasetSequence();
401 * @return true if the forward reference was fully resolved
403 abstract boolean resolve();
406 public String toString()
408 return type + " reference to " + sref;
413 * create forward reference for a mapping
419 public SeqFref newMappingRef(final String sref,
420 final jalview.datamodel.Mapping _jmap)
422 SeqFref fref = new SeqFref(sref, "Mapping")
424 public jalview.datamodel.Mapping jmap = _jmap;
429 SequenceI seq = getSrefDatasetSeq();
441 public SeqFref newAlcodMapRef(final String sref,
442 final AlignedCodonFrame _cf,
443 final jalview.datamodel.Mapping _jmap)
446 SeqFref fref = new SeqFref(sref, "Codon Frame")
448 AlignedCodonFrame cf = _cf;
450 public jalview.datamodel.Mapping mp = _jmap;
453 public boolean isResolvable()
455 return super.isResolvable() && mp.getTo() != null;
461 SequenceI seq = getSrefDatasetSeq();
466 cf.addMap(seq, mp.getTo(), mp.getMap());
473 public void resolveFrefedSequences()
475 Iterator<SeqFref> nextFref = frefedSequence.iterator();
476 int toresolve = frefedSequence.size();
477 int unresolved = 0, failedtoresolve = 0;
478 while (nextFref.hasNext())
480 SeqFref ref = nextFref.next();
481 if (ref.isResolvable())
493 } catch (Exception x)
496 "IMPLEMENTATION ERROR: Failed to resolve forward reference for sequence "
509 System.err.println("Jalview Project Import: There were " + unresolved
510 + " forward references left unresolved on the stack.");
512 if (failedtoresolve > 0)
514 System.err.println("SERIOUS! " + failedtoresolve
515 + " resolvable forward references failed to resolve.");
517 if (incompleteSeqs != null && incompleteSeqs.size() > 0)
520 "Jalview Project Import: There are " + incompleteSeqs.size()
521 + " sequences which may have incomplete metadata.");
522 if (incompleteSeqs.size() < 10)
524 for (SequenceI s : incompleteSeqs.values())
526 System.err.println(s.toString());
532 "Too many to report. Skipping output of incomplete sequences.");
538 * This maintains a map of viewports, the key being the seqSetId. Important to
539 * set historyItem and redoList for multiple views
541 Map<String, AlignViewport> viewportsAdded = new HashMap<>();
543 Map<String, AlignmentAnnotation> annotationIds = new HashMap<>();
545 String uniqueSetSuffix = "";
548 * List of pdbfiles added to Jar
550 List<String> pdbfiles = null;
552 // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
553 public void saveState(File statefile)
555 FileOutputStream fos = null;
560 fos = new FileOutputStream(statefile);
562 JarOutputStream jout = new JarOutputStream(fos);
566 } catch (Exception e)
568 Cache.log.error("Couln't write Jalview state to " + statefile, e);
569 // TODO: inform user of the problem - they need to know if their data was
571 if (errorMessage == null)
573 errorMessage = "Did't write Jalview Archive to output file '"
574 + statefile + "' - See console error log for details";
578 errorMessage += "(Didn't write Jalview Archive to output file '"
589 } catch (IOException e)
599 * Writes a jalview project archive to the given Jar output stream.
603 public void saveState(JarOutputStream jout)
605 AlignFrame[] frames = Desktop.getAlignFrames();
611 saveAllFrames(Arrays.asList(frames), jout);
615 * core method for storing state for a set of AlignFrames.
618 * - frames involving all data to be exported (including containing
621 * - project output stream
623 private void saveAllFrames(List<AlignFrame> frames, JarOutputStream jout)
625 Hashtable<String, AlignFrame> dsses = new Hashtable<>();
628 * ensure cached data is clear before starting
630 // todo tidy up seqRefIds, seqsToIds initialisation / reset
632 splitFrameCandidates.clear();
637 // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
638 // //////////////////////////////////////////////////
640 List<String> shortNames = new ArrayList<>();
641 List<String> viewIds = new ArrayList<>();
644 for (int i = frames.size() - 1; i > -1; i--)
646 AlignFrame af = frames.get(i);
648 if (skipList != null && skipList
649 .containsKey(af.getViewport().getSequenceSetId()))
654 String shortName = makeFilename(af, shortNames);
656 int apSize = af.getAlignPanels().size();
658 for (int ap = 0; ap < apSize; ap++)
660 AlignmentPanel apanel = (AlignmentPanel) af.getAlignPanels()
662 String fileName = apSize == 1 ? shortName : ap + shortName;
663 if (!fileName.endsWith(".xml"))
665 fileName = fileName + ".xml";
668 saveState(apanel, fileName, jout, viewIds);
670 String dssid = getDatasetIdRef(
671 af.getViewport().getAlignment().getDataset());
672 if (!dsses.containsKey(dssid))
674 dsses.put(dssid, af);
679 writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix,
685 } catch (Exception foo)
690 } catch (Exception ex)
692 // TODO: inform user of the problem - they need to know if their data was
694 if (errorMessage == null)
696 errorMessage = "Couldn't write Jalview Archive - see error output for details";
698 ex.printStackTrace();
703 * Generates a distinct file name, based on the title of the AlignFrame, by
704 * appending _n for increasing n until an unused name is generated. The new
705 * name (without its extension) is added to the list.
709 * @return the generated name, with .xml extension
711 protected String makeFilename(AlignFrame af, List<String> namesUsed)
713 String shortName = af.getTitle();
715 if (shortName.indexOf(File.separatorChar) > -1)
717 shortName = shortName
718 .substring(shortName.lastIndexOf(File.separatorChar) + 1);
723 while (namesUsed.contains(shortName))
725 if (shortName.endsWith("_" + (count - 1)))
727 shortName = shortName.substring(0, shortName.lastIndexOf("_"));
730 shortName = shortName.concat("_" + count);
734 namesUsed.add(shortName);
736 if (!shortName.endsWith(".xml"))
738 shortName = shortName + ".xml";
743 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
744 public boolean saveAlignment(AlignFrame af, String jarFile,
749 // create backupfiles object and get new temp filename destination
750 BackupFiles backupfiles = new BackupFiles(jarFile);
751 FileOutputStream fos = new FileOutputStream(
752 backupfiles.getTempFilePath());
754 JarOutputStream jout = new JarOutputStream(fos);
755 List<AlignFrame> frames = new ArrayList<>();
757 // resolve splitframes
758 if (af.getViewport().getCodingComplement() != null)
760 frames = ((SplitFrame) af.getSplitViewContainer()).getAlignFrames();
766 saveAllFrames(frames, jout);
770 } catch (Exception foo)
775 boolean success = true;
777 backupfiles.setWriteSuccess(success);
778 success = backupfiles.rollBackupsAndRenameTempFile();
781 } catch (Exception ex)
783 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
784 ex.printStackTrace();
789 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
790 String fileName, JarOutputStream jout)
793 for (String dssids : dsses.keySet())
795 AlignFrame _af = dsses.get(dssids);
796 String jfileName = fileName + " Dataset for " + _af.getTitle();
797 if (!jfileName.endsWith(".xml"))
799 jfileName = jfileName + ".xml";
801 saveState(_af.alignPanel, jfileName, true, jout, null);
806 * create a JalviewModel from an alignment view and marshall it to a
810 * panel to create jalview model for
812 * name of alignment panel written to output stream
819 public JalviewModel saveState(AlignmentPanel ap, String fileName,
820 JarOutputStream jout, List<String> viewIds)
822 return saveState(ap, fileName, false, jout, viewIds);
826 * create a JalviewModel from an alignment view and marshall it to a
830 * panel to create jalview model for
832 * name of alignment panel written to output stream
834 * when true, only write the dataset for the alignment, not the data
835 * associated with the view.
841 public JalviewModel saveState(AlignmentPanel ap, String fileName,
842 boolean storeDS, JarOutputStream jout, List<String> viewIds)
846 viewIds = new ArrayList<>();
851 List<UserColourScheme> userColours = new ArrayList<>();
853 AlignViewport av = ap.av;
854 ViewportRanges vpRanges = av.getRanges();
856 final ObjectFactory objectFactory = new ObjectFactory();
857 JalviewModel object = objectFactory.createJalviewModel();
858 object.setVamsasModel(new VAMSAS());
860 // object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
863 GregorianCalendar c = new GregorianCalendar();
864 DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
865 XMLGregorianCalendar now = datatypeFactory.newXMLGregorianCalendar(c);// gregorianCalendar);
866 object.setCreationDate(now);
867 } catch (DatatypeConfigurationException e)
869 System.err.println("error writing date: " + e.toString());
872 jalview.bin.Cache.getDefault("VERSION", "Development Build"));
875 * rjal is full height alignment, jal is actual alignment with full metadata
876 * but excludes hidden sequences.
878 jalview.datamodel.AlignmentI rjal = av.getAlignment(), jal = rjal;
880 if (av.hasHiddenRows())
882 rjal = jal.getHiddenSequences().getFullAlignment();
885 SequenceSet vamsasSet = new SequenceSet();
887 // JalviewModelSequence jms = new JalviewModelSequence();
889 vamsasSet.setGapChar(jal.getGapCharacter() + "");
891 if (jal.getDataset() != null)
893 // dataset id is the dataset's hashcode
894 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
897 // switch jal and the dataset
898 jal = jal.getDataset();
902 if (jal.getProperties() != null)
904 Enumeration en = jal.getProperties().keys();
905 while (en.hasMoreElements())
907 String key = en.nextElement().toString();
908 SequenceSetProperties ssp = new SequenceSetProperties();
910 ssp.setValue(jal.getProperties().get(key).toString());
911 // vamsasSet.addSequenceSetProperties(ssp);
912 vamsasSet.getSequenceSetProperties().add(ssp);
917 Set<String> calcIdSet = new HashSet<>();
918 // record the set of vamsas sequence XML POJO we create.
919 HashMap<String, Sequence> vamsasSetIds = new HashMap<>();
921 for (final SequenceI jds : rjal.getSequences())
923 final SequenceI jdatasq = jds.getDatasetSequence() == null ? jds
924 : jds.getDatasetSequence();
925 String id = seqHash(jds);
926 if (vamsasSetIds.get(id) == null)
928 if (seqRefIds.get(id) != null && !storeDS)
930 // This happens for two reasons: 1. multiple views are being
932 // 2. the hashCode has collided with another sequence's code. This
934 // HAPPEN! (PF00072.15.stk does this)
935 // JBPNote: Uncomment to debug writing out of files that do not read
936 // back in due to ArrayOutOfBoundExceptions.
937 // System.err.println("vamsasSeq backref: "+id+"");
938 // System.err.println(jds.getName()+"
939 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
940 // System.err.println("Hashcode: "+seqHash(jds));
941 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
942 // System.err.println(rsq.getName()+"
943 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
944 // System.err.println("Hashcode: "+seqHash(rsq));
948 vamsasSeq = createVamsasSequence(id, jds);
949 // vamsasSet.addSequence(vamsasSeq);
950 vamsasSet.getSequence().add(vamsasSeq);
951 vamsasSetIds.put(id, vamsasSeq);
952 seqRefIds.put(id, jds);
956 jseq.setStart(jds.getStart());
957 jseq.setEnd(jds.getEnd());
958 jseq.setColour(av.getSequenceColour(jds).getRGB());
960 jseq.setId(id); // jseq id should be a string not a number
963 // Store any sequences this sequence represents
964 if (av.hasHiddenRows())
966 // use rjal, contains the full height alignment
968 av.getAlignment().getHiddenSequences().isHidden(jds));
970 if (av.isHiddenRepSequence(jds))
972 jalview.datamodel.SequenceI[] reps = av
973 .getRepresentedSequences(jds).getSequencesInOrder(rjal);
975 for (int h = 0; h < reps.length; h++)
979 // jseq.addHiddenSequences(rjal.findIndex(reps[h]));
980 jseq.getHiddenSequences().add(rjal.findIndex(reps[h]));
985 // mark sequence as reference - if it is the reference for this view
988 jseq.setViewreference(jds == jal.getSeqrep());
992 // TODO: omit sequence features from each alignment view's XML dump if we
993 // are storing dataset
994 List<SequenceFeature> sfs = jds.getSequenceFeatures();
995 for (SequenceFeature sf : sfs)
997 // Features features = new Features();
998 Feature features = new Feature();
1000 features.setBegin(sf.getBegin());
1001 features.setEnd(sf.getEnd());
1002 features.setDescription(sf.getDescription());
1003 features.setType(sf.getType());
1004 features.setFeatureGroup(sf.getFeatureGroup());
1005 features.setScore(sf.getScore());
1006 if (sf.links != null)
1008 for (int l = 0; l < sf.links.size(); l++)
1010 OtherData keyValue = new OtherData();
1011 keyValue.setKey("LINK_" + l);
1012 keyValue.setValue(sf.links.elementAt(l).toString());
1013 // features.addOtherData(keyValue);
1014 features.getOtherData().add(keyValue);
1017 if (sf.otherDetails != null)
1020 * save feature attributes, which may be simple strings or
1021 * map valued (have sub-attributes)
1023 for (Entry<String, Object> entry : sf.otherDetails.entrySet())
1025 String key = entry.getKey();
1026 Object value = entry.getValue();
1027 if (value instanceof Map<?, ?>)
1029 for (Entry<String, Object> subAttribute : ((Map<String, Object>) value)
1032 OtherData otherData = new OtherData();
1033 otherData.setKey(key);
1034 otherData.setKey2(subAttribute.getKey());
1035 otherData.setValue(subAttribute.getValue().toString());
1036 // features.addOtherData(otherData);
1037 features.getOtherData().add(otherData);
1042 OtherData otherData = new OtherData();
1043 otherData.setKey(key);
1044 otherData.setValue(value.toString());
1045 // features.addOtherData(otherData);
1046 features.getOtherData().add(otherData);
1051 // jseq.addFeatures(features);
1052 jseq.getFeatures().add(features);
1055 if (jdatasq.getAllPDBEntries() != null)
1057 Enumeration<PDBEntry> en = jdatasq.getAllPDBEntries().elements();
1058 while (en.hasMoreElements())
1060 Pdbids pdb = new Pdbids();
1061 jalview.datamodel.PDBEntry entry = en.nextElement();
1063 String pdbId = entry.getId();
1065 pdb.setType(entry.getType());
1068 * Store any structure views associated with this sequence. This
1069 * section copes with duplicate entries in the project, so a dataset
1070 * only view *should* be coped with sensibly.
1072 // This must have been loaded, is it still visible?
1073 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1074 String matchedFile = null;
1075 for (int f = frames.length - 1; f > -1; f--)
1077 if (frames[f] instanceof StructureViewerBase)
1079 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
1080 matchedFile = saveStructureState(ap, jds, pdb, entry, viewIds,
1081 matchedFile, viewFrame);
1083 * Only store each structure viewer's state once in the project
1084 * jar. First time through only (storeDS==false)
1086 String viewId = viewFrame.getViewId();
1087 if (!storeDS && !viewIds.contains(viewId))
1089 viewIds.add(viewId);
1092 String viewerState = viewFrame.getStateInfo();
1093 writeJarEntry(jout, getViewerJarEntryName(viewId),
1094 viewerState.getBytes());
1095 } catch (IOException e)
1098 "Error saving viewer state: " + e.getMessage());
1104 if (matchedFile != null || entry.getFile() != null)
1106 if (entry.getFile() != null)
1109 matchedFile = entry.getFile();
1111 pdb.setFile(matchedFile); // entry.getFile());
1112 if (pdbfiles == null)
1114 pdbfiles = new ArrayList<>();
1117 if (!pdbfiles.contains(pdbId))
1119 pdbfiles.add(pdbId);
1120 copyFileToJar(jout, matchedFile, pdbId);
1124 Enumeration<String> props = entry.getProperties();
1125 if (props.hasMoreElements())
1127 // PdbentryItem item = new PdbentryItem();
1128 while (props.hasMoreElements())
1130 Property prop = new Property();
1131 String key = props.nextElement();
1133 prop.setValue(entry.getProperty(key).toString());
1134 // item.addProperty(prop);
1135 pdb.getProperty().add(prop);
1137 // pdb.addPdbentryItem(item);
1140 // jseq.addPdbids(pdb);
1141 jseq.getPdbids().add(pdb);
1145 saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
1147 // jms.addJSeq(jseq);
1148 object.getJSeq().add(jseq);
1151 if (!storeDS && av.hasHiddenRows())
1153 jal = av.getAlignment();
1157 if (storeDS && jal.getCodonFrames() != null)
1159 List<AlignedCodonFrame> jac = jal.getCodonFrames();
1160 for (AlignedCodonFrame acf : jac)
1162 AlcodonFrame alc = new AlcodonFrame();
1163 if (acf.getProtMappings() != null
1164 && acf.getProtMappings().length > 0)
1166 boolean hasMap = false;
1167 SequenceI[] dnas = acf.getdnaSeqs();
1168 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1169 for (int m = 0; m < pmaps.length; m++)
1171 AlcodMap alcmap = new AlcodMap();
1172 alcmap.setDnasq(seqHash(dnas[m]));
1174 createVamsasMapping(pmaps[m], dnas[m], null, false));
1175 // alc.addAlcodMap(alcmap);
1176 alc.getAlcodMap().add(alcmap);
1181 // vamsasSet.addAlcodonFrame(alc);
1182 vamsasSet.getAlcodonFrame().add(alc);
1185 // TODO: delete this ? dead code from 2.8.3->2.9 ?
1187 // AlcodonFrame alc = new AlcodonFrame();
1188 // vamsasSet.addAlcodonFrame(alc);
1189 // for (int p = 0; p < acf.aaWidth; p++)
1191 // Alcodon cmap = new Alcodon();
1192 // if (acf.codons[p] != null)
1194 // // Null codons indicate a gapped column in the translated peptide
1196 // cmap.setPos1(acf.codons[p][0]);
1197 // cmap.setPos2(acf.codons[p][1]);
1198 // cmap.setPos3(acf.codons[p][2]);
1200 // alc.addAlcodon(cmap);
1202 // if (acf.getProtMappings() != null
1203 // && acf.getProtMappings().length > 0)
1205 // SequenceI[] dnas = acf.getdnaSeqs();
1206 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1207 // for (int m = 0; m < pmaps.length; m++)
1209 // AlcodMap alcmap = new AlcodMap();
1210 // alcmap.setDnasq(seqHash(dnas[m]));
1211 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
1213 // alc.addAlcodMap(alcmap);
1220 // /////////////////////////////////
1221 if (!storeDS && av.getCurrentTree() != null)
1223 // FIND ANY ASSOCIATED TREES
1224 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
1225 if (Desktop.desktop != null)
1227 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1229 for (int t = 0; t < frames.length; t++)
1231 if (frames[t] instanceof TreePanel)
1233 TreePanel tp = (TreePanel) frames[t];
1235 if (tp.getTreeCanvas().getViewport().getAlignment() == jal)
1237 JalviewModel.Tree tree = new JalviewModel.Tree();
1238 tree.setTitle(tp.getTitle());
1239 tree.setCurrentTree((av.getCurrentTree() == tp.getTree()));
1240 tree.setNewick(tp.getTree().print());
1241 tree.setThreshold(tp.getTreeCanvas().getThreshold());
1243 tree.setFitToWindow(tp.fitToWindow.getState());
1244 tree.setFontName(tp.getTreeFont().getName());
1245 tree.setFontSize(tp.getTreeFont().getSize());
1246 tree.setFontStyle(tp.getTreeFont().getStyle());
1247 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
1249 tree.setShowBootstrap(tp.bootstrapMenu.getState());
1250 tree.setShowDistances(tp.distanceMenu.getState());
1252 tree.setHeight(tp.getHeight());
1253 tree.setWidth(tp.getWidth());
1254 tree.setXpos(tp.getX());
1255 tree.setYpos(tp.getY());
1256 tree.setId(makeHashCode(tp, null));
1257 tree.setLinkToAllViews(
1258 tp.getTreeCanvas().isApplyToAllViews());
1260 // jms.addTree(tree);
1261 object.getTree().add(tree);
1271 if (!storeDS && Desktop.desktop != null)
1273 for (JInternalFrame frame : Desktop.desktop.getAllFrames())
1275 if (frame instanceof PCAPanel)
1277 PCAPanel panel = (PCAPanel) frame;
1278 if (panel.getAlignViewport().getAlignment() == jal)
1280 savePCA(panel, object);
1288 * store forward refs from an annotationRow to any groups
1290 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<>();
1293 for (SequenceI sq : jal.getSequences())
1295 // Store annotation on dataset sequences only
1296 AlignmentAnnotation[] aa = sq.getAnnotation();
1297 if (aa != null && aa.length > 0)
1299 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1306 if (jal.getAlignmentAnnotation() != null)
1308 // Store the annotation shown on the alignment.
1309 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1310 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1315 if (jal.getGroups() != null)
1317 JGroup[] groups = new JGroup[jal.getGroups().size()];
1319 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1321 JGroup jGroup = new JGroup();
1322 groups[++i] = jGroup;
1324 jGroup.setStart(sg.getStartRes());
1325 jGroup.setEnd(sg.getEndRes());
1326 jGroup.setName(sg.getName());
1327 if (groupRefs.containsKey(sg))
1329 // group has references so set its ID field
1330 jGroup.setId(groupRefs.get(sg));
1332 ColourSchemeI colourScheme = sg.getColourScheme();
1333 if (colourScheme != null)
1335 ResidueShaderI groupColourScheme = sg.getGroupColourScheme();
1336 if (groupColourScheme.conservationApplied())
1338 jGroup.setConsThreshold(groupColourScheme.getConservationInc());
1340 if (colourScheme instanceof jalview.schemes.UserColourScheme)
1343 setUserColourScheme(colourScheme, userColours,
1348 jGroup.setColour(colourScheme.getSchemeName());
1351 else if (colourScheme instanceof jalview.schemes.AnnotationColourGradient)
1353 jGroup.setColour("AnnotationColourGradient");
1354 jGroup.setAnnotationColours(constructAnnotationColours(
1355 (jalview.schemes.AnnotationColourGradient) colourScheme,
1356 userColours, object));
1358 else if (colourScheme instanceof jalview.schemes.UserColourScheme)
1361 setUserColourScheme(colourScheme, userColours, object));
1365 jGroup.setColour(colourScheme.getSchemeName());
1368 jGroup.setPidThreshold(groupColourScheme.getThreshold());
1371 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1372 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1373 jGroup.setDisplayText(sg.getDisplayText());
1374 jGroup.setColourText(sg.getColourText());
1375 jGroup.setTextCol1(sg.textColour.getRGB());
1376 jGroup.setTextCol2(sg.textColour2.getRGB());
1377 jGroup.setTextColThreshold(sg.thresholdTextColour);
1378 jGroup.setShowUnconserved(sg.getShowNonconserved());
1379 jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1380 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1381 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1382 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1383 for (SequenceI seq : sg.getSequences())
1385 // jGroup.addSeq(seqHash(seq));
1386 jGroup.getSeq().add(seqHash(seq));
1390 //jms.setJGroup(groups);
1392 for (JGroup grp : groups)
1394 object.getJGroup().add(grp);
1399 // /////////SAVE VIEWPORT
1400 Viewport view = new Viewport();
1401 view.setTitle(ap.alignFrame.getTitle());
1402 view.setSequenceSetId(
1403 makeHashCode(av.getSequenceSetId(), av.getSequenceSetId()));
1404 view.setId(av.getViewId());
1405 if (av.getCodingComplement() != null)
1407 view.setComplementId(av.getCodingComplement().getViewId());
1409 view.setViewName(av.getViewName());
1410 view.setGatheredViews(av.isGatherViewsHere());
1412 Rectangle size = ap.av.getExplodedGeometry();
1413 Rectangle position = size;
1416 size = ap.alignFrame.getBounds();
1417 if (av.getCodingComplement() != null)
1419 position = ((SplitFrame) ap.alignFrame.getSplitViewContainer())
1427 view.setXpos(position.x);
1428 view.setYpos(position.y);
1430 view.setWidth(size.width);
1431 view.setHeight(size.height);
1433 view.setStartRes(vpRanges.getStartRes());
1434 view.setStartSeq(vpRanges.getStartSeq());
1436 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1438 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1439 userColours, object));
1442 .getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1444 AnnotationColourScheme ac = constructAnnotationColours(
1445 (jalview.schemes.AnnotationColourGradient) av
1446 .getGlobalColourScheme(),
1447 userColours, object);
1449 view.setAnnotationColours(ac);
1450 view.setBgColour("AnnotationColourGradient");
1454 view.setBgColour(ColourSchemeProperty
1455 .getColourName(av.getGlobalColourScheme()));
1458 ResidueShaderI vcs = av.getResidueShading();
1459 ColourSchemeI cs = av.getGlobalColourScheme();
1463 if (vcs.conservationApplied())
1465 view.setConsThreshold(vcs.getConservationInc());
1466 if (cs instanceof jalview.schemes.UserColourScheme)
1468 view.setBgColour(setUserColourScheme(cs, userColours, object));
1471 view.setPidThreshold(vcs.getThreshold());
1474 view.setConservationSelected(av.getConservationSelected());
1475 view.setPidSelected(av.getAbovePIDThreshold());
1476 final Font font = av.getFont();
1477 view.setFontName(font.getName());
1478 view.setFontSize(font.getSize());
1479 view.setFontStyle(font.getStyle());
1480 view.setScaleProteinAsCdna(av.getViewStyle().isScaleProteinAsCdna());
1481 view.setRenderGaps(av.isRenderGaps());
1482 view.setShowAnnotation(av.isShowAnnotation());
1483 view.setShowBoxes(av.getShowBoxes());
1484 view.setShowAutocalcAbove(av.isShowAutocalculatedAbove());
1485 view.setSortAnnotationsBy(av.getSortAnnotationsBy().name());
1486 view.setShowColourText(av.getColourText());
1487 view.setShowFullId(av.getShowJVSuffix());
1488 view.setRightAlignIds(av.isRightAlignIds());
1489 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1490 view.setShowText(av.getShowText());
1491 view.setShowUnconserved(av.getShowUnconserved());
1492 view.setWrapAlignment(av.getWrapAlignment());
1493 view.setTextCol1(av.getTextColour().getRGB());
1494 view.setTextCol2(av.getTextColour2().getRGB());
1495 view.setTextColThreshold(av.getThresholdTextColour());
1496 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1497 view.setShowSequenceLogo(av.isShowSequenceLogo());
1498 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1499 view.setShowGroupConsensus(av.isShowGroupConsensus());
1500 view.setShowGroupConservation(av.isShowGroupConservation());
1501 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1502 view.setShowDbRefTooltip(av.isShowDBRefs());
1503 view.setFollowHighlight(av.isFollowHighlight());
1504 view.setFollowSelection(av.followSelection);
1505 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1506 if (av.getFeaturesDisplayed() != null)
1508 FeatureSettings fs = new FeatureSettings();
1510 FeatureRenderer fr = ap.getSeqPanel().seqCanvas
1511 .getFeatureRenderer();
1512 String[] renderOrder = fr.getRenderOrder().toArray(new String[0]);
1514 Vector<String> settingsAdded = new Vector<>();
1515 if (renderOrder != null)
1517 for (String featureType : renderOrder)
1519 FeatureSettings.Setting setting = new FeatureSettings.Setting();
1520 setting.setType(featureType);
1523 * save any filter for the feature type
1525 FeatureMatcherSetI filter = fr.getFeatureFilter(featureType);
1526 if (filter != null) {
1527 Iterator<FeatureMatcherI> filters = filter.getMatchers().iterator();
1528 FeatureMatcherI firstFilter = filters.next();
1529 setting.setMatcherSet(Jalview2XML.marshalFilter(
1530 firstFilter, filters, filter.isAnded()));
1534 * save colour scheme for the feature type
1536 FeatureColourI fcol = fr.getFeatureStyle(featureType);
1537 if (!fcol.isSimpleColour())
1539 setting.setColour(fcol.getMaxColour().getRGB());
1540 setting.setMincolour(fcol.getMinColour().getRGB());
1541 setting.setMin(fcol.getMin());
1542 setting.setMax(fcol.getMax());
1543 setting.setColourByLabel(fcol.isColourByLabel());
1544 if (fcol.isColourByAttribute())
1546 String[] attName = fcol.getAttributeName();
1547 setting.getAttributeName().add(attName[0]);
1548 if (attName.length > 1)
1550 setting.getAttributeName().add(attName[1]);
1553 setting.setAutoScale(fcol.isAutoScaled());
1554 setting.setThreshold(fcol.getThreshold());
1555 Color noColour = fcol.getNoColour();
1556 if (noColour == null)
1558 setting.setNoValueColour(NoValueColour.NONE);
1560 else if (noColour.equals(fcol.getMaxColour()))
1562 setting.setNoValueColour(NoValueColour.MAX);
1566 setting.setNoValueColour(NoValueColour.MIN);
1568 // -1 = No threshold, 0 = Below, 1 = Above
1569 setting.setThreshstate(fcol.isAboveThreshold() ? 1
1570 : (fcol.isBelowThreshold() ? 0 : -1));
1574 setting.setColour(fcol.getColour().getRGB());
1578 av.getFeaturesDisplayed().isVisible(featureType));
1580 .getOrder(featureType);
1583 setting.setOrder(rorder);
1585 /// fs.addSetting(setting);
1586 fs.getSetting().add(setting);
1587 settingsAdded.addElement(featureType);
1591 // is groups actually supposed to be a map here ?
1592 Iterator<String> en = fr.getFeatureGroups().iterator();
1593 Vector<String> groupsAdded = new Vector<>();
1594 while (en.hasNext())
1596 String grp = en.next();
1597 if (groupsAdded.contains(grp))
1601 Group g = new Group();
1603 g.setDisplay(((Boolean) fr.checkGroupVisibility(grp, false))
1606 fs.getGroup().add(g);
1607 groupsAdded.addElement(grp);
1609 // jms.setFeatureSettings(fs);
1610 object.setFeatureSettings(fs);
1613 if (av.hasHiddenColumns())
1615 jalview.datamodel.HiddenColumns hidden = av.getAlignment()
1616 .getHiddenColumns();
1619 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1623 Iterator<int[]> hiddenRegions = hidden.iterator();
1624 while (hiddenRegions.hasNext())
1626 int[] region = hiddenRegions.next();
1627 HiddenColumns hc = new HiddenColumns();
1628 hc.setStart(region[0]);
1629 hc.setEnd(region[1]);
1630 // view.addHiddenColumns(hc);
1631 view.getHiddenColumns().add(hc);
1635 if (calcIdSet.size() > 0)
1637 for (String calcId : calcIdSet)
1639 if (calcId.trim().length() > 0)
1641 CalcIdParam cidp = createCalcIdParam(calcId, av);
1642 // Some calcIds have no parameters.
1645 // view.addCalcIdParam(cidp);
1646 view.getCalcIdParam().add(cidp);
1652 // jms.addViewport(view);
1653 object.getViewport().add(view);
1655 // object.setJalviewModelSequence(jms);
1656 // object.getVamsasModel().addSequenceSet(vamsasSet);
1657 object.getVamsasModel().getSequenceSet().add(vamsasSet);
1659 if (jout != null && fileName != null)
1661 // We may not want to write the object to disk,
1662 // eg we can copy the alignViewport to a new view object
1663 // using save and then load
1666 System.out.println("Writing jar entry " + fileName);
1667 JarEntry entry = new JarEntry(fileName);
1668 jout.putNextEntry(entry);
1669 PrintWriter pout = new PrintWriter(
1670 new OutputStreamWriter(jout, UTF_8));
1671 JAXBContext jaxbContext = JAXBContext
1672 .newInstance(JalviewModel.class);
1673 Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
1675 // output pretty printed
1676 // jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
1677 jaxbMarshaller.marshal(
1678 new ObjectFactory().createJalviewModel(object), pout);
1680 // jaxbMarshaller.marshal(object, pout);
1681 // marshaller.marshal(object);
1684 } catch (Exception ex)
1686 // TODO: raise error in GUI if marshalling failed.
1687 System.err.println("Error writing Jalview project");
1688 ex.printStackTrace();
1695 * Writes PCA viewer attributes and computed values to an XML model object and
1696 * adds it to the JalviewModel. Any exceptions are reported by logging.
1698 protected void savePCA(PCAPanel panel, JalviewModel object)
1702 PcaViewer viewer = new PcaViewer();
1703 viewer.setHeight(panel.getHeight());
1704 viewer.setWidth(panel.getWidth());
1705 viewer.setXpos(panel.getX());
1706 viewer.setYpos(panel.getY());
1707 viewer.setTitle(panel.getTitle());
1708 PCAModel pcaModel = panel.getPcaModel();
1709 viewer.setScoreModelName(pcaModel.getScoreModelName());
1710 viewer.setXDim(panel.getSelectedDimensionIndex(X));
1711 viewer.setYDim(panel.getSelectedDimensionIndex(Y));
1712 viewer.setZDim(panel.getSelectedDimensionIndex(Z));
1714 panel.getRotatableCanvas().getBackgroundColour().getRGB());
1715 viewer.setScaleFactor(panel.getRotatableCanvas().getScaleFactor());
1716 float[] spMin = panel.getRotatableCanvas().getSeqMin();
1717 SeqPointMin spmin = new SeqPointMin();
1718 spmin.setXPos(spMin[0]);
1719 spmin.setYPos(spMin[1]);
1720 spmin.setZPos(spMin[2]);
1721 viewer.setSeqPointMin(spmin);
1722 float[] spMax = panel.getRotatableCanvas().getSeqMax();
1723 SeqPointMax spmax = new SeqPointMax();
1724 spmax.setXPos(spMax[0]);
1725 spmax.setYPos(spMax[1]);
1726 spmax.setZPos(spMax[2]);
1727 viewer.setSeqPointMax(spmax);
1728 viewer.setShowLabels(panel.getRotatableCanvas().isShowLabels());
1729 viewer.setLinkToAllViews(
1730 panel.getRotatableCanvas().isApplyToAllViews());
1731 SimilarityParamsI sp = pcaModel.getSimilarityParameters();
1732 viewer.setIncludeGaps(sp.includeGaps());
1733 viewer.setMatchGaps(sp.matchGaps());
1734 viewer.setIncludeGappedColumns(sp.includeGappedColumns());
1735 viewer.setDenominateByShortestLength(sp.denominateByShortestLength());
1738 * sequence points on display
1740 for (jalview.datamodel.SequencePoint spt : pcaModel
1741 .getSequencePoints())
1743 SequencePoint point = new SequencePoint();
1744 point.setSequenceRef(seqHash(spt.getSequence()));
1745 point.setXPos(spt.coord.x);
1746 point.setYPos(spt.coord.y);
1747 point.setZPos(spt.coord.z);
1748 viewer.getSequencePoint().add(point);
1752 * (end points of) axes on display
1754 for (Point p : panel.getRotatableCanvas().getAxisEndPoints())
1757 Axis axis = new Axis();
1761 viewer.getAxis().add(axis);
1765 * raw PCA data (note we are not restoring PCA inputs here -
1766 * alignment view, score model, similarity parameters)
1768 PcaDataType data = new PcaDataType();
1769 viewer.setPcaData(data);
1770 PCA pca = pcaModel.getPcaData();
1772 DoubleMatrix pm = new DoubleMatrix();
1773 saveDoubleMatrix(pca.getPairwiseScores(), pm);
1774 data.setPairwiseMatrix(pm);
1776 DoubleMatrix tm = new DoubleMatrix();
1777 saveDoubleMatrix(pca.getTridiagonal(), tm);
1778 data.setTridiagonalMatrix(tm);
1780 DoubleMatrix eigenMatrix = new DoubleMatrix();
1781 data.setEigenMatrix(eigenMatrix);
1782 saveDoubleMatrix(pca.getEigenmatrix(), eigenMatrix);
1784 object.getPcaViewer().add(viewer);
1785 } catch (Throwable t)
1787 Cache.log.error("Error saving PCA: " + t.getMessage());
1792 * Stores values from a matrix into an XML element, including (if present) the
1797 * @see #loadDoubleMatrix(DoubleMatrix)
1799 protected void saveDoubleMatrix(MatrixI m, DoubleMatrix xmlMatrix)
1801 xmlMatrix.setRows(m.height());
1802 xmlMatrix.setColumns(m.width());
1803 for (int i = 0; i < m.height(); i++)
1805 DoubleVector row = new DoubleVector();
1806 for (int j = 0; j < m.width(); j++)
1808 row.getV().add(m.getValue(i, j));
1810 xmlMatrix.getRow().add(row);
1812 if (m.getD() != null)
1814 DoubleVector dVector = new DoubleVector();
1815 for (double d : m.getD())
1817 dVector.getV().add(d);
1819 xmlMatrix.setD(dVector);
1821 if (m.getE() != null)
1823 DoubleVector eVector = new DoubleVector();
1824 for (double e : m.getE())
1826 eVector.getV().add(e);
1828 xmlMatrix.setE(eVector);
1833 * Loads XML matrix data into a new Matrix object, including the D and/or E
1834 * vectors (if present)
1838 * @see Jalview2XML#saveDoubleMatrix(MatrixI, DoubleMatrix)
1840 protected MatrixI loadDoubleMatrix(DoubleMatrix mData)
1842 int rows = mData.getRows();
1843 double[][] vals = new double[rows][];
1845 for (int i = 0; i < rows; i++)
1847 List<Double> dVector = mData.getRow().get(i).getV();
1848 vals[i] = new double[dVector.size()];
1850 for (Double d : dVector)
1856 MatrixI m = new Matrix(vals);
1858 if (mData.getD() != null)
1860 List<Double> dVector = mData.getD().getV();
1861 double[] vec = new double[dVector.size()];
1863 for (Double d : dVector)
1869 if (mData.getE() != null)
1871 List<Double> dVector = mData.getE().getV();
1872 double[] vec = new double[dVector.size()];
1874 for (Double d : dVector)
1885 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1886 * for each viewer, with
1888 * <li>viewer geometry (position, size, split pane divider location)</li>
1889 * <li>index of the selected structure in the viewer (currently shows gapped
1891 * <li>the id of the annotation holding RNA secondary structure</li>
1892 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1894 * Varna viewer state is also written out (in native Varna XML) to separate
1895 * project jar entries. A separate entry is written for each RNA structure
1896 * displayed, with the naming convention
1898 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
1906 * @param storeDataset
1908 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
1909 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
1910 boolean storeDataset)
1912 if (Desktop.desktop == null)
1916 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1917 for (int f = frames.length - 1; f > -1; f--)
1919 if (frames[f] instanceof AppVarna)
1921 AppVarna varna = (AppVarna) frames[f];
1923 * link the sequence to every viewer that is showing it and is linked to
1924 * its alignment panel
1926 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1928 String viewId = varna.getViewId();
1929 RnaViewer rna = new RnaViewer();
1930 rna.setViewId(viewId);
1931 rna.setTitle(varna.getTitle());
1932 rna.setXpos(varna.getX());
1933 rna.setYpos(varna.getY());
1934 rna.setWidth(varna.getWidth());
1935 rna.setHeight(varna.getHeight());
1936 rna.setDividerLocation(varna.getDividerLocation());
1937 rna.setSelectedRna(varna.getSelectedIndex());
1938 // jseq.addRnaViewer(rna);
1939 jseq.getRnaViewer().add(rna);
1942 * Store each Varna panel's state once in the project per sequence.
1943 * First time through only (storeDataset==false)
1945 // boolean storeSessions = false;
1946 // String sequenceViewId = viewId + seqsToIds.get(jds);
1947 // if (!storeDataset && !viewIds.contains(sequenceViewId))
1949 // viewIds.add(sequenceViewId);
1950 // storeSessions = true;
1952 for (RnaModel model : varna.getModels())
1954 if (model.seq == jds)
1957 * VARNA saves each view (sequence or alignment secondary
1958 * structure, gapped or trimmed) as a separate XML file
1960 String jarEntryName = rnaSessions.get(model);
1961 if (jarEntryName == null)
1964 String varnaStateFile = varna.getStateInfo(model.rna);
1965 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
1966 copyFileToJar(jout, varnaStateFile, jarEntryName);
1967 rnaSessions.put(model, jarEntryName);
1969 SecondaryStructure ss = new SecondaryStructure();
1970 String annotationId = varna.getAnnotation(jds).annotationId;
1971 ss.setAnnotationId(annotationId);
1972 ss.setViewerState(jarEntryName);
1973 ss.setGapped(model.gapped);
1974 ss.setTitle(model.title);
1975 // rna.addSecondaryStructure(ss);
1976 rna.getSecondaryStructure().add(ss);
1985 * Copy the contents of a file to a new entry added to the output jar
1989 * @param jarEntryName
1991 protected void copyFileToJar(JarOutputStream jout, String infilePath,
1992 String jarEntryName)
1994 DataInputStream dis = null;
1997 File file = new File(infilePath);
1998 if (file.exists() && jout != null)
2000 dis = new DataInputStream(new FileInputStream(file));
2001 byte[] data = new byte[(int) file.length()];
2002 dis.readFully(data);
2003 writeJarEntry(jout, jarEntryName, data);
2005 } catch (Exception ex)
2007 ex.printStackTrace();
2015 } catch (IOException e)
2024 * Write the data to a new entry of given name in the output jar file
2027 * @param jarEntryName
2029 * @throws IOException
2031 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
2032 byte[] data) throws IOException
2036 System.out.println("Writing jar entry " + jarEntryName);
2037 jout.putNextEntry(new JarEntry(jarEntryName));
2038 DataOutputStream dout = new DataOutputStream(jout);
2039 dout.write(data, 0, data.length);
2046 * Save the state of a structure viewer
2051 * the archive XML element under which to save the state
2054 * @param matchedFile
2058 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
2059 Pdbids pdb, PDBEntry entry, List<String> viewIds,
2060 String matchedFile, StructureViewerBase viewFrame)
2062 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
2065 * Look for any bindings for this viewer to the PDB file of interest
2066 * (including part matches excluding chain id)
2068 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
2070 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
2071 final String pdbId = pdbentry.getId();
2072 if (!pdbId.equals(entry.getId())
2073 && !(entry.getId().length() > 4 && entry.getId().toLowerCase()
2074 .startsWith(pdbId.toLowerCase())))
2077 * not interested in a binding to a different PDB entry here
2081 if (matchedFile == null)
2083 matchedFile = pdbentry.getFile();
2085 else if (!matchedFile.equals(pdbentry.getFile()))
2088 "Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
2089 + pdbentry.getFile());
2093 // can get at it if the ID
2094 // match is ambiguous (e.g.
2097 for (int smap = 0; smap < viewFrame.getBinding()
2098 .getSequence()[peid].length; smap++)
2100 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
2101 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
2103 StructureState state = new StructureState();
2104 state.setVisible(true);
2105 state.setXpos(viewFrame.getX());
2106 state.setYpos(viewFrame.getY());
2107 state.setWidth(viewFrame.getWidth());
2108 state.setHeight(viewFrame.getHeight());
2109 final String viewId = viewFrame.getViewId();
2110 state.setViewId(viewId);
2111 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
2112 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
2113 state.setColourByJmol(viewFrame.isColouredByViewer());
2114 state.setType(viewFrame.getViewerType().toString());
2115 // pdb.addStructureState(state);
2116 pdb.getStructureState().add(state);
2124 * Populates the AnnotationColourScheme xml for save. This captures the
2125 * settings of the options in the 'Colour by Annotation' dialog.
2128 * @param userColours
2132 private AnnotationColourScheme constructAnnotationColours(
2133 AnnotationColourGradient acg, List<UserColourScheme> userColours,
2136 AnnotationColourScheme ac = new AnnotationColourScheme();
2137 ac.setAboveThreshold(acg.getAboveThreshold());
2138 ac.setThreshold(acg.getAnnotationThreshold());
2139 // 2.10.2 save annotationId (unique) not annotation label
2140 ac.setAnnotation(acg.getAnnotation().annotationId);
2141 if (acg.getBaseColour() instanceof UserColourScheme)
2144 setUserColourScheme(acg.getBaseColour(), userColours, jm));
2149 ColourSchemeProperty.getColourName(acg.getBaseColour()));
2152 ac.setMaxColour(acg.getMaxColour().getRGB());
2153 ac.setMinColour(acg.getMinColour().getRGB());
2154 ac.setPerSequence(acg.isSeqAssociated());
2155 ac.setPredefinedColours(acg.isPredefinedColours());
2159 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
2160 IdentityHashMap<SequenceGroup, String> groupRefs,
2161 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
2162 SequenceSet vamsasSet)
2165 for (int i = 0; i < aa.length; i++)
2167 Annotation an = new Annotation();
2169 AlignmentAnnotation annotation = aa[i];
2170 if (annotation.annotationId != null)
2172 annotationIds.put(annotation.annotationId, annotation);
2175 an.setId(annotation.annotationId);
2177 an.setVisible(annotation.visible);
2179 an.setDescription(annotation.description);
2181 if (annotation.sequenceRef != null)
2183 // 2.9 JAL-1781 xref on sequence id rather than name
2184 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
2186 if (annotation.groupRef != null)
2188 String groupIdr = groupRefs.get(annotation.groupRef);
2189 if (groupIdr == null)
2191 // make a locally unique String
2192 groupRefs.put(annotation.groupRef,
2193 groupIdr = ("" + System.currentTimeMillis()
2194 + annotation.groupRef.getName()
2195 + groupRefs.size()));
2197 an.setGroupRef(groupIdr.toString());
2200 // store all visualization attributes for annotation
2201 an.setGraphHeight(annotation.graphHeight);
2202 an.setCentreColLabels(annotation.centreColLabels);
2203 an.setScaleColLabels(annotation.scaleColLabel);
2204 an.setShowAllColLabels(annotation.showAllColLabels);
2205 an.setBelowAlignment(annotation.belowAlignment);
2207 if (annotation.graph > 0)
2210 an.setGraphType(annotation.graph);
2211 an.setGraphGroup(annotation.graphGroup);
2212 if (annotation.getThreshold() != null)
2214 ThresholdLine line = new ThresholdLine();
2215 line.setLabel(annotation.getThreshold().label);
2216 line.setValue(annotation.getThreshold().value);
2217 line.setColour(annotation.getThreshold().colour.getRGB());
2218 an.setThresholdLine(line);
2226 an.setLabel(annotation.label);
2228 if (annotation == av.getAlignmentQualityAnnot()
2229 || annotation == av.getAlignmentConservationAnnotation()
2230 || annotation == av.getAlignmentConsensusAnnotation()
2231 || annotation.autoCalculated)
2233 // new way of indicating autocalculated annotation -
2234 an.setAutoCalculated(annotation.autoCalculated);
2236 if (annotation.hasScore())
2238 an.setScore(annotation.getScore());
2241 if (annotation.getCalcId() != null)
2243 calcIdSet.add(annotation.getCalcId());
2244 an.setCalcId(annotation.getCalcId());
2246 if (annotation.hasProperties())
2248 for (String pr : annotation.getProperties())
2250 jalview.xml.binding.jalview.Annotation.Property prop = new jalview.xml.binding.jalview.Annotation.Property();
2252 prop.setValue(annotation.getProperty(pr));
2253 // an.addProperty(prop);
2254 an.getProperty().add(prop);
2258 AnnotationElement ae;
2259 if (annotation.annotations != null)
2261 an.setScoreOnly(false);
2262 for (int a = 0; a < annotation.annotations.length; a++)
2264 if ((annotation == null) || (annotation.annotations[a] == null))
2269 ae = new AnnotationElement();
2270 if (annotation.annotations[a].description != null)
2272 ae.setDescription(annotation.annotations[a].description);
2274 if (annotation.annotations[a].displayCharacter != null)
2276 ae.setDisplayCharacter(
2277 annotation.annotations[a].displayCharacter);
2280 if (!Float.isNaN(annotation.annotations[a].value))
2282 ae.setValue(annotation.annotations[a].value);
2286 if (annotation.annotations[a].secondaryStructure > ' ')
2288 ae.setSecondaryStructure(
2289 annotation.annotations[a].secondaryStructure + "");
2292 if (annotation.annotations[a].colour != null
2293 && annotation.annotations[a].colour != java.awt.Color.black)
2295 ae.setColour(annotation.annotations[a].colour.getRGB());
2298 // an.addAnnotationElement(ae);
2299 an.getAnnotationElement().add(ae);
2300 if (annotation.autoCalculated)
2302 // only write one non-null entry into the annotation row -
2303 // sufficient to get the visualization attributes necessary to
2311 an.setScoreOnly(true);
2313 if (!storeDS || (storeDS && !annotation.autoCalculated))
2315 // skip autocalculated annotation - these are only provided for
2317 // vamsasSet.addAnnotation(an);
2318 vamsasSet.getAnnotation().add(an);
2324 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
2326 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
2327 if (settings != null)
2329 CalcIdParam vCalcIdParam = new CalcIdParam();
2330 vCalcIdParam.setCalcId(calcId);
2331 // vCalcIdParam.addServiceURL(settings.getServiceURI());
2332 vCalcIdParam.getServiceURL().add(settings.getServiceURI());
2333 // generic URI allowing a third party to resolve another instance of the
2334 // service used for this calculation
2335 for (String url : settings.getServiceURLs())
2337 // vCalcIdParam.addServiceURL(urls);
2338 vCalcIdParam.getServiceURL().add(url);
2340 vCalcIdParam.setVersion("1.0");
2341 if (settings.getPreset() != null)
2343 WsParamSetI setting = settings.getPreset();
2344 vCalcIdParam.setName(setting.getName());
2345 vCalcIdParam.setDescription(setting.getDescription());
2349 vCalcIdParam.setName("");
2350 vCalcIdParam.setDescription("Last used parameters");
2352 // need to be able to recover 1) settings 2) user-defined presets or
2353 // recreate settings from preset 3) predefined settings provided by
2354 // service - or settings that can be transferred (or discarded)
2355 vCalcIdParam.setParameters(
2356 settings.getWsParamFile().replace("\n", "|\\n|"));
2357 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
2358 // todo - decide if updateImmediately is needed for any projects.
2360 return vCalcIdParam;
2365 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
2368 if (calcIdParam.getVersion().equals("1.0"))
2370 final String[] calcIds = calcIdParam.getServiceURL().toArray(new String[0]);
2371 Jws2Instance service = Jws2Discoverer.getDiscoverer()
2372 .getPreferredServiceFor(calcIds);
2373 if (service != null)
2375 WsParamSetI parmSet = null;
2378 parmSet = service.getParamStore().parseServiceParameterFile(
2379 calcIdParam.getName(), calcIdParam.getDescription(),
2381 calcIdParam.getParameters().replace("|\\n|", "\n"));
2382 } catch (IOException x)
2384 warn("Couldn't parse parameter data for "
2385 + calcIdParam.getCalcId(), x);
2388 List<ArgumentI> argList = null;
2389 if (calcIdParam.getName().length() > 0)
2391 parmSet = service.getParamStore()
2392 .getPreset(calcIdParam.getName());
2393 if (parmSet != null)
2395 // TODO : check we have a good match with settings in AACon -
2396 // otherwise we'll need to create a new preset
2401 argList = parmSet.getArguments();
2404 AAConSettings settings = new AAConSettings(
2405 calcIdParam.isAutoUpdate(), service, parmSet, argList);
2406 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
2407 calcIdParam.isNeedsUpdate());
2412 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
2416 throw new Error(MessageManager.formatMessage(
2417 "error.unsupported_version_calcIdparam", new Object[]
2418 { calcIdParam.toString() }));
2422 * External mapping between jalview objects and objects yielding a valid and
2423 * unique object ID string. This is null for normal Jalview project IO, but
2424 * non-null when a jalview project is being read or written as part of a
2427 IdentityHashMap jv2vobj = null;
2430 * Construct a unique ID for jvobj using either existing bindings or if none
2431 * exist, the result of the hashcode call for the object.
2434 * jalview data object
2435 * @return unique ID for referring to jvobj
2437 private String makeHashCode(Object jvobj, String altCode)
2439 if (jv2vobj != null)
2441 Object id = jv2vobj.get(jvobj);
2444 return id.toString();
2446 // check string ID mappings
2447 if (jvids2vobj != null && jvobj instanceof String)
2449 id = jvids2vobj.get(jvobj);
2453 return id.toString();
2455 // give up and warn that something has gone wrong
2456 warn("Cannot find ID for object in external mapping : " + jvobj);
2462 * return local jalview object mapped to ID, if it exists
2466 * @return null or object bound to idcode
2468 private Object retrieveExistingObj(String idcode)
2470 if (idcode != null && vobj2jv != null)
2472 return vobj2jv.get(idcode);
2478 * binding from ID strings from external mapping table to jalview data model
2481 private Hashtable vobj2jv;
2483 private Sequence createVamsasSequence(String id, SequenceI jds)
2485 return createVamsasSequence(true, id, jds, null);
2488 private Sequence createVamsasSequence(boolean recurse, String id,
2489 SequenceI jds, SequenceI parentseq)
2491 Sequence vamsasSeq = new Sequence();
2492 vamsasSeq.setId(id);
2493 vamsasSeq.setName(jds.getName());
2494 vamsasSeq.setSequence(jds.getSequenceAsString());
2495 vamsasSeq.setDescription(jds.getDescription());
2496 jalview.datamodel.DBRefEntry[] dbrefs = null;
2497 if (jds.getDatasetSequence() != null)
2499 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
2503 // seqId==dsseqid so we can tell which sequences really are
2504 // dataset sequences only
2505 vamsasSeq.setDsseqid(id);
2506 dbrefs = jds.getDBRefs();
2507 if (parentseq == null)
2514 for (int d = 0; d < dbrefs.length; d++)
2516 DBRef dbref = new DBRef();
2517 dbref.setSource(dbrefs[d].getSource());
2518 dbref.setVersion(dbrefs[d].getVersion());
2519 dbref.setAccessionId(dbrefs[d].getAccessionId());
2520 if (dbrefs[d].hasMap())
2522 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
2524 dbref.setMapping(mp);
2526 // vamsasSeq.addDBRef(dbref);
2527 vamsasSeq.getDBRef().add(dbref);
2533 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
2534 SequenceI parentseq, SequenceI jds, boolean recurse)
2537 if (jmp.getMap() != null)
2541 jalview.util.MapList mlst = jmp.getMap();
2542 List<int[]> r = mlst.getFromRanges();
2543 for (int[] range : r)
2545 MapListFrom mfrom = new MapListFrom();
2546 mfrom.setStart(range[0]);
2547 mfrom.setEnd(range[1]);
2548 // mp.addMapListFrom(mfrom);
2549 mp.getMapListFrom().add(mfrom);
2551 r = mlst.getToRanges();
2552 for (int[] range : r)
2554 MapListTo mto = new MapListTo();
2555 mto.setStart(range[0]);
2556 mto.setEnd(range[1]);
2557 // mp.addMapListTo(mto);
2558 mp.getMapListTo().add(mto);
2560 mp.setMapFromUnit(BigInteger.valueOf(mlst.getFromRatio()));
2561 mp.setMapToUnit(BigInteger.valueOf(mlst.getToRatio()));
2562 if (jmp.getTo() != null)
2564 // MappingChoice mpc = new MappingChoice();
2566 // check/create ID for the sequence referenced by getTo()
2569 SequenceI ps = null;
2570 if (parentseq != jmp.getTo()
2571 && parentseq.getDatasetSequence() != jmp.getTo())
2573 // chaining dbref rather than a handshaking one
2574 jmpid = seqHash(ps = jmp.getTo());
2578 jmpid = seqHash(ps = parentseq);
2580 // mpc.setDseqFor(jmpid);
2581 mp.setDseqFor(jmpid);
2582 if (!seqRefIds.containsKey(jmpid))
2584 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2585 seqRefIds.put(jmpid, ps);
2589 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2592 // mp.setMappingChoice(mpc);
2598 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2599 List<UserColourScheme> userColours, JalviewModel jm)
2602 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2603 boolean newucs = false;
2604 if (!userColours.contains(ucs))
2606 userColours.add(ucs);
2609 id = "ucs" + userColours.indexOf(ucs);
2612 // actually create the scheme's entry in the XML model
2613 java.awt.Color[] colours = ucs.getColours();
2614 UserColours uc = new UserColours();
2615 // UserColourScheme jbucs = new UserColourScheme();
2616 JalviewUserColours jbucs = new JalviewUserColours();
2618 for (int i = 0; i < colours.length; i++)
2620 Colour col = new Colour();
2621 col.setName(ResidueProperties.aa[i]);
2622 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2623 // jbucs.addColour(col);
2624 jbucs.getColour().add(col);
2626 if (ucs.getLowerCaseColours() != null)
2628 colours = ucs.getLowerCaseColours();
2629 for (int i = 0; i < colours.length; i++)
2631 Colour col = new Colour();
2632 col.setName(ResidueProperties.aa[i].toLowerCase());
2633 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2634 // jbucs.addColour(col);
2635 jbucs.getColour().add(col);
2640 uc.setUserColourScheme(jbucs);
2641 // jm.addUserColours(uc);
2642 jm.getUserColours().add(uc);
2648 jalview.schemes.UserColourScheme getUserColourScheme(
2649 JalviewModel jm, String id)
2651 List<UserColours> uc = jm.getUserColours();
2652 UserColours colours = null;
2654 for (int i = 0; i < uc.length; i++)
2656 if (uc[i].getId().equals(id))
2663 for (UserColours c : uc)
2665 if (c.getId().equals(id))
2672 java.awt.Color[] newColours = new java.awt.Color[24];
2674 for (int i = 0; i < 24; i++)
2676 newColours[i] = new java.awt.Color(Integer.parseInt(
2677 // colours.getUserColourScheme().getColour(i).getRGB(), 16));
2678 colours.getUserColourScheme().getColour().get(i).getRGB(),
2682 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2685 if (colours.getUserColourScheme().getColour().size()/*Count()*/ > 24)
2687 newColours = new java.awt.Color[23];
2688 for (int i = 0; i < 23; i++)
2690 newColours[i] = new java.awt.Color(Integer.parseInt(
2691 colours.getUserColourScheme().getColour().get(i + 24)
2695 ucs.setLowerCaseColours(newColours);
2702 * contains last error message (if any) encountered by XML loader.
2704 String errorMessage = null;
2707 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2708 * exceptions are raised during project XML parsing
2710 public boolean attemptversion1parse = false;
2713 * Load a jalview project archive from a jar file
2716 * - HTTP URL or filename
2718 public AlignFrame loadJalviewAlign(final String file)
2721 jalview.gui.AlignFrame af = null;
2725 // create list to store references for any new Jmol viewers created
2726 newStructureViewers = new Vector<>();
2727 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2728 // Workaround is to make sure caller implements the JarInputStreamProvider
2730 // so we can re-open the jar input stream for each entry.
2732 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2733 af = loadJalviewAlign(jprovider);
2736 af.setMenusForViewport();
2738 } catch (MalformedURLException e)
2740 errorMessage = "Invalid URL format for '" + file + "'";
2746 SwingUtilities.invokeAndWait(new Runnable()
2751 setLoadingFinishedForNewStructureViewers();
2754 } catch (Exception x)
2756 System.err.println("Error loading alignment: " + x.getMessage());
2762 private jarInputStreamProvider createjarInputStreamProvider(
2763 final String file) throws MalformedURLException
2766 errorMessage = null;
2767 uniqueSetSuffix = null;
2769 viewportsAdded.clear();
2770 frefedSequence = null;
2772 if (file.startsWith("http://"))
2774 url = new URL(file);
2776 final URL _url = url;
2777 return new jarInputStreamProvider()
2781 public JarInputStream getJarInputStream() throws IOException
2785 return new JarInputStream(_url.openStream());
2789 return new JarInputStream(new FileInputStream(file));
2794 public String getFilename()
2802 * Recover jalview session from a jalview project archive. Caller may
2803 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2804 * themselves. Any null fields will be initialised with default values,
2805 * non-null fields are left alone.
2810 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2812 errorMessage = null;
2813 if (uniqueSetSuffix == null)
2815 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2817 if (seqRefIds == null)
2821 AlignFrame af = null, _af = null;
2822 IdentityHashMap<AlignmentI, AlignmentI> importedDatasets = new IdentityHashMap<>();
2823 Map<String, AlignFrame> gatherToThisFrame = new HashMap<>();
2824 final String file = jprovider.getFilename();
2827 JarInputStream jin = null;
2828 JarEntry jarentry = null;
2833 jin = jprovider.getJarInputStream();
2834 for (int i = 0; i < entryCount; i++)
2836 jarentry = jin.getNextJarEntry();
2839 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2841 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2842 // JalviewModel object = new JalviewModel();
2844 JAXBContext jc = JAXBContext
2845 .newInstance("jalview.xml.binding.jalview");
2846 XMLStreamReader streamReader = XMLInputFactory.newInstance()
2847 .createXMLStreamReader(jin);
2848 javax.xml.bind.Unmarshaller um = jc.createUnmarshaller();
2849 JAXBElement<JalviewModel> jbe = um
2850 .unmarshal(streamReader, JalviewModel.class);
2851 JalviewModel object = jbe.getValue();
2854 Unmarshaller unmar = new Unmarshaller(object);
2855 unmar.setValidation(false);
2856 object = (JalviewModel) unmar.unmarshal(in);
2858 if (true) // !skipViewport(object))
2860 _af = loadFromObject(object, file, true, jprovider);
2861 if (_af != null && object.getViewport().size() > 0)
2862 // getJalviewModelSequence().getViewportCount() > 0)
2866 // store a reference to the first view
2869 if (_af.getViewport().isGatherViewsHere())
2871 // if this is a gathered view, keep its reference since
2872 // after gathering views, only this frame will remain
2874 gatherToThisFrame.put(_af.getViewport().getSequenceSetId(),
2877 // Save dataset to register mappings once all resolved
2878 importedDatasets.put(
2879 af.getViewport().getAlignment().getDataset(),
2880 af.getViewport().getAlignment().getDataset());
2885 else if (jarentry != null)
2887 // Some other file here.
2890 } while (jarentry != null);
2891 resolveFrefedSequences();
2892 } catch (IOException ex)
2894 ex.printStackTrace();
2895 errorMessage = "Couldn't locate Jalview XML file : " + file;
2897 "Exception whilst loading jalview XML file : " + ex + "\n");
2898 } catch (Exception ex)
2900 System.err.println("Parsing as Jalview Version 2 file failed.");
2901 ex.printStackTrace(System.err);
2902 if (attemptversion1parse)
2904 // used to attempt to parse as V1 castor-generated xml
2906 if (Desktop.instance != null)
2908 Desktop.instance.stopLoading();
2912 System.out.println("Successfully loaded archive file");
2915 ex.printStackTrace();
2918 "Exception whilst loading jalview XML file : " + ex + "\n");
2919 } catch (OutOfMemoryError e)
2921 // Don't use the OOM Window here
2922 errorMessage = "Out of memory loading jalview XML file";
2923 System.err.println("Out of memory whilst loading jalview XML file");
2924 e.printStackTrace();
2928 * Regather multiple views (with the same sequence set id) to the frame (if
2929 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2930 * views instead of separate frames. Note this doesn't restore a state where
2931 * some expanded views in turn have tabbed views - the last "first tab" read
2932 * in will play the role of gatherer for all.
2934 for (AlignFrame fr : gatherToThisFrame.values())
2936 Desktop.instance.gatherViews(fr);
2939 restoreSplitFrames();
2940 for (AlignmentI ds : importedDatasets.keySet())
2942 if (ds.getCodonFrames() != null)
2944 StructureSelectionManager
2945 .getStructureSelectionManager(Desktop.instance)
2946 .registerMappings(ds.getCodonFrames());
2949 if (errorMessage != null)
2954 if (Desktop.instance != null)
2956 Desktop.instance.stopLoading();
2963 * Try to reconstruct and display SplitFrame windows, where each contains
2964 * complementary dna and protein alignments. Done by pairing up AlignFrame
2965 * objects (created earlier) which have complementary viewport ids associated.
2967 protected void restoreSplitFrames()
2969 List<SplitFrame> gatherTo = new ArrayList<>();
2970 List<AlignFrame> addedToSplitFrames = new ArrayList<>();
2971 Map<String, AlignFrame> dna = new HashMap<>();
2974 * Identify the DNA alignments
2976 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2979 AlignFrame af = candidate.getValue();
2980 if (af.getViewport().getAlignment().isNucleotide())
2982 dna.put(candidate.getKey().getId(), af);
2987 * Try to match up the protein complements
2989 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2992 AlignFrame af = candidate.getValue();
2993 if (!af.getViewport().getAlignment().isNucleotide())
2995 String complementId = candidate.getKey().getComplementId();
2996 // only non-null complements should be in the Map
2997 if (complementId != null && dna.containsKey(complementId))
2999 final AlignFrame dnaFrame = dna.get(complementId);
3000 SplitFrame sf = createSplitFrame(dnaFrame, af);
3001 addedToSplitFrames.add(dnaFrame);
3002 addedToSplitFrames.add(af);
3003 dnaFrame.setMenusForViewport();
3004 af.setMenusForViewport();
3005 if (af.getViewport().isGatherViewsHere())
3014 * Open any that we failed to pair up (which shouldn't happen!) as
3015 * standalone AlignFrame's.
3017 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
3020 AlignFrame af = candidate.getValue();
3021 if (!addedToSplitFrames.contains(af))
3023 Viewport view = candidate.getKey();
3024 Desktop.addInternalFrame(af, view.getTitle(),
3025 safeInt(view.getWidth()), safeInt(view.getHeight()));
3026 af.setMenusForViewport();
3027 System.err.println("Failed to restore view " + view.getTitle()
3028 + " to split frame");
3033 * Gather back into tabbed views as flagged.
3035 for (SplitFrame sf : gatherTo)
3037 Desktop.instance.gatherViews(sf);
3040 splitFrameCandidates.clear();
3044 * Construct and display one SplitFrame holding DNA and protein alignments.
3047 * @param proteinFrame
3050 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
3051 AlignFrame proteinFrame)
3053 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
3054 String title = MessageManager.getString("label.linked_view_title");
3055 int width = (int) dnaFrame.getBounds().getWidth();
3056 int height = (int) (dnaFrame.getBounds().getHeight()
3057 + proteinFrame.getBounds().getHeight() + 50);
3060 * SplitFrame location is saved to both enclosed frames
3062 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
3063 Desktop.addInternalFrame(splitFrame, title, width, height);
3066 * And compute cDNA consensus (couldn't do earlier with consensus as
3067 * mappings were not yet present)
3069 proteinFrame.getViewport().alignmentChanged(proteinFrame.alignPanel);
3075 * check errorMessage for a valid error message and raise an error box in the
3076 * GUI or write the current errorMessage to stderr and then clear the error
3079 protected void reportErrors()
3081 reportErrors(false);
3084 protected void reportErrors(final boolean saving)
3086 if (errorMessage != null)
3088 final String finalErrorMessage = errorMessage;
3091 javax.swing.SwingUtilities.invokeLater(new Runnable()
3096 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
3098 "Error " + (saving ? "saving" : "loading")
3100 JvOptionPane.WARNING_MESSAGE);
3106 System.err.println("Problem loading Jalview file: " + errorMessage);
3109 errorMessage = null;
3112 Map<String, String> alreadyLoadedPDB = new HashMap<>();
3115 * when set, local views will be updated from view stored in JalviewXML
3116 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
3117 * sync if this is set to true.
3119 private final boolean updateLocalViews = false;
3122 * Returns the path to a temporary file holding the PDB file for the given PDB
3123 * id. The first time of asking, searches for a file of that name in the
3124 * Jalview project jar, and copies it to a new temporary file. Any repeat
3125 * requests just return the path to the file previously created.
3131 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId,
3134 if (alreadyLoadedPDB.containsKey(pdbId))
3136 return alreadyLoadedPDB.get(pdbId).toString();
3139 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb",
3141 if (tempFile != null)
3143 alreadyLoadedPDB.put(pdbId, tempFile);
3149 * Copies the jar entry of given name to a new temporary file and returns the
3150 * path to the file, or null if the entry is not found.
3153 * @param jarEntryName
3155 * a prefix for the temporary file name, must be at least three
3158 * null or original file - so new file can be given the same suffix
3162 protected String copyJarEntry(jarInputStreamProvider jprovider,
3163 String jarEntryName, String prefix, String origFile)
3165 BufferedReader in = null;
3166 PrintWriter out = null;
3167 String suffix = ".tmp";
3168 if (origFile == null)
3170 origFile = jarEntryName;
3172 int sfpos = origFile.lastIndexOf(".");
3173 if (sfpos > -1 && sfpos < (origFile.length() - 3))
3175 suffix = "." + origFile.substring(sfpos + 1);
3179 JarInputStream jin = jprovider.getJarInputStream();
3181 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
3182 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
3183 * FileInputStream(jprovider)); }
3186 JarEntry entry = null;
3189 entry = jin.getNextJarEntry();
3190 } while (entry != null && !entry.getName().equals(jarEntryName));
3193 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
3194 File outFile = File.createTempFile(prefix, suffix);
3195 outFile.deleteOnExit();
3196 out = new PrintWriter(new FileOutputStream(outFile));
3199 while ((data = in.readLine()) != null)
3204 String t = outFile.getAbsolutePath();
3209 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
3211 } catch (Exception ex)
3213 ex.printStackTrace();
3221 } catch (IOException e)
3235 private class JvAnnotRow
3237 public JvAnnotRow(int i, AlignmentAnnotation jaa)
3244 * persisted version of annotation row from which to take vis properties
3246 public jalview.datamodel.AlignmentAnnotation template;
3249 * original position of the annotation row in the alignment
3255 * Load alignment frame from jalview XML DOM object
3257 * @param jalviewModel
3260 * filename source string
3261 * @param loadTreesAndStructures
3262 * when false only create Viewport
3264 * data source provider
3265 * @return alignment frame created from view stored in DOM
3267 AlignFrame loadFromObject(JalviewModel jalviewModel, String file,
3268 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
3270 SequenceSet vamsasSet = jalviewModel.getVamsasModel().getSequenceSet().get(0);
3271 List<Sequence> vamsasSeqs = vamsasSet.getSequence();
3273 // JalviewModelSequence jms = object.getJalviewModelSequence();
3275 // Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
3277 Viewport view = (jalviewModel.getViewport().size() > 0)
3278 ? jalviewModel.getViewport().get(0)
3281 // ////////////////////////////////
3282 // INITIALISE ALIGNMENT SEQUENCESETID AND VIEWID
3285 // If we just load in the same jar file again, the sequenceSetId
3286 // will be the same, and we end up with multiple references
3287 // to the same sequenceSet. We must modify this id on load
3288 // so that each load of the file gives a unique id
3291 * used to resolve correct alignment dataset for alignments with multiple
3294 String uniqueSeqSetId = null;
3295 String viewId = null;
3298 uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3299 viewId = (view.getId() == null ? null
3300 : view.getId() + uniqueSetSuffix);
3303 // ////////////////////////////////
3306 List<SequenceI> hiddenSeqs = null;
3308 List<SequenceI> tmpseqs = new ArrayList<>();
3310 boolean multipleView = false;
3311 SequenceI referenceseqForView = null;
3312 // JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
3313 List<JSeq> jseqs = jalviewModel.getJSeq();
3314 int vi = 0; // counter in vamsasSeq array
3315 for (int i = 0; i < jseqs.size(); i++)
3317 JSeq jseq = jseqs.get(i);
3318 String seqId = jseq.getId();
3320 SequenceI tmpSeq = seqRefIds.get(seqId);
3323 if (!incompleteSeqs.containsKey(seqId))
3325 // may not need this check, but keep it for at least 2.9,1 release
3326 if (tmpSeq.getStart() != jseq.getStart()
3327 || tmpSeq.getEnd() != jseq.getEnd())
3330 "Warning JAL-2154 regression: updating start/end for sequence "
3331 + tmpSeq.toString() + " to " + jseq);
3336 incompleteSeqs.remove(seqId);
3338 if (vamsasSeqs.size() > vi
3339 && vamsasSeqs.get(vi).getId().equals(seqId))
3341 // most likely we are reading a dataset XML document so
3342 // update from vamsasSeq section of XML for this sequence
3343 tmpSeq.setName(vamsasSeqs.get(vi).getName());
3344 tmpSeq.setDescription(vamsasSeqs.get(vi).getDescription());
3345 tmpSeq.setSequence(vamsasSeqs.get(vi).getSequence());
3350 // reading multiple views, so vamsasSeq set is a subset of JSeq
3351 multipleView = true;
3353 tmpSeq.setStart(jseq.getStart());
3354 tmpSeq.setEnd(jseq.getEnd());
3355 tmpseqs.add(tmpSeq);
3359 Sequence vamsasSeq = vamsasSeqs.get(vi);
3360 tmpSeq = new jalview.datamodel.Sequence(vamsasSeq.getName(),
3361 vamsasSeq.getSequence());
3362 tmpSeq.setDescription(vamsasSeq.getDescription());
3363 tmpSeq.setStart(jseq.getStart());
3364 tmpSeq.setEnd(jseq.getEnd());
3365 tmpSeq.setVamsasId(uniqueSetSuffix + seqId);
3366 seqRefIds.put(vamsasSeq.getId(), tmpSeq);
3367 tmpseqs.add(tmpSeq);
3371 if (safeBoolean(jseq.isViewreference()))
3373 referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
3376 if (jseq.isHidden() != null && jseq.isHidden().booleanValue())
3378 if (hiddenSeqs == null)
3380 hiddenSeqs = new ArrayList<>();
3383 hiddenSeqs.add(tmpSeq);
3388 // Create the alignment object from the sequence set
3389 // ///////////////////////////////
3390 SequenceI[] orderedSeqs = tmpseqs
3391 .toArray(new SequenceI[tmpseqs.size()]);
3393 AlignmentI al = null;
3394 // so we must create or recover the dataset alignment before going further
3395 // ///////////////////////////////
3396 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
3398 // older jalview projects do not have a dataset - so creat alignment and
3400 al = new Alignment(orderedSeqs);
3401 al.setDataset(null);
3405 boolean isdsal = jalviewModel.getViewport().isEmpty();
3408 // we are importing a dataset record, so
3409 // recover reference to an alignment already materialsed as dataset
3410 al = getDatasetFor(vamsasSet.getDatasetId());
3414 // materialse the alignment
3415 al = new Alignment(orderedSeqs);
3419 addDatasetRef(vamsasSet.getDatasetId(), al);
3422 // finally, verify all data in vamsasSet is actually present in al
3423 // passing on flag indicating if it is actually a stored dataset
3424 recoverDatasetFor(vamsasSet, al, isdsal, uniqueSeqSetId);
3427 if (referenceseqForView != null)
3429 al.setSeqrep(referenceseqForView);
3431 // / Add the alignment properties
3432 for (int i = 0; i < vamsasSet.getSequenceSetProperties().size(); i++)
3434 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties()
3436 al.setProperty(ssp.getKey(), ssp.getValue());
3439 // ///////////////////////////////
3441 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
3444 // load sequence features, database references and any associated PDB
3445 // structures for the alignment
3447 // prior to 2.10, this part would only be executed the first time a
3448 // sequence was encountered, but not afterwards.
3449 // now, for 2.10 projects, this is also done if the xml doc includes
3450 // dataset sequences not actually present in any particular view.
3452 for (int i = 0; i < vamsasSeqs.size(); i++)
3454 JSeq jseq = jseqs.get(i);
3455 if (jseq.getFeatures().size() > 0)
3457 List<Feature> features = jseq.getFeatures();
3458 for (int f = 0; f < features.size(); f++)
3460 Feature feat = features.get(f);
3461 SequenceFeature sf = new SequenceFeature(feat.getType(),
3462 feat.getDescription(), feat.getBegin(), feat.getEnd(),
3463 safeFloat(feat.getScore()), feat.getFeatureGroup());
3464 sf.setStatus(feat.getStatus());
3467 * load any feature attributes - include map-valued attributes
3469 Map<String, Map<String, String>> mapAttributes = new HashMap<>();
3470 for (int od = 0; od < feat.getOtherData().size(); od++)
3472 OtherData keyValue = feat.getOtherData().get(od);
3473 String attributeName = keyValue.getKey();
3474 String attributeValue = keyValue.getValue();
3475 if (attributeName.startsWith("LINK"))
3477 sf.addLink(attributeValue);
3481 String subAttribute = keyValue.getKey2();
3482 if (subAttribute == null)
3484 // simple string-valued attribute
3485 sf.setValue(attributeName, attributeValue);
3489 // attribute 'key' has sub-attribute 'key2'
3490 if (!mapAttributes.containsKey(attributeName))
3492 mapAttributes.put(attributeName, new HashMap<>());
3494 mapAttributes.get(attributeName).put(subAttribute,
3499 for (Entry<String, Map<String, String>> mapAttribute : mapAttributes
3502 sf.setValue(mapAttribute.getKey(), mapAttribute.getValue());
3505 // adds feature to datasequence's feature set (since Jalview 2.10)
3506 al.getSequenceAt(i).addSequenceFeature(sf);
3509 if (vamsasSeqs.get(i).getDBRef().size() > 0)
3511 // adds dbrefs to datasequence's set (since Jalview 2.10)
3513 al.getSequenceAt(i).getDatasetSequence() == null
3514 ? al.getSequenceAt(i)
3515 : al.getSequenceAt(i).getDatasetSequence(),
3518 if (jseq.getPdbids().size() > 0)
3520 List<Pdbids> ids = jseq.getPdbids();
3521 for (int p = 0; p < ids.size(); p++)
3523 Pdbids pdbid = ids.get(p);
3524 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
3525 entry.setId(pdbid.getId());
3526 if (pdbid.getType() != null)
3528 if (PDBEntry.Type.getType(pdbid.getType()) != null)
3530 entry.setType(PDBEntry.Type.getType(pdbid.getType()));
3534 entry.setType(PDBEntry.Type.FILE);
3537 // jprovider is null when executing 'New View'
3538 if (pdbid.getFile() != null && jprovider != null)
3540 if (!pdbloaded.containsKey(pdbid.getFile()))
3542 entry.setFile(loadPDBFile(jprovider, pdbid.getId(),
3547 entry.setFile(pdbloaded.get(pdbid.getId()).toString());
3551 if (pdbid.getPdbentryItem() != null)
3553 for (PdbentryItem item : pdbid.getPdbentryItem())
3555 for (Property pr : item.getProperty())
3557 entry.setProperty(pr.getName(), pr.getValue());
3562 for (Property prop : pdbid.getProperty())
3564 entry.setProperty(prop.getName(), prop.getValue());
3566 StructureSelectionManager
3567 .getStructureSelectionManager(Desktop.instance)
3568 .registerPDBEntry(entry);
3569 // adds PDBEntry to datasequence's set (since Jalview 2.10)
3570 if (al.getSequenceAt(i).getDatasetSequence() != null)
3572 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
3576 al.getSequenceAt(i).addPDBId(entry);
3581 } // end !multipleview
3583 // ///////////////////////////////
3584 // LOAD SEQUENCE MAPPINGS
3586 if (vamsasSet.getAlcodonFrame().size() > 0)
3588 // TODO Potentially this should only be done once for all views of an
3590 List<AlcodonFrame> alc = vamsasSet.getAlcodonFrame();
3591 for (int i = 0; i < alc.size(); i++)
3593 AlignedCodonFrame cf = new AlignedCodonFrame();
3594 if (alc.get(i).getAlcodMap().size() > 0)
3596 List<AlcodMap> maps = alc.get(i).getAlcodMap();
3597 for (int m = 0; m < maps.size(); m++)
3599 AlcodMap map = maps.get(m);
3600 SequenceI dnaseq = seqRefIds.get(map.getDnasq());
3602 jalview.datamodel.Mapping mapping = null;
3603 // attach to dna sequence reference.
3604 if (map.getMapping() != null)
3606 mapping = addMapping(map.getMapping());
3607 if (dnaseq != null && mapping.getTo() != null)
3609 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
3615 newAlcodMapRef(map.getDnasq(), cf, mapping));
3619 al.addCodonFrame(cf);
3624 // ////////////////////////////////
3626 List<AlignmentAnnotation> addedAnnotation = new ArrayList<>();
3629 * store any annotations which forward reference a group's ID
3631 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<>();
3633 if (vamsasSet.getAnnotation().size()/*Count()*/ > 0)
3635 List<Annotation> an = vamsasSet.getAnnotation();
3637 for (int i = 0; i < an.size(); i++)
3639 Annotation annotation = an.get(i);
3642 * test if annotation is automatically calculated for this view only
3644 boolean autoForView = false;
3645 if (annotation.getLabel().equals("Quality")
3646 || annotation.getLabel().equals("Conservation")
3647 || annotation.getLabel().equals("Consensus"))
3649 // Kludge for pre 2.5 projects which lacked the autocalculated flag
3651 // JAXB has no has() test; schema defaults value to false
3652 // if (!annotation.hasAutoCalculated())
3654 // annotation.setAutoCalculated(true);
3657 if (autoForView || annotation.isAutoCalculated())
3659 // remove ID - we don't recover annotation from other views for
3660 // view-specific annotation
3661 annotation.setId(null);
3664 // set visibility for other annotation in this view
3665 String annotationId = annotation.getId();
3666 if (annotationId != null && annotationIds.containsKey(annotationId))
3668 AlignmentAnnotation jda = annotationIds.get(annotationId);
3669 // in principle Visible should always be true for annotation displayed
3670 // in multiple views
3671 if (annotation.isVisible() != null)
3673 jda.visible = annotation.isVisible();
3676 al.addAnnotation(jda);
3680 // Construct new annotation from model.
3681 List<AnnotationElement> ae = annotation.getAnnotationElement();
3682 jalview.datamodel.Annotation[] anot = null;
3683 java.awt.Color firstColour = null;
3685 if (!annotation.isScoreOnly())
3687 anot = new jalview.datamodel.Annotation[al.getWidth()];
3688 for (int aa = 0; aa < ae.size() && aa < anot.length; aa++)
3690 AnnotationElement annElement = ae.get(aa);
3691 anpos = annElement.getPosition();
3693 if (anpos >= anot.length)
3698 float value = safeFloat(annElement.getValue());
3699 anot[anpos] = new jalview.datamodel.Annotation(
3700 annElement.getDisplayCharacter(),
3701 annElement.getDescription(),
3702 (annElement.getSecondaryStructure() == null
3703 || annElement.getSecondaryStructure()
3707 .getSecondaryStructure()
3710 anot[anpos].colour = new Color(safeInt(annElement.getColour()));
3711 if (firstColour == null)
3713 firstColour = anot[anpos].colour;
3719 * construct the Jalview AlignmentAnnotation, add to alignment
3721 AlignmentAnnotation jaa = null;
3723 if (annotation.isGraph())
3725 float llim = 0, hlim = 0;
3726 // if (autoForView || an[i].isAutoCalculated()) {
3729 jaa = new jalview.datamodel.AlignmentAnnotation(
3730 annotation.getLabel(), annotation.getDescription(), anot,
3731 llim, hlim, safeInt(annotation.getGraphType()));
3733 jaa.graphGroup = safeInt(annotation.getGraphGroup());
3734 jaa._linecolour = firstColour;
3735 if (annotation.getThresholdLine() != null)
3737 jaa.setThreshold(new jalview.datamodel.GraphLine(
3738 safeFloat(annotation.getThresholdLine().getValue()),
3739 annotation.getThresholdLine().getLabel(),
3740 new java.awt.Color(safeInt(
3741 annotation.getThresholdLine().getColour()))));
3743 if (autoForView || annotation.isAutoCalculated())
3745 // Hardwire the symbol display line to ensure that labels for
3746 // histograms are displayed
3752 jaa = new jalview.datamodel.AlignmentAnnotation(
3753 annotation.getLabel(), annotation.getDescription(), anot);
3754 jaa._linecolour = firstColour;
3756 // register new annotation
3757 if (annotation.getId() != null)
3759 annotationIds.put(annotation.getId(), jaa);
3760 jaa.annotationId = annotation.getId();
3762 // recover sequence association
3763 String sequenceRef = annotation.getSequenceRef();
3764 if (sequenceRef != null)
3766 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3767 SequenceI sequence = seqRefIds.get(sequenceRef);
3768 if (sequence == null)
3770 // in pre-2.9 projects sequence ref is to sequence name
3771 sequence = al.findName(sequenceRef);
3773 if (sequence != null)
3775 jaa.createSequenceMapping(sequence, 1, true);
3776 sequence.addAlignmentAnnotation(jaa);
3779 // and make a note of any group association
3780 if (annotation.getGroupRef() != null
3781 && annotation.getGroupRef().length() > 0)
3783 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3784 .get(annotation.getGroupRef());
3787 aal = new ArrayList<>();
3788 groupAnnotRefs.put(annotation.getGroupRef(), aal);
3793 if (annotation.getScore() != null)
3795 jaa.setScore(annotation.getScore().doubleValue());
3797 if (annotation.isVisible() != null)
3799 jaa.visible = annotation.isVisible().booleanValue();
3802 if (annotation.isCentreColLabels() != null)
3804 jaa.centreColLabels = annotation.isCentreColLabels()
3808 if (annotation.isScaleColLabels() != null)
3810 jaa.scaleColLabel = annotation.isScaleColLabels().booleanValue();
3812 if (annotation.isAutoCalculated())
3814 // newer files have an 'autoCalculated' flag and store calculation
3815 // state in viewport properties
3816 jaa.autoCalculated = true; // means annotation will be marked for
3817 // update at end of load.
3819 Integer graphHeight = annotation.getGraphHeight();
3820 if (graphHeight != null)
3822 jaa.graphHeight = graphHeight.intValue();
3824 jaa.belowAlignment = annotation.isBelowAlignment();
3825 jaa.setCalcId(annotation.getCalcId());
3826 if (annotation.getProperty().size() > 0)
3828 for (Annotation.Property prop : annotation
3831 jaa.setProperty(prop.getName(), prop.getValue());
3834 if (!jaa.autoCalculated)
3836 // TODO ensure Consensus etc is enabled if found in project?
3838 * add autocalculated group annotation and any user created annotation
3841 al.addAnnotation(jaa);
3843 addedAnnotation.add(jaa);
3846 // ///////////////////////
3848 // Create alignment markup and styles for this view
3849 if (jalviewModel.getJGroup().size() > 0)
3851 List<JGroup> groups = jalviewModel.getJGroup();
3852 boolean addAnnotSchemeGroup = false;
3853 for (int i = 0; i < groups.size(); i++)
3855 JGroup jGroup = groups.get(i);
3856 ColourSchemeI cs = null;
3857 if (jGroup.getColour() != null)
3859 if (jGroup.getColour().startsWith("ucs"))
3861 cs = getUserColourScheme(jalviewModel, jGroup.getColour());
3863 else if (jGroup.getColour().equals("AnnotationColourGradient")
3864 && jGroup.getAnnotationColours() != null)
3866 addAnnotSchemeGroup = true;
3870 cs = ColourSchemeProperty.getColourScheme(null, al,
3871 jGroup.getColour());
3874 int pidThreshold = safeInt(jGroup.getPidThreshold());
3876 Vector<SequenceI> seqs = new Vector<>();
3878 for (int s = 0; s < jGroup.getSeq().size(); s++)
3880 String seqId = jGroup.getSeq().get(s);
3881 SequenceI ts = seqRefIds.get(seqId);
3885 seqs.addElement(ts);
3889 if (seqs.size() < 1)
3894 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3895 safeBoolean(jGroup.isDisplayBoxes()),
3896 safeBoolean(jGroup.isDisplayText()),
3897 safeBoolean(jGroup.isColourText()),
3898 safeInt(jGroup.getStart()), safeInt(jGroup.getEnd()));
3899 sg.getGroupColourScheme().setThreshold(pidThreshold, true);
3900 sg.getGroupColourScheme()
3901 .setConservationInc(safeInt(jGroup.getConsThreshold()));
3902 sg.setOutlineColour(new Color(safeInt(jGroup.getOutlineColour())));
3904 sg.textColour = new Color(safeInt(jGroup.getTextCol1()));
3905 sg.textColour2 = new Color(safeInt(jGroup.getTextCol2()));
3906 sg.setShowNonconserved(safeBoolean(jGroup.isShowUnconserved()));
3907 sg.thresholdTextColour = safeInt(jGroup.getTextColThreshold());
3908 // attributes with a default in the schema are never null
3909 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3910 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3911 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3912 sg.setIgnoreGapsConsensus(jGroup.isIgnoreGapsinConsensus());
3913 if (jGroup.getConsThreshold() != null
3914 && jGroup.getConsThreshold().intValue() != 0)
3916 Conservation c = new Conservation("All", sg.getSequences(null), 0,
3919 c.verdict(false, 25);
3920 sg.cs.setConservation(c);
3923 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3925 // re-instate unique group/annotation row reference
3926 List<AlignmentAnnotation> jaal = groupAnnotRefs
3927 .get(jGroup.getId());
3930 for (AlignmentAnnotation jaa : jaal)
3933 if (jaa.autoCalculated)
3935 // match up and try to set group autocalc alignment row for this
3937 if (jaa.label.startsWith("Consensus for "))
3939 sg.setConsensus(jaa);
3941 // match up and try to set group autocalc alignment row for this
3943 if (jaa.label.startsWith("Conservation for "))
3945 sg.setConservationRow(jaa);
3952 if (addAnnotSchemeGroup)
3954 // reconstruct the annotation colourscheme
3955 sg.setColourScheme(constructAnnotationColour(
3956 jGroup.getAnnotationColours(), null, al, jalviewModel, false));
3962 // only dataset in this model, so just return.
3965 // ///////////////////////////////
3968 AlignFrame af = null;
3969 AlignViewport av = null;
3970 // now check to see if we really need to create a new viewport.
3971 if (multipleView && viewportsAdded.size() == 0)
3973 // We recovered an alignment for which a viewport already exists.
3974 // TODO: fix up any settings necessary for overlaying stored state onto
3975 // state recovered from another document. (may not be necessary).
3976 // we may need a binding from a viewport in memory to one recovered from
3978 // and then recover its containing af to allow the settings to be applied.
3979 // TODO: fix for vamsas demo
3981 "About to recover a viewport for existing alignment: Sequence set ID is "
3983 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3984 if (seqsetobj != null)
3986 if (seqsetobj instanceof String)
3988 uniqueSeqSetId = (String) seqsetobj;
3990 "Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
3996 "Warning : Collision between sequence set ID string and existing jalview object mapping.");
4002 * indicate that annotation colours are applied across all groups (pre
4003 * Jalview 2.8.1 behaviour)
4005 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan("2.8.1",
4006 jalviewModel.getVersion());
4008 AlignmentPanel ap = null;
4009 boolean isnewview = true;
4012 // Check to see if this alignment already has a view id == viewId
4013 jalview.gui.AlignmentPanel views[] = Desktop
4014 .getAlignmentPanels(uniqueSeqSetId);
4015 if (views != null && views.length > 0)
4017 for (int v = 0; v < views.length; v++)
4019 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
4021 // recover the existing alignpanel, alignframe, viewport
4022 af = views[v].alignFrame;
4025 // TODO: could even skip resetting view settings if we don't want to
4026 // change the local settings from other jalview processes
4035 af = loadViewport(file, jseqs, hiddenSeqs, al, jalviewModel, view,
4036 uniqueSeqSetId, viewId);
4037 // TODO restore autocalc preferences if overridden earlier?
4039 * resort annotations to their order in the project
4040 * (also sets height and visibility for autocalc'd annotation)
4042 av = af.getViewport();
4043 new AnnotationSorter(av).sort(addedAnnotation);
4045 ap.adjustAnnotationHeight();
4049 * Load any trees, PDB structures and viewers
4051 * Not done if flag is false (when this method is used for New View)
4053 if (loadTreesAndStructures)
4055 loadTrees(jalviewModel, view, af, av, ap);
4056 loadPCAViewers(jalviewModel, ap);
4057 loadPDBStructures(jprovider, jseqs, af, ap);
4058 loadRnaViewers(jprovider, jseqs, ap);
4060 // and finally return.
4065 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
4066 * panel is restored from separate jar entries, two (gapped and trimmed) per
4067 * sequence and secondary structure.
4069 * Currently each viewer shows just one sequence and structure (gapped and
4070 * trimmed), however this method is designed to support multiple sequences or
4071 * structures in viewers if wanted in future.
4077 private void loadRnaViewers(jarInputStreamProvider jprovider,
4078 List<JSeq> jseqs, AlignmentPanel ap)
4081 * scan the sequences for references to viewers; create each one the first
4082 * time it is referenced, add Rna models to existing viewers
4084 for (JSeq jseq : jseqs)
4086 for (int i = 0; i < jseq.getRnaViewer().size(); i++)
4088 RnaViewer viewer = jseq.getRnaViewer().get(i);
4089 AppVarna appVarna = findOrCreateVarnaViewer(viewer, uniqueSetSuffix,
4092 for (int j = 0; j < viewer.getSecondaryStructure().size(); j++)
4094 SecondaryStructure ss = viewer.getSecondaryStructure().get(j);
4095 SequenceI seq = seqRefIds.get(jseq.getId());
4096 AlignmentAnnotation ann = this.annotationIds
4097 .get(ss.getAnnotationId());
4100 * add the structure to the Varna display (with session state copied
4101 * from the jar to a temporary file)
4103 boolean gapped = safeBoolean(ss.isGapped());
4104 String rnaTitle = ss.getTitle();
4105 String sessionState = ss.getViewerState();
4106 String tempStateFile = copyJarEntry(jprovider, sessionState,
4108 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
4109 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
4111 appVarna.setInitialSelection(safeInt(viewer.getSelectedRna()));
4117 * Locate and return an already instantiated matching AppVarna, or create one
4121 * @param viewIdSuffix
4125 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
4126 String viewIdSuffix, AlignmentPanel ap)
4129 * on each load a suffix is appended to the saved viewId, to avoid conflicts
4130 * if load is repeated
4132 String postLoadId = viewer.getViewId() + viewIdSuffix;
4133 for (JInternalFrame frame : getAllFrames())
4135 if (frame instanceof AppVarna)
4137 AppVarna varna = (AppVarna) frame;
4138 if (postLoadId.equals(varna.getViewId()))
4140 // this viewer is already instantiated
4141 // could in future here add ap as another 'parent' of the
4142 // AppVarna window; currently just 1-to-many
4149 * viewer not found - make it
4151 RnaViewerModel model = new RnaViewerModel(postLoadId, viewer.getTitle(),
4152 safeInt(viewer.getXpos()), safeInt(viewer.getYpos()),
4153 safeInt(viewer.getWidth()), safeInt(viewer.getHeight()),
4154 safeInt(viewer.getDividerLocation()));
4155 AppVarna varna = new AppVarna(model, ap);
4161 * Load any saved trees
4169 protected void loadTrees(JalviewModel jm, Viewport view,
4170 AlignFrame af, AlignViewport av, AlignmentPanel ap)
4172 // TODO result of automated refactoring - are all these parameters needed?
4175 for (int t = 0; t < jm.getTree().size(); t++)
4178 Tree tree = jm.getTree().get(t);
4180 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
4183 tp = af.showNewickTree(new NewickFile(tree.getNewick()),
4184 tree.getTitle(), safeInt(tree.getWidth()),
4185 safeInt(tree.getHeight()), safeInt(tree.getXpos()),
4186 safeInt(tree.getYpos()));
4187 if (tree.getId() != null)
4189 // perhaps bind the tree id to something ?
4194 // update local tree attributes ?
4195 // TODO: should check if tp has been manipulated by user - if so its
4196 // settings shouldn't be modified
4197 tp.setTitle(tree.getTitle());
4198 tp.setBounds(new Rectangle(safeInt(tree.getXpos()),
4199 safeInt(tree.getYpos()), safeInt(tree.getWidth()),
4200 safeInt(tree.getHeight())));
4201 tp.setViewport(av); // af.viewport;
4202 // TODO: verify 'associate with all views' works still
4203 tp.getTreeCanvas().setViewport(av); // af.viewport;
4204 tp.getTreeCanvas().setAssociatedPanel(ap); // af.alignPanel;
4206 tp.getTreeCanvas().setApplyToAllViews(tree.isLinkToAllViews());
4209 warn("There was a problem recovering stored Newick tree: \n"
4210 + tree.getNewick());
4214 tp.fitToWindow.setState(safeBoolean(tree.isFitToWindow()));
4215 tp.fitToWindow_actionPerformed(null);
4217 if (tree.getFontName() != null)
4220 new Font(tree.getFontName(), safeInt(tree.getFontStyle()),
4221 safeInt(tree.getFontSize())));
4226 new Font(view.getFontName(), safeInt(view.getFontStyle()),
4227 safeInt(view.getFontSize())));
4230 tp.showPlaceholders(safeBoolean(tree.isMarkUnlinked()));
4231 tp.showBootstrap(safeBoolean(tree.isShowBootstrap()));
4232 tp.showDistances(safeBoolean(tree.isShowDistances()));
4234 tp.getTreeCanvas().setThreshold(safeFloat(tree.getThreshold()));
4236 if (safeBoolean(tree.isCurrentTree()))
4238 af.getViewport().setCurrentTree(tp.getTree());
4242 } catch (Exception ex)
4244 ex.printStackTrace();
4249 * Load and link any saved structure viewers.
4256 protected void loadPDBStructures(jarInputStreamProvider jprovider,
4257 List<JSeq> jseqs, AlignFrame af, AlignmentPanel ap)
4260 * Run through all PDB ids on the alignment, and collect mappings between
4261 * distinct view ids and all sequences referring to that view.
4263 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<>();
4265 for (int i = 0; i < jseqs.size(); i++)
4267 JSeq jseq = jseqs.get(i);
4268 if (jseq.getPdbids().size() > 0)
4270 List<Pdbids> ids = jseq.getPdbids();
4271 for (int p = 0; p < ids.size(); p++)
4273 Pdbids pdbid = ids.get(p);
4274 final int structureStateCount = pdbid.getStructureState().size();
4275 for (int s = 0; s < structureStateCount; s++)
4277 // check to see if we haven't already created this structure view
4278 final StructureState structureState = pdbid
4279 .getStructureState().get(s);
4280 String sviewid = (structureState.getViewId() == null) ? null
4281 : structureState.getViewId() + uniqueSetSuffix;
4282 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
4283 // Originally : pdbid.getFile()
4284 // : TODO: verify external PDB file recovery still works in normal
4285 // jalview project load
4287 loadPDBFile(jprovider, pdbid.getId(), pdbid.getFile()));
4288 jpdb.setId(pdbid.getId());
4290 int x = safeInt(structureState.getXpos());
4291 int y = safeInt(structureState.getYpos());
4292 int width = safeInt(structureState.getWidth());
4293 int height = safeInt(structureState.getHeight());
4295 // Probably don't need to do this anymore...
4296 // Desktop.desktop.getComponentAt(x, y);
4297 // TODO: NOW: check that this recovers the PDB file correctly.
4298 String pdbFile = loadPDBFile(jprovider, pdbid.getId(),
4300 jalview.datamodel.SequenceI seq = seqRefIds
4301 .get(jseq.getId() + "");
4302 if (sviewid == null)
4304 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width + ","
4307 if (!structureViewers.containsKey(sviewid))
4309 structureViewers.put(sviewid,
4310 new StructureViewerModel(x, y, width, height, false,
4311 false, true, structureState.getViewId(),
4312 structureState.getType()));
4313 // Legacy pre-2.7 conversion JAL-823 :
4314 // do not assume any view has to be linked for colour by
4318 // assemble String[] { pdb files }, String[] { id for each
4319 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
4320 // seqs_file 2}, boolean[] {
4321 // linkAlignPanel,superposeWithAlignpanel}} from hash
4322 StructureViewerModel jmoldat = structureViewers.get(sviewid);
4323 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
4324 || structureState.isAlignwithAlignPanel());
4327 * Default colour by linked panel to false if not specified (e.g.
4328 * for pre-2.7 projects)
4330 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
4331 colourWithAlignPanel |= structureState.isColourwithAlignPanel();
4332 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
4335 * Default colour by viewer to true if not specified (e.g. for
4338 boolean colourByViewer = jmoldat.isColourByViewer();
4339 colourByViewer &= structureState.isColourByJmol();
4340 jmoldat.setColourByViewer(colourByViewer);
4342 if (jmoldat.getStateData().length() < structureState
4343 .getValue()/*Content()*/.length())
4345 jmoldat.setStateData(structureState.getValue());// Content());
4347 if (pdbid.getFile() != null)
4349 File mapkey = new File(pdbid.getFile());
4350 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
4351 if (seqstrmaps == null)
4353 jmoldat.getFileData().put(mapkey,
4354 seqstrmaps = jmoldat.new StructureData(pdbFile,
4357 if (!seqstrmaps.getSeqList().contains(seq))
4359 seqstrmaps.getSeqList().add(seq);
4365 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");
4372 // Instantiate the associated structure views
4373 for (Entry<String, StructureViewerModel> entry : structureViewers
4378 createOrLinkStructureViewer(entry, af, ap, jprovider);
4379 } catch (Exception e)
4382 "Error loading structure viewer: " + e.getMessage());
4383 // failed - try the next one
4395 protected void createOrLinkStructureViewer(
4396 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4397 AlignmentPanel ap, jarInputStreamProvider jprovider)
4399 final StructureViewerModel stateData = viewerData.getValue();
4402 * Search for any viewer windows already open from other alignment views
4403 * that exactly match the stored structure state
4405 StructureViewerBase comp = findMatchingViewer(viewerData);
4409 linkStructureViewer(ap, comp, stateData);
4414 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
4415 * "viewer_"+stateData.viewId
4417 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
4419 createChimeraViewer(viewerData, af, jprovider);
4424 * else Jmol (if pre-2.9, stateData contains JMOL state string)
4426 createJmolViewer(viewerData, af, jprovider);
4431 * Create a new Chimera viewer.
4437 protected void createChimeraViewer(
4438 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4439 jarInputStreamProvider jprovider)
4441 StructureViewerModel data = viewerData.getValue();
4442 String chimeraSessionFile = data.getStateData();
4445 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
4447 * NB this is the 'saved' viewId as in the project file XML, _not_ the
4448 * 'uniquified' sviewid used to reconstruct the viewer here
4450 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
4451 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
4454 Set<Entry<File, StructureData>> fileData = data.getFileData()
4456 List<PDBEntry> pdbs = new ArrayList<>();
4457 List<SequenceI[]> allseqs = new ArrayList<>();
4458 for (Entry<File, StructureData> pdb : fileData)
4460 String filePath = pdb.getValue().getFilePath();
4461 String pdbId = pdb.getValue().getPdbId();
4462 // pdbs.add(new PDBEntry(filePath, pdbId));
4463 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
4464 final List<SequenceI> seqList = pdb.getValue().getSeqList();
4465 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
4469 boolean colourByChimera = data.isColourByViewer();
4470 boolean colourBySequence = data.isColourWithAlignPanel();
4472 // TODO use StructureViewer as a factory here, see JAL-1761
4473 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
4474 final SequenceI[][] seqsArray = allseqs
4475 .toArray(new SequenceI[allseqs.size()][]);
4476 String newViewId = viewerData.getKey();
4478 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
4479 af.alignPanel, pdbArray, seqsArray, colourByChimera,
4480 colourBySequence, newViewId);
4481 cvf.setSize(data.getWidth(), data.getHeight());
4482 cvf.setLocation(data.getX(), data.getY());
4486 * Create a new Jmol window. First parse the Jmol state to translate filenames
4487 * loaded into the view, and record the order in which files are shown in the
4488 * Jmol view, so we can add the sequence mappings in same order.
4494 protected void createJmolViewer(
4495 final Entry<String, StructureViewerModel> viewerData,
4496 AlignFrame af, jarInputStreamProvider jprovider)
4498 final StructureViewerModel svattrib = viewerData.getValue();
4499 String state = svattrib.getStateData();
4502 * Pre-2.9: state element value is the Jmol state string
4504 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
4507 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
4509 state = readJarEntry(jprovider,
4510 getViewerJarEntryName(svattrib.getViewId()));
4513 List<String> pdbfilenames = new ArrayList<>();
4514 List<SequenceI[]> seqmaps = new ArrayList<>();
4515 List<String> pdbids = new ArrayList<>();
4516 StringBuilder newFileLoc = new StringBuilder(64);
4517 int cp = 0, ncp, ecp;
4518 Map<File, StructureData> oldFiles = svattrib.getFileData();
4519 while ((ncp = state.indexOf("load ", cp)) > -1)
4523 // look for next filename in load statement
4524 newFileLoc.append(state.substring(cp,
4525 ncp = (state.indexOf("\"", ncp + 1) + 1)));
4526 String oldfilenam = state.substring(ncp,
4527 ecp = state.indexOf("\"", ncp));
4528 // recover the new mapping data for this old filename
4529 // have to normalize filename - since Jmol and jalview do
4531 // translation differently.
4532 StructureData filedat = oldFiles.get(new File(oldfilenam));
4533 if (filedat == null)
4535 String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\");
4536 filedat = oldFiles.get(new File(reformatedOldFilename));
4538 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
4539 pdbfilenames.add(filedat.getFilePath());
4540 pdbids.add(filedat.getPdbId());
4541 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4542 newFileLoc.append("\"");
4543 cp = ecp + 1; // advance beyond last \" and set cursor so we can
4544 // look for next file statement.
4545 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
4549 // just append rest of state
4550 newFileLoc.append(state.substring(cp));
4554 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
4555 newFileLoc = new StringBuilder(state);
4556 newFileLoc.append("; load append ");
4557 for (File id : oldFiles.keySet())
4559 // add this and any other pdb files that should be present in
4561 StructureData filedat = oldFiles.get(id);
4562 newFileLoc.append(filedat.getFilePath());
4563 pdbfilenames.add(filedat.getFilePath());
4564 pdbids.add(filedat.getPdbId());
4565 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4566 newFileLoc.append(" \"");
4567 newFileLoc.append(filedat.getFilePath());
4568 newFileLoc.append("\"");
4571 newFileLoc.append(";");
4574 if (newFileLoc.length() == 0)
4578 int histbug = newFileLoc.indexOf("history = ");
4582 * change "history = [true|false];" to "history = [1|0];"
4585 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
4586 String val = (diff == -1) ? null
4587 : newFileLoc.substring(histbug, diff);
4588 if (val != null && val.length() >= 4)
4590 if (val.contains("e")) // eh? what can it be?
4592 if (val.trim().equals("true"))
4600 newFileLoc.replace(histbug, diff, val);
4605 final String[] pdbf = pdbfilenames
4606 .toArray(new String[pdbfilenames.size()]);
4607 final String[] id = pdbids.toArray(new String[pdbids.size()]);
4608 final SequenceI[][] sq = seqmaps
4609 .toArray(new SequenceI[seqmaps.size()][]);
4610 final String fileloc = newFileLoc.toString();
4611 final String sviewid = viewerData.getKey();
4612 final AlignFrame alf = af;
4613 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
4614 svattrib.getWidth(), svattrib.getHeight());
4617 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
4622 JalviewStructureDisplayI sview = null;
4625 sview = new StructureViewer(
4626 alf.alignPanel.getStructureSelectionManager())
4627 .createView(StructureViewer.ViewerType.JMOL,
4628 pdbf, id, sq, alf.alignPanel, svattrib,
4629 fileloc, rect, sviewid);
4630 addNewStructureViewer(sview);
4631 } catch (OutOfMemoryError ex)
4633 new OOMWarning("restoring structure view for PDB id " + id,
4634 (OutOfMemoryError) ex.getCause());
4635 if (sview != null && sview.isVisible())
4637 sview.closeViewer(false);
4638 sview.setVisible(false);
4644 } catch (InvocationTargetException ex)
4646 warn("Unexpected error when opening Jmol view.", ex);
4648 } catch (InterruptedException e)
4650 // e.printStackTrace();
4656 * Generates a name for the entry in the project jar file to hold state
4657 * information for a structure viewer
4662 protected String getViewerJarEntryName(String viewId)
4664 return VIEWER_PREFIX + viewId;
4668 * Returns any open frame that matches given structure viewer data. The match
4669 * is based on the unique viewId, or (for older project versions) the frame's
4675 protected StructureViewerBase findMatchingViewer(
4676 Entry<String, StructureViewerModel> viewerData)
4678 final String sviewid = viewerData.getKey();
4679 final StructureViewerModel svattrib = viewerData.getValue();
4680 StructureViewerBase comp = null;
4681 JInternalFrame[] frames = getAllFrames();
4682 for (JInternalFrame frame : frames)
4684 if (frame instanceof StructureViewerBase)
4687 * Post jalview 2.4 schema includes structure view id
4689 if (sviewid != null && ((StructureViewerBase) frame).getViewId()
4692 comp = (StructureViewerBase) frame;
4693 break; // break added in 2.9
4696 * Otherwise test for matching position and size of viewer frame
4698 else if (frame.getX() == svattrib.getX()
4699 && frame.getY() == svattrib.getY()
4700 && frame.getHeight() == svattrib.getHeight()
4701 && frame.getWidth() == svattrib.getWidth())
4703 comp = (StructureViewerBase) frame;
4704 // no break in faint hope of an exact match on viewId
4712 * Link an AlignmentPanel to an existing structure viewer.
4717 * @param useinViewerSuperpos
4718 * @param usetoColourbyseq
4719 * @param viewerColouring
4721 protected void linkStructureViewer(AlignmentPanel ap,
4722 StructureViewerBase viewer, StructureViewerModel stateData)
4724 // NOTE: if the jalview project is part of a shared session then
4725 // view synchronization should/could be done here.
4727 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4728 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4729 final boolean viewerColouring = stateData.isColourByViewer();
4730 Map<File, StructureData> oldFiles = stateData.getFileData();
4733 * Add mapping for sequences in this view to an already open viewer
4735 final AAStructureBindingModel binding = viewer.getBinding();
4736 for (File id : oldFiles.keySet())
4738 // add this and any other pdb files that should be present in the
4740 StructureData filedat = oldFiles.get(id);
4741 String pdbFile = filedat.getFilePath();
4742 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4743 binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE,
4745 binding.addSequenceForStructFile(pdbFile, seq);
4747 // and add the AlignmentPanel's reference to the view panel
4748 viewer.addAlignmentPanel(ap);
4749 if (useinViewerSuperpos)
4751 viewer.useAlignmentPanelForSuperposition(ap);
4755 viewer.excludeAlignmentPanelForSuperposition(ap);
4757 if (usetoColourbyseq)
4759 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4763 viewer.excludeAlignmentPanelForColourbyseq(ap);
4768 * Get all frames within the Desktop.
4772 protected JInternalFrame[] getAllFrames()
4774 JInternalFrame[] frames = null;
4775 // TODO is this necessary - is it safe - risk of hanging?
4780 frames = Desktop.desktop.getAllFrames();
4781 } catch (ArrayIndexOutOfBoundsException e)
4783 // occasional No such child exceptions are thrown here...
4787 } catch (InterruptedException f)
4791 } while (frames == null);
4796 * Answers true if 'version' is equal to or later than 'supported', where each
4797 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4798 * changes. Development and test values for 'version' are leniently treated
4802 * - minimum version we are comparing against
4804 * - version of data being processsed
4807 public static boolean isVersionStringLaterThan(String supported,
4810 if (supported == null || version == null
4811 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4812 || version.equalsIgnoreCase("Test")
4813 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4815 System.err.println("Assuming project file with "
4816 + (version == null ? "null" : version)
4817 + " is compatible with Jalview version " + supported);
4822 return StringUtils.compareVersions(version, supported, "b") >= 0;
4826 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4828 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4830 if (newStructureViewers != null)
4832 sview.getBinding().setFinishedLoadingFromArchive(false);
4833 newStructureViewers.add(sview);
4837 protected void setLoadingFinishedForNewStructureViewers()
4839 if (newStructureViewers != null)
4841 for (JalviewStructureDisplayI sview : newStructureViewers)
4843 sview.getBinding().setFinishedLoadingFromArchive(true);
4845 newStructureViewers.clear();
4846 newStructureViewers = null;
4850 AlignFrame loadViewport(String file, List<JSeq> JSEQ,
4851 List<SequenceI> hiddenSeqs, AlignmentI al,
4852 JalviewModel jm, Viewport view, String uniqueSeqSetId,
4855 AlignFrame af = null;
4856 af = new AlignFrame(al, safeInt(view.getWidth()),
4857 safeInt(view.getHeight()), uniqueSeqSetId, viewId);
4859 af.setFileName(file, FileFormat.Jalview);
4861 final AlignViewport viewport = af.getViewport();
4862 for (int i = 0; i < JSEQ.size(); i++)
4864 int colour = safeInt(JSEQ.get(i).getColour());
4865 viewport.setSequenceColour(viewport.getAlignment().getSequenceAt(i),
4871 viewport.setColourByReferenceSeq(true);
4872 viewport.setDisplayReferenceSeq(true);
4875 viewport.setGatherViewsHere(safeBoolean(view.isGatheredViews()));
4877 if (view.getSequenceSetId() != null)
4879 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4881 viewport.setSequenceSetId(uniqueSeqSetId);
4884 // propagate shared settings to this new view
4885 viewport.setHistoryList(av.getHistoryList());
4886 viewport.setRedoList(av.getRedoList());
4890 viewportsAdded.put(uniqueSeqSetId, viewport);
4892 // TODO: check if this method can be called repeatedly without
4893 // side-effects if alignpanel already registered.
4894 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4896 // apply Hidden regions to view.
4897 if (hiddenSeqs != null)
4899 for (int s = 0; s < JSEQ.size(); s++)
4901 SequenceGroup hidden = new SequenceGroup();
4902 boolean isRepresentative = false;
4903 for (int r = 0; r < JSEQ.get(s).getHiddenSequences().size(); r++)
4905 isRepresentative = true;
4906 SequenceI sequenceToHide = al
4907 .getSequenceAt(JSEQ.get(s).getHiddenSequences().get(r));
4908 hidden.addSequence(sequenceToHide, false);
4909 // remove from hiddenSeqs list so we don't try to hide it twice
4910 hiddenSeqs.remove(sequenceToHide);
4912 if (isRepresentative)
4914 SequenceI representativeSequence = al.getSequenceAt(s);
4915 hidden.addSequence(representativeSequence, false);
4916 viewport.hideRepSequences(representativeSequence, hidden);
4920 SequenceI[] hseqs = hiddenSeqs
4921 .toArray(new SequenceI[hiddenSeqs.size()]);
4922 viewport.hideSequence(hseqs);
4925 // recover view properties and display parameters
4927 viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
4928 viewport.setAbovePIDThreshold(safeBoolean(view.isPidSelected()));
4929 final int pidThreshold = safeInt(view.getPidThreshold());
4930 viewport.setThreshold(pidThreshold);
4932 viewport.setColourText(safeBoolean(view.isShowColourText()));
4934 viewport.setConservationSelected(
4935 safeBoolean(view.isConservationSelected()));
4936 viewport.setIncrement(safeInt(view.getConsThreshold()));
4937 viewport.setShowJVSuffix(safeBoolean(view.isShowFullId()));
4938 viewport.setRightAlignIds(safeBoolean(view.isRightAlignIds()));
4939 viewport.setFont(new Font(view.getFontName(),
4940 safeInt(view.getFontStyle()), safeInt(view.getFontSize())),
4942 ViewStyleI vs = viewport.getViewStyle();
4943 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
4944 viewport.setViewStyle(vs);
4945 // TODO: allow custom charWidth/Heights to be restored by updating them
4946 // after setting font - which means set above to false
4947 viewport.setRenderGaps(safeBoolean(view.isRenderGaps()));
4948 viewport.setWrapAlignment(safeBoolean(view.isWrapAlignment()));
4949 viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
4951 Boolean autocalcFirst = view.isShowAutocalcAbove();
4952 if (autocalcFirst != null)
4954 af.setShowAutoCalculatedAbove(autocalcFirst.booleanValue());
4956 String sortBy = view.getSortAnnotationsBy();
4961 viewport.setSortAnnotationsBy(
4962 SequenceAnnotationOrder.valueOf(sortBy));
4963 } catch (IllegalArgumentException e)
4966 "Invalid annotation sort specifier in project: " + sortBy);
4970 viewport.setShowBoxes(safeBoolean(view.isShowBoxes()));
4971 viewport.setShowText(safeBoolean(view.isShowText()));
4972 viewport.setTextColour(new Color(safeInt(view.getTextCol1())));
4973 viewport.setTextColour2(new Color(safeInt(view.getTextCol2())));
4974 viewport.setThresholdTextColour(safeInt(view.getTextColThreshold()));
4975 viewport.setShowUnconserved(view.isShowUnconserved());
4976 viewport.getRanges().setStartRes(safeInt(view.getStartRes()));
4978 if (view.getViewName() != null)
4980 viewport.setViewName(view.getViewName());
4981 af.setInitialTabVisible();
4983 af.setBounds(safeInt(view.getXpos()), safeInt(view.getYpos()),
4984 safeInt(view.getWidth()), safeInt(view.getHeight()));
4985 // startSeq set in af.alignPanel.updateLayout below
4986 af.alignPanel.updateLayout();
4987 ColourSchemeI cs = null;
4988 // apply colourschemes
4989 if (view.getBgColour() != null)
4991 if (view.getBgColour().startsWith("ucs"))
4993 cs = getUserColourScheme(jm, view.getBgColour());
4995 else if (view.getBgColour().startsWith("Annotation"))
4997 AnnotationColourScheme viewAnnColour = view.getAnnotationColours();
4998 cs = constructAnnotationColour(viewAnnColour, af, al, jm, true);
5005 cs = ColourSchemeProperty.getColourScheme(af.getViewport(), al,
5006 view.getBgColour());
5011 * turn off 'alignment colour applies to all groups'
5012 * while restoring global colour scheme
5014 viewport.setColourAppliesToAllGroups(false);
5015 viewport.setGlobalColourScheme(cs);
5016 viewport.getResidueShading().setThreshold(pidThreshold,
5017 view.isIgnoreGapsinConsensus());
5018 viewport.getResidueShading()
5019 .setConsensus(viewport.getSequenceConsensusHash());
5020 if (safeBoolean(view.isConservationSelected()) && cs != null)
5022 viewport.getResidueShading()
5023 .setConservationInc(safeInt(view.getConsThreshold()));
5025 af.changeColour(cs);
5026 viewport.setColourAppliesToAllGroups(true);
5029 .setShowSequenceFeatures(
5030 safeBoolean(view.isShowSequenceFeatures()));
5032 viewport.setCentreColumnLabels(view.isCentreColumnLabels());
5033 viewport.setIgnoreGapsConsensus(view.isIgnoreGapsinConsensus(), null);
5034 viewport.setFollowHighlight(view.isFollowHighlight());
5035 viewport.followSelection = view.isFollowSelection();
5036 viewport.setShowConsensusHistogram(view.isShowConsensusHistogram());
5037 viewport.setShowSequenceLogo(view.isShowSequenceLogo());
5038 viewport.setNormaliseSequenceLogo(view.isNormaliseSequenceLogo());
5039 viewport.setShowDBRefs(safeBoolean(view.isShowDbRefTooltip()));
5040 viewport.setShowNPFeats(safeBoolean(view.isShowNPfeatureTooltip()));
5041 viewport.setShowGroupConsensus(view.isShowGroupConsensus());
5042 viewport.setShowGroupConservation(view.isShowGroupConservation());
5044 // recover feature settings
5045 if (jm.getFeatureSettings() != null)
5047 FeatureRenderer fr = af.alignPanel.getSeqPanel().seqCanvas
5048 .getFeatureRenderer();
5049 FeaturesDisplayed fdi;
5050 viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
5051 String[] renderOrder = new String[jm.getFeatureSettings()
5052 .getSetting().size()];
5053 Map<String, FeatureColourI> featureColours = new Hashtable<>();
5054 Map<String, Float> featureOrder = new Hashtable<>();
5056 for (int fs = 0; fs < jm.getFeatureSettings()
5057 .getSetting().size(); fs++)
5059 Setting setting = jm.getFeatureSettings().getSetting().get(fs);
5060 String featureType = setting.getType();
5063 * restore feature filters (if any)
5065 jalview.xml.binding.jalview.FeatureMatcherSet filters = setting
5067 if (filters != null)
5069 FeatureMatcherSetI filter = Jalview2XML
5070 .parseFilter(featureType, filters);
5071 if (!filter.isEmpty())
5073 fr.setFeatureFilter(featureType, filter);
5078 * restore feature colour scheme
5080 Color maxColour = new Color(setting.getColour());
5081 if (setting.getMincolour() != null)
5084 * minColour is always set unless a simple colour
5085 * (including for colour by label though it doesn't use it)
5087 Color minColour = new Color(setting.getMincolour().intValue());
5088 Color noValueColour = minColour;
5089 NoValueColour noColour = setting.getNoValueColour();
5090 if (noColour == NoValueColour.NONE)
5092 noValueColour = null;
5094 else if (noColour == NoValueColour.MAX)
5096 noValueColour = maxColour;
5098 float min = safeFloat(safeFloat(setting.getMin()));
5099 float max = setting.getMax() == null ? 1f
5100 : setting.getMax().floatValue();
5101 FeatureColourI gc = new FeatureColour(maxColour, minColour,
5103 noValueColour, min, max);
5104 if (setting.getAttributeName().size() > 0)
5106 gc.setAttributeName(setting.getAttributeName().toArray(
5107 new String[setting.getAttributeName().size()]));
5109 if (setting.getThreshold() != null)
5111 gc.setThreshold(setting.getThreshold().floatValue());
5112 int threshstate = safeInt(setting.getThreshstate());
5113 // -1 = None, 0 = Below, 1 = Above threshold
5114 if (threshstate == 0)
5116 gc.setBelowThreshold(true);
5118 else if (threshstate == 1)
5120 gc.setAboveThreshold(true);
5123 gc.setAutoScaled(true); // default
5124 if (setting.isAutoScale() != null)
5126 gc.setAutoScaled(setting.isAutoScale());
5128 if (setting.isColourByLabel() != null)
5130 gc.setColourByLabel(setting.isColourByLabel());
5132 // and put in the feature colour table.
5133 featureColours.put(featureType, gc);
5137 featureColours.put(featureType,
5138 new FeatureColour(maxColour));
5140 renderOrder[fs] = featureType;
5141 if (setting.getOrder() != null)
5143 featureOrder.put(featureType, setting.getOrder().floatValue());
5147 featureOrder.put(featureType, new Float(
5148 fs / jm.getFeatureSettings().getSetting().size()));
5150 if (safeBoolean(setting.isDisplay()))
5152 fdi.setVisible(featureType);
5155 Map<String, Boolean> fgtable = new Hashtable<>();
5156 for (int gs = 0; gs < jm.getFeatureSettings().getGroup().size(); gs++)
5158 Group grp = jm.getFeatureSettings().getGroup().get(gs);
5159 fgtable.put(grp.getName(), new Boolean(grp.isDisplay()));
5161 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
5162 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
5163 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
5164 FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
5165 fgtable, featureColours, 1.0f, featureOrder);
5166 fr.transferSettings(frs);
5169 if (view.getHiddenColumns().size() > 0)
5171 for (int c = 0; c < view.getHiddenColumns().size(); c++)
5173 final HiddenColumns hc = view.getHiddenColumns().get(c);
5174 viewport.hideColumns(safeInt(hc.getStart()),
5175 safeInt(hc.getEnd()) /* +1 */);
5178 if (view.getCalcIdParam() != null)
5180 for (CalcIdParam calcIdParam : view.getCalcIdParam())
5182 if (calcIdParam != null)
5184 if (recoverCalcIdParam(calcIdParam, viewport))
5189 warn("Couldn't recover parameters for "
5190 + calcIdParam.getCalcId());
5195 af.setMenusFromViewport(viewport);
5196 af.setTitle(view.getTitle());
5197 // TODO: we don't need to do this if the viewport is aready visible.
5199 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
5200 * has a 'cdna/protein complement' view, in which case save it in order to
5201 * populate a SplitFrame once all views have been read in.
5203 String complementaryViewId = view.getComplementId();
5204 if (complementaryViewId == null)
5206 Desktop.addInternalFrame(af, view.getTitle(),
5207 safeInt(view.getWidth()), safeInt(view.getHeight()));
5208 // recompute any autoannotation
5209 af.alignPanel.updateAnnotation(false, true);
5210 af.alignPanel.alignmentChanged();
5214 splitFrameCandidates.put(view, af);
5220 * Reads saved data to restore Colour by Annotation settings
5222 * @param viewAnnColour
5226 * @param checkGroupAnnColour
5229 private ColourSchemeI constructAnnotationColour(
5230 AnnotationColourScheme viewAnnColour, AlignFrame af,
5231 AlignmentI al, JalviewModel model, boolean checkGroupAnnColour)
5233 boolean propagateAnnColour = false;
5234 AlignmentI annAlignment = af != null ? af.getViewport().getAlignment()
5236 if (checkGroupAnnColour && al.getGroups() != null
5237 && al.getGroups().size() > 0)
5239 // pre 2.8.1 behaviour
5240 // check to see if we should transfer annotation colours
5241 propagateAnnColour = true;
5242 for (SequenceGroup sg : al.getGroups())
5244 if (sg.getColourScheme() instanceof AnnotationColourGradient)
5246 propagateAnnColour = false;
5252 * 2.10.2- : saved annotationId is AlignmentAnnotation.annotationId
5254 String annotationId = viewAnnColour.getAnnotation();
5255 AlignmentAnnotation matchedAnnotation = annotationIds.get(annotationId);
5258 * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
5260 if (matchedAnnotation == null
5261 && annAlignment.getAlignmentAnnotation() != null)
5263 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
5266 .equals(annAlignment.getAlignmentAnnotation()[i].label))
5268 matchedAnnotation = annAlignment.getAlignmentAnnotation()[i];
5273 if (matchedAnnotation == null)
5275 System.err.println("Failed to match annotation colour scheme for "
5279 if (matchedAnnotation.getThreshold() == null)
5281 matchedAnnotation.setThreshold(
5282 new GraphLine(safeFloat(viewAnnColour.getThreshold()),
5283 "Threshold", Color.black));
5286 AnnotationColourGradient cs = null;
5287 if (viewAnnColour.getColourScheme().equals("None"))
5289 cs = new AnnotationColourGradient(matchedAnnotation,
5290 new Color(safeInt(viewAnnColour.getMinColour())),
5291 new Color(safeInt(viewAnnColour.getMaxColour())),
5292 safeInt(viewAnnColour.getAboveThreshold()));
5294 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
5296 cs = new AnnotationColourGradient(matchedAnnotation,
5297 getUserColourScheme(model, viewAnnColour.getColourScheme()),
5298 safeInt(viewAnnColour.getAboveThreshold()));
5302 cs = new AnnotationColourGradient(matchedAnnotation,
5303 ColourSchemeProperty.getColourScheme(af.getViewport(), al,
5304 viewAnnColour.getColourScheme()),
5305 safeInt(viewAnnColour.getAboveThreshold()));
5308 boolean perSequenceOnly = safeBoolean(viewAnnColour.isPerSequence());
5309 boolean useOriginalColours = safeBoolean(
5310 viewAnnColour.isPredefinedColours());
5311 cs.setSeqAssociated(perSequenceOnly);
5312 cs.setPredefinedColours(useOriginalColours);
5314 if (propagateAnnColour && al.getGroups() != null)
5316 // Also use these settings for all the groups
5317 for (int g = 0; g < al.getGroups().size(); g++)
5319 SequenceGroup sg = al.getGroups().get(g);
5320 if (sg.getGroupColourScheme() == null)
5325 AnnotationColourGradient groupScheme = new AnnotationColourGradient(
5326 matchedAnnotation, sg.getColourScheme(),
5327 safeInt(viewAnnColour.getAboveThreshold()));
5328 sg.setColourScheme(groupScheme);
5329 groupScheme.setSeqAssociated(perSequenceOnly);
5330 groupScheme.setPredefinedColours(useOriginalColours);
5336 Hashtable skipList = null;
5339 * TODO remove this method
5342 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
5343 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
5344 * throw new Error("Implementation Error. No skipList defined for this
5345 * Jalview2XML instance."); } return (AlignFrame)
5346 * skipList.get(view.getSequenceSetId()); }
5350 * Check if the Jalview view contained in object should be skipped or not.
5353 * @return true if view's sequenceSetId is a key in skipList
5355 private boolean skipViewport(JalviewModel object)
5357 if (skipList == null)
5361 String id = object.getViewport().get(0).getSequenceSetId();
5362 if (skipList.containsKey(id))
5364 if (Cache.log != null && Cache.log.isDebugEnabled())
5366 Cache.log.debug("Skipping seuqence set id " + id);
5373 public void addToSkipList(AlignFrame af)
5375 if (skipList == null)
5377 skipList = new Hashtable();
5379 skipList.put(af.getViewport().getSequenceSetId(), af);
5382 public void clearSkipList()
5384 if (skipList != null)
5391 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
5392 boolean ignoreUnrefed, String uniqueSeqSetId)
5394 jalview.datamodel.AlignmentI ds = getDatasetFor(
5395 vamsasSet.getDatasetId());
5396 AlignmentI xtant_ds = ds;
5397 if (xtant_ds == null)
5399 // good chance we are about to create a new dataset, but check if we've
5400 // seen some of the dataset sequence IDs before.
5401 // TODO: skip this check if we are working with project generated by
5402 // version 2.11 or later
5403 xtant_ds = checkIfHasDataset(vamsasSet.getSequence());
5404 if (xtant_ds != null)
5407 addDatasetRef(vamsasSet.getDatasetId(), ds);
5410 Vector dseqs = null;
5413 // recovering an alignment View
5414 AlignmentI seqSetDS = getDatasetFor(UNIQSEQSETID + uniqueSeqSetId);
5415 if (seqSetDS != null)
5417 if (ds != null && ds != seqSetDS)
5419 warn("JAL-3171 regression: Overwriting a dataset reference for an alignment"
5420 + " - CDS/Protein crossreference data may be lost");
5421 if (xtant_ds != null)
5423 // This can only happen if the unique sequence set ID was bound to a
5424 // dataset that did not contain any of the sequences in the view
5425 // currently being restored.
5426 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.");
5430 addDatasetRef(vamsasSet.getDatasetId(), ds);
5435 // try even harder to restore dataset
5436 AlignmentI xtantDS = checkIfHasDataset(vamsasSet.getSequence());
5437 // create a list of new dataset sequences
5438 dseqs = new Vector();
5440 for (int i = 0, iSize = vamsasSet.getSequence().size(); i < iSize; i++)
5442 Sequence vamsasSeq = vamsasSet.getSequence().get(i);
5443 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
5445 // create a new dataset
5448 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
5449 dseqs.copyInto(dsseqs);
5450 ds = new jalview.datamodel.Alignment(dsseqs);
5451 debug("Created new dataset " + vamsasSet.getDatasetId()
5452 + " for alignment " + System.identityHashCode(al));
5453 addDatasetRef(vamsasSet.getDatasetId(), ds);
5455 // set the dataset for the newly imported alignment.
5456 if (al.getDataset() == null && !ignoreUnrefed)
5459 // register dataset for the alignment's uniqueSeqSetId for legacy projects
5460 addDatasetRef(UNIQSEQSETID + uniqueSeqSetId, ds);
5462 updateSeqDatasetBinding(vamsasSet.getSequence(), ds);
5466 * XML dataset sequence ID to materialised dataset reference
5468 HashMap<String, AlignmentI> seqToDataset = new HashMap<>();
5471 * @return the first materialised dataset reference containing a dataset
5472 * sequence referenced in the given view
5474 * - sequences from the view
5476 AlignmentI checkIfHasDataset(List<Sequence> list)
5478 for (Sequence restoredSeq : list)
5480 AlignmentI datasetFor = seqToDataset.get(restoredSeq.getDsseqid());
5481 if (datasetFor != null)
5490 * Register ds as the containing dataset for the dataset sequences referenced
5491 * by sequences in list
5494 * - sequences in a view
5497 void updateSeqDatasetBinding(List<Sequence> list, AlignmentI ds)
5499 for (Sequence restoredSeq : list)
5501 AlignmentI prevDS = seqToDataset.put(restoredSeq.getDsseqid(), ds);
5502 if (prevDS != null && prevDS != ds)
5504 warn("Dataset sequence appears in many datasets: "
5505 + restoredSeq.getDsseqid());
5506 // TODO: try to merge!
5513 * sequence definition to create/merge dataset sequence for
5517 * vector to add new dataset sequence to
5518 * @param ignoreUnrefed
5519 * - when true, don't create new sequences from vamsasSeq if it's id
5520 * doesn't already have an asssociated Jalview sequence.
5522 * - used to reorder the sequence in the alignment according to the
5523 * vamsasSeq array ordering, to preserve ordering of dataset
5525 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
5526 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed, int vseqpos)
5528 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
5530 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
5531 boolean reorder = false;
5532 SequenceI dsq = null;
5533 if (sq != null && sq.getDatasetSequence() != null)
5535 dsq = sq.getDatasetSequence();
5541 if (sq == null && ignoreUnrefed)
5545 String sqid = vamsasSeq.getDsseqid();
5548 // need to create or add a new dataset sequence reference to this sequence
5551 dsq = seqRefIds.get(sqid);
5556 // make a new dataset sequence
5557 dsq = sq.createDatasetSequence();
5560 // make up a new dataset reference for this sequence
5561 sqid = seqHash(dsq);
5563 dsq.setVamsasId(uniqueSetSuffix + sqid);
5564 seqRefIds.put(sqid, dsq);
5569 dseqs.addElement(dsq);
5574 ds.addSequence(dsq);
5580 { // make this dataset sequence sq's dataset sequence
5581 sq.setDatasetSequence(dsq);
5582 // and update the current dataset alignment
5587 if (!dseqs.contains(dsq))
5594 if (ds.findIndex(dsq) < 0)
5596 ds.addSequence(dsq);
5603 // TODO: refactor this as a merge dataset sequence function
5604 // now check that sq (the dataset sequence) sequence really is the union of
5605 // all references to it
5606 // boolean pre = sq.getStart() < dsq.getStart();
5607 // boolean post = sq.getEnd() > dsq.getEnd();
5611 // StringBuffer sb = new StringBuffer();
5612 String newres = jalview.analysis.AlignSeq.extractGaps(
5613 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
5614 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
5615 && newres.length() > dsq.getLength())
5617 // Update with the longer sequence.
5621 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
5622 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
5623 * sb.append(newres.substring(newres.length() - sq.getEnd() -
5624 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
5626 dsq.setSequence(newres);
5628 // TODO: merges will never happen if we 'know' we have the real dataset
5629 // sequence - this should be detected when id==dssid
5631 "DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
5632 // + (pre ? "prepended" : "") + " "
5633 // + (post ? "appended" : ""));
5638 // sequence refs are identical. We may need to update the existing dataset
5639 // alignment with this one, though.
5640 if (ds != null && dseqs == null)
5642 int opos = ds.findIndex(dsq);
5643 SequenceI tseq = null;
5644 if (opos != -1 && vseqpos != opos)
5646 // remove from old position
5647 ds.deleteSequence(dsq);
5649 if (vseqpos < ds.getHeight())
5651 if (vseqpos != opos)
5653 // save sequence at destination position
5654 tseq = ds.getSequenceAt(vseqpos);
5655 ds.replaceSequenceAt(vseqpos, dsq);
5656 ds.addSequence(tseq);
5661 ds.addSequence(dsq);
5668 * TODO use AlignmentI here and in related methods - needs
5669 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
5671 Hashtable<String, AlignmentI> datasetIds = null;
5673 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
5675 private AlignmentI getDatasetFor(String datasetId)
5677 if (datasetIds == null)
5679 datasetIds = new Hashtable<>();
5682 if (datasetIds.containsKey(datasetId))
5684 return datasetIds.get(datasetId);
5689 private void addDatasetRef(String datasetId, AlignmentI dataset)
5691 if (datasetIds == null)
5693 datasetIds = new Hashtable<>();
5695 datasetIds.put(datasetId, dataset);
5699 * make a new dataset ID for this jalview dataset alignment
5704 private String getDatasetIdRef(AlignmentI dataset)
5706 if (dataset.getDataset() != null)
5708 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
5710 String datasetId = makeHashCode(dataset, null);
5711 if (datasetId == null)
5713 // make a new datasetId and record it
5714 if (dataset2Ids == null)
5716 dataset2Ids = new IdentityHashMap<>();
5720 datasetId = dataset2Ids.get(dataset);
5722 if (datasetId == null)
5724 datasetId = "ds" + dataset2Ids.size() + 1;
5725 dataset2Ids.put(dataset, datasetId);
5731 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5733 for (int d = 0; d < sequence.getDBRef().size(); d++)
5735 DBRef dr = sequence.getDBRef().get(d);
5736 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
5737 dr.getSource(), dr.getVersion(), dr.getAccessionId());
5738 if (dr.getMapping() != null)
5740 entry.setMap(addMapping(dr.getMapping()));
5742 datasetSequence.addDBRef(entry);
5746 private jalview.datamodel.Mapping addMapping(Mapping m)
5748 SequenceI dsto = null;
5749 // Mapping m = dr.getMapping();
5750 int fr[] = new int[m.getMapListFrom().size() * 2];
5751 Iterator<MapListFrom> from = m.getMapListFrom().iterator();// enumerateMapListFrom();
5752 for (int _i = 0; from.hasNext(); _i += 2)
5754 MapListFrom mf = from.next();
5755 fr[_i] = mf.getStart();
5756 fr[_i + 1] = mf.getEnd();
5758 int fto[] = new int[m.getMapListTo().size() * 2];
5759 Iterator<MapListTo> to = m.getMapListTo().iterator();// enumerateMapListTo();
5760 for (int _i = 0; to.hasNext(); _i += 2)
5762 MapListTo mf = to.next();
5763 fto[_i] = mf.getStart();
5764 fto[_i + 1] = mf.getEnd();
5766 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto, fr,
5767 fto, m.getMapFromUnit().intValue(),
5768 m.getMapToUnit().intValue());
5771 * (optional) choice of dseqFor or Sequence
5773 if (m.getDseqFor() != null)
5775 String dsfor = m.getDseqFor();
5776 if (seqRefIds.containsKey(dsfor))
5781 jmap.setTo(seqRefIds.get(dsfor));
5785 frefedSequence.add(newMappingRef(dsfor, jmap));
5788 else if (m.getSequence() != null)
5791 * local sequence definition
5793 Sequence ms = m.getSequence();
5794 SequenceI djs = null;
5795 String sqid = ms.getDsseqid();
5796 if (sqid != null && sqid.length() > 0)
5799 * recover dataset sequence
5801 djs = seqRefIds.get(sqid);
5806 "Warning - making up dataset sequence id for DbRef sequence map reference");
5807 sqid = ((Object) ms).toString(); // make up a new hascode for
5808 // undefined dataset sequence hash
5809 // (unlikely to happen)
5815 * make a new dataset sequence and add it to refIds hash
5817 djs = new jalview.datamodel.Sequence(ms.getName(),
5819 djs.setStart(jmap.getMap().getToLowest());
5820 djs.setEnd(jmap.getMap().getToHighest());
5821 djs.setVamsasId(uniqueSetSuffix + sqid);
5823 incompleteSeqs.put(sqid, djs);
5824 seqRefIds.put(sqid, djs);
5827 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5836 * Provides a 'copy' of an alignment view (on action New View) by 'saving' the
5837 * view as XML (but not to file), and then reloading it
5842 public AlignmentPanel copyAlignPanel(AlignmentPanel ap)
5845 JalviewModel jm = saveState(ap, null, null, null);
5848 jm.getVamsasModel().getSequenceSet().get(0).getDatasetId(),
5849 ap.getAlignment().getDataset());
5851 uniqueSetSuffix = "";
5852 // jm.getJalviewModelSequence().getViewport(0).setId(null);
5853 jm.getViewport().get(0).setId(null);
5854 // we don't overwrite the view we just copied
5856 if (this.frefedSequence == null)
5858 frefedSequence = new Vector<>();
5861 viewportsAdded.clear();
5863 AlignFrame af = loadFromObject(jm, null, false, null);
5864 af.getAlignPanels().clear();
5865 af.closeMenuItem_actionPerformed(true);
5868 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5869 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5870 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5871 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5872 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5875 return af.alignPanel;
5878 private Hashtable jvids2vobj;
5880 private void warn(String msg)
5885 private void warn(String msg, Exception e)
5887 if (Cache.log != null)
5891 Cache.log.warn(msg, e);
5895 Cache.log.warn(msg);
5900 System.err.println("Warning: " + msg);
5903 e.printStackTrace();
5908 private void debug(String string)
5910 debug(string, null);
5913 private void debug(String msg, Exception e)
5915 if (Cache.log != null)
5919 Cache.log.debug(msg, e);
5923 Cache.log.debug(msg);
5928 System.err.println("Warning: " + msg);
5931 e.printStackTrace();
5937 * set the object to ID mapping tables used to write/recover objects and XML
5938 * ID strings for the jalview project. If external tables are provided then
5939 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
5940 * object goes out of scope. - also populates the datasetIds hashtable with
5941 * alignment objects containing dataset sequences
5944 * Map from ID strings to jalview datamodel
5946 * Map from jalview datamodel to ID strings
5950 public void setObjectMappingTables(Hashtable vobj2jv,
5951 IdentityHashMap jv2vobj)
5953 this.jv2vobj = jv2vobj;
5954 this.vobj2jv = vobj2jv;
5955 Iterator ds = jv2vobj.keySet().iterator();
5957 while (ds.hasNext())
5959 Object jvobj = ds.next();
5960 id = jv2vobj.get(jvobj).toString();
5961 if (jvobj instanceof jalview.datamodel.Alignment)
5963 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
5965 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
5968 else if (jvobj instanceof jalview.datamodel.Sequence)
5970 // register sequence object so the XML parser can recover it.
5971 if (seqRefIds == null)
5973 seqRefIds = new HashMap<>();
5975 if (seqsToIds == null)
5977 seqsToIds = new IdentityHashMap<>();
5979 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
5980 seqsToIds.put((SequenceI) jvobj, id);
5982 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
5985 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
5986 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
5987 if (jvann.annotationId == null)
5989 jvann.annotationId = anid;
5991 if (!jvann.annotationId.equals(anid))
5993 // TODO verify that this is the correct behaviour
5994 this.warn("Overriding Annotation ID for " + anid
5995 + " from different id : " + jvann.annotationId);
5996 jvann.annotationId = anid;
5999 else if (jvobj instanceof String)
6001 if (jvids2vobj == null)
6003 jvids2vobj = new Hashtable();
6004 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
6009 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
6015 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
6016 * objects created from the project archive. If string is null (default for
6017 * construction) then suffix will be set automatically.
6021 public void setUniqueSetSuffix(String string)
6023 uniqueSetSuffix = string;
6028 * uses skipList2 as the skipList for skipping views on sequence sets
6029 * associated with keys in the skipList
6033 public void setSkipList(Hashtable skipList2)
6035 skipList = skipList2;
6039 * Reads the jar entry of given name and returns its contents, or null if the
6040 * entry is not found.
6043 * @param jarEntryName
6046 protected String readJarEntry(jarInputStreamProvider jprovider,
6047 String jarEntryName)
6049 String result = null;
6050 BufferedReader in = null;
6055 * Reopen the jar input stream and traverse its entries to find a matching
6058 JarInputStream jin = jprovider.getJarInputStream();
6059 JarEntry entry = null;
6062 entry = jin.getNextJarEntry();
6063 } while (entry != null && !entry.getName().equals(jarEntryName));
6067 StringBuilder out = new StringBuilder(256);
6068 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
6071 while ((data = in.readLine()) != null)
6075 result = out.toString();
6079 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
6081 } catch (Exception ex)
6083 ex.printStackTrace();
6091 } catch (IOException e)
6102 * Returns an incrementing counter (0, 1, 2...)
6106 private synchronized int nextCounter()
6112 * Loads any saved PCA viewers
6117 protected void loadPCAViewers(JalviewModel model, AlignmentPanel ap)
6121 List<PcaViewer> pcaviewers = model.getPcaViewer();
6122 for (PcaViewer viewer : pcaviewers)
6124 String modelName = viewer.getScoreModelName();
6125 SimilarityParamsI params = new SimilarityParams(
6126 viewer.isIncludeGappedColumns(), viewer.isMatchGaps(),
6127 viewer.isIncludeGaps(),
6128 viewer.isDenominateByShortestLength());
6131 * create the panel (without computing the PCA)
6133 PCAPanel panel = new PCAPanel(ap, modelName, params);
6135 panel.setTitle(viewer.getTitle());
6136 panel.setBounds(new Rectangle(viewer.getXpos(), viewer.getYpos(),
6137 viewer.getWidth(), viewer.getHeight()));
6139 boolean showLabels = viewer.isShowLabels();
6140 panel.setShowLabels(showLabels);
6141 panel.getRotatableCanvas().setShowLabels(showLabels);
6142 panel.getRotatableCanvas()
6143 .setBgColour(new Color(viewer.getBgColour()));
6144 panel.getRotatableCanvas()
6145 .setApplyToAllViews(viewer.isLinkToAllViews());
6148 * load PCA output data
6150 ScoreModelI scoreModel = ScoreModels.getInstance()
6151 .getScoreModel(modelName, ap);
6152 PCA pca = new PCA(null, scoreModel, params);
6153 PcaDataType pcaData = viewer.getPcaData();
6155 MatrixI pairwise = loadDoubleMatrix(pcaData.getPairwiseMatrix());
6156 pca.setPairwiseScores(pairwise);
6158 MatrixI triDiag = loadDoubleMatrix(pcaData.getTridiagonalMatrix());
6159 pca.setTridiagonal(triDiag);
6161 MatrixI result = loadDoubleMatrix(pcaData.getEigenMatrix());
6162 pca.setEigenmatrix(result);
6164 panel.getPcaModel().setPCA(pca);
6167 * we haven't saved the input data! (JAL-2647 to do)
6169 panel.setInputData(null);
6172 * add the sequence points for the PCA display
6174 List<jalview.datamodel.SequencePoint> seqPoints = new ArrayList<>();
6175 for (SequencePoint sp : viewer.getSequencePoint())
6177 String seqId = sp.getSequenceRef();
6178 SequenceI seq = seqRefIds.get(seqId);
6181 throw new IllegalStateException(
6182 "Unmatched seqref for PCA: " + seqId);
6184 Point pt = new Point(sp.getXPos(), sp.getYPos(), sp.getZPos());
6185 jalview.datamodel.SequencePoint seqPoint = new jalview.datamodel.SequencePoint(
6187 seqPoints.add(seqPoint);
6189 panel.getRotatableCanvas().setPoints(seqPoints, seqPoints.size());
6192 * set min-max ranges and scale after setPoints (which recomputes them)
6194 panel.getRotatableCanvas().setScaleFactor(viewer.getScaleFactor());
6195 SeqPointMin spMin = viewer.getSeqPointMin();
6196 float[] min = new float[] { spMin.getXPos(), spMin.getYPos(),
6198 SeqPointMax spMax = viewer.getSeqPointMax();
6199 float[] max = new float[] { spMax.getXPos(), spMax.getYPos(),
6201 panel.getRotatableCanvas().setSeqMinMax(min, max);
6203 // todo: hold points list in PCAModel only
6204 panel.getPcaModel().setSequencePoints(seqPoints);
6206 panel.setSelectedDimensionIndex(viewer.getXDim(), X);
6207 panel.setSelectedDimensionIndex(viewer.getYDim(), Y);
6208 panel.setSelectedDimensionIndex(viewer.getZDim(), Z);
6210 // is this duplication needed?
6211 panel.setTop(seqPoints.size() - 1);
6212 panel.getPcaModel().setTop(seqPoints.size() - 1);
6215 * add the axes' end points for the display
6217 for (int i = 0; i < 3; i++)
6219 Axis axis = viewer.getAxis().get(i);
6220 panel.getRotatableCanvas().getAxisEndPoints()[i] = new Point(
6221 axis.getXPos(), axis.getYPos(), axis.getZPos());
6224 Desktop.addInternalFrame(panel, MessageManager.formatMessage(
6225 "label.calc_title", "PCA", modelName), 475, 450);
6227 } catch (Exception ex)
6229 Cache.log.error("Error loading PCA: " + ex.toString());
6234 * Populates an XML model of the feature colour scheme for one feature type
6236 * @param featureType
6240 public static Colour marshalColour(
6241 String featureType, FeatureColourI fcol)
6243 Colour col = new Colour();
6244 if (fcol.isSimpleColour())
6246 col.setRGB(Format.getHexString(fcol.getColour()));
6250 col.setRGB(Format.getHexString(fcol.getMaxColour()));
6251 col.setMin(fcol.getMin());
6252 col.setMax(fcol.getMax());
6253 col.setMinRGB(jalview.util.Format.getHexString(fcol.getMinColour()));
6254 col.setAutoScale(fcol.isAutoScaled());
6255 col.setThreshold(fcol.getThreshold());
6256 col.setColourByLabel(fcol.isColourByLabel());
6257 col.setThreshType(fcol.isAboveThreshold() ? ThresholdType.ABOVE
6258 : (fcol.isBelowThreshold() ? ThresholdType.BELOW
6259 : ThresholdType.NONE));
6260 if (fcol.isColourByAttribute())
6262 final String[] attName = fcol.getAttributeName();
6263 col.getAttributeName().add(attName[0]);
6264 if (attName.length > 1)
6266 col.getAttributeName().add(attName[1]);
6269 Color noColour = fcol.getNoColour();
6270 if (noColour == null)
6272 col.setNoValueColour(NoValueColour.NONE);
6274 else if (noColour == fcol.getMaxColour())
6276 col.setNoValueColour(NoValueColour.MAX);
6280 col.setNoValueColour(NoValueColour.MIN);
6283 col.setName(featureType);
6288 * Populates an XML model of the feature filter(s) for one feature type
6290 * @param firstMatcher
6291 * the first (or only) match condition)
6293 * remaining match conditions (if any)
6295 * if true, conditions are and-ed, else or-ed
6297 public static jalview.xml.binding.jalview.FeatureMatcherSet marshalFilter(
6298 FeatureMatcherI firstMatcher, Iterator<FeatureMatcherI> filters,
6301 jalview.xml.binding.jalview.FeatureMatcherSet result = new jalview.xml.binding.jalview.FeatureMatcherSet();
6303 if (filters.hasNext())
6308 CompoundMatcher compound = new CompoundMatcher();
6309 compound.setAnd(and);
6310 jalview.xml.binding.jalview.FeatureMatcherSet matcher1 = marshalFilter(
6311 firstMatcher, Collections.emptyIterator(), and);
6312 // compound.addMatcherSet(matcher1);
6313 compound.getMatcherSet().add(matcher1);
6314 FeatureMatcherI nextMatcher = filters.next();
6315 jalview.xml.binding.jalview.FeatureMatcherSet matcher2 = marshalFilter(
6316 nextMatcher, filters, and);
6317 // compound.addMatcherSet(matcher2);
6318 compound.getMatcherSet().add(matcher2);
6319 result.setCompoundMatcher(compound);
6324 * single condition matcher
6326 // MatchCondition matcherModel = new MatchCondition();
6327 jalview.xml.binding.jalview.FeatureMatcher matcherModel = new jalview.xml.binding.jalview.FeatureMatcher();
6328 matcherModel.setCondition(
6329 firstMatcher.getMatcher().getCondition().getStableName());
6330 matcherModel.setValue(firstMatcher.getMatcher().getPattern());
6331 if (firstMatcher.isByAttribute())
6333 matcherModel.setBy(FilterBy.BY_ATTRIBUTE);
6334 // matcherModel.setAttributeName(firstMatcher.getAttribute());
6335 String[] attName = firstMatcher.getAttribute();
6336 matcherModel.getAttributeName().add(attName[0]); // attribute
6337 if (attName.length > 1)
6339 matcherModel.getAttributeName().add(attName[1]); // sub-attribute
6342 else if (firstMatcher.isByLabel())
6344 matcherModel.setBy(FilterBy.BY_LABEL);
6346 else if (firstMatcher.isByScore())
6348 matcherModel.setBy(FilterBy.BY_SCORE);
6350 result.setMatchCondition(matcherModel);
6357 * Loads one XML model of a feature filter to a Jalview object
6359 * @param featureType
6360 * @param matcherSetModel
6363 public static FeatureMatcherSetI parseFilter(
6365 jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel)
6367 FeatureMatcherSetI result = new FeatureMatcherSet();
6370 parseFilterConditions(result, matcherSetModel, true);
6371 } catch (IllegalStateException e)
6373 // mixing AND and OR conditions perhaps
6375 String.format("Error reading filter conditions for '%s': %s",
6376 featureType, e.getMessage()));
6377 // return as much as was parsed up to the error
6384 * Adds feature match conditions to matcherSet as unmarshalled from XML
6385 * (possibly recursively for compound conditions)
6388 * @param matcherSetModel
6390 * if true, multiple conditions are AND-ed, else they are OR-ed
6391 * @throws IllegalStateException
6392 * if AND and OR conditions are mixed
6394 protected static void parseFilterConditions(
6395 FeatureMatcherSetI matcherSet,
6396 jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel,
6399 jalview.xml.binding.jalview.FeatureMatcher mc = matcherSetModel
6400 .getMatchCondition();
6406 FilterBy filterBy = mc.getBy();
6407 Condition cond = Condition.fromString(mc.getCondition());
6408 String pattern = mc.getValue();
6409 FeatureMatcherI matchCondition = null;
6410 if (filterBy == FilterBy.BY_LABEL)
6412 matchCondition = FeatureMatcher.byLabel(cond, pattern);
6414 else if (filterBy == FilterBy.BY_SCORE)
6416 matchCondition = FeatureMatcher.byScore(cond, pattern);
6419 else if (filterBy == FilterBy.BY_ATTRIBUTE)
6421 final List<String> attributeName = mc.getAttributeName();
6422 String[] attNames = attributeName
6423 .toArray(new String[attributeName.size()]);
6424 matchCondition = FeatureMatcher.byAttribute(cond, pattern,
6429 * note this throws IllegalStateException if AND-ing to a
6430 * previously OR-ed compound condition, or vice versa
6434 matcherSet.and(matchCondition);
6438 matcherSet.or(matchCondition);
6444 * compound condition
6446 List<jalview.xml.binding.jalview.FeatureMatcherSet> matchers = matcherSetModel
6447 .getCompoundMatcher().getMatcherSet();
6448 boolean anded = matcherSetModel.getCompoundMatcher().isAnd();
6449 if (matchers.size() == 2)
6451 parseFilterConditions(matcherSet, matchers.get(0), anded);
6452 parseFilterConditions(matcherSet, matchers.get(1), anded);
6456 System.err.println("Malformed compound filter condition");
6462 * Loads one XML model of a feature colour to a Jalview object
6464 * @param colourModel
6467 public static FeatureColourI parseColour(Colour colourModel)
6469 FeatureColourI colour = null;
6471 if (colourModel.getMax() != null)
6473 Color mincol = null;
6474 Color maxcol = null;
6475 Color noValueColour = null;
6479 mincol = new Color(Integer.parseInt(colourModel.getMinRGB(), 16));
6480 maxcol = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6481 } catch (Exception e)
6483 Cache.log.warn("Couldn't parse out graduated feature color.", e);
6486 NoValueColour noCol = colourModel.getNoValueColour();
6487 if (noCol == NoValueColour.MIN)
6489 noValueColour = mincol;
6491 else if (noCol == NoValueColour.MAX)
6493 noValueColour = maxcol;
6496 colour = new FeatureColour(maxcol, mincol, maxcol, noValueColour,
6497 safeFloat(colourModel.getMin()),
6498 safeFloat(colourModel.getMax()));
6499 final List<String> attributeName = colourModel.getAttributeName();
6500 String[] attributes = attributeName
6501 .toArray(new String[attributeName.size()]);
6502 if (attributes != null && attributes.length > 0)
6504 colour.setAttributeName(attributes);
6506 if (colourModel.isAutoScale() != null)
6508 colour.setAutoScaled(colourModel.isAutoScale().booleanValue());
6510 if (colourModel.isColourByLabel() != null)
6512 colour.setColourByLabel(
6513 colourModel.isColourByLabel().booleanValue());
6515 if (colourModel.getThreshold() != null)
6517 colour.setThreshold(colourModel.getThreshold().floatValue());
6519 ThresholdType ttyp = colourModel.getThreshType();
6520 if (ttyp == ThresholdType.ABOVE)
6522 colour.setAboveThreshold(true);
6524 else if (ttyp == ThresholdType.BELOW)
6526 colour.setBelowThreshold(true);
6531 Color color = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6532 colour = new FeatureColour(color);