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.
23 import static jalview.math.RotatableMatrix.Axis.X;
24 import static jalview.math.RotatableMatrix.Axis.Y;
25 import static jalview.math.RotatableMatrix.Axis.Z;
27 import jalview.analysis.Conservation;
28 import jalview.analysis.PCA;
29 import jalview.analysis.scoremodels.ScoreModels;
30 import jalview.analysis.scoremodels.SimilarityParams;
31 import jalview.api.FeatureColourI;
32 import jalview.api.ViewStyleI;
33 import jalview.api.analysis.ScoreModelI;
34 import jalview.api.analysis.SimilarityParamsI;
35 import jalview.api.structures.JalviewStructureDisplayI;
36 import jalview.bin.Cache;
37 import jalview.datamodel.AlignedCodonFrame;
38 import jalview.datamodel.Alignment;
39 import jalview.datamodel.AlignmentAnnotation;
40 import jalview.datamodel.AlignmentI;
41 import jalview.datamodel.GraphLine;
42 import jalview.datamodel.PDBEntry;
43 import jalview.datamodel.Point;
44 import jalview.datamodel.RnaViewerModel;
45 import jalview.datamodel.SequenceFeature;
46 import jalview.datamodel.SequenceGroup;
47 import jalview.datamodel.SequenceI;
48 import jalview.datamodel.StructureViewerModel;
49 import jalview.datamodel.StructureViewerModel.StructureData;
50 import jalview.datamodel.features.FeatureMatcher;
51 import jalview.datamodel.features.FeatureMatcherI;
52 import jalview.datamodel.features.FeatureMatcherSet;
53 import jalview.datamodel.features.FeatureMatcherSetI;
54 import jalview.ext.varna.RnaModel;
55 import jalview.gui.StructureViewer.ViewerType;
56 import jalview.io.DataSourceType;
57 import jalview.io.FileFormat;
58 import jalview.math.Matrix;
59 import jalview.math.MatrixI;
60 import jalview.renderer.ResidueShaderI;
61 import jalview.schemabinding.version2.AlcodMap;
62 import jalview.schemabinding.version2.AlcodonFrame;
63 import jalview.schemabinding.version2.Annotation;
64 import jalview.schemabinding.version2.AnnotationColours;
65 import jalview.schemabinding.version2.AnnotationElement;
66 import jalview.schemabinding.version2.Axis;
67 import jalview.schemabinding.version2.CalcIdParam;
68 import jalview.schemabinding.version2.CompoundMatcher;
69 import jalview.schemabinding.version2.D;
70 import jalview.schemabinding.version2.DBRef;
71 import jalview.schemabinding.version2.DoubleMatrix;
72 import jalview.schemabinding.version2.E;
73 import jalview.schemabinding.version2.EigenMatrix;
74 import jalview.schemabinding.version2.Features;
75 import jalview.schemabinding.version2.Group;
76 import jalview.schemabinding.version2.HiddenColumns;
77 import jalview.schemabinding.version2.JGroup;
78 import jalview.schemabinding.version2.JSeq;
79 import jalview.schemabinding.version2.JalviewModel;
80 import jalview.schemabinding.version2.JalviewModelSequence;
81 import jalview.schemabinding.version2.MapListFrom;
82 import jalview.schemabinding.version2.MapListTo;
83 import jalview.schemabinding.version2.Mapping;
84 import jalview.schemabinding.version2.MappingChoice;
85 import jalview.schemabinding.version2.MatchCondition;
86 import jalview.schemabinding.version2.MatcherSet;
87 import jalview.schemabinding.version2.OtherData;
88 import jalview.schemabinding.version2.PairwiseMatrix;
89 import jalview.schemabinding.version2.PcaData;
90 import jalview.schemabinding.version2.PcaViewer;
91 import jalview.schemabinding.version2.PdbentryItem;
92 import jalview.schemabinding.version2.Pdbids;
93 import jalview.schemabinding.version2.Property;
94 import jalview.schemabinding.version2.RnaViewer;
95 import jalview.schemabinding.version2.Row;
96 import jalview.schemabinding.version2.SecondaryStructure;
97 import jalview.schemabinding.version2.SeqPointMax;
98 import jalview.schemabinding.version2.SeqPointMin;
99 import jalview.schemabinding.version2.Sequence;
100 import jalview.schemabinding.version2.SequencePoint;
101 import jalview.schemabinding.version2.SequenceSet;
102 import jalview.schemabinding.version2.SequenceSetProperties;
103 import jalview.schemabinding.version2.Setting;
104 import jalview.schemabinding.version2.StructureState;
105 import jalview.schemabinding.version2.ThresholdLine;
106 import jalview.schemabinding.version2.Tree;
107 import jalview.schemabinding.version2.TridiagonalMatrix;
108 import jalview.schemabinding.version2.UserColours;
109 import jalview.schemabinding.version2.Viewport;
110 import jalview.schemabinding.version2.types.ColourThreshTypeType;
111 import jalview.schemabinding.version2.types.FeatureMatcherByType;
112 import jalview.schemabinding.version2.types.NoValueColour;
113 import jalview.schemes.AnnotationColourGradient;
114 import jalview.schemes.ColourSchemeI;
115 import jalview.schemes.ColourSchemeProperty;
116 import jalview.schemes.FeatureColour;
117 import jalview.schemes.ResidueProperties;
118 import jalview.schemes.UserColourScheme;
119 import jalview.structure.StructureSelectionManager;
120 import jalview.structures.models.AAStructureBindingModel;
121 import jalview.util.Format;
122 import jalview.util.MessageManager;
123 import jalview.util.Platform;
124 import jalview.util.StringUtils;
125 import jalview.util.jarInputStreamProvider;
126 import jalview.util.matcher.Condition;
127 import jalview.viewmodel.AlignmentViewport;
128 import jalview.viewmodel.PCAModel;
129 import jalview.viewmodel.ViewportRanges;
130 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
131 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
132 import jalview.ws.jws2.Jws2Discoverer;
133 import jalview.ws.jws2.dm.AAConSettings;
134 import jalview.ws.jws2.jabaws2.Jws2Instance;
135 import jalview.ws.params.ArgumentI;
136 import jalview.ws.params.AutoCalcSetting;
137 import jalview.ws.params.WsParamSetI;
139 import java.awt.Color;
140 import java.awt.Rectangle;
141 import java.io.BufferedReader;
142 import java.io.DataInputStream;
143 import java.io.DataOutputStream;
145 import java.io.FileInputStream;
146 import java.io.FileOutputStream;
147 import java.io.IOException;
148 import java.io.InputStreamReader;
149 import java.io.OutputStreamWriter;
150 import java.io.PrintWriter;
151 import java.lang.reflect.InvocationTargetException;
152 import java.net.MalformedURLException;
154 import java.util.ArrayList;
155 import java.util.Arrays;
156 import java.util.Collections;
157 import java.util.Enumeration;
158 import java.util.HashMap;
159 import java.util.HashSet;
160 import java.util.Hashtable;
161 import java.util.IdentityHashMap;
162 import java.util.Iterator;
163 import java.util.LinkedHashMap;
164 import java.util.List;
165 import java.util.Map;
166 import java.util.Map.Entry;
167 import java.util.Set;
168 import java.util.Vector;
169 import java.util.jar.JarEntry;
170 import java.util.jar.JarInputStream;
171 import java.util.jar.JarOutputStream;
173 import javax.swing.JInternalFrame;
174 import javax.swing.SwingUtilities;
176 import org.exolab.castor.xml.Marshaller;
177 import org.exolab.castor.xml.Unmarshaller;
180 * Write out the current jalview desktop state as a Jalview XML stream.
182 * Note: the vamsas objects referred to here are primitive versions of the
183 * VAMSAS project schema elements - they are not the same and most likely never
187 * @version $Revision: 1.134 $
189 public class Jalview2XML
191 private static final String VIEWER_PREFIX = "viewer_";
193 private static final String RNA_PREFIX = "rna_";
195 private static final String UTF_8 = "UTF-8";
198 * prefix for recovering datasets for alignments with multiple views where
199 * non-existent dataset IDs were written for some views
201 private static final String UNIQSEQSETID = "uniqueSeqSetId.";
203 // use this with nextCounter() to make unique names for entities
204 private int counter = 0;
207 * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
208 * of sequence objects are created.
210 IdentityHashMap<SequenceI, String> seqsToIds = null;
213 * jalview XML Sequence ID to jalview sequence object reference (both dataset
214 * and alignment sequences. Populated as XML reps of sequence objects are
217 Map<String, SequenceI> seqRefIds = null;
219 Map<String, SequenceI> incompleteSeqs = null;
221 List<SeqFref> frefedSequence = null;
223 boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
226 * Map of reconstructed AlignFrame objects that appear to have come from
227 * SplitFrame objects (have a dna/protein complement view).
229 private Map<Viewport, AlignFrame> splitFrameCandidates = new HashMap<>();
232 * Map from displayed rna structure models to their saved session state jar
235 private Map<RnaModel, String> rnaSessions = new HashMap<>();
238 * create/return unique hash string for sq
241 * @return new or existing unique string for sq
243 String seqHash(SequenceI sq)
245 if (seqsToIds == null)
249 if (seqsToIds.containsKey(sq))
251 return seqsToIds.get(sq);
255 // create sequential key
256 String key = "sq" + (seqsToIds.size() + 1);
257 key = makeHashCode(sq, key); // check we don't have an external reference
259 seqsToIds.put(sq, key);
266 if (seqsToIds == null)
268 seqsToIds = new IdentityHashMap<>();
270 if (seqRefIds == null)
272 seqRefIds = new HashMap<>();
274 if (incompleteSeqs == null)
276 incompleteSeqs = new HashMap<>();
278 if (frefedSequence == null)
280 frefedSequence = new ArrayList<>();
288 public Jalview2XML(boolean raiseGUI)
290 this.raiseGUI = raiseGUI;
294 * base class for resolving forward references to sequences by their ID
299 abstract class SeqFref
305 public SeqFref(String _sref, String type)
311 public String getSref()
316 public SequenceI getSrefSeq()
318 return seqRefIds.get(sref);
321 public boolean isResolvable()
323 return seqRefIds.get(sref) != null;
326 public SequenceI getSrefDatasetSeq()
328 SequenceI sq = seqRefIds.get(sref);
331 while (sq.getDatasetSequence() != null)
333 sq = sq.getDatasetSequence();
340 * @return true if the forward reference was fully resolved
342 abstract boolean resolve();
345 public String toString()
347 return type + " reference to " + sref;
352 * create forward reference for a mapping
358 public SeqFref newMappingRef(final String sref,
359 final jalview.datamodel.Mapping _jmap)
361 SeqFref fref = new SeqFref(sref, "Mapping")
363 public jalview.datamodel.Mapping jmap = _jmap;
368 SequenceI seq = getSrefDatasetSeq();
380 public SeqFref newAlcodMapRef(final String sref,
381 final AlignedCodonFrame _cf,
382 final jalview.datamodel.Mapping _jmap)
385 SeqFref fref = new SeqFref(sref, "Codon Frame")
387 AlignedCodonFrame cf = _cf;
389 public jalview.datamodel.Mapping mp = _jmap;
392 public boolean isResolvable()
394 return super.isResolvable() && mp.getTo() != null;
400 SequenceI seq = getSrefDatasetSeq();
405 cf.addMap(seq, mp.getTo(), mp.getMap());
412 public void resolveFrefedSequences()
414 Iterator<SeqFref> nextFref = frefedSequence.iterator();
415 int toresolve = frefedSequence.size();
416 int unresolved = 0, failedtoresolve = 0;
417 while (nextFref.hasNext())
419 SeqFref ref = nextFref.next();
420 if (ref.isResolvable())
432 } catch (Exception x)
435 "IMPLEMENTATION ERROR: Failed to resolve forward reference for sequence "
448 System.err.println("Jalview Project Import: There were " + unresolved
449 + " forward references left unresolved on the stack.");
451 if (failedtoresolve > 0)
453 System.err.println("SERIOUS! " + failedtoresolve
454 + " resolvable forward references failed to resolve.");
456 if (incompleteSeqs != null && incompleteSeqs.size() > 0)
459 "Jalview Project Import: There are " + incompleteSeqs.size()
460 + " sequences which may have incomplete metadata.");
461 if (incompleteSeqs.size() < 10)
463 for (SequenceI s : incompleteSeqs.values())
465 System.err.println(s.toString());
471 "Too many to report. Skipping output of incomplete sequences.");
477 * This maintains a map of viewports, the key being the seqSetId. Important to
478 * set historyItem and redoList for multiple views
480 Map<String, AlignViewport> viewportsAdded = new HashMap<>();
482 Map<String, AlignmentAnnotation> annotationIds = new HashMap<>();
484 String uniqueSetSuffix = "";
487 * List of pdbfiles added to Jar
489 List<String> pdbfiles = null;
491 // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
492 public void saveState(File statefile)
494 FileOutputStream fos = null;
497 fos = new FileOutputStream(statefile);
498 JarOutputStream jout = new JarOutputStream(fos);
501 } catch (Exception e)
503 // TODO: inform user of the problem - they need to know if their data was
505 if (errorMessage == null)
507 errorMessage = "Couldn't write Jalview Archive to output file '"
508 + statefile + "' - See console error log for details";
512 errorMessage += "(output file was '" + statefile + "')";
522 } catch (IOException e)
532 * Writes a jalview project archive to the given Jar output stream.
536 public void saveState(JarOutputStream jout)
538 AlignFrame[] frames = Desktop.getAlignFrames();
544 saveAllFrames(Arrays.asList(frames), jout);
548 * core method for storing state for a set of AlignFrames.
551 * - frames involving all data to be exported (including containing
554 * - project output stream
556 private void saveAllFrames(List<AlignFrame> frames, JarOutputStream jout)
558 Hashtable<String, AlignFrame> dsses = new Hashtable<>();
561 * ensure cached data is clear before starting
563 // todo tidy up seqRefIds, seqsToIds initialisation / reset
565 splitFrameCandidates.clear();
570 // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
571 // //////////////////////////////////////////////////
573 List<String> shortNames = new ArrayList<>();
574 List<String> viewIds = new ArrayList<>();
577 for (int i = frames.size() - 1; i > -1; i--)
579 AlignFrame af = frames.get(i);
581 if (skipList != null && skipList
582 .containsKey(af.getViewport().getSequenceSetId()))
587 String shortName = makeFilename(af, shortNames);
589 int ap, apSize = af.alignPanels.size();
591 for (ap = 0; ap < apSize; ap++)
593 AlignmentPanel apanel = af.alignPanels.get(ap);
594 String fileName = apSize == 1 ? shortName : ap + shortName;
595 if (!fileName.endsWith(".xml"))
597 fileName = fileName + ".xml";
600 saveState(apanel, fileName, jout, viewIds);
602 String dssid = getDatasetIdRef(
603 af.getViewport().getAlignment().getDataset());
604 if (!dsses.containsKey(dssid))
606 dsses.put(dssid, af);
611 writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix,
617 } catch (Exception foo)
622 } catch (Exception ex)
624 // TODO: inform user of the problem - they need to know if their data was
626 if (errorMessage == null)
628 errorMessage = "Couldn't write Jalview Archive - see error output for details";
630 ex.printStackTrace();
635 * Generates a distinct file name, based on the title of the AlignFrame, by
636 * appending _n for increasing n until an unused name is generated. The new
637 * name (without its extension) is added to the list.
641 * @return the generated name, with .xml extension
643 protected String makeFilename(AlignFrame af, List<String> namesUsed)
645 String shortName = af.getTitle();
647 if (shortName.indexOf(File.separatorChar) > -1)
649 shortName = shortName
650 .substring(shortName.lastIndexOf(File.separatorChar) + 1);
655 while (namesUsed.contains(shortName))
657 if (shortName.endsWith("_" + (count - 1)))
659 shortName = shortName.substring(0, shortName.lastIndexOf("_"));
662 shortName = shortName.concat("_" + count);
666 namesUsed.add(shortName);
668 if (!shortName.endsWith(".xml"))
670 shortName = shortName + ".xml";
675 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
676 public boolean saveAlignment(AlignFrame af, String jarFile,
681 FileOutputStream fos = new FileOutputStream(jarFile);
682 JarOutputStream jout = new JarOutputStream(fos);
683 List<AlignFrame> frames = new ArrayList<>();
685 // resolve splitframes
686 if (af.getViewport().getCodingComplement() != null)
688 frames = ((SplitFrame) af.getSplitViewContainer()).getAlignFrames();
694 saveAllFrames(frames, jout);
698 } catch (Exception foo)
704 } catch (Exception ex)
706 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
707 ex.printStackTrace();
712 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
713 String fileName, JarOutputStream jout)
716 for (String dssids : dsses.keySet())
718 AlignFrame _af = dsses.get(dssids);
719 String jfileName = fileName + " Dataset for " + _af.getTitle();
720 if (!jfileName.endsWith(".xml"))
722 jfileName = jfileName + ".xml";
724 saveState(_af.alignPanel, jfileName, true, jout, null);
729 * create a JalviewModel from an alignment view and marshall it to a
733 * panel to create jalview model for
735 * name of alignment panel written to output stream
742 public JalviewModel saveState(AlignmentPanel ap, String fileName,
743 JarOutputStream jout, List<String> viewIds)
745 return saveState(ap, fileName, false, jout, viewIds);
749 * create a JalviewModel from an alignment view and marshall it to a
753 * panel to create jalview model for
755 * name of alignment panel written to output stream
757 * when true, only write the dataset for the alignment, not the data
758 * associated with the view.
764 public JalviewModel saveState(AlignmentPanel ap, String fileName,
765 boolean storeDS, JarOutputStream jout, List<String> viewIds)
769 viewIds = new ArrayList<>();
774 List<UserColourScheme> userColours = new ArrayList<>();
776 AlignViewport av = ap.av;
777 ViewportRanges vpRanges = av.getRanges();
779 JalviewModel object = new JalviewModel();
780 object.setVamsasModel(new jalview.schemabinding.version2.VamsasModel());
782 object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
784 jalview.bin.Cache.getDefault("VERSION", "Development Build"));
787 * rjal is full height alignment, jal is actual alignment with full metadata
788 * but excludes hidden sequences.
790 jalview.datamodel.AlignmentI rjal = av.getAlignment(), jal = rjal;
792 if (av.hasHiddenRows())
794 rjal = jal.getHiddenSequences().getFullAlignment();
797 SequenceSet vamsasSet = new SequenceSet();
799 JalviewModelSequence jms = new JalviewModelSequence();
801 vamsasSet.setGapChar(jal.getGapCharacter() + "");
803 if (jal.getDataset() != null)
805 // dataset id is the dataset's hashcode
806 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
809 // switch jal and the dataset
810 jal = jal.getDataset();
814 if (jal.getProperties() != null)
816 Enumeration en = jal.getProperties().keys();
817 while (en.hasMoreElements())
819 String key = en.nextElement().toString();
820 SequenceSetProperties ssp = new SequenceSetProperties();
822 ssp.setValue(jal.getProperties().get(key).toString());
823 vamsasSet.addSequenceSetProperties(ssp);
828 Set<String> calcIdSet = new HashSet<>();
829 // record the set of vamsas sequence XML POJO we create.
830 HashMap<String, Sequence> vamsasSetIds = new HashMap<>();
832 for (final SequenceI jds : rjal.getSequences())
834 final SequenceI jdatasq = jds.getDatasetSequence() == null ? jds
835 : jds.getDatasetSequence();
836 String id = seqHash(jds);
837 if (vamsasSetIds.get(id) == null)
839 if (seqRefIds.get(id) != null && !storeDS)
841 // This happens for two reasons: 1. multiple views are being
843 // 2. the hashCode has collided with another sequence's code. This
845 // HAPPEN! (PF00072.15.stk does this)
846 // JBPNote: Uncomment to debug writing out of files that do not read
847 // back in due to ArrayOutOfBoundExceptions.
848 // System.err.println("vamsasSeq backref: "+id+"");
849 // System.err.println(jds.getName()+"
850 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
851 // System.err.println("Hashcode: "+seqHash(jds));
852 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
853 // System.err.println(rsq.getName()+"
854 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
855 // System.err.println("Hashcode: "+seqHash(rsq));
859 vamsasSeq = createVamsasSequence(id, jds);
860 vamsasSet.addSequence(vamsasSeq);
861 vamsasSetIds.put(id, vamsasSeq);
862 seqRefIds.put(id, jds);
866 jseq.setStart(jds.getStart());
867 jseq.setEnd(jds.getEnd());
868 jseq.setColour(av.getSequenceColour(jds).getRGB());
870 jseq.setId(id); // jseq id should be a string not a number
873 // Store any sequences this sequence represents
874 if (av.hasHiddenRows())
876 // use rjal, contains the full height alignment
878 av.getAlignment().getHiddenSequences().isHidden(jds));
880 if (av.isHiddenRepSequence(jds))
882 jalview.datamodel.SequenceI[] reps = av
883 .getRepresentedSequences(jds).getSequencesInOrder(rjal);
885 for (int h = 0; h < reps.length; h++)
889 jseq.addHiddenSequences(rjal.findIndex(reps[h]));
894 // mark sequence as reference - if it is the reference for this view
897 jseq.setViewreference(jds == jal.getSeqrep());
901 // TODO: omit sequence features from each alignment view's XML dump if we
902 // are storing dataset
903 List<jalview.datamodel.SequenceFeature> sfs = jds
904 .getSequenceFeatures();
905 for (SequenceFeature sf : sfs)
907 Features features = new Features();
909 features.setBegin(sf.getBegin());
910 features.setEnd(sf.getEnd());
911 features.setDescription(sf.getDescription());
912 features.setType(sf.getType());
913 features.setFeatureGroup(sf.getFeatureGroup());
914 features.setScore(sf.getScore());
915 if (sf.links != null)
917 for (int l = 0; l < sf.links.size(); l++)
919 OtherData keyValue = new OtherData();
920 keyValue.setKey("LINK_" + l);
921 keyValue.setValue(sf.links.elementAt(l).toString());
922 features.addOtherData(keyValue);
925 if (sf.otherDetails != null)
928 * save feature attributes, which may be simple strings or
929 * map valued (have sub-attributes)
931 for (Entry<String, Object> entry : sf.otherDetails.entrySet())
933 String key = entry.getKey();
934 Object value = entry.getValue();
935 if (value instanceof Map<?, ?>)
937 for (Entry<String, Object> subAttribute : ((Map<String, Object>) value)
940 OtherData otherData = new OtherData();
941 otherData.setKey(key);
942 otherData.setKey2(subAttribute.getKey());
943 otherData.setValue(subAttribute.getValue().toString());
944 features.addOtherData(otherData);
949 OtherData otherData = new OtherData();
950 otherData.setKey(key);
951 otherData.setValue(value.toString());
952 features.addOtherData(otherData);
957 jseq.addFeatures(features);
960 if (jdatasq.getAllPDBEntries() != null)
962 Enumeration en = jdatasq.getAllPDBEntries().elements();
963 while (en.hasMoreElements())
965 Pdbids pdb = new Pdbids();
966 jalview.datamodel.PDBEntry entry = (jalview.datamodel.PDBEntry) en
969 String pdbId = entry.getId();
971 pdb.setType(entry.getType());
974 * Store any structure views associated with this sequence. This
975 * section copes with duplicate entries in the project, so a dataset
976 * only view *should* be coped with sensibly.
978 // This must have been loaded, is it still visible?
979 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
980 String matchedFile = null;
981 for (int f = frames.length - 1; f > -1; f--)
983 if (frames[f] instanceof StructureViewerBase)
985 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
986 matchedFile = saveStructureState(ap, jds, pdb, entry, viewIds,
987 matchedFile, viewFrame);
989 * Only store each structure viewer's state once in the project
990 * jar. First time through only (storeDS==false)
992 String viewId = viewFrame.getViewId();
993 if (!storeDS && !viewIds.contains(viewId))
998 String viewerState = viewFrame.getStateInfo();
999 writeJarEntry(jout, getViewerJarEntryName(viewId),
1000 viewerState.getBytes());
1001 } catch (IOException e)
1004 "Error saving viewer state: " + e.getMessage());
1010 if (matchedFile != null || entry.getFile() != null)
1012 if (entry.getFile() != null)
1015 matchedFile = entry.getFile();
1017 pdb.setFile(matchedFile); // entry.getFile());
1018 if (pdbfiles == null)
1020 pdbfiles = new ArrayList<>();
1023 if (!pdbfiles.contains(pdbId))
1025 pdbfiles.add(pdbId);
1026 copyFileToJar(jout, matchedFile, pdbId);
1030 Enumeration<String> props = entry.getProperties();
1031 if (props.hasMoreElements())
1033 PdbentryItem item = new PdbentryItem();
1034 while (props.hasMoreElements())
1036 Property prop = new Property();
1037 String key = props.nextElement();
1039 prop.setValue(entry.getProperty(key).toString());
1040 item.addProperty(prop);
1042 pdb.addPdbentryItem(item);
1045 jseq.addPdbids(pdb);
1049 saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
1054 if (!storeDS && av.hasHiddenRows())
1056 jal = av.getAlignment();
1060 if (storeDS && jal.getCodonFrames() != null)
1062 List<AlignedCodonFrame> jac = jal.getCodonFrames();
1063 for (AlignedCodonFrame acf : jac)
1065 AlcodonFrame alc = new AlcodonFrame();
1066 if (acf.getProtMappings() != null
1067 && acf.getProtMappings().length > 0)
1069 boolean hasMap = false;
1070 SequenceI[] dnas = acf.getdnaSeqs();
1071 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1072 for (int m = 0; m < pmaps.length; m++)
1074 AlcodMap alcmap = new AlcodMap();
1075 alcmap.setDnasq(seqHash(dnas[m]));
1077 createVamsasMapping(pmaps[m], dnas[m], null, false));
1078 alc.addAlcodMap(alcmap);
1083 vamsasSet.addAlcodonFrame(alc);
1086 // TODO: delete this ? dead code from 2.8.3->2.9 ?
1088 // AlcodonFrame alc = new AlcodonFrame();
1089 // vamsasSet.addAlcodonFrame(alc);
1090 // for (int p = 0; p < acf.aaWidth; p++)
1092 // Alcodon cmap = new Alcodon();
1093 // if (acf.codons[p] != null)
1095 // // Null codons indicate a gapped column in the translated peptide
1097 // cmap.setPos1(acf.codons[p][0]);
1098 // cmap.setPos2(acf.codons[p][1]);
1099 // cmap.setPos3(acf.codons[p][2]);
1101 // alc.addAlcodon(cmap);
1103 // if (acf.getProtMappings() != null
1104 // && acf.getProtMappings().length > 0)
1106 // SequenceI[] dnas = acf.getdnaSeqs();
1107 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1108 // for (int m = 0; m < pmaps.length; m++)
1110 // AlcodMap alcmap = new AlcodMap();
1111 // alcmap.setDnasq(seqHash(dnas[m]));
1112 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
1114 // alc.addAlcodMap(alcmap);
1121 // /////////////////////////////////
1122 if (!storeDS && av.getCurrentTree() != null)
1124 // FIND ANY ASSOCIATED TREES
1125 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
1126 if (Desktop.desktop != null)
1128 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1130 for (int t = 0; t < frames.length; t++)
1132 if (frames[t] instanceof TreePanel)
1134 TreePanel tp = (TreePanel) frames[t];
1136 if (tp.getTreeCanvas().getViewport().getAlignment() == jal)
1138 Tree tree = new Tree();
1139 tree.setTitle(tp.getTitle());
1140 tree.setCurrentTree((av.getCurrentTree() == tp.getTree()));
1141 tree.setNewick(tp.getTree().print());
1142 tree.setThreshold(tp.getTreeCanvas().getThreshold());
1144 tree.setFitToWindow(tp.fitToWindow.getState());
1145 tree.setFontName(tp.getTreeFont().getName());
1146 tree.setFontSize(tp.getTreeFont().getSize());
1147 tree.setFontStyle(tp.getTreeFont().getStyle());
1148 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
1150 tree.setShowBootstrap(tp.bootstrapMenu.getState());
1151 tree.setShowDistances(tp.distanceMenu.getState());
1153 tree.setHeight(tp.getHeight());
1154 tree.setWidth(tp.getWidth());
1155 tree.setXpos(tp.getX());
1156 tree.setYpos(tp.getY());
1157 tree.setId(makeHashCode(tp, null));
1158 tree.setLinkToAllViews(tp.getTreeCanvas().applyToAllViews);
1169 if (!storeDS && Desktop.desktop != null)
1171 for (JInternalFrame frame : Desktop.desktop.getAllFrames())
1173 if (frame instanceof PCAPanel)
1175 PCAPanel panel = (PCAPanel) frame;
1176 if (panel.av.getAlignment() == jal)
1178 savePCA(panel, jms);
1186 * store forward refs from an annotationRow to any groups
1188 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<>();
1191 for (SequenceI sq : jal.getSequences())
1193 // Store annotation on dataset sequences only
1194 AlignmentAnnotation[] aa = sq.getAnnotation();
1195 if (aa != null && aa.length > 0)
1197 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1204 if (jal.getAlignmentAnnotation() != null)
1206 // Store the annotation shown on the alignment.
1207 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1208 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1213 if (jal.getGroups() != null)
1215 JGroup[] groups = new JGroup[jal.getGroups().size()];
1217 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1219 JGroup jGroup = new JGroup();
1220 groups[++i] = jGroup;
1222 jGroup.setStart(sg.getStartRes());
1223 jGroup.setEnd(sg.getEndRes());
1224 jGroup.setName(sg.getName());
1225 if (groupRefs.containsKey(sg))
1227 // group has references so set its ID field
1228 jGroup.setId(groupRefs.get(sg));
1230 ColourSchemeI colourScheme = sg.getColourScheme();
1231 if (colourScheme != null)
1233 ResidueShaderI groupColourScheme = sg.getGroupColourScheme();
1234 if (groupColourScheme.conservationApplied())
1236 jGroup.setConsThreshold(groupColourScheme.getConservationInc());
1238 if (colourScheme instanceof jalview.schemes.UserColourScheme)
1241 setUserColourScheme(colourScheme, userColours, jms));
1245 jGroup.setColour(colourScheme.getSchemeName());
1248 else if (colourScheme instanceof jalview.schemes.AnnotationColourGradient)
1250 jGroup.setColour("AnnotationColourGradient");
1251 jGroup.setAnnotationColours(constructAnnotationColours(
1252 (jalview.schemes.AnnotationColourGradient) colourScheme,
1255 else if (colourScheme instanceof jalview.schemes.UserColourScheme)
1258 setUserColourScheme(colourScheme, userColours, jms));
1262 jGroup.setColour(colourScheme.getSchemeName());
1265 jGroup.setPidThreshold(groupColourScheme.getThreshold());
1268 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1269 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1270 jGroup.setDisplayText(sg.getDisplayText());
1271 jGroup.setColourText(sg.getColourText());
1272 jGroup.setTextCol1(sg.textColour.getRGB());
1273 jGroup.setTextCol2(sg.textColour2.getRGB());
1274 jGroup.setTextColThreshold(sg.thresholdTextColour);
1275 jGroup.setShowUnconserved(sg.getShowNonconserved());
1276 jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1277 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1278 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1279 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1280 for (SequenceI seq : sg.getSequences())
1282 jGroup.addSeq(seqHash(seq));
1286 jms.setJGroup(groups);
1290 // /////////SAVE VIEWPORT
1291 Viewport view = new Viewport();
1292 view.setTitle(ap.alignFrame.getTitle());
1293 view.setSequenceSetId(
1294 makeHashCode(av.getSequenceSetId(), av.getSequenceSetId()));
1295 view.setId(av.getViewId());
1296 if (av.getCodingComplement() != null)
1298 view.setComplementId(av.getCodingComplement().getViewId());
1300 view.setViewName(av.getViewName());
1301 view.setGatheredViews(av.isGatherViewsHere());
1303 Rectangle size = ap.av.getExplodedGeometry();
1304 Rectangle position = size;
1307 size = ap.alignFrame.getBounds();
1308 if (av.getCodingComplement() != null)
1310 position = ((SplitFrame) ap.alignFrame.getSplitViewContainer())
1318 view.setXpos(position.x);
1319 view.setYpos(position.y);
1321 view.setWidth(size.width);
1322 view.setHeight(size.height);
1324 view.setStartRes(vpRanges.getStartRes());
1325 view.setStartSeq(vpRanges.getStartSeq());
1327 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1329 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1333 .getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1335 AnnotationColours ac = constructAnnotationColours(
1336 (jalview.schemes.AnnotationColourGradient) av
1337 .getGlobalColourScheme(),
1340 view.setAnnotationColours(ac);
1341 view.setBgColour("AnnotationColourGradient");
1345 view.setBgColour(ColourSchemeProperty
1346 .getColourName(av.getGlobalColourScheme()));
1349 ResidueShaderI vcs = av.getResidueShading();
1350 ColourSchemeI cs = av.getGlobalColourScheme();
1354 if (vcs.conservationApplied())
1356 view.setConsThreshold(vcs.getConservationInc());
1357 if (cs instanceof jalview.schemes.UserColourScheme)
1359 view.setBgColour(setUserColourScheme(cs, userColours, jms));
1362 view.setPidThreshold(vcs.getThreshold());
1365 view.setConservationSelected(av.getConservationSelected());
1366 view.setPidSelected(av.getAbovePIDThreshold());
1367 view.setFontName(av.font.getName());
1368 view.setFontSize(av.font.getSize());
1369 view.setFontStyle(av.font.getStyle());
1370 view.setScaleProteinAsCdna(av.getViewStyle().isScaleProteinAsCdna());
1371 view.setRenderGaps(av.isRenderGaps());
1372 view.setShowAnnotation(av.isShowAnnotation());
1373 view.setShowBoxes(av.getShowBoxes());
1374 view.setShowColourText(av.getColourText());
1375 view.setShowFullId(av.getShowJVSuffix());
1376 view.setRightAlignIds(av.isRightAlignIds());
1377 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1378 view.setShowText(av.getShowText());
1379 view.setShowUnconserved(av.getShowUnconserved());
1380 view.setWrapAlignment(av.getWrapAlignment());
1381 view.setTextCol1(av.getTextColour().getRGB());
1382 view.setTextCol2(av.getTextColour2().getRGB());
1383 view.setTextColThreshold(av.getThresholdTextColour());
1384 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1385 view.setShowSequenceLogo(av.isShowSequenceLogo());
1386 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1387 view.setShowGroupConsensus(av.isShowGroupConsensus());
1388 view.setShowGroupConservation(av.isShowGroupConservation());
1389 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1390 view.setShowDbRefTooltip(av.isShowDBRefs());
1391 view.setFollowHighlight(av.isFollowHighlight());
1392 view.setFollowSelection(av.followSelection);
1393 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1394 if (av.getFeaturesDisplayed() != null)
1396 jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
1398 FeatureRenderer fr = ap.getSeqPanel().seqCanvas
1399 .getFeatureRenderer();
1400 String[] renderOrder = fr.getRenderOrder().toArray(new String[0]);
1402 Vector<String> settingsAdded = new Vector<>();
1403 if (renderOrder != null)
1405 for (String featureType : renderOrder)
1407 Setting setting = new Setting();
1408 setting.setType(featureType);
1411 * save any filter for the feature type
1413 FeatureMatcherSetI filter = fr.getFeatureFilter(featureType);
1414 if (filter != null) {
1415 Iterator<FeatureMatcherI> filters = filter.getMatchers().iterator();
1416 FeatureMatcherI firstFilter = filters.next();
1417 setting.setMatcherSet(Jalview2XML.marshalFilter(
1418 firstFilter, filters, filter.isAnded()));
1422 * save colour scheme for the feature type
1424 FeatureColourI fcol = fr.getFeatureStyle(featureType);
1425 if (!fcol.isSimpleColour())
1427 setting.setColour(fcol.getMaxColour().getRGB());
1428 setting.setMincolour(fcol.getMinColour().getRGB());
1429 setting.setMin(fcol.getMin());
1430 setting.setMax(fcol.getMax());
1431 setting.setColourByLabel(fcol.isColourByLabel());
1432 if (fcol.isColourByAttribute())
1434 setting.setAttributeName(fcol.getAttributeName());
1436 setting.setAutoScale(fcol.isAutoScaled());
1437 setting.setThreshold(fcol.getThreshold());
1438 Color noColour = fcol.getNoColour();
1439 if (noColour == null)
1441 setting.setNoValueColour(NoValueColour.NONE);
1443 else if (noColour.equals(fcol.getMaxColour()))
1445 setting.setNoValueColour(NoValueColour.MAX);
1449 setting.setNoValueColour(NoValueColour.MIN);
1451 // -1 = No threshold, 0 = Below, 1 = Above
1452 setting.setThreshstate(fcol.isAboveThreshold() ? 1
1453 : (fcol.isBelowThreshold() ? 0 : -1));
1457 setting.setColour(fcol.getColour().getRGB());
1461 av.getFeaturesDisplayed().isVisible(featureType));
1463 .getOrder(featureType);
1466 setting.setOrder(rorder);
1468 fs.addSetting(setting);
1469 settingsAdded.addElement(featureType);
1473 // is groups actually supposed to be a map here ?
1474 Iterator<String> en = fr.getFeatureGroups().iterator();
1475 Vector<String> groupsAdded = new Vector<>();
1476 while (en.hasNext())
1478 String grp = en.next();
1479 if (groupsAdded.contains(grp))
1483 Group g = new Group();
1485 g.setDisplay(((Boolean) fr.checkGroupVisibility(grp, false))
1488 groupsAdded.addElement(grp);
1490 jms.setFeatureSettings(fs);
1493 if (av.hasHiddenColumns())
1495 jalview.datamodel.HiddenColumns hidden = av.getAlignment()
1496 .getHiddenColumns();
1499 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1503 Iterator<int[]> hiddenRegions = hidden.iterator();
1504 while (hiddenRegions.hasNext())
1506 int[] region = hiddenRegions.next();
1507 HiddenColumns hc = new HiddenColumns();
1508 hc.setStart(region[0]);
1509 hc.setEnd(region[1]);
1510 view.addHiddenColumns(hc);
1514 if (calcIdSet.size() > 0)
1516 for (String calcId : calcIdSet)
1518 if (calcId.trim().length() > 0)
1520 CalcIdParam cidp = createCalcIdParam(calcId, av);
1521 // Some calcIds have no parameters.
1524 view.addCalcIdParam(cidp);
1530 jms.addViewport(view);
1532 object.setJalviewModelSequence(jms);
1533 object.getVamsasModel().addSequenceSet(vamsasSet);
1535 if (jout != null && fileName != null)
1537 // We may not want to write the object to disk,
1538 // eg we can copy the alignViewport to a new view object
1539 // using save and then load
1542 System.out.println("Writing jar entry " + fileName);
1543 JarEntry entry = new JarEntry(fileName);
1544 jout.putNextEntry(entry);
1545 PrintWriter pout = new PrintWriter(
1546 new OutputStreamWriter(jout, UTF_8));
1547 Marshaller marshaller = new Marshaller(pout);
1548 marshaller.marshal(object);
1551 } catch (Exception ex)
1553 // TODO: raise error in GUI if marshalling failed.
1554 ex.printStackTrace();
1561 * Writes PCA viewer attributes and computed values to an XML model object and adds it to the JalviewModel. Any exceptions are reported by logging.
1563 protected void savePCA(PCAPanel panel, JalviewModelSequence jms)
1567 PcaViewer viewer = new PcaViewer();
1568 viewer.setHeight(panel.getHeight());
1569 viewer.setWidth(panel.getWidth());
1570 viewer.setXpos(panel.getX());
1571 viewer.setYpos(panel.getY());
1572 viewer.setTitle(panel.getTitle());
1573 PCAModel pcaModel = panel.getPcaModel();
1574 viewer.setScoreModelName(pcaModel.getScoreModelName());
1575 viewer.setXDim(panel.getSelectedDimensionIndex(X));
1576 viewer.setYDim(panel.getSelectedDimensionIndex(Y));
1577 viewer.setZDim(panel.getSelectedDimensionIndex(Z));
1578 viewer.setBgColour(panel.getRotatableCanvas().getBackgroundColour().getRGB());
1579 viewer.setScaleFactor(panel.getRotatableCanvas().getScaleFactor());
1580 float[] spMin = panel.getRotatableCanvas().getSeqMin();
1581 SeqPointMin spmin = new SeqPointMin();
1582 spmin.setXPos(spMin[0]);
1583 spmin.setYPos(spMin[1]);
1584 spmin.setZPos(spMin[2]);
1585 viewer.setSeqPointMin(spmin);
1586 float[] spMax = panel.getRotatableCanvas().getSeqMax();
1587 SeqPointMax spmax = new SeqPointMax();
1588 spmax.setXPos(spMax[0]);
1589 spmax.setYPos(spMax[1]);
1590 spmax.setZPos(spMax[2]);
1591 viewer.setSeqPointMax(spmax);
1592 viewer.setShowLabels(panel.getRotatableCanvas().isShowLabels());
1593 viewer.setLinkToAllViews(panel.getRotatableCanvas().isApplyToAllViews());
1594 SimilarityParamsI sp = pcaModel.getSimilarityParameters();
1595 viewer.setIncludeGaps(sp.includeGaps());
1596 viewer.setMatchGaps(sp.matchGaps());
1597 viewer.setIncludeGappedColumns(sp.includeGappedColumns());
1598 viewer.setDenominateByShortestLength(sp.denominateByShortestLength());
1601 * sequence points on display
1603 for (jalview.datamodel.SequencePoint spt : pcaModel
1604 .getSequencePoints())
1606 SequencePoint point = new SequencePoint();
1607 point.setSequenceRef(seqHash(spt.getSequence()));
1608 point.setXPos(spt.coord.x);
1609 point.setYPos(spt.coord.y);
1610 point.setZPos(spt.coord.z);
1611 viewer.addSequencePoint(point);
1615 * (end points of) axes on display
1617 for (Point p : panel.getRotatableCanvas().getAxisEndPoints())
1619 Axis axis = new Axis();
1623 viewer.addAxis(axis);
1627 * raw PCA data (note we are not restoring PCA inputs here -
1628 * alignment view, score model, similarity parameters)
1630 PcaData data = new PcaData();
1631 viewer.setPcaData(data);
1632 PCA pca = pcaModel.getPcaData();
1634 PairwiseMatrix pm = new PairwiseMatrix();
1635 saveDoubleMatrix(pca.getPairwiseScores(), pm);
1636 data.setPairwiseMatrix(pm);
1638 TridiagonalMatrix tm = new TridiagonalMatrix();
1639 saveDoubleMatrix(pca.getTridiagonal(), tm);
1640 data.setTridiagonalMatrix(tm);
1642 EigenMatrix eigenMatrix = new EigenMatrix();
1643 data.setEigenMatrix(eigenMatrix);
1644 saveDoubleMatrix(pca.getEigenmatrix(), eigenMatrix);
1646 jms.addPcaViewer(viewer);
1647 } catch (Throwable t)
1649 Cache.log.error("Error saving PCA: " + t.getMessage());
1654 * Stores values from a matrix into an XML element, including (if present) the
1659 * @see #loadDoubleMatrix(DoubleMatrix)
1661 protected void saveDoubleMatrix(MatrixI m, DoubleMatrix xmlMatrix)
1663 xmlMatrix.setRows(m.height());
1664 xmlMatrix.setColumns(m.width());
1665 for (int i = 0; i < m.height(); i++)
1667 Row row = new Row();
1668 for (int j = 0; j < m.width(); j++)
1670 row.addV(m.getValue(i, j));
1672 xmlMatrix.addRow(row);
1674 if (m.getD() != null)
1676 D dVector = new D();
1677 dVector.setV(m.getD());
1678 xmlMatrix.setD(dVector);
1680 if (m.getE() != null)
1682 E eVector = new E();
1683 eVector.setV(m.getE());
1684 xmlMatrix.setE(eVector);
1689 * Loads XML matrix data into a new Matrix object, including the D and/or E
1690 * vectors (if present)
1694 * @see Jalview2XML#saveDoubleMatrix(MatrixI, DoubleMatrix)
1696 protected MatrixI loadDoubleMatrix(DoubleMatrix mData)
1698 int rows = mData.getRows();
1699 double[][] vals = new double[rows][];
1701 for (int i = 0; i < rows; i++)
1703 vals[i] = mData.getRow(i).getV();
1706 MatrixI m = new Matrix(vals);
1708 if (mData.getD() != null) {
1709 m.setD(mData.getD().getV());
1711 if (mData.getE() != null)
1713 m.setE(mData.getE().getV());
1720 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1721 * for each viewer, with
1723 * <li>viewer geometry (position, size, split pane divider location)</li>
1724 * <li>index of the selected structure in the viewer (currently shows gapped
1726 * <li>the id of the annotation holding RNA secondary structure</li>
1727 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1729 * Varna viewer state is also written out (in native Varna XML) to separate
1730 * project jar entries. A separate entry is written for each RNA structure
1731 * displayed, with the naming convention
1733 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
1741 * @param storeDataset
1743 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
1744 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
1745 boolean storeDataset)
1747 if (Desktop.desktop == null)
1751 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1752 for (int f = frames.length - 1; f > -1; f--)
1754 if (frames[f] instanceof AppVarna)
1756 AppVarna varna = (AppVarna) frames[f];
1758 * link the sequence to every viewer that is showing it and is linked to
1759 * its alignment panel
1761 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1763 String viewId = varna.getViewId();
1764 RnaViewer rna = new RnaViewer();
1765 rna.setViewId(viewId);
1766 rna.setTitle(varna.getTitle());
1767 rna.setXpos(varna.getX());
1768 rna.setYpos(varna.getY());
1769 rna.setWidth(varna.getWidth());
1770 rna.setHeight(varna.getHeight());
1771 rna.setDividerLocation(varna.getDividerLocation());
1772 rna.setSelectedRna(varna.getSelectedIndex());
1773 jseq.addRnaViewer(rna);
1776 * Store each Varna panel's state once in the project per sequence.
1777 * First time through only (storeDataset==false)
1779 // boolean storeSessions = false;
1780 // String sequenceViewId = viewId + seqsToIds.get(jds);
1781 // if (!storeDataset && !viewIds.contains(sequenceViewId))
1783 // viewIds.add(sequenceViewId);
1784 // storeSessions = true;
1786 for (RnaModel model : varna.getModels())
1788 if (model.seq == jds)
1791 * VARNA saves each view (sequence or alignment secondary
1792 * structure, gapped or trimmed) as a separate XML file
1794 String jarEntryName = rnaSessions.get(model);
1795 if (jarEntryName == null)
1798 String varnaStateFile = varna.getStateInfo(model.rna);
1799 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
1800 copyFileToJar(jout, varnaStateFile, jarEntryName);
1801 rnaSessions.put(model, jarEntryName);
1803 SecondaryStructure ss = new SecondaryStructure();
1804 String annotationId = varna.getAnnotation(jds).annotationId;
1805 ss.setAnnotationId(annotationId);
1806 ss.setViewerState(jarEntryName);
1807 ss.setGapped(model.gapped);
1808 ss.setTitle(model.title);
1809 rna.addSecondaryStructure(ss);
1818 * Copy the contents of a file to a new entry added to the output jar
1822 * @param jarEntryName
1824 protected void copyFileToJar(JarOutputStream jout, String infilePath,
1825 String jarEntryName)
1827 DataInputStream dis = null;
1830 File file = new File(infilePath);
1831 if (file.exists() && jout != null)
1833 dis = new DataInputStream(new FileInputStream(file));
1834 byte[] data = new byte[(int) file.length()];
1835 dis.readFully(data);
1836 writeJarEntry(jout, jarEntryName, data);
1838 } catch (Exception ex)
1840 ex.printStackTrace();
1848 } catch (IOException e)
1857 * Write the data to a new entry of given name in the output jar file
1860 * @param jarEntryName
1862 * @throws IOException
1864 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
1865 byte[] data) throws IOException
1869 System.out.println("Writing jar entry " + jarEntryName);
1870 jout.putNextEntry(new JarEntry(jarEntryName));
1871 DataOutputStream dout = new DataOutputStream(jout);
1872 dout.write(data, 0, data.length);
1879 * Save the state of a structure viewer
1884 * the archive XML element under which to save the state
1887 * @param matchedFile
1891 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
1892 Pdbids pdb, PDBEntry entry, List<String> viewIds,
1893 String matchedFile, StructureViewerBase viewFrame)
1895 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
1898 * Look for any bindings for this viewer to the PDB file of interest
1899 * (including part matches excluding chain id)
1901 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
1903 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
1904 final String pdbId = pdbentry.getId();
1905 if (!pdbId.equals(entry.getId())
1906 && !(entry.getId().length() > 4 && entry.getId().toLowerCase()
1907 .startsWith(pdbId.toLowerCase())))
1910 * not interested in a binding to a different PDB entry here
1914 if (matchedFile == null)
1916 matchedFile = pdbentry.getFile();
1918 else if (!matchedFile.equals(pdbentry.getFile()))
1921 "Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
1922 + pdbentry.getFile());
1926 // can get at it if the ID
1927 // match is ambiguous (e.g.
1930 for (int smap = 0; smap < viewFrame.getBinding()
1931 .getSequence()[peid].length; smap++)
1933 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
1934 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
1936 StructureState state = new StructureState();
1937 state.setVisible(true);
1938 state.setXpos(viewFrame.getX());
1939 state.setYpos(viewFrame.getY());
1940 state.setWidth(viewFrame.getWidth());
1941 state.setHeight(viewFrame.getHeight());
1942 final String viewId = viewFrame.getViewId();
1943 state.setViewId(viewId);
1944 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
1945 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
1946 state.setColourByJmol(viewFrame.isColouredByViewer());
1947 state.setType(viewFrame.getViewerType().toString());
1948 pdb.addStructureState(state);
1956 * Populates the AnnotationColours xml for save. This captures the settings of
1957 * the options in the 'Colour by Annotation' dialog.
1960 * @param userColours
1964 private AnnotationColours constructAnnotationColours(
1965 AnnotationColourGradient acg, List<UserColourScheme> userColours,
1966 JalviewModelSequence jms)
1968 AnnotationColours ac = new AnnotationColours();
1969 ac.setAboveThreshold(acg.getAboveThreshold());
1970 ac.setThreshold(acg.getAnnotationThreshold());
1971 // 2.10.2 save annotationId (unique) not annotation label
1972 ac.setAnnotation(acg.getAnnotation().annotationId);
1973 if (acg.getBaseColour() instanceof UserColourScheme)
1976 setUserColourScheme(acg.getBaseColour(), userColours, jms));
1981 ColourSchemeProperty.getColourName(acg.getBaseColour()));
1984 ac.setMaxColour(acg.getMaxColour().getRGB());
1985 ac.setMinColour(acg.getMinColour().getRGB());
1986 ac.setPerSequence(acg.isSeqAssociated());
1987 ac.setPredefinedColours(acg.isPredefinedColours());
1991 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
1992 IdentityHashMap<SequenceGroup, String> groupRefs,
1993 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
1994 SequenceSet vamsasSet)
1997 for (int i = 0; i < aa.length; i++)
1999 Annotation an = new Annotation();
2001 AlignmentAnnotation annotation = aa[i];
2002 if (annotation.annotationId != null)
2004 annotationIds.put(annotation.annotationId, annotation);
2007 an.setId(annotation.annotationId);
2009 an.setVisible(annotation.visible);
2011 an.setDescription(annotation.description);
2013 if (annotation.sequenceRef != null)
2015 // 2.9 JAL-1781 xref on sequence id rather than name
2016 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
2018 if (annotation.groupRef != null)
2020 String groupIdr = groupRefs.get(annotation.groupRef);
2021 if (groupIdr == null)
2023 // make a locally unique String
2024 groupRefs.put(annotation.groupRef,
2025 groupIdr = ("" + System.currentTimeMillis()
2026 + annotation.groupRef.getName()
2027 + groupRefs.size()));
2029 an.setGroupRef(groupIdr.toString());
2032 // store all visualization attributes for annotation
2033 an.setGraphHeight(annotation.graphHeight);
2034 an.setCentreColLabels(annotation.centreColLabels);
2035 an.setScaleColLabels(annotation.scaleColLabel);
2036 an.setShowAllColLabels(annotation.showAllColLabels);
2037 an.setBelowAlignment(annotation.belowAlignment);
2039 if (annotation.graph > 0)
2042 an.setGraphType(annotation.graph);
2043 an.setGraphGroup(annotation.graphGroup);
2044 if (annotation.getThreshold() != null)
2046 ThresholdLine line = new ThresholdLine();
2047 line.setLabel(annotation.getThreshold().label);
2048 line.setValue(annotation.getThreshold().value);
2049 line.setColour(annotation.getThreshold().colour.getRGB());
2050 an.setThresholdLine(line);
2058 an.setLabel(annotation.label);
2060 if (annotation == av.getAlignmentQualityAnnot()
2061 || annotation == av.getAlignmentConservationAnnotation()
2062 || annotation == av.getAlignmentConsensusAnnotation()
2063 || annotation.autoCalculated)
2065 // new way of indicating autocalculated annotation -
2066 an.setAutoCalculated(annotation.autoCalculated);
2068 if (annotation.hasScore())
2070 an.setScore(annotation.getScore());
2073 if (annotation.getCalcId() != null)
2075 calcIdSet.add(annotation.getCalcId());
2076 an.setCalcId(annotation.getCalcId());
2078 if (annotation.hasProperties())
2080 for (String pr : annotation.getProperties())
2082 Property prop = new Property();
2084 prop.setValue(annotation.getProperty(pr));
2085 an.addProperty(prop);
2089 AnnotationElement ae;
2090 if (annotation.annotations != null)
2092 an.setScoreOnly(false);
2093 for (int a = 0; a < annotation.annotations.length; a++)
2095 if ((annotation == null) || (annotation.annotations[a] == null))
2100 ae = new AnnotationElement();
2101 if (annotation.annotations[a].description != null)
2103 ae.setDescription(annotation.annotations[a].description);
2105 if (annotation.annotations[a].displayCharacter != null)
2107 ae.setDisplayCharacter(
2108 annotation.annotations[a].displayCharacter);
2111 if (!Float.isNaN(annotation.annotations[a].value))
2113 ae.setValue(annotation.annotations[a].value);
2117 if (annotation.annotations[a].secondaryStructure > ' ')
2119 ae.setSecondaryStructure(
2120 annotation.annotations[a].secondaryStructure + "");
2123 if (annotation.annotations[a].colour != null
2124 && annotation.annotations[a].colour != java.awt.Color.black)
2126 ae.setColour(annotation.annotations[a].colour.getRGB());
2129 an.addAnnotationElement(ae);
2130 if (annotation.autoCalculated)
2132 // only write one non-null entry into the annotation row -
2133 // sufficient to get the visualization attributes necessary to
2141 an.setScoreOnly(true);
2143 if (!storeDS || (storeDS && !annotation.autoCalculated))
2145 // skip autocalculated annotation - these are only provided for
2147 vamsasSet.addAnnotation(an);
2153 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
2155 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
2156 if (settings != null)
2158 CalcIdParam vCalcIdParam = new CalcIdParam();
2159 vCalcIdParam.setCalcId(calcId);
2160 vCalcIdParam.addServiceURL(settings.getServiceURI());
2161 // generic URI allowing a third party to resolve another instance of the
2162 // service used for this calculation
2163 for (String urls : settings.getServiceURLs())
2165 vCalcIdParam.addServiceURL(urls);
2167 vCalcIdParam.setVersion("1.0");
2168 if (settings.getPreset() != null)
2170 WsParamSetI setting = settings.getPreset();
2171 vCalcIdParam.setName(setting.getName());
2172 vCalcIdParam.setDescription(setting.getDescription());
2176 vCalcIdParam.setName("");
2177 vCalcIdParam.setDescription("Last used parameters");
2179 // need to be able to recover 1) settings 2) user-defined presets or
2180 // recreate settings from preset 3) predefined settings provided by
2181 // service - or settings that can be transferred (or discarded)
2182 vCalcIdParam.setParameters(
2183 settings.getWsParamFile().replace("\n", "|\\n|"));
2184 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
2185 // todo - decide if updateImmediately is needed for any projects.
2187 return vCalcIdParam;
2192 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
2195 if (calcIdParam.getVersion().equals("1.0"))
2197 Jws2Instance service = Jws2Discoverer.getDiscoverer()
2198 .getPreferredServiceFor(calcIdParam.getServiceURL());
2199 if (service != null)
2201 WsParamSetI parmSet = null;
2204 parmSet = service.getParamStore().parseServiceParameterFile(
2205 calcIdParam.getName(), calcIdParam.getDescription(),
2206 calcIdParam.getServiceURL(),
2207 calcIdParam.getParameters().replace("|\\n|", "\n"));
2208 } catch (IOException x)
2210 warn("Couldn't parse parameter data for "
2211 + calcIdParam.getCalcId(), x);
2214 List<ArgumentI> argList = null;
2215 if (calcIdParam.getName().length() > 0)
2217 parmSet = service.getParamStore()
2218 .getPreset(calcIdParam.getName());
2219 if (parmSet != null)
2221 // TODO : check we have a good match with settings in AACon -
2222 // otherwise we'll need to create a new preset
2227 argList = parmSet.getArguments();
2230 AAConSettings settings = new AAConSettings(
2231 calcIdParam.isAutoUpdate(), service, parmSet, argList);
2232 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
2233 calcIdParam.isNeedsUpdate());
2238 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
2242 throw new Error(MessageManager.formatMessage(
2243 "error.unsupported_version_calcIdparam", new Object[]
2244 { calcIdParam.toString() }));
2248 * External mapping between jalview objects and objects yielding a valid and
2249 * unique object ID string. This is null for normal Jalview project IO, but
2250 * non-null when a jalview project is being read or written as part of a
2253 IdentityHashMap jv2vobj = null;
2256 * Construct a unique ID for jvobj using either existing bindings or if none
2257 * exist, the result of the hashcode call for the object.
2260 * jalview data object
2261 * @return unique ID for referring to jvobj
2263 private String makeHashCode(Object jvobj, String altCode)
2265 if (jv2vobj != null)
2267 Object id = jv2vobj.get(jvobj);
2270 return id.toString();
2272 // check string ID mappings
2273 if (jvids2vobj != null && jvobj instanceof String)
2275 id = jvids2vobj.get(jvobj);
2279 return id.toString();
2281 // give up and warn that something has gone wrong
2282 warn("Cannot find ID for object in external mapping : " + jvobj);
2288 * return local jalview object mapped to ID, if it exists
2292 * @return null or object bound to idcode
2294 private Object retrieveExistingObj(String idcode)
2296 if (idcode != null && vobj2jv != null)
2298 return vobj2jv.get(idcode);
2304 * binding from ID strings from external mapping table to jalview data model
2307 private Hashtable vobj2jv;
2309 private Sequence createVamsasSequence(String id, SequenceI jds)
2311 return createVamsasSequence(true, id, jds, null);
2314 private Sequence createVamsasSequence(boolean recurse, String id,
2315 SequenceI jds, SequenceI parentseq)
2317 Sequence vamsasSeq = new Sequence();
2318 vamsasSeq.setId(id);
2319 vamsasSeq.setName(jds.getName());
2320 vamsasSeq.setSequence(jds.getSequenceAsString());
2321 vamsasSeq.setDescription(jds.getDescription());
2322 jalview.datamodel.DBRefEntry[] dbrefs = null;
2323 if (jds.getDatasetSequence() != null)
2325 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
2329 // seqId==dsseqid so we can tell which sequences really are
2330 // dataset sequences only
2331 vamsasSeq.setDsseqid(id);
2332 dbrefs = jds.getDBRefs();
2333 if (parentseq == null)
2340 for (int d = 0; d < dbrefs.length; d++)
2342 DBRef dbref = new DBRef();
2343 dbref.setSource(dbrefs[d].getSource());
2344 dbref.setVersion(dbrefs[d].getVersion());
2345 dbref.setAccessionId(dbrefs[d].getAccessionId());
2346 if (dbrefs[d].hasMap())
2348 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
2350 dbref.setMapping(mp);
2352 vamsasSeq.addDBRef(dbref);
2358 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
2359 SequenceI parentseq, SequenceI jds, boolean recurse)
2362 if (jmp.getMap() != null)
2366 jalview.util.MapList mlst = jmp.getMap();
2367 List<int[]> r = mlst.getFromRanges();
2368 for (int[] range : r)
2370 MapListFrom mfrom = new MapListFrom();
2371 mfrom.setStart(range[0]);
2372 mfrom.setEnd(range[1]);
2373 mp.addMapListFrom(mfrom);
2375 r = mlst.getToRanges();
2376 for (int[] range : r)
2378 MapListTo mto = new MapListTo();
2379 mto.setStart(range[0]);
2380 mto.setEnd(range[1]);
2381 mp.addMapListTo(mto);
2383 mp.setMapFromUnit(mlst.getFromRatio());
2384 mp.setMapToUnit(mlst.getToRatio());
2385 if (jmp.getTo() != null)
2387 MappingChoice mpc = new MappingChoice();
2389 // check/create ID for the sequence referenced by getTo()
2392 SequenceI ps = null;
2393 if (parentseq != jmp.getTo()
2394 && parentseq.getDatasetSequence() != jmp.getTo())
2396 // chaining dbref rather than a handshaking one
2397 jmpid = seqHash(ps = jmp.getTo());
2401 jmpid = seqHash(ps = parentseq);
2403 mpc.setDseqFor(jmpid);
2404 if (!seqRefIds.containsKey(mpc.getDseqFor()))
2406 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2407 seqRefIds.put(mpc.getDseqFor(), ps);
2411 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2414 mp.setMappingChoice(mpc);
2420 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2421 List<UserColourScheme> userColours, JalviewModelSequence jms)
2424 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2425 boolean newucs = false;
2426 if (!userColours.contains(ucs))
2428 userColours.add(ucs);
2431 id = "ucs" + userColours.indexOf(ucs);
2434 // actually create the scheme's entry in the XML model
2435 java.awt.Color[] colours = ucs.getColours();
2436 jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
2437 jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
2439 for (int i = 0; i < colours.length; i++)
2441 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2442 col.setName(ResidueProperties.aa[i]);
2443 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2444 jbucs.addColour(col);
2446 if (ucs.getLowerCaseColours() != null)
2448 colours = ucs.getLowerCaseColours();
2449 for (int i = 0; i < colours.length; i++)
2451 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2452 col.setName(ResidueProperties.aa[i].toLowerCase());
2453 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2454 jbucs.addColour(col);
2459 uc.setUserColourScheme(jbucs);
2460 jms.addUserColours(uc);
2466 jalview.schemes.UserColourScheme getUserColourScheme(
2467 JalviewModelSequence jms, String id)
2469 UserColours[] uc = jms.getUserColours();
2470 UserColours colours = null;
2472 for (int i = 0; i < uc.length; i++)
2474 if (uc[i].getId().equals(id))
2482 java.awt.Color[] newColours = new java.awt.Color[24];
2484 for (int i = 0; i < 24; i++)
2486 newColours[i] = new java.awt.Color(Integer.parseInt(
2487 colours.getUserColourScheme().getColour(i).getRGB(), 16));
2490 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2493 if (colours.getUserColourScheme().getColourCount() > 24)
2495 newColours = new java.awt.Color[23];
2496 for (int i = 0; i < 23; i++)
2498 newColours[i] = new java.awt.Color(Integer.parseInt(
2499 colours.getUserColourScheme().getColour(i + 24).getRGB(),
2502 ucs.setLowerCaseColours(newColours);
2509 * contains last error message (if any) encountered by XML loader.
2511 String errorMessage = null;
2514 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2515 * exceptions are raised during project XML parsing
2517 public boolean attemptversion1parse = true;
2520 * Load a jalview project archive from a jar file
2523 * - HTTP URL or filename
2525 public AlignFrame loadJalviewAlign(final String file)
2528 jalview.gui.AlignFrame af = null;
2532 // create list to store references for any new Jmol viewers created
2533 newStructureViewers = new Vector<>();
2534 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2535 // Workaround is to make sure caller implements the JarInputStreamProvider
2537 // so we can re-open the jar input stream for each entry.
2539 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2540 af = loadJalviewAlign(jprovider);
2541 af.setMenusForViewport();
2543 } catch (MalformedURLException e)
2545 errorMessage = "Invalid URL format for '" + file + "'";
2551 SwingUtilities.invokeAndWait(new Runnable()
2556 setLoadingFinishedForNewStructureViewers();
2559 } catch (Exception x)
2561 System.err.println("Error loading alignment: " + x.getMessage());
2567 private jarInputStreamProvider createjarInputStreamProvider(
2568 final String file) throws MalformedURLException
2571 errorMessage = null;
2572 uniqueSetSuffix = null;
2574 viewportsAdded.clear();
2575 frefedSequence = null;
2577 if (file.startsWith("http://"))
2579 url = new URL(file);
2581 final URL _url = url;
2582 return new jarInputStreamProvider()
2586 public JarInputStream getJarInputStream() throws IOException
2590 return new JarInputStream(_url.openStream());
2594 return new JarInputStream(new FileInputStream(file));
2599 public String getFilename()
2607 * Recover jalview session from a jalview project archive. Caller may
2608 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2609 * themselves. Any null fields will be initialised with default values,
2610 * non-null fields are left alone.
2615 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2617 errorMessage = null;
2618 if (uniqueSetSuffix == null)
2620 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2622 if (seqRefIds == null)
2626 AlignFrame af = null, _af = null;
2627 IdentityHashMap<AlignmentI, AlignmentI> importedDatasets = new IdentityHashMap<>();
2628 Map<String, AlignFrame> gatherToThisFrame = new HashMap<>();
2629 final String file = jprovider.getFilename();
2632 JarInputStream jin = null;
2633 JarEntry jarentry = null;
2638 jin = jprovider.getJarInputStream();
2639 for (int i = 0; i < entryCount; i++)
2641 jarentry = jin.getNextJarEntry();
2644 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2646 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2647 JalviewModel object = new JalviewModel();
2649 Unmarshaller unmar = new Unmarshaller(object);
2650 unmar.setValidation(false);
2651 object = (JalviewModel) unmar.unmarshal(in);
2652 if (true) // !skipViewport(object))
2654 _af = loadFromObject(object, file, true, jprovider);
2655 if (_af != null && object.getJalviewModelSequence()
2656 .getViewportCount() > 0)
2660 // store a reference to the first view
2663 if (_af.viewport.isGatherViewsHere())
2665 // if this is a gathered view, keep its reference since
2666 // after gathering views, only this frame will remain
2668 gatherToThisFrame.put(_af.viewport.getSequenceSetId(), _af);
2670 // Save dataset to register mappings once all resolved
2671 importedDatasets.put(af.viewport.getAlignment().getDataset(),
2672 af.viewport.getAlignment().getDataset());
2677 else if (jarentry != null)
2679 // Some other file here.
2682 } while (jarentry != null);
2683 resolveFrefedSequences();
2684 } catch (IOException ex)
2686 ex.printStackTrace();
2687 errorMessage = "Couldn't locate Jalview XML file : " + file;
2689 "Exception whilst loading jalview XML file : " + ex + "\n");
2690 } catch (Exception ex)
2692 System.err.println("Parsing as Jalview Version 2 file failed.");
2693 ex.printStackTrace(System.err);
2694 if (attemptversion1parse)
2696 // Is Version 1 Jar file?
2699 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
2700 } catch (Exception ex2)
2702 System.err.println("Exception whilst loading as jalviewXMLV1:");
2703 ex2.printStackTrace();
2707 if (Desktop.instance != null)
2709 Desktop.instance.stopLoading();
2713 System.out.println("Successfully loaded archive file");
2716 ex.printStackTrace();
2719 "Exception whilst loading jalview XML file : " + ex + "\n");
2720 } catch (OutOfMemoryError e)
2722 // Don't use the OOM Window here
2723 errorMessage = "Out of memory loading jalview XML file";
2724 System.err.println("Out of memory whilst loading jalview XML file");
2725 e.printStackTrace();
2729 * Regather multiple views (with the same sequence set id) to the frame (if
2730 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2731 * views instead of separate frames. Note this doesn't restore a state where
2732 * some expanded views in turn have tabbed views - the last "first tab" read
2733 * in will play the role of gatherer for all.
2735 for (AlignFrame fr : gatherToThisFrame.values())
2737 Desktop.instance.gatherViews(fr);
2740 restoreSplitFrames();
2741 for (AlignmentI ds : importedDatasets.keySet())
2743 if (ds.getCodonFrames() != null)
2745 StructureSelectionManager
2746 .getStructureSelectionManager(Desktop.instance)
2747 .registerMappings(ds.getCodonFrames());
2750 if (errorMessage != null)
2755 if (Desktop.instance != null)
2757 Desktop.instance.stopLoading();
2764 * Try to reconstruct and display SplitFrame windows, where each contains
2765 * complementary dna and protein alignments. Done by pairing up AlignFrame
2766 * objects (created earlier) which have complementary viewport ids associated.
2768 protected void restoreSplitFrames()
2770 List<SplitFrame> gatherTo = new ArrayList<>();
2771 List<AlignFrame> addedToSplitFrames = new ArrayList<>();
2772 Map<String, AlignFrame> dna = new HashMap<>();
2775 * Identify the DNA alignments
2777 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2780 AlignFrame af = candidate.getValue();
2781 if (af.getViewport().getAlignment().isNucleotide())
2783 dna.put(candidate.getKey().getId(), af);
2788 * Try to match up the protein complements
2790 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2793 AlignFrame af = candidate.getValue();
2794 if (!af.getViewport().getAlignment().isNucleotide())
2796 String complementId = candidate.getKey().getComplementId();
2797 // only non-null complements should be in the Map
2798 if (complementId != null && dna.containsKey(complementId))
2800 final AlignFrame dnaFrame = dna.get(complementId);
2801 SplitFrame sf = createSplitFrame(dnaFrame, af);
2802 addedToSplitFrames.add(dnaFrame);
2803 addedToSplitFrames.add(af);
2804 dnaFrame.setMenusForViewport();
2805 af.setMenusForViewport();
2806 if (af.viewport.isGatherViewsHere())
2815 * Open any that we failed to pair up (which shouldn't happen!) as
2816 * standalone AlignFrame's.
2818 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2821 AlignFrame af = candidate.getValue();
2822 if (!addedToSplitFrames.contains(af))
2824 Viewport view = candidate.getKey();
2825 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
2827 af.setMenusForViewport();
2828 System.err.println("Failed to restore view " + view.getTitle()
2829 + " to split frame");
2834 * Gather back into tabbed views as flagged.
2836 for (SplitFrame sf : gatherTo)
2838 Desktop.instance.gatherViews(sf);
2841 splitFrameCandidates.clear();
2845 * Construct and display one SplitFrame holding DNA and protein alignments.
2848 * @param proteinFrame
2851 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
2852 AlignFrame proteinFrame)
2854 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
2855 String title = MessageManager.getString("label.linked_view_title");
2856 int width = (int) dnaFrame.getBounds().getWidth();
2857 int height = (int) (dnaFrame.getBounds().getHeight()
2858 + proteinFrame.getBounds().getHeight() + 50);
2861 * SplitFrame location is saved to both enclosed frames
2863 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
2864 Desktop.addInternalFrame(splitFrame, title, width, height);
2867 * And compute cDNA consensus (couldn't do earlier with consensus as
2868 * mappings were not yet present)
2870 proteinFrame.viewport.alignmentChanged(proteinFrame.alignPanel);
2876 * check errorMessage for a valid error message and raise an error box in the
2877 * GUI or write the current errorMessage to stderr and then clear the error
2880 protected void reportErrors()
2882 reportErrors(false);
2885 protected void reportErrors(final boolean saving)
2887 if (errorMessage != null)
2889 final String finalErrorMessage = errorMessage;
2892 javax.swing.SwingUtilities.invokeLater(new Runnable()
2897 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2899 "Error " + (saving ? "saving" : "loading")
2901 JvOptionPane.WARNING_MESSAGE);
2907 System.err.println("Problem loading Jalview file: " + errorMessage);
2910 errorMessage = null;
2913 Map<String, String> alreadyLoadedPDB = new HashMap<>();
2916 * when set, local views will be updated from view stored in JalviewXML
2917 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2918 * sync if this is set to true.
2920 private final boolean updateLocalViews = false;
2923 * Returns the path to a temporary file holding the PDB file for the given PDB
2924 * id. The first time of asking, searches for a file of that name in the
2925 * Jalview project jar, and copies it to a new temporary file. Any repeat
2926 * requests just return the path to the file previously created.
2932 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId,
2935 if (alreadyLoadedPDB.containsKey(pdbId))
2937 return alreadyLoadedPDB.get(pdbId).toString();
2940 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb",
2942 if (tempFile != null)
2944 alreadyLoadedPDB.put(pdbId, tempFile);
2950 * Copies the jar entry of given name to a new temporary file and returns the
2951 * path to the file, or null if the entry is not found.
2954 * @param jarEntryName
2956 * a prefix for the temporary file name, must be at least three
2959 * null or original file - so new file can be given the same suffix
2963 protected String copyJarEntry(jarInputStreamProvider jprovider,
2964 String jarEntryName, String prefix, String origFile)
2966 BufferedReader in = null;
2967 PrintWriter out = null;
2968 String suffix = ".tmp";
2969 if (origFile == null)
2971 origFile = jarEntryName;
2973 int sfpos = origFile.lastIndexOf(".");
2974 if (sfpos > -1 && sfpos < (origFile.length() - 3))
2976 suffix = "." + origFile.substring(sfpos + 1);
2980 JarInputStream jin = jprovider.getJarInputStream();
2982 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2983 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2984 * FileInputStream(jprovider)); }
2987 JarEntry entry = null;
2990 entry = jin.getNextJarEntry();
2991 } while (entry != null && !entry.getName().equals(jarEntryName));
2994 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
2995 File outFile = File.createTempFile(prefix, suffix);
2996 outFile.deleteOnExit();
2997 out = new PrintWriter(new FileOutputStream(outFile));
3000 while ((data = in.readLine()) != null)
3005 String t = outFile.getAbsolutePath();
3010 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
3012 } catch (Exception ex)
3014 ex.printStackTrace();
3022 } catch (IOException e)
3036 private class JvAnnotRow
3038 public JvAnnotRow(int i, AlignmentAnnotation jaa)
3045 * persisted version of annotation row from which to take vis properties
3047 public jalview.datamodel.AlignmentAnnotation template;
3050 * original position of the annotation row in the alignment
3056 * Load alignment frame from jalview XML DOM object
3061 * filename source string
3062 * @param loadTreesAndStructures
3063 * when false only create Viewport
3065 * data source provider
3066 * @return alignment frame created from view stored in DOM
3068 AlignFrame loadFromObject(JalviewModel object, String file,
3069 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
3071 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
3072 Sequence[] vamsasSeq = vamsasSet.getSequence();
3074 JalviewModelSequence jms = object.getJalviewModelSequence();
3076 Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
3079 // ////////////////////////////////
3080 // INITIALISE ALIGNMENT SEQUENCESETID AND VIEWID
3083 // If we just load in the same jar file again, the sequenceSetId
3084 // will be the same, and we end up with multiple references
3085 // to the same sequenceSet. We must modify this id on load
3086 // so that each load of the file gives a unique id
3089 * used to resolve correct alignment dataset for alignments with multiple
3092 String uniqueSeqSetId = null;
3093 String viewId = null;
3096 uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3097 viewId = (view.getId() == null ? null
3098 : view.getId() + uniqueSetSuffix);
3101 // ////////////////////////////////
3104 List<SequenceI> hiddenSeqs = null;
3106 List<SequenceI> tmpseqs = new ArrayList<>();
3108 boolean multipleView = false;
3109 SequenceI referenceseqForView = null;
3110 JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
3111 int vi = 0; // counter in vamsasSeq array
3112 for (int i = 0; i < jseqs.length; i++)
3114 String seqId = jseqs[i].getId();
3116 SequenceI tmpSeq = seqRefIds.get(seqId);
3119 if (!incompleteSeqs.containsKey(seqId))
3121 // may not need this check, but keep it for at least 2.9,1 release
3122 if (tmpSeq.getStart() != jseqs[i].getStart()
3123 || tmpSeq.getEnd() != jseqs[i].getEnd())
3126 "Warning JAL-2154 regression: updating start/end for sequence "
3127 + tmpSeq.toString() + " to " + jseqs[i]);
3132 incompleteSeqs.remove(seqId);
3134 if (vamsasSeq.length > vi && vamsasSeq[vi].getId().equals(seqId))
3136 // most likely we are reading a dataset XML document so
3137 // update from vamsasSeq section of XML for this sequence
3138 tmpSeq.setName(vamsasSeq[vi].getName());
3139 tmpSeq.setDescription(vamsasSeq[vi].getDescription());
3140 tmpSeq.setSequence(vamsasSeq[vi].getSequence());
3145 // reading multiple views, so vamsasSeq set is a subset of JSeq
3146 multipleView = true;
3148 tmpSeq.setStart(jseqs[i].getStart());
3149 tmpSeq.setEnd(jseqs[i].getEnd());
3150 tmpseqs.add(tmpSeq);
3154 tmpSeq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
3155 vamsasSeq[vi].getSequence());
3156 tmpSeq.setDescription(vamsasSeq[vi].getDescription());
3157 tmpSeq.setStart(jseqs[i].getStart());
3158 tmpSeq.setEnd(jseqs[i].getEnd());
3159 tmpSeq.setVamsasId(uniqueSetSuffix + seqId);
3160 seqRefIds.put(vamsasSeq[vi].getId(), tmpSeq);
3161 tmpseqs.add(tmpSeq);
3165 if (jseqs[i].hasViewreference() && jseqs[i].getViewreference())
3167 referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
3170 if (jseqs[i].getHidden())
3172 if (hiddenSeqs == null)
3174 hiddenSeqs = new ArrayList<>();
3177 hiddenSeqs.add(tmpSeq);
3182 // Create the alignment object from the sequence set
3183 // ///////////////////////////////
3184 SequenceI[] orderedSeqs = tmpseqs
3185 .toArray(new SequenceI[tmpseqs.size()]);
3187 AlignmentI al = null;
3188 // so we must create or recover the dataset alignment before going further
3189 // ///////////////////////////////
3190 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
3192 // older jalview projects do not have a dataset - so creat alignment and
3194 al = new Alignment(orderedSeqs);
3195 al.setDataset(null);
3199 boolean isdsal = object.getJalviewModelSequence()
3200 .getViewportCount() == 0;
3203 // we are importing a dataset record, so
3204 // recover reference to an alignment already materialsed as dataset
3205 al = getDatasetFor(vamsasSet.getDatasetId());
3209 // materialse the alignment
3210 al = new Alignment(orderedSeqs);
3214 addDatasetRef(vamsasSet.getDatasetId(), al);
3217 // finally, verify all data in vamsasSet is actually present in al
3218 // passing on flag indicating if it is actually a stored dataset
3219 recoverDatasetFor(vamsasSet, al, isdsal, uniqueSeqSetId);
3222 if (referenceseqForView != null)
3224 al.setSeqrep(referenceseqForView);
3226 // / Add the alignment properties
3227 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
3229 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
3230 al.setProperty(ssp.getKey(), ssp.getValue());
3233 // ///////////////////////////////
3235 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
3238 // load sequence features, database references and any associated PDB
3239 // structures for the alignment
3241 // prior to 2.10, this part would only be executed the first time a
3242 // sequence was encountered, but not afterwards.
3243 // now, for 2.10 projects, this is also done if the xml doc includes
3244 // dataset sequences not actually present in any particular view.
3246 for (int i = 0; i < vamsasSeq.length; i++)
3248 if (jseqs[i].getFeaturesCount() > 0)
3250 Features[] features = jseqs[i].getFeatures();
3251 for (int f = 0; f < features.length; f++)
3253 SequenceFeature sf = new SequenceFeature(features[f].getType(),
3254 features[f].getDescription(), features[f].getBegin(),
3255 features[f].getEnd(), features[f].getScore(),
3256 features[f].getFeatureGroup());
3257 sf.setStatus(features[f].getStatus());
3260 * load any feature attributes - include map-valued attributes
3262 Map<String, Map<String, String>> mapAttributes = new HashMap<>();
3263 for (int od = 0; od < features[f].getOtherDataCount(); od++)
3265 OtherData keyValue = features[f].getOtherData(od);
3266 String attributeName = keyValue.getKey();
3267 String attributeValue = keyValue.getValue();
3268 if (attributeName.startsWith("LINK"))
3270 sf.addLink(attributeValue);
3274 String subAttribute = keyValue.getKey2();
3275 if (subAttribute == null)
3277 // simple string-valued attribute
3278 sf.setValue(attributeName, attributeValue);
3282 // attribute 'key' has sub-attribute 'key2'
3283 if (!mapAttributes.containsKey(attributeName))
3285 mapAttributes.put(attributeName, new HashMap<>());
3287 mapAttributes.get(attributeName).put(subAttribute,
3292 for (Entry<String, Map<String, String>> mapAttribute : mapAttributes
3295 sf.setValue(mapAttribute.getKey(), mapAttribute.getValue());
3298 // adds feature to datasequence's feature set (since Jalview 2.10)
3299 al.getSequenceAt(i).addSequenceFeature(sf);
3302 if (vamsasSeq[i].getDBRefCount() > 0)
3304 // adds dbrefs to datasequence's set (since Jalview 2.10)
3306 al.getSequenceAt(i).getDatasetSequence() == null
3307 ? al.getSequenceAt(i)
3308 : al.getSequenceAt(i).getDatasetSequence(),
3311 if (jseqs[i].getPdbidsCount() > 0)
3313 Pdbids[] ids = jseqs[i].getPdbids();
3314 for (int p = 0; p < ids.length; p++)
3316 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
3317 entry.setId(ids[p].getId());
3318 if (ids[p].getType() != null)
3320 if (PDBEntry.Type.getType(ids[p].getType()) != null)
3322 entry.setType(PDBEntry.Type.getType(ids[p].getType()));
3326 entry.setType(PDBEntry.Type.FILE);
3329 // jprovider is null when executing 'New View'
3330 if (ids[p].getFile() != null && jprovider != null)
3332 if (!pdbloaded.containsKey(ids[p].getFile()))
3334 entry.setFile(loadPDBFile(jprovider, ids[p].getId(),
3339 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
3342 if (ids[p].getPdbentryItem() != null)
3344 for (PdbentryItem item : ids[p].getPdbentryItem())
3346 for (Property pr : item.getProperty())
3348 entry.setProperty(pr.getName(), pr.getValue());
3352 StructureSelectionManager
3353 .getStructureSelectionManager(Desktop.instance)
3354 .registerPDBEntry(entry);
3355 // adds PDBEntry to datasequence's set (since Jalview 2.10)
3356 if (al.getSequenceAt(i).getDatasetSequence() != null)
3358 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
3362 al.getSequenceAt(i).addPDBId(entry);
3367 } // end !multipleview
3369 // ///////////////////////////////
3370 // LOAD SEQUENCE MAPPINGS
3372 if (vamsasSet.getAlcodonFrameCount() > 0)
3374 // TODO Potentially this should only be done once for all views of an
3376 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
3377 for (int i = 0; i < alc.length; i++)
3379 AlignedCodonFrame cf = new AlignedCodonFrame();
3380 if (alc[i].getAlcodMapCount() > 0)
3382 AlcodMap[] maps = alc[i].getAlcodMap();
3383 for (int m = 0; m < maps.length; m++)
3385 SequenceI dnaseq = seqRefIds.get(maps[m].getDnasq());
3387 jalview.datamodel.Mapping mapping = null;
3388 // attach to dna sequence reference.
3389 if (maps[m].getMapping() != null)
3391 mapping = addMapping(maps[m].getMapping());
3392 if (dnaseq != null && mapping.getTo() != null)
3394 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
3400 newAlcodMapRef(maps[m].getDnasq(), cf, mapping));
3404 al.addCodonFrame(cf);
3409 // ////////////////////////////////
3411 List<JvAnnotRow> autoAlan = new ArrayList<>();
3414 * store any annotations which forward reference a group's ID
3416 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<>();
3418 if (vamsasSet.getAnnotationCount() > 0)
3420 Annotation[] an = vamsasSet.getAnnotation();
3422 for (int i = 0; i < an.length; i++)
3424 Annotation annotation = an[i];
3427 * test if annotation is automatically calculated for this view only
3429 boolean autoForView = false;
3430 if (annotation.getLabel().equals("Quality")
3431 || annotation.getLabel().equals("Conservation")
3432 || annotation.getLabel().equals("Consensus"))
3434 // Kludge for pre 2.5 projects which lacked the autocalculated flag
3436 if (!annotation.hasAutoCalculated())
3438 annotation.setAutoCalculated(true);
3441 if (autoForView || (annotation.hasAutoCalculated()
3442 && annotation.isAutoCalculated()))
3444 // remove ID - we don't recover annotation from other views for
3445 // view-specific annotation
3446 annotation.setId(null);
3449 // set visiblity for other annotation in this view
3450 String annotationId = annotation.getId();
3451 if (annotationId != null && annotationIds.containsKey(annotationId))
3453 AlignmentAnnotation jda = annotationIds.get(annotationId);
3454 // in principle Visible should always be true for annotation displayed
3455 // in multiple views
3456 if (annotation.hasVisible())
3458 jda.visible = annotation.getVisible();
3461 al.addAnnotation(jda);
3465 // Construct new annotation from model.
3466 AnnotationElement[] ae = annotation.getAnnotationElement();
3467 jalview.datamodel.Annotation[] anot = null;
3468 java.awt.Color firstColour = null;
3470 if (!annotation.getScoreOnly())
3472 anot = new jalview.datamodel.Annotation[al.getWidth()];
3473 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
3475 anpos = ae[aa].getPosition();
3477 if (anpos >= anot.length)
3482 anot[anpos] = new jalview.datamodel.Annotation(
3484 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
3485 (ae[aa].getSecondaryStructure() == null
3486 || ae[aa].getSecondaryStructure().length() == 0)
3488 : ae[aa].getSecondaryStructure()
3493 // JBPNote: Consider verifying dataflow for IO of secondary
3494 // structure annotation read from Stockholm files
3495 // this was added to try to ensure that
3496 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
3498 // anot[ae[aa].getPosition()].displayCharacter = "";
3500 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
3501 if (firstColour == null)
3503 firstColour = anot[anpos].colour;
3507 jalview.datamodel.AlignmentAnnotation jaa = null;
3509 if (annotation.getGraph())
3511 float llim = 0, hlim = 0;
3512 // if (autoForView || an[i].isAutoCalculated()) {
3515 jaa = new jalview.datamodel.AlignmentAnnotation(
3516 annotation.getLabel(), annotation.getDescription(), anot,
3517 llim, hlim, annotation.getGraphType());
3519 jaa.graphGroup = annotation.getGraphGroup();
3520 jaa._linecolour = firstColour;
3521 if (annotation.getThresholdLine() != null)
3523 jaa.setThreshold(new jalview.datamodel.GraphLine(
3524 annotation.getThresholdLine().getValue(),
3525 annotation.getThresholdLine().getLabel(),
3527 annotation.getThresholdLine().getColour())));
3530 if (autoForView || annotation.isAutoCalculated())
3532 // Hardwire the symbol display line to ensure that labels for
3533 // histograms are displayed
3539 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
3540 an[i].getDescription(), anot);
3541 jaa._linecolour = firstColour;
3543 // register new annotation
3544 if (an[i].getId() != null)
3546 annotationIds.put(an[i].getId(), jaa);
3547 jaa.annotationId = an[i].getId();
3549 // recover sequence association
3550 String sequenceRef = an[i].getSequenceRef();
3551 if (sequenceRef != null)
3553 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3554 SequenceI sequence = seqRefIds.get(sequenceRef);
3555 if (sequence == null)
3557 // in pre-2.9 projects sequence ref is to sequence name
3558 sequence = al.findName(sequenceRef);
3560 if (sequence != null)
3562 jaa.createSequenceMapping(sequence, 1, true);
3563 sequence.addAlignmentAnnotation(jaa);
3566 // and make a note of any group association
3567 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
3569 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3570 .get(an[i].getGroupRef());
3573 aal = new ArrayList<>();
3574 groupAnnotRefs.put(an[i].getGroupRef(), aal);
3579 if (an[i].hasScore())
3581 jaa.setScore(an[i].getScore());
3583 if (an[i].hasVisible())
3585 jaa.visible = an[i].getVisible();
3588 if (an[i].hasCentreColLabels())
3590 jaa.centreColLabels = an[i].getCentreColLabels();
3593 if (an[i].hasScaleColLabels())
3595 jaa.scaleColLabel = an[i].getScaleColLabels();
3597 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
3599 // newer files have an 'autoCalculated' flag and store calculation
3600 // state in viewport properties
3601 jaa.autoCalculated = true; // means annotation will be marked for
3602 // update at end of load.
3604 if (an[i].hasGraphHeight())
3606 jaa.graphHeight = an[i].getGraphHeight();
3608 if (an[i].hasBelowAlignment())
3610 jaa.belowAlignment = an[i].isBelowAlignment();
3612 jaa.setCalcId(an[i].getCalcId());
3613 if (an[i].getPropertyCount() > 0)
3615 for (jalview.schemabinding.version2.Property prop : an[i]
3618 jaa.setProperty(prop.getName(), prop.getValue());
3621 if (jaa.autoCalculated)
3623 autoAlan.add(new JvAnnotRow(i, jaa));
3626 // if (!autoForView)
3628 // add autocalculated group annotation and any user created annotation
3630 al.addAnnotation(jaa);
3634 // ///////////////////////
3636 // Create alignment markup and styles for this view
3637 if (jms.getJGroupCount() > 0)
3639 JGroup[] groups = jms.getJGroup();
3640 boolean addAnnotSchemeGroup = false;
3641 for (int i = 0; i < groups.length; i++)
3643 JGroup jGroup = groups[i];
3644 ColourSchemeI cs = null;
3645 if (jGroup.getColour() != null)
3647 if (jGroup.getColour().startsWith("ucs"))
3649 cs = getUserColourScheme(jms, jGroup.getColour());
3651 else if (jGroup.getColour().equals("AnnotationColourGradient")
3652 && jGroup.getAnnotationColours() != null)
3654 addAnnotSchemeGroup = true;
3658 cs = ColourSchemeProperty.getColourScheme(al,
3659 jGroup.getColour());
3662 int pidThreshold = jGroup.getPidThreshold();
3664 Vector<SequenceI> seqs = new Vector<>();
3666 for (int s = 0; s < jGroup.getSeqCount(); s++)
3668 String seqId = jGroup.getSeq(s) + "";
3669 SequenceI ts = seqRefIds.get(seqId);
3673 seqs.addElement(ts);
3677 if (seqs.size() < 1)
3682 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3683 jGroup.getDisplayBoxes(), jGroup.getDisplayText(),
3684 jGroup.getColourText(), jGroup.getStart(), jGroup.getEnd());
3685 sg.getGroupColourScheme().setThreshold(pidThreshold, true);
3686 sg.getGroupColourScheme()
3687 .setConservationInc(jGroup.getConsThreshold());
3688 sg.setOutlineColour(new java.awt.Color(jGroup.getOutlineColour()));
3690 sg.textColour = new java.awt.Color(jGroup.getTextCol1());
3691 sg.textColour2 = new java.awt.Color(jGroup.getTextCol2());
3692 sg.setShowNonconserved(
3693 jGroup.hasShowUnconserved() ? jGroup.isShowUnconserved()
3695 sg.thresholdTextColour = jGroup.getTextColThreshold();
3696 if (jGroup.hasShowConsensusHistogram())
3698 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3701 if (jGroup.hasShowSequenceLogo())
3703 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3705 if (jGroup.hasNormaliseSequenceLogo())
3707 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3709 if (jGroup.hasIgnoreGapsinConsensus())
3711 sg.setIgnoreGapsConsensus(jGroup.getIgnoreGapsinConsensus());
3713 if (jGroup.getConsThreshold() != 0)
3715 Conservation c = new Conservation("All", sg.getSequences(null), 0,
3718 c.verdict(false, 25);
3719 sg.cs.setConservation(c);
3722 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3724 // re-instate unique group/annotation row reference
3725 List<AlignmentAnnotation> jaal = groupAnnotRefs
3726 .get(jGroup.getId());
3729 for (AlignmentAnnotation jaa : jaal)
3732 if (jaa.autoCalculated)
3734 // match up and try to set group autocalc alignment row for this
3736 if (jaa.label.startsWith("Consensus for "))
3738 sg.setConsensus(jaa);
3740 // match up and try to set group autocalc alignment row for this
3742 if (jaa.label.startsWith("Conservation for "))
3744 sg.setConservationRow(jaa);
3751 if (addAnnotSchemeGroup)
3753 // reconstruct the annotation colourscheme
3754 sg.setColourScheme(constructAnnotationColour(
3755 jGroup.getAnnotationColours(), null, al, jms, false));
3761 // only dataset in this model, so just return.
3764 // ///////////////////////////////
3767 AlignFrame af = null;
3768 AlignViewport av = null;
3769 // now check to see if we really need to create a new viewport.
3770 if (multipleView && viewportsAdded.size() == 0)
3772 // We recovered an alignment for which a viewport already exists.
3773 // TODO: fix up any settings necessary for overlaying stored state onto
3774 // state recovered from another document. (may not be necessary).
3775 // we may need a binding from a viewport in memory to one recovered from
3777 // and then recover its containing af to allow the settings to be applied.
3778 // TODO: fix for vamsas demo
3780 "About to recover a viewport for existing alignment: Sequence set ID is "
3782 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3783 if (seqsetobj != null)
3785 if (seqsetobj instanceof String)
3787 uniqueSeqSetId = (String) seqsetobj;
3789 "Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
3795 "Warning : Collision between sequence set ID string and existing jalview object mapping.");
3801 * indicate that annotation colours are applied across all groups (pre
3802 * Jalview 2.8.1 behaviour)
3804 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan("2.8.1",
3805 object.getVersion());
3807 AlignmentPanel ap = null;
3808 boolean isnewview = true;
3811 // Check to see if this alignment already has a view id == viewId
3812 jalview.gui.AlignmentPanel views[] = Desktop
3813 .getAlignmentPanels(uniqueSeqSetId);
3814 if (views != null && views.length > 0)
3816 for (int v = 0; v < views.length; v++)
3818 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
3820 // recover the existing alignpanel, alignframe, viewport
3821 af = views[v].alignFrame;
3824 // TODO: could even skip resetting view settings if we don't want to
3825 // change the local settings from other jalview processes
3834 af = loadViewport(file, jseqs, hiddenSeqs, al, jms, view,
3835 uniqueSeqSetId, viewId, autoAlan);
3841 * Load any trees, PDB structures and viewers
3843 * Not done if flag is false (when this method is used for New View)
3845 if (loadTreesAndStructures)
3847 loadTrees(jms, view, af, av, ap);
3848 loadPCAViewers(jms, ap);
3849 loadPDBStructures(jprovider, jseqs, af, ap);
3850 loadRnaViewers(jprovider, jseqs, ap);
3852 // and finally return.
3857 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
3858 * panel is restored from separate jar entries, two (gapped and trimmed) per
3859 * sequence and secondary structure.
3861 * Currently each viewer shows just one sequence and structure (gapped and
3862 * trimmed), however this method is designed to support multiple sequences or
3863 * structures in viewers if wanted in future.
3869 private void loadRnaViewers(jarInputStreamProvider jprovider,
3870 JSeq[] jseqs, AlignmentPanel ap)
3873 * scan the sequences for references to viewers; create each one the first
3874 * time it is referenced, add Rna models to existing viewers
3876 for (JSeq jseq : jseqs)
3878 for (int i = 0; i < jseq.getRnaViewerCount(); i++)
3880 RnaViewer viewer = jseq.getRnaViewer(i);
3881 AppVarna appVarna = findOrCreateVarnaViewer(viewer, uniqueSetSuffix,
3884 for (int j = 0; j < viewer.getSecondaryStructureCount(); j++)
3886 SecondaryStructure ss = viewer.getSecondaryStructure(j);
3887 SequenceI seq = seqRefIds.get(jseq.getId());
3888 AlignmentAnnotation ann = this.annotationIds
3889 .get(ss.getAnnotationId());
3892 * add the structure to the Varna display (with session state copied
3893 * from the jar to a temporary file)
3895 boolean gapped = ss.isGapped();
3896 String rnaTitle = ss.getTitle();
3897 String sessionState = ss.getViewerState();
3898 String tempStateFile = copyJarEntry(jprovider, sessionState,
3900 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
3901 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
3903 appVarna.setInitialSelection(viewer.getSelectedRna());
3909 * Locate and return an already instantiated matching AppVarna, or create one
3913 * @param viewIdSuffix
3917 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
3918 String viewIdSuffix, AlignmentPanel ap)
3921 * on each load a suffix is appended to the saved viewId, to avoid conflicts
3922 * if load is repeated
3924 String postLoadId = viewer.getViewId() + viewIdSuffix;
3925 for (JInternalFrame frame : getAllFrames())
3927 if (frame instanceof AppVarna)
3929 AppVarna varna = (AppVarna) frame;
3930 if (postLoadId.equals(varna.getViewId()))
3932 // this viewer is already instantiated
3933 // could in future here add ap as another 'parent' of the
3934 // AppVarna window; currently just 1-to-many
3941 * viewer not found - make it
3943 RnaViewerModel model = new RnaViewerModel(postLoadId, viewer.getTitle(),
3944 viewer.getXpos(), viewer.getYpos(), viewer.getWidth(),
3945 viewer.getHeight(), viewer.getDividerLocation());
3946 AppVarna varna = new AppVarna(model, ap);
3952 * Load any saved trees
3960 protected void loadTrees(JalviewModelSequence jms, Viewport view,
3961 AlignFrame af, AlignViewport av, AlignmentPanel ap)
3963 // TODO result of automated refactoring - are all these parameters needed?
3966 for (int t = 0; t < jms.getTreeCount(); t++)
3969 Tree tree = jms.getTree(t);
3971 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
3974 tp = af.showNewickTree(
3975 new jalview.io.NewickFile(tree.getNewick()),
3976 tree.getTitle(), tree.getWidth(), tree.getHeight(),
3977 tree.getXpos(), tree.getYpos());
3978 if (tree.getId() != null)
3980 // perhaps bind the tree id to something ?
3985 // update local tree attributes ?
3986 // TODO: should check if tp has been manipulated by user - if so its
3987 // settings shouldn't be modified
3988 tp.setTitle(tree.getTitle());
3989 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(),
3990 tree.getWidth(), tree.getHeight()));
3991 tp.setViewport(av); // af.viewport; // TODO: verify 'associate with all
3994 tp.getTreeCanvas().setViewport(av); // af.viewport;
3995 tp.getTreeCanvas().setAssociatedPanel(ap); // af.alignPanel;
3999 warn("There was a problem recovering stored Newick tree: \n"
4000 + tree.getNewick());
4004 tp.fitToWindow.setState(tree.getFitToWindow());
4005 tp.fitToWindow_actionPerformed(null);
4007 if (tree.getFontName() != null)
4009 tp.setTreeFont(new java.awt.Font(tree.getFontName(),
4010 tree.getFontStyle(), tree.getFontSize()));
4014 tp.setTreeFont(new java.awt.Font(view.getFontName(),
4015 view.getFontStyle(), tree.getFontSize()));
4018 tp.showPlaceholders(tree.getMarkUnlinked());
4019 tp.showBootstrap(tree.getShowBootstrap());
4020 tp.showDistances(tree.getShowDistances());
4022 tp.getTreeCanvas().setThreshold(tree.getThreshold());
4023 tp.getTreeCanvas().applyToAllViews = tree.isLinkToAllViews();
4025 if (tree.getCurrentTree())
4027 af.viewport.setCurrentTree(tp.getTree());
4031 } catch (Exception ex)
4033 ex.printStackTrace();
4038 * Load and link any saved structure viewers.
4045 protected void loadPDBStructures(jarInputStreamProvider jprovider,
4046 JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
4049 * Run through all PDB ids on the alignment, and collect mappings between
4050 * distinct view ids and all sequences referring to that view.
4052 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<>();
4054 for (int i = 0; i < jseqs.length; i++)
4056 if (jseqs[i].getPdbidsCount() > 0)
4058 Pdbids[] ids = jseqs[i].getPdbids();
4059 for (int p = 0; p < ids.length; p++)
4061 final int structureStateCount = ids[p].getStructureStateCount();
4062 for (int s = 0; s < structureStateCount; s++)
4064 // check to see if we haven't already created this structure view
4065 final StructureState structureState = ids[p]
4066 .getStructureState(s);
4067 String sviewid = (structureState.getViewId() == null) ? null
4068 : structureState.getViewId() + uniqueSetSuffix;
4069 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
4070 // Originally : ids[p].getFile()
4071 // : TODO: verify external PDB file recovery still works in normal
4072 // jalview project load
4073 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId(),
4075 jpdb.setId(ids[p].getId());
4077 int x = structureState.getXpos();
4078 int y = structureState.getYpos();
4079 int width = structureState.getWidth();
4080 int height = structureState.getHeight();
4082 // Probably don't need to do this anymore...
4083 // Desktop.desktop.getComponentAt(x, y);
4084 // TODO: NOW: check that this recovers the PDB file correctly.
4085 String pdbFile = loadPDBFile(jprovider, ids[p].getId(),
4087 jalview.datamodel.SequenceI seq = seqRefIds
4088 .get(jseqs[i].getId() + "");
4089 if (sviewid == null)
4091 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width + ","
4094 if (!structureViewers.containsKey(sviewid))
4096 structureViewers.put(sviewid,
4097 new StructureViewerModel(x, y, width, height, false,
4098 false, true, structureState.getViewId(),
4099 structureState.getType()));
4100 // Legacy pre-2.7 conversion JAL-823 :
4101 // do not assume any view has to be linked for colour by
4105 // assemble String[] { pdb files }, String[] { id for each
4106 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
4107 // seqs_file 2}, boolean[] {
4108 // linkAlignPanel,superposeWithAlignpanel}} from hash
4109 StructureViewerModel jmoldat = structureViewers.get(sviewid);
4110 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
4111 | (structureState.hasAlignwithAlignPanel()
4112 ? structureState.getAlignwithAlignPanel()
4116 * Default colour by linked panel to false if not specified (e.g.
4117 * for pre-2.7 projects)
4119 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
4120 colourWithAlignPanel |= (structureState
4121 .hasColourwithAlignPanel()
4122 ? structureState.getColourwithAlignPanel()
4124 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
4127 * Default colour by viewer to true if not specified (e.g. for
4130 boolean colourByViewer = jmoldat.isColourByViewer();
4131 colourByViewer &= structureState.hasColourByJmol()
4132 ? structureState.getColourByJmol()
4134 jmoldat.setColourByViewer(colourByViewer);
4136 if (jmoldat.getStateData().length() < structureState
4137 .getContent().length())
4140 jmoldat.setStateData(structureState.getContent());
4143 if (ids[p].getFile() != null)
4145 File mapkey = new File(ids[p].getFile());
4146 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
4147 if (seqstrmaps == null)
4149 jmoldat.getFileData().put(mapkey,
4150 seqstrmaps = jmoldat.new StructureData(pdbFile,
4153 if (!seqstrmaps.getSeqList().contains(seq))
4155 seqstrmaps.getSeqList().add(seq);
4161 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");
4168 // Instantiate the associated structure views
4169 for (Entry<String, StructureViewerModel> entry : structureViewers
4174 createOrLinkStructureViewer(entry, af, ap, jprovider);
4175 } catch (Exception e)
4178 "Error loading structure viewer: " + e.getMessage());
4179 // failed - try the next one
4191 protected void createOrLinkStructureViewer(
4192 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4193 AlignmentPanel ap, jarInputStreamProvider jprovider)
4195 final StructureViewerModel stateData = viewerData.getValue();
4198 * Search for any viewer windows already open from other alignment views
4199 * that exactly match the stored structure state
4201 StructureViewerBase comp = findMatchingViewer(viewerData);
4205 linkStructureViewer(ap, comp, stateData);
4210 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
4211 * "viewer_"+stateData.viewId
4213 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
4215 createChimeraViewer(viewerData, af, jprovider);
4220 * else Jmol (if pre-2.9, stateData contains JMOL state string)
4222 createJmolViewer(viewerData, af, jprovider);
4227 * Create a new Chimera viewer.
4233 protected void createChimeraViewer(
4234 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4235 jarInputStreamProvider jprovider)
4237 StructureViewerModel data = viewerData.getValue();
4238 String chimeraSessionFile = data.getStateData();
4241 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
4243 * NB this is the 'saved' viewId as in the project file XML, _not_ the
4244 * 'uniquified' sviewid used to reconstruct the viewer here
4246 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
4247 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
4250 Set<Entry<File, StructureData>> fileData = data.getFileData()
4252 List<PDBEntry> pdbs = new ArrayList<>();
4253 List<SequenceI[]> allseqs = new ArrayList<>();
4254 for (Entry<File, StructureData> pdb : fileData)
4256 String filePath = pdb.getValue().getFilePath();
4257 String pdbId = pdb.getValue().getPdbId();
4258 // pdbs.add(new PDBEntry(filePath, pdbId));
4259 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
4260 final List<SequenceI> seqList = pdb.getValue().getSeqList();
4261 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
4265 boolean colourByChimera = data.isColourByViewer();
4266 boolean colourBySequence = data.isColourWithAlignPanel();
4268 // TODO use StructureViewer as a factory here, see JAL-1761
4269 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
4270 final SequenceI[][] seqsArray = allseqs
4271 .toArray(new SequenceI[allseqs.size()][]);
4272 String newViewId = viewerData.getKey();
4274 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
4275 af.alignPanel, pdbArray, seqsArray, colourByChimera,
4276 colourBySequence, newViewId);
4277 cvf.setSize(data.getWidth(), data.getHeight());
4278 cvf.setLocation(data.getX(), data.getY());
4282 * Create a new Jmol window. First parse the Jmol state to translate filenames
4283 * loaded into the view, and record the order in which files are shown in the
4284 * Jmol view, so we can add the sequence mappings in same order.
4290 protected void createJmolViewer(
4291 final Entry<String, StructureViewerModel> viewerData,
4292 AlignFrame af, jarInputStreamProvider jprovider)
4294 final StructureViewerModel svattrib = viewerData.getValue();
4295 String state = svattrib.getStateData();
4298 * Pre-2.9: state element value is the Jmol state string
4300 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
4303 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
4305 state = readJarEntry(jprovider,
4306 getViewerJarEntryName(svattrib.getViewId()));
4309 List<String> pdbfilenames = new ArrayList<>();
4310 List<SequenceI[]> seqmaps = new ArrayList<>();
4311 List<String> pdbids = new ArrayList<>();
4312 StringBuilder newFileLoc = new StringBuilder(64);
4313 int cp = 0, ncp, ecp;
4314 Map<File, StructureData> oldFiles = svattrib.getFileData();
4315 while ((ncp = state.indexOf("load ", cp)) > -1)
4319 // look for next filename in load statement
4320 newFileLoc.append(state.substring(cp,
4321 ncp = (state.indexOf("\"", ncp + 1) + 1)));
4322 String oldfilenam = state.substring(ncp,
4323 ecp = state.indexOf("\"", ncp));
4324 // recover the new mapping data for this old filename
4325 // have to normalize filename - since Jmol and jalview do
4327 // translation differently.
4328 StructureData filedat = oldFiles.get(new File(oldfilenam));
4329 if (filedat == null)
4331 String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\");
4332 filedat = oldFiles.get(new File(reformatedOldFilename));
4334 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
4335 pdbfilenames.add(filedat.getFilePath());
4336 pdbids.add(filedat.getPdbId());
4337 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4338 newFileLoc.append("\"");
4339 cp = ecp + 1; // advance beyond last \" and set cursor so we can
4340 // look for next file statement.
4341 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
4345 // just append rest of state
4346 newFileLoc.append(state.substring(cp));
4350 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
4351 newFileLoc = new StringBuilder(state);
4352 newFileLoc.append("; load append ");
4353 for (File id : oldFiles.keySet())
4355 // add this and any other pdb files that should be present in
4357 StructureData filedat = oldFiles.get(id);
4358 newFileLoc.append(filedat.getFilePath());
4359 pdbfilenames.add(filedat.getFilePath());
4360 pdbids.add(filedat.getPdbId());
4361 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4362 newFileLoc.append(" \"");
4363 newFileLoc.append(filedat.getFilePath());
4364 newFileLoc.append("\"");
4367 newFileLoc.append(";");
4370 if (newFileLoc.length() == 0)
4374 int histbug = newFileLoc.indexOf("history = ");
4378 * change "history = [true|false];" to "history = [1|0];"
4381 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
4382 String val = (diff == -1) ? null
4383 : newFileLoc.substring(histbug, diff);
4384 if (val != null && val.length() >= 4)
4386 if (val.contains("e")) // eh? what can it be?
4388 if (val.trim().equals("true"))
4396 newFileLoc.replace(histbug, diff, val);
4401 final String[] pdbf = pdbfilenames
4402 .toArray(new String[pdbfilenames.size()]);
4403 final String[] id = pdbids.toArray(new String[pdbids.size()]);
4404 final SequenceI[][] sq = seqmaps
4405 .toArray(new SequenceI[seqmaps.size()][]);
4406 final String fileloc = newFileLoc.toString();
4407 final String sviewid = viewerData.getKey();
4408 final AlignFrame alf = af;
4409 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
4410 svattrib.getWidth(), svattrib.getHeight());
4413 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
4418 JalviewStructureDisplayI sview = null;
4421 sview = new StructureViewer(
4422 alf.alignPanel.getStructureSelectionManager())
4423 .createView(StructureViewer.ViewerType.JMOL,
4424 pdbf, id, sq, alf.alignPanel, svattrib,
4425 fileloc, rect, sviewid);
4426 addNewStructureViewer(sview);
4427 } catch (OutOfMemoryError ex)
4429 new OOMWarning("restoring structure view for PDB id " + id,
4430 (OutOfMemoryError) ex.getCause());
4431 if (sview != null && sview.isVisible())
4433 sview.closeViewer(false);
4434 sview.setVisible(false);
4440 } catch (InvocationTargetException ex)
4442 warn("Unexpected error when opening Jmol view.", ex);
4444 } catch (InterruptedException e)
4446 // e.printStackTrace();
4452 * Generates a name for the entry in the project jar file to hold state
4453 * information for a structure viewer
4458 protected String getViewerJarEntryName(String viewId)
4460 return VIEWER_PREFIX + viewId;
4464 * Returns any open frame that matches given structure viewer data. The match
4465 * is based on the unique viewId, or (for older project versions) the frame's
4471 protected StructureViewerBase findMatchingViewer(
4472 Entry<String, StructureViewerModel> viewerData)
4474 final String sviewid = viewerData.getKey();
4475 final StructureViewerModel svattrib = viewerData.getValue();
4476 StructureViewerBase comp = null;
4477 JInternalFrame[] frames = getAllFrames();
4478 for (JInternalFrame frame : frames)
4480 if (frame instanceof StructureViewerBase)
4483 * Post jalview 2.4 schema includes structure view id
4485 if (sviewid != null && ((StructureViewerBase) frame).getViewId()
4488 comp = (StructureViewerBase) frame;
4489 break; // break added in 2.9
4492 * Otherwise test for matching position and size of viewer frame
4494 else if (frame.getX() == svattrib.getX()
4495 && frame.getY() == svattrib.getY()
4496 && frame.getHeight() == svattrib.getHeight()
4497 && frame.getWidth() == svattrib.getWidth())
4499 comp = (StructureViewerBase) frame;
4500 // no break in faint hope of an exact match on viewId
4508 * Link an AlignmentPanel to an existing structure viewer.
4513 * @param useinViewerSuperpos
4514 * @param usetoColourbyseq
4515 * @param viewerColouring
4517 protected void linkStructureViewer(AlignmentPanel ap,
4518 StructureViewerBase viewer, StructureViewerModel stateData)
4520 // NOTE: if the jalview project is part of a shared session then
4521 // view synchronization should/could be done here.
4523 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4524 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4525 final boolean viewerColouring = stateData.isColourByViewer();
4526 Map<File, StructureData> oldFiles = stateData.getFileData();
4529 * Add mapping for sequences in this view to an already open viewer
4531 final AAStructureBindingModel binding = viewer.getBinding();
4532 for (File id : oldFiles.keySet())
4534 // add this and any other pdb files that should be present in the
4536 StructureData filedat = oldFiles.get(id);
4537 String pdbFile = filedat.getFilePath();
4538 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4539 binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE,
4541 binding.addSequenceForStructFile(pdbFile, seq);
4543 // and add the AlignmentPanel's reference to the view panel
4544 viewer.addAlignmentPanel(ap);
4545 if (useinViewerSuperpos)
4547 viewer.useAlignmentPanelForSuperposition(ap);
4551 viewer.excludeAlignmentPanelForSuperposition(ap);
4553 if (usetoColourbyseq)
4555 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4559 viewer.excludeAlignmentPanelForColourbyseq(ap);
4564 * Get all frames within the Desktop.
4568 protected JInternalFrame[] getAllFrames()
4570 JInternalFrame[] frames = null;
4571 // TODO is this necessary - is it safe - risk of hanging?
4576 frames = Desktop.desktop.getAllFrames();
4577 } catch (ArrayIndexOutOfBoundsException e)
4579 // occasional No such child exceptions are thrown here...
4583 } catch (InterruptedException f)
4587 } while (frames == null);
4592 * Answers true if 'version' is equal to or later than 'supported', where each
4593 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4594 * changes. Development and test values for 'version' are leniently treated
4598 * - minimum version we are comparing against
4600 * - version of data being processsed
4603 public static boolean isVersionStringLaterThan(String supported,
4606 if (supported == null || version == null
4607 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4608 || version.equalsIgnoreCase("Test")
4609 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4611 System.err.println("Assuming project file with "
4612 + (version == null ? "null" : version)
4613 + " is compatible with Jalview version " + supported);
4618 return StringUtils.compareVersions(version, supported, "b") >= 0;
4622 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4624 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4626 if (newStructureViewers != null)
4628 sview.getBinding().setFinishedLoadingFromArchive(false);
4629 newStructureViewers.add(sview);
4633 protected void setLoadingFinishedForNewStructureViewers()
4635 if (newStructureViewers != null)
4637 for (JalviewStructureDisplayI sview : newStructureViewers)
4639 sview.getBinding().setFinishedLoadingFromArchive(true);
4641 newStructureViewers.clear();
4642 newStructureViewers = null;
4646 AlignFrame loadViewport(String file, JSeq[] JSEQ,
4647 List<SequenceI> hiddenSeqs, AlignmentI al,
4648 JalviewModelSequence jms, Viewport view, String uniqueSeqSetId,
4649 String viewId, List<JvAnnotRow> autoAlan)
4651 AlignFrame af = null;
4652 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
4653 uniqueSeqSetId, viewId);
4655 af.setFileName(file, FileFormat.Jalview);
4657 for (int i = 0; i < JSEQ.length; i++)
4659 af.viewport.setSequenceColour(
4660 af.viewport.getAlignment().getSequenceAt(i),
4661 new java.awt.Color(JSEQ[i].getColour()));
4666 af.getViewport().setColourByReferenceSeq(true);
4667 af.getViewport().setDisplayReferenceSeq(true);
4670 af.viewport.setGatherViewsHere(view.getGatheredViews());
4672 if (view.getSequenceSetId() != null)
4674 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4676 af.viewport.setSequenceSetId(uniqueSeqSetId);
4679 // propagate shared settings to this new view
4680 af.viewport.setHistoryList(av.getHistoryList());
4681 af.viewport.setRedoList(av.getRedoList());
4685 viewportsAdded.put(uniqueSeqSetId, af.viewport);
4687 // TODO: check if this method can be called repeatedly without
4688 // side-effects if alignpanel already registered.
4689 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4691 // apply Hidden regions to view.
4692 if (hiddenSeqs != null)
4694 for (int s = 0; s < JSEQ.length; s++)
4696 SequenceGroup hidden = new SequenceGroup();
4697 boolean isRepresentative = false;
4698 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
4700 isRepresentative = true;
4701 SequenceI sequenceToHide = al
4702 .getSequenceAt(JSEQ[s].getHiddenSequences(r));
4703 hidden.addSequence(sequenceToHide, false);
4704 // remove from hiddenSeqs list so we don't try to hide it twice
4705 hiddenSeqs.remove(sequenceToHide);
4707 if (isRepresentative)
4709 SequenceI representativeSequence = al.getSequenceAt(s);
4710 hidden.addSequence(representativeSequence, false);
4711 af.viewport.hideRepSequences(representativeSequence, hidden);
4715 SequenceI[] hseqs = hiddenSeqs
4716 .toArray(new SequenceI[hiddenSeqs.size()]);
4717 af.viewport.hideSequence(hseqs);
4720 // recover view properties and display parameters
4722 af.viewport.setShowAnnotation(view.getShowAnnotation());
4723 af.viewport.setAbovePIDThreshold(view.getPidSelected());
4724 af.viewport.setThreshold(view.getPidThreshold());
4726 af.viewport.setColourText(view.getShowColourText());
4728 af.viewport.setConservationSelected(view.getConservationSelected());
4729 af.viewport.setIncrement(view.getConsThreshold());
4730 af.viewport.setShowJVSuffix(view.getShowFullId());
4731 af.viewport.setRightAlignIds(view.getRightAlignIds());
4732 af.viewport.setFont(new java.awt.Font(view.getFontName(),
4733 view.getFontStyle(), view.getFontSize()), true);
4734 ViewStyleI vs = af.viewport.getViewStyle();
4735 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
4736 af.viewport.setViewStyle(vs);
4737 // TODO: allow custom charWidth/Heights to be restored by updating them
4738 // after setting font - which means set above to false
4739 af.viewport.setRenderGaps(view.getRenderGaps());
4740 af.viewport.setWrapAlignment(view.getWrapAlignment());
4741 af.viewport.setShowAnnotation(view.getShowAnnotation());
4743 af.viewport.setShowBoxes(view.getShowBoxes());
4745 af.viewport.setShowText(view.getShowText());
4747 af.viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
4748 af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
4749 af.viewport.setThresholdTextColour(view.getTextColThreshold());
4750 af.viewport.setShowUnconserved(
4751 view.hasShowUnconserved() ? view.isShowUnconserved() : false);
4752 af.viewport.getRanges().setStartRes(view.getStartRes());
4754 if (view.getViewName() != null)
4756 af.viewport.setViewName(view.getViewName());
4757 af.setInitialTabVisible();
4759 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
4761 // startSeq set in af.alignPanel.updateLayout below
4762 af.alignPanel.updateLayout();
4763 ColourSchemeI cs = null;
4764 // apply colourschemes
4765 if (view.getBgColour() != null)
4767 if (view.getBgColour().startsWith("ucs"))
4769 cs = getUserColourScheme(jms, view.getBgColour());
4771 else if (view.getBgColour().startsWith("Annotation"))
4773 AnnotationColours viewAnnColour = view.getAnnotationColours();
4774 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
4781 cs = ColourSchemeProperty.getColourScheme(al, view.getBgColour());
4785 af.viewport.setGlobalColourScheme(cs);
4786 af.viewport.getResidueShading().setThreshold(view.getPidThreshold(),
4787 view.getIgnoreGapsinConsensus());
4788 af.viewport.getResidueShading()
4789 .setConsensus(af.viewport.getSequenceConsensusHash());
4790 af.viewport.setColourAppliesToAllGroups(false);
4792 if (view.getConservationSelected() && cs != null)
4794 af.viewport.getResidueShading()
4795 .setConservationInc(view.getConsThreshold());
4798 af.changeColour(cs);
4800 af.viewport.setColourAppliesToAllGroups(true);
4802 af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures());
4804 if (view.hasCentreColumnLabels())
4806 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
4808 if (view.hasIgnoreGapsinConsensus())
4810 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
4813 if (view.hasFollowHighlight())
4815 af.viewport.setFollowHighlight(view.getFollowHighlight());
4817 if (view.hasFollowSelection())
4819 af.viewport.followSelection = view.getFollowSelection();
4821 if (view.hasShowConsensusHistogram())
4824 .setShowConsensusHistogram(view.getShowConsensusHistogram());
4828 af.viewport.setShowConsensusHistogram(true);
4830 if (view.hasShowSequenceLogo())
4832 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
4836 af.viewport.setShowSequenceLogo(false);
4838 if (view.hasNormaliseSequenceLogo())
4840 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
4842 if (view.hasShowDbRefTooltip())
4844 af.viewport.setShowDBRefs(view.getShowDbRefTooltip());
4846 if (view.hasShowNPfeatureTooltip())
4848 af.viewport.setShowNPFeats(view.hasShowNPfeatureTooltip());
4850 if (view.hasShowGroupConsensus())
4852 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
4856 af.viewport.setShowGroupConsensus(false);
4858 if (view.hasShowGroupConservation())
4860 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
4864 af.viewport.setShowGroupConservation(false);
4867 // recover feature settings
4868 if (jms.getFeatureSettings() != null)
4870 FeatureRenderer fr = af.alignPanel.getSeqPanel().seqCanvas
4871 .getFeatureRenderer();
4872 FeaturesDisplayed fdi;
4873 af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
4874 String[] renderOrder = new String[jms.getFeatureSettings()
4875 .getSettingCount()];
4876 Map<String, FeatureColourI> featureColours = new Hashtable<>();
4877 Map<String, Float> featureOrder = new Hashtable<>();
4879 for (int fs = 0; fs < jms.getFeatureSettings()
4880 .getSettingCount(); fs++)
4882 Setting setting = jms.getFeatureSettings().getSetting(fs);
4883 String featureType = setting.getType();
4886 * restore feature filters (if any)
4888 MatcherSet filters = setting.getMatcherSet();
4889 if (filters != null)
4891 FeatureMatcherSetI filter = Jalview2XML
4892 .unmarshalFilter(featureType, filters);
4893 if (!filter.isEmpty())
4895 fr.setFeatureFilter(featureType, filter);
4900 * restore feature colour scheme
4902 Color maxColour = new Color(setting.getColour());
4903 if (setting.hasMincolour())
4906 * minColour is always set unless a simple colour
4907 * (including for colour by label though it doesn't use it)
4909 Color minColour = new Color(setting.getMincolour());
4910 Color noValueColour = minColour;
4911 NoValueColour noColour = setting.getNoValueColour();
4912 if (noColour == NoValueColour.NONE)
4914 noValueColour = null;
4916 else if (noColour == NoValueColour.MAX)
4918 noValueColour = maxColour;
4920 float min = setting.hasMin() ? setting.getMin() : 0f;
4921 float max = setting.hasMin() ? setting.getMax() : 1f;
4922 FeatureColourI gc = new FeatureColour(minColour, maxColour,
4923 noValueColour, min, max);
4924 if (setting.getAttributeNameCount() > 0)
4926 gc.setAttributeName(setting.getAttributeName());
4928 if (setting.hasThreshold())
4930 gc.setThreshold(setting.getThreshold());
4931 int threshstate = setting.getThreshstate();
4932 // -1 = None, 0 = Below, 1 = Above threshold
4933 if (threshstate == 0)
4935 gc.setBelowThreshold(true);
4937 else if (threshstate == 1)
4939 gc.setAboveThreshold(true);
4942 gc.setAutoScaled(true); // default
4943 if (setting.hasAutoScale())
4945 gc.setAutoScaled(setting.getAutoScale());
4947 if (setting.hasColourByLabel())
4949 gc.setColourByLabel(setting.getColourByLabel());
4951 // and put in the feature colour table.
4952 featureColours.put(featureType, gc);
4956 featureColours.put(featureType,
4957 new FeatureColour(maxColour));
4959 renderOrder[fs] = featureType;
4960 if (setting.hasOrder())
4962 featureOrder.put(featureType, setting.getOrder());
4966 featureOrder.put(featureType, new Float(
4967 fs / jms.getFeatureSettings().getSettingCount()));
4969 if (setting.getDisplay())
4971 fdi.setVisible(featureType);
4974 Map<String, Boolean> fgtable = new Hashtable<>();
4975 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
4977 Group grp = jms.getFeatureSettings().getGroup(gs);
4978 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
4980 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4981 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
4982 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
4983 FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4984 fgtable, featureColours, 1.0f, featureOrder);
4985 fr.transferSettings(frs);
4988 if (view.getHiddenColumnsCount() > 0)
4990 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
4992 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(),
4993 view.getHiddenColumns(c).getEnd() // +1
4997 if (view.getCalcIdParam() != null)
4999 for (CalcIdParam calcIdParam : view.getCalcIdParam())
5001 if (calcIdParam != null)
5003 if (recoverCalcIdParam(calcIdParam, af.viewport))
5008 warn("Couldn't recover parameters for "
5009 + calcIdParam.getCalcId());
5014 af.setMenusFromViewport(af.viewport);
5015 af.setTitle(view.getTitle());
5016 // TODO: we don't need to do this if the viewport is aready visible.
5018 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
5019 * has a 'cdna/protein complement' view, in which case save it in order to
5020 * populate a SplitFrame once all views have been read in.
5022 String complementaryViewId = view.getComplementId();
5023 if (complementaryViewId == null)
5025 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
5027 // recompute any autoannotation
5028 af.alignPanel.updateAnnotation(false, true);
5029 reorderAutoannotation(af, al, autoAlan);
5030 af.alignPanel.alignmentChanged();
5034 splitFrameCandidates.put(view, af);
5040 * Reads saved data to restore Colour by Annotation settings
5042 * @param viewAnnColour
5046 * @param checkGroupAnnColour
5049 private ColourSchemeI constructAnnotationColour(
5050 AnnotationColours viewAnnColour, AlignFrame af, AlignmentI al,
5051 JalviewModelSequence jms, boolean checkGroupAnnColour)
5053 boolean propagateAnnColour = false;
5054 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
5055 if (checkGroupAnnColour && al.getGroups() != null
5056 && al.getGroups().size() > 0)
5058 // pre 2.8.1 behaviour
5059 // check to see if we should transfer annotation colours
5060 propagateAnnColour = true;
5061 for (SequenceGroup sg : al.getGroups())
5063 if (sg.getColourScheme() instanceof AnnotationColourGradient)
5065 propagateAnnColour = false;
5071 * 2.10.2- : saved annotationId is AlignmentAnnotation.annotationId
5073 String annotationId = viewAnnColour.getAnnotation();
5074 AlignmentAnnotation matchedAnnotation = annotationIds.get(annotationId);
5077 * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
5079 if (matchedAnnotation == null
5080 && annAlignment.getAlignmentAnnotation() != null)
5082 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
5085 .equals(annAlignment.getAlignmentAnnotation()[i].label))
5087 matchedAnnotation = annAlignment.getAlignmentAnnotation()[i];
5092 if (matchedAnnotation == null)
5094 System.err.println("Failed to match annotation colour scheme for "
5098 if (matchedAnnotation.getThreshold() == null)
5100 matchedAnnotation.setThreshold(new GraphLine(
5101 viewAnnColour.getThreshold(), "Threshold", Color.black));
5104 AnnotationColourGradient cs = null;
5105 if (viewAnnColour.getColourScheme().equals("None"))
5107 cs = new AnnotationColourGradient(matchedAnnotation,
5108 new Color(viewAnnColour.getMinColour()),
5109 new Color(viewAnnColour.getMaxColour()),
5110 viewAnnColour.getAboveThreshold());
5112 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
5114 cs = new AnnotationColourGradient(matchedAnnotation,
5115 getUserColourScheme(jms, viewAnnColour.getColourScheme()),
5116 viewAnnColour.getAboveThreshold());
5120 cs = new AnnotationColourGradient(matchedAnnotation,
5121 ColourSchemeProperty.getColourScheme(al,
5122 viewAnnColour.getColourScheme()),
5123 viewAnnColour.getAboveThreshold());
5126 boolean perSequenceOnly = viewAnnColour.isPerSequence();
5127 boolean useOriginalColours = viewAnnColour.isPredefinedColours();
5128 cs.setSeqAssociated(perSequenceOnly);
5129 cs.setPredefinedColours(useOriginalColours);
5131 if (propagateAnnColour && al.getGroups() != null)
5133 // Also use these settings for all the groups
5134 for (int g = 0; g < al.getGroups().size(); g++)
5136 SequenceGroup sg = al.getGroups().get(g);
5137 if (sg.getGroupColourScheme() == null)
5142 AnnotationColourGradient groupScheme = new AnnotationColourGradient(
5143 matchedAnnotation, sg.getColourScheme(),
5144 viewAnnColour.getAboveThreshold());
5145 sg.setColourScheme(groupScheme);
5146 groupScheme.setSeqAssociated(perSequenceOnly);
5147 groupScheme.setPredefinedColours(useOriginalColours);
5153 private void reorderAutoannotation(AlignFrame af, AlignmentI al,
5154 List<JvAnnotRow> autoAlan)
5156 // copy over visualization settings for autocalculated annotation in the
5158 if (al.getAlignmentAnnotation() != null)
5161 * Kludge for magic autoannotation names (see JAL-811)
5163 String[] magicNames = new String[] { "Consensus", "Quality",
5165 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
5166 Hashtable<String, JvAnnotRow> visan = new Hashtable<>();
5167 for (String nm : magicNames)
5169 visan.put(nm, nullAnnot);
5171 for (JvAnnotRow auan : autoAlan)
5173 visan.put(auan.template.label
5174 + (auan.template.getCalcId() == null ? ""
5175 : "\t" + auan.template.getCalcId()),
5178 int hSize = al.getAlignmentAnnotation().length;
5179 List<JvAnnotRow> reorder = new ArrayList<>();
5180 // work through any autoCalculated annotation already on the view
5181 // removing it if it should be placed in a different location on the
5182 // annotation panel.
5183 List<String> remains = new ArrayList<>(visan.keySet());
5184 for (int h = 0; h < hSize; h++)
5186 jalview.datamodel.AlignmentAnnotation jalan = al
5187 .getAlignmentAnnotation()[h];
5188 if (jalan.autoCalculated)
5191 JvAnnotRow valan = visan.get(k = jalan.label);
5192 if (jalan.getCalcId() != null)
5194 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
5199 // delete the auto calculated row from the alignment
5200 al.deleteAnnotation(jalan, false);
5204 if (valan != nullAnnot)
5206 if (jalan != valan.template)
5208 // newly created autoannotation row instance
5209 // so keep a reference to the visible annotation row
5210 // and copy over all relevant attributes
5211 if (valan.template.graphHeight >= 0)
5214 jalan.graphHeight = valan.template.graphHeight;
5216 jalan.visible = valan.template.visible;
5218 reorder.add(new JvAnnotRow(valan.order, jalan));
5223 // Add any (possibly stale) autocalculated rows that were not appended to
5224 // the view during construction
5225 for (String other : remains)
5227 JvAnnotRow othera = visan.get(other);
5228 if (othera != nullAnnot && othera.template.getCalcId() != null
5229 && othera.template.getCalcId().length() > 0)
5231 reorder.add(othera);
5234 // now put the automatic annotation in its correct place
5235 int s = 0, srt[] = new int[reorder.size()];
5236 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
5237 for (JvAnnotRow jvar : reorder)
5240 srt[s++] = jvar.order;
5243 jalview.util.QuickSort.sort(srt, rws);
5244 // and re-insert the annotation at its correct position
5245 for (JvAnnotRow jvar : rws)
5247 al.addAnnotation(jvar.template, jvar.order);
5249 af.alignPanel.adjustAnnotationHeight();
5253 Hashtable skipList = null;
5256 * TODO remove this method
5259 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
5260 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
5261 * throw new Error("Implementation Error. No skipList defined for this
5262 * Jalview2XML instance."); } return (AlignFrame)
5263 * skipList.get(view.getSequenceSetId()); }
5267 * Check if the Jalview view contained in object should be skipped or not.
5270 * @return true if view's sequenceSetId is a key in skipList
5272 private boolean skipViewport(JalviewModel object)
5274 if (skipList == null)
5279 if (skipList.containsKey(
5280 id = object.getJalviewModelSequence().getViewport()[0]
5281 .getSequenceSetId()))
5283 if (Cache.log != null && Cache.log.isDebugEnabled())
5285 Cache.log.debug("Skipping seuqence set id " + id);
5292 public void addToSkipList(AlignFrame af)
5294 if (skipList == null)
5296 skipList = new Hashtable();
5298 skipList.put(af.getViewport().getSequenceSetId(), af);
5301 public void clearSkipList()
5303 if (skipList != null)
5310 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
5311 boolean ignoreUnrefed, String uniqueSeqSetId)
5313 jalview.datamodel.AlignmentI ds = getDatasetFor(
5314 vamsasSet.getDatasetId());
5315 Vector dseqs = null;
5320 // try to resolve the dataset via uniqueSeqSetId
5321 ds = getDatasetFor(UNIQSEQSETID + uniqueSeqSetId);
5324 addDatasetRef(vamsasSet.getDatasetId(), ds);
5330 // create a list of new dataset sequences
5331 dseqs = new Vector();
5333 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
5335 Sequence vamsasSeq = vamsasSet.getSequence(i);
5336 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
5338 // create a new dataset
5341 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
5342 dseqs.copyInto(dsseqs);
5343 ds = new jalview.datamodel.Alignment(dsseqs);
5344 debug("Created new dataset " + vamsasSet.getDatasetId()
5345 + " for alignment " + System.identityHashCode(al));
5346 addDatasetRef(vamsasSet.getDatasetId(), ds);
5348 // set the dataset for the newly imported alignment.
5349 if (al.getDataset() == null && !ignoreUnrefed)
5352 // register dataset for the alignment's uniqueSeqSetId for legacy projects
5353 addDatasetRef(UNIQSEQSETID + uniqueSeqSetId, ds);
5360 * sequence definition to create/merge dataset sequence for
5364 * vector to add new dataset sequence to
5365 * @param ignoreUnrefed
5366 * - when true, don't create new sequences from vamsasSeq if it's id
5367 * doesn't already have an asssociated Jalview sequence.
5369 * - used to reorder the sequence in the alignment according to the
5370 * vamsasSeq array ordering, to preserve ordering of dataset
5372 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
5373 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed, int vseqpos)
5375 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
5377 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
5378 boolean reorder = false;
5379 SequenceI dsq = null;
5380 if (sq != null && sq.getDatasetSequence() != null)
5382 dsq = sq.getDatasetSequence();
5388 if (sq == null && ignoreUnrefed)
5392 String sqid = vamsasSeq.getDsseqid();
5395 // need to create or add a new dataset sequence reference to this sequence
5398 dsq = seqRefIds.get(sqid);
5403 // make a new dataset sequence
5404 dsq = sq.createDatasetSequence();
5407 // make up a new dataset reference for this sequence
5408 sqid = seqHash(dsq);
5410 dsq.setVamsasId(uniqueSetSuffix + sqid);
5411 seqRefIds.put(sqid, dsq);
5416 dseqs.addElement(dsq);
5421 ds.addSequence(dsq);
5427 { // make this dataset sequence sq's dataset sequence
5428 sq.setDatasetSequence(dsq);
5429 // and update the current dataset alignment
5434 if (!dseqs.contains(dsq))
5441 if (ds.findIndex(dsq) < 0)
5443 ds.addSequence(dsq);
5450 // TODO: refactor this as a merge dataset sequence function
5451 // now check that sq (the dataset sequence) sequence really is the union of
5452 // all references to it
5453 // boolean pre = sq.getStart() < dsq.getStart();
5454 // boolean post = sq.getEnd() > dsq.getEnd();
5458 // StringBuffer sb = new StringBuffer();
5459 String newres = jalview.analysis.AlignSeq.extractGaps(
5460 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
5461 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
5462 && newres.length() > dsq.getLength())
5464 // Update with the longer sequence.
5468 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
5469 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
5470 * sb.append(newres.substring(newres.length() - sq.getEnd() -
5471 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
5473 dsq.setSequence(newres);
5475 // TODO: merges will never happen if we 'know' we have the real dataset
5476 // sequence - this should be detected when id==dssid
5478 "DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
5479 // + (pre ? "prepended" : "") + " "
5480 // + (post ? "appended" : ""));
5485 // sequence refs are identical. We may need to update the existing dataset
5486 // alignment with this one, though.
5487 if (ds != null && dseqs == null)
5489 int opos = ds.findIndex(dsq);
5490 SequenceI tseq = null;
5491 if (opos != -1 && vseqpos != opos)
5493 // remove from old position
5494 ds.deleteSequence(dsq);
5496 if (vseqpos < ds.getHeight())
5498 if (vseqpos != opos)
5500 // save sequence at destination position
5501 tseq = ds.getSequenceAt(vseqpos);
5502 ds.replaceSequenceAt(vseqpos, dsq);
5503 ds.addSequence(tseq);
5508 ds.addSequence(dsq);
5515 * TODO use AlignmentI here and in related methods - needs
5516 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
5518 Hashtable<String, AlignmentI> datasetIds = null;
5520 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
5522 private AlignmentI getDatasetFor(String datasetId)
5524 if (datasetIds == null)
5526 datasetIds = new Hashtable<>();
5529 if (datasetIds.containsKey(datasetId))
5531 return datasetIds.get(datasetId);
5536 private void addDatasetRef(String datasetId, AlignmentI dataset)
5538 if (datasetIds == null)
5540 datasetIds = new Hashtable<>();
5542 datasetIds.put(datasetId, dataset);
5546 * make a new dataset ID for this jalview dataset alignment
5551 private String getDatasetIdRef(AlignmentI dataset)
5553 if (dataset.getDataset() != null)
5555 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
5557 String datasetId = makeHashCode(dataset, null);
5558 if (datasetId == null)
5560 // make a new datasetId and record it
5561 if (dataset2Ids == null)
5563 dataset2Ids = new IdentityHashMap<>();
5567 datasetId = dataset2Ids.get(dataset);
5569 if (datasetId == null)
5571 datasetId = "ds" + dataset2Ids.size() + 1;
5572 dataset2Ids.put(dataset, datasetId);
5578 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5580 for (int d = 0; d < sequence.getDBRefCount(); d++)
5582 DBRef dr = sequence.getDBRef(d);
5583 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
5584 sequence.getDBRef(d).getSource(),
5585 sequence.getDBRef(d).getVersion(),
5586 sequence.getDBRef(d).getAccessionId());
5587 if (dr.getMapping() != null)
5589 entry.setMap(addMapping(dr.getMapping()));
5591 datasetSequence.addDBRef(entry);
5595 private jalview.datamodel.Mapping addMapping(Mapping m)
5597 SequenceI dsto = null;
5598 // Mapping m = dr.getMapping();
5599 int fr[] = new int[m.getMapListFromCount() * 2];
5600 Enumeration f = m.enumerateMapListFrom();
5601 for (int _i = 0; f.hasMoreElements(); _i += 2)
5603 MapListFrom mf = (MapListFrom) f.nextElement();
5604 fr[_i] = mf.getStart();
5605 fr[_i + 1] = mf.getEnd();
5607 int fto[] = new int[m.getMapListToCount() * 2];
5608 f = m.enumerateMapListTo();
5609 for (int _i = 0; f.hasMoreElements(); _i += 2)
5611 MapListTo mf = (MapListTo) f.nextElement();
5612 fto[_i] = mf.getStart();
5613 fto[_i + 1] = mf.getEnd();
5615 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto, fr,
5616 fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
5617 if (m.getMappingChoice() != null)
5619 MappingChoice mc = m.getMappingChoice();
5620 if (mc.getDseqFor() != null)
5622 String dsfor = "" + mc.getDseqFor();
5623 if (seqRefIds.containsKey(dsfor))
5628 jmap.setTo(seqRefIds.get(dsfor));
5632 frefedSequence.add(newMappingRef(dsfor, jmap));
5638 * local sequence definition
5640 Sequence ms = mc.getSequence();
5641 SequenceI djs = null;
5642 String sqid = ms.getDsseqid();
5643 if (sqid != null && sqid.length() > 0)
5646 * recover dataset sequence
5648 djs = seqRefIds.get(sqid);
5653 "Warning - making up dataset sequence id for DbRef sequence map reference");
5654 sqid = ((Object) ms).toString(); // make up a new hascode for
5655 // undefined dataset sequence hash
5656 // (unlikely to happen)
5662 * make a new dataset sequence and add it to refIds hash
5664 djs = new jalview.datamodel.Sequence(ms.getName(),
5666 djs.setStart(jmap.getMap().getToLowest());
5667 djs.setEnd(jmap.getMap().getToHighest());
5668 djs.setVamsasId(uniqueSetSuffix + sqid);
5670 incompleteSeqs.put(sqid, djs);
5671 seqRefIds.put(sqid, djs);
5674 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5684 * Provides a 'copy' of an alignment view (on action New View) by 'saving' the
5685 * view as XML (but not to file), and then reloading it
5690 public AlignmentPanel copyAlignPanel(AlignmentPanel ap)
5693 JalviewModel jm = saveState(ap, null, null, null);
5695 addDatasetRef(jm.getVamsasModel().getSequenceSet()[0].getDatasetId(),
5696 ap.getAlignment().getDataset());
5698 uniqueSetSuffix = "";
5699 jm.getJalviewModelSequence().getViewport(0).setId(null);
5700 // we don't overwrite the view we just copied
5702 if (this.frefedSequence == null)
5704 frefedSequence = new Vector<>();
5707 viewportsAdded.clear();
5709 AlignFrame af = loadFromObject(jm, null, false, null);
5710 af.alignPanels.clear();
5711 af.closeMenuItem_actionPerformed(true);
5714 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5715 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5716 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5717 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5718 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5721 return af.alignPanel;
5724 private Hashtable jvids2vobj;
5726 private void warn(String msg)
5731 private void warn(String msg, Exception e)
5733 if (Cache.log != null)
5737 Cache.log.warn(msg, e);
5741 Cache.log.warn(msg);
5746 System.err.println("Warning: " + msg);
5749 e.printStackTrace();
5754 private void debug(String string)
5756 debug(string, null);
5759 private void debug(String msg, Exception e)
5761 if (Cache.log != null)
5765 Cache.log.debug(msg, e);
5769 Cache.log.debug(msg);
5774 System.err.println("Warning: " + msg);
5777 e.printStackTrace();
5783 * set the object to ID mapping tables used to write/recover objects and XML
5784 * ID strings for the jalview project. If external tables are provided then
5785 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
5786 * object goes out of scope. - also populates the datasetIds hashtable with
5787 * alignment objects containing dataset sequences
5790 * Map from ID strings to jalview datamodel
5792 * Map from jalview datamodel to ID strings
5796 public void setObjectMappingTables(Hashtable vobj2jv,
5797 IdentityHashMap jv2vobj)
5799 this.jv2vobj = jv2vobj;
5800 this.vobj2jv = vobj2jv;
5801 Iterator ds = jv2vobj.keySet().iterator();
5803 while (ds.hasNext())
5805 Object jvobj = ds.next();
5806 id = jv2vobj.get(jvobj).toString();
5807 if (jvobj instanceof jalview.datamodel.Alignment)
5809 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
5811 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
5814 else if (jvobj instanceof jalview.datamodel.Sequence)
5816 // register sequence object so the XML parser can recover it.
5817 if (seqRefIds == null)
5819 seqRefIds = new HashMap<>();
5821 if (seqsToIds == null)
5823 seqsToIds = new IdentityHashMap<>();
5825 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
5826 seqsToIds.put((SequenceI) jvobj, id);
5828 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
5831 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
5832 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
5833 if (jvann.annotationId == null)
5835 jvann.annotationId = anid;
5837 if (!jvann.annotationId.equals(anid))
5839 // TODO verify that this is the correct behaviour
5840 this.warn("Overriding Annotation ID for " + anid
5841 + " from different id : " + jvann.annotationId);
5842 jvann.annotationId = anid;
5845 else if (jvobj instanceof String)
5847 if (jvids2vobj == null)
5849 jvids2vobj = new Hashtable();
5850 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
5855 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
5861 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
5862 * objects created from the project archive. If string is null (default for
5863 * construction) then suffix will be set automatically.
5867 public void setUniqueSetSuffix(String string)
5869 uniqueSetSuffix = string;
5874 * uses skipList2 as the skipList for skipping views on sequence sets
5875 * associated with keys in the skipList
5879 public void setSkipList(Hashtable skipList2)
5881 skipList = skipList2;
5885 * Reads the jar entry of given name and returns its contents, or null if the
5886 * entry is not found.
5889 * @param jarEntryName
5892 protected String readJarEntry(jarInputStreamProvider jprovider,
5893 String jarEntryName)
5895 String result = null;
5896 BufferedReader in = null;
5901 * Reopen the jar input stream and traverse its entries to find a matching
5904 JarInputStream jin = jprovider.getJarInputStream();
5905 JarEntry entry = null;
5908 entry = jin.getNextJarEntry();
5909 } while (entry != null && !entry.getName().equals(jarEntryName));
5913 StringBuilder out = new StringBuilder(256);
5914 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
5917 while ((data = in.readLine()) != null)
5921 result = out.toString();
5925 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
5927 } catch (Exception ex)
5929 ex.printStackTrace();
5937 } catch (IOException e)
5948 * Returns an incrementing counter (0, 1, 2...)
5952 private synchronized int nextCounter()
5958 * Loads any saved PCA viewers
5963 protected void loadPCAViewers(JalviewModelSequence jms, AlignmentPanel ap)
5967 for (int t = 0; t < jms.getPcaViewerCount(); t++)
5969 PcaViewer viewer = jms.getPcaViewer(t);
5970 String modelName = viewer.getScoreModelName();
5971 SimilarityParamsI params = new SimilarityParams(
5972 viewer.isIncludeGappedColumns(),
5973 viewer.isMatchGaps(), viewer.isIncludeGaps(),
5974 viewer.isDenominateByShortestLength());
5977 * create the panel (without computing the PCA)
5979 PCAPanel panel = new PCAPanel(ap, modelName, params);
5981 panel.setTitle(viewer.getTitle());
5982 panel.setBounds(new Rectangle(viewer.getXpos(), viewer.getYpos(),
5983 viewer.getWidth(), viewer.getHeight()));
5985 boolean showLabels = viewer.isShowLabels();
5986 panel.setShowLabels(showLabels);
5987 panel.getRotatableCanvas().setShowLabels(showLabels);
5988 panel.getRotatableCanvas().setBgColour(new Color(viewer.getBgColour()));
5989 panel.getRotatableCanvas().setApplyToAllViews(viewer.isLinkToAllViews());
5992 * load PCA output data
5994 ScoreModelI scoreModel = ScoreModels.getInstance()
5995 .getScoreModel(modelName, ap);
5996 PCA pca = new PCA(null, scoreModel, params);
5997 PcaData pcaData = viewer.getPcaData();
5999 MatrixI pairwise = loadDoubleMatrix(pcaData.getPairwiseMatrix());
6000 pca.setPairwiseScores(pairwise);
6002 MatrixI triDiag = loadDoubleMatrix(pcaData.getTridiagonalMatrix());
6003 pca.setTridiagonal(triDiag);
6005 MatrixI result = loadDoubleMatrix(pcaData.getEigenMatrix());
6006 pca.setEigenmatrix(result);
6008 panel.getPcaModel().setPCA(pca);
6011 * we haven't saved the input data! (JAL-2647 to do)
6013 panel.setInputData(null);
6016 * add the sequence points for the PCA display
6018 List<jalview.datamodel.SequencePoint> seqPoints = new ArrayList<>();
6019 for (SequencePoint sp : viewer.getSequencePoint())
6021 String seqId = sp.getSequenceRef();
6022 SequenceI seq = seqRefIds.get(seqId);
6025 throw new IllegalStateException(
6026 "Unmatched seqref for PCA: " + seqId);
6028 Point pt = new Point(sp.getXPos(), sp.getYPos(), sp.getZPos());
6029 jalview.datamodel.SequencePoint seqPoint = new jalview.datamodel.SequencePoint(
6031 seqPoints.add(seqPoint);
6033 panel.getRotatableCanvas().setPoints(seqPoints, seqPoints.size());
6036 * set min-max ranges and scale after setPoints (which recomputes them)
6038 panel.getRotatableCanvas().setScaleFactor(viewer.getScaleFactor());
6039 SeqPointMin spMin = viewer.getSeqPointMin();
6040 float[] min = new float[] { spMin.getXPos(), spMin.getYPos(),
6042 SeqPointMax spMax = viewer.getSeqPointMax();
6043 float[] max = new float[] { spMax.getXPos(), spMax.getYPos(),
6045 panel.getRotatableCanvas().setSeqMinMax(min, max);
6047 // todo: hold points list in PCAModel only
6048 panel.getPcaModel().setSequencePoints(seqPoints);
6050 panel.setSelectedDimensionIndex(viewer.getXDim(), X);
6051 panel.setSelectedDimensionIndex(viewer.getYDim(), Y);
6052 panel.setSelectedDimensionIndex(viewer.getZDim(), Z);
6054 // is this duplication needed?
6055 panel.setTop(seqPoints.size() - 1);
6056 panel.getPcaModel().setTop(seqPoints.size() - 1);
6059 * add the axes' end points for the display
6061 for (int i = 0; i < 3; i++)
6063 Axis axis = viewer.getAxis(i);
6064 panel.getRotatableCanvas().getAxisEndPoints()[i] = new Point(axis.getXPos(),
6065 axis.getYPos(), axis.getZPos());
6068 Desktop.addInternalFrame(panel, MessageManager.formatMessage(
6069 "label.calc_title", "PCA", modelName), 475, 450);
6071 } catch (Exception ex)
6073 Cache.log.error("Error loading PCA: " + ex.toString());
6078 * Populates an XML model of the feature colour scheme for one feature type
6080 * @param featureType
6084 protected static jalview.schemabinding.version2.Colour marshalColour(
6085 String featureType, FeatureColourI fcol)
6087 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
6088 if (fcol.isSimpleColour())
6090 col.setRGB(Format.getHexString(fcol.getColour()));
6094 col.setRGB(Format.getHexString(fcol.getMaxColour()));
6095 col.setMin(fcol.getMin());
6096 col.setMax(fcol.getMax());
6097 col.setMinRGB(jalview.util.Format.getHexString(fcol.getMinColour()));
6098 col.setAutoScale(fcol.isAutoScaled());
6099 col.setThreshold(fcol.getThreshold());
6100 col.setColourByLabel(fcol.isColourByLabel());
6101 col.setThreshType(fcol.isAboveThreshold() ? ColourThreshTypeType.ABOVE
6102 : (fcol.isBelowThreshold() ? ColourThreshTypeType.BELOW
6103 : ColourThreshTypeType.NONE));
6104 if (fcol.isColourByAttribute())
6106 col.setAttributeName(fcol.getAttributeName());
6108 Color noColour = fcol.getNoColour();
6109 if (noColour == null)
6111 col.setNoValueColour(NoValueColour.NONE);
6113 else if (noColour == fcol.getMaxColour())
6115 col.setNoValueColour(NoValueColour.MAX);
6119 col.setNoValueColour(NoValueColour.MIN);
6122 col.setName(featureType);
6127 * Populates an XML model of the feature filter(s) for one feature type
6129 * @param firstMatcher
6130 * the first (or only) match condition)
6132 * remaining match conditions (if any)
6134 * if true, conditions are and-ed, else or-ed
6136 protected static MatcherSet marshalFilter(FeatureMatcherI firstMatcher,
6137 Iterator<FeatureMatcherI> filters, boolean and)
6139 MatcherSet result = new MatcherSet();
6141 if (filters.hasNext())
6146 CompoundMatcher compound = new CompoundMatcher();
6147 compound.setAnd(and);
6148 MatcherSet matcher1 = marshalFilter(firstMatcher,
6149 Collections.emptyIterator(), and);
6150 compound.addMatcherSet(matcher1);
6151 FeatureMatcherI nextMatcher = filters.next();
6152 MatcherSet matcher2 = marshalFilter(nextMatcher, filters, and);
6153 compound.addMatcherSet(matcher2);
6154 result.setCompoundMatcher(compound);
6159 * single condition matcher
6161 MatchCondition matcherModel = new MatchCondition();
6162 matcherModel.setCondition(
6163 firstMatcher.getMatcher().getCondition().getStableName());
6164 matcherModel.setValue(firstMatcher.getMatcher().getPattern());
6165 if (firstMatcher.isByAttribute())
6167 matcherModel.setBy(FeatureMatcherByType.BYATTRIBUTE);
6168 matcherModel.setAttributeName(firstMatcher.getAttribute());
6170 else if (firstMatcher.isByLabel())
6172 matcherModel.setBy(FeatureMatcherByType.BYLABEL);
6174 else if (firstMatcher.isByScore())
6176 matcherModel.setBy(FeatureMatcherByType.BYSCORE);
6178 result.setMatchCondition(matcherModel);
6185 * Loads one XML model of a feature filter to a Jalview object
6187 * @param featureType
6188 * @param matcherSetModel
6191 protected static FeatureMatcherSetI unmarshalFilter(
6192 String featureType, MatcherSet matcherSetModel)
6194 FeatureMatcherSetI result = new FeatureMatcherSet();
6197 unmarshalFilterConditions(result, matcherSetModel, true);
6198 } catch (IllegalStateException e)
6200 // mixing AND and OR conditions perhaps
6202 String.format("Error reading filter conditions for '%s': %s",
6203 featureType, e.getMessage()));
6204 // return as much as was parsed up to the error
6211 * Adds feature match conditions to matcherSet as unmarshalled from XML
6212 * (possibly recursively for compound conditions)
6215 * @param matcherSetModel
6217 * if true, multiple conditions are AND-ed, else they are OR-ed
6218 * @throws IllegalStateException
6219 * if AND and OR conditions are mixed
6221 protected static void unmarshalFilterConditions(
6222 FeatureMatcherSetI matcherSet, MatcherSet matcherSetModel,
6225 MatchCondition mc = matcherSetModel.getMatchCondition();
6231 FeatureMatcherByType filterBy = mc.getBy();
6232 Condition cond = Condition.fromString(mc.getCondition());
6233 String pattern = mc.getValue();
6234 FeatureMatcherI matchCondition = null;
6235 if (filterBy == FeatureMatcherByType.BYLABEL)
6237 matchCondition = FeatureMatcher.byLabel(cond, pattern);
6239 else if (filterBy == FeatureMatcherByType.BYSCORE)
6241 matchCondition = FeatureMatcher.byScore(cond, pattern);
6244 else if (filterBy == FeatureMatcherByType.BYATTRIBUTE)
6246 String[] attNames = mc.getAttributeName();
6247 matchCondition = FeatureMatcher.byAttribute(cond, pattern,
6252 * note this throws IllegalStateException if AND-ing to a
6253 * previously OR-ed compound condition, or vice versa
6257 matcherSet.and(matchCondition);
6261 matcherSet.or(matchCondition);
6267 * compound condition
6269 MatcherSet[] matchers = matcherSetModel.getCompoundMatcher()
6271 boolean anded = matcherSetModel.getCompoundMatcher().getAnd();
6272 if (matchers.length == 2)
6274 unmarshalFilterConditions(matcherSet, matchers[0], anded);
6275 unmarshalFilterConditions(matcherSet, matchers[1], anded);
6279 System.err.println("Malformed compound filter condition");
6285 * Loads one XML model of a feature colour to a Jalview object
6287 * @param colourModel
6290 protected static FeatureColourI unmarshalColour(
6291 jalview.schemabinding.version2.Colour colourModel)
6293 FeatureColourI colour = null;
6295 if (colourModel.hasMax())
6297 Color mincol = null;
6298 Color maxcol = null;
6299 Color noValueColour = null;
6303 mincol = new Color(Integer.parseInt(colourModel.getMinRGB(), 16));
6304 maxcol = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6305 } catch (Exception e)
6307 Cache.log.warn("Couldn't parse out graduated feature color.", e);
6310 NoValueColour noCol = colourModel.getNoValueColour();
6311 if (noCol == NoValueColour.MIN)
6313 noValueColour = mincol;
6315 else if (noCol == NoValueColour.MAX)
6317 noValueColour = maxcol;
6320 colour = new FeatureColour(mincol, maxcol, noValueColour,
6321 colourModel.getMin(),
6322 colourModel.getMax());
6323 String[] attributes = colourModel.getAttributeName();
6324 if (attributes != null && attributes.length > 0)
6326 colour.setAttributeName(attributes);
6328 if (colourModel.hasAutoScale())
6330 colour.setAutoScaled(colourModel.getAutoScale());
6332 if (colourModel.hasColourByLabel())
6334 colour.setColourByLabel(colourModel.getColourByLabel());
6336 if (colourModel.hasThreshold())
6338 colour.setThreshold(colourModel.getThreshold());
6340 ColourThreshTypeType ttyp = colourModel.getThreshType();
6343 if (ttyp == ColourThreshTypeType.ABOVE)
6345 colour.setAboveThreshold(true);
6347 else if (ttyp == ColourThreshTypeType.BELOW)
6349 colour.setBelowThreshold(true);
6355 Color color = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6356 colour = new FeatureColour(color);