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.DBRef;
70 import jalview.schemabinding.version2.DoubleMatrix;
71 import jalview.schemabinding.version2.EigenMatrix;
72 import jalview.schemabinding.version2.EigenMatrixD;
73 import jalview.schemabinding.version2.EigenMatrixE;
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.UserColours;
108 import jalview.schemabinding.version2.Viewport;
109 import jalview.schemabinding.version2.types.ColourThreshTypeType;
110 import jalview.schemabinding.version2.types.FeatureMatcherByType;
111 import jalview.schemabinding.version2.types.NoValueColour;
112 import jalview.schemes.AnnotationColourGradient;
113 import jalview.schemes.ColourSchemeI;
114 import jalview.schemes.ColourSchemeProperty;
115 import jalview.schemes.FeatureColour;
116 import jalview.schemes.ResidueProperties;
117 import jalview.schemes.UserColourScheme;
118 import jalview.structure.StructureSelectionManager;
119 import jalview.structures.models.AAStructureBindingModel;
120 import jalview.util.Format;
121 import jalview.util.MessageManager;
122 import jalview.util.Platform;
123 import jalview.util.StringUtils;
124 import jalview.util.jarInputStreamProvider;
125 import jalview.util.matcher.Condition;
126 import jalview.viewmodel.AlignmentViewport;
127 import jalview.viewmodel.PCAModel;
128 import jalview.viewmodel.ViewportRanges;
129 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
130 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
131 import jalview.ws.jws2.Jws2Discoverer;
132 import jalview.ws.jws2.dm.AAConSettings;
133 import jalview.ws.jws2.jabaws2.Jws2Instance;
134 import jalview.ws.params.ArgumentI;
135 import jalview.ws.params.AutoCalcSetting;
136 import jalview.ws.params.WsParamSetI;
138 import java.awt.Color;
139 import java.awt.Rectangle;
140 import java.io.BufferedReader;
141 import java.io.DataInputStream;
142 import java.io.DataOutputStream;
144 import java.io.FileInputStream;
145 import java.io.FileOutputStream;
146 import java.io.IOException;
147 import java.io.InputStreamReader;
148 import java.io.OutputStreamWriter;
149 import java.io.PrintWriter;
150 import java.lang.reflect.InvocationTargetException;
151 import java.net.MalformedURLException;
153 import java.util.ArrayList;
154 import java.util.Arrays;
155 import java.util.Collections;
156 import java.util.Enumeration;
157 import java.util.HashMap;
158 import java.util.HashSet;
159 import java.util.Hashtable;
160 import java.util.IdentityHashMap;
161 import java.util.Iterator;
162 import java.util.LinkedHashMap;
163 import java.util.List;
164 import java.util.Map;
165 import java.util.Map.Entry;
166 import java.util.Set;
167 import java.util.Vector;
168 import java.util.jar.JarEntry;
169 import java.util.jar.JarInputStream;
170 import java.util.jar.JarOutputStream;
172 import javax.swing.JInternalFrame;
173 import javax.swing.SwingUtilities;
175 import org.exolab.castor.xml.Marshaller;
176 import org.exolab.castor.xml.Unmarshaller;
179 * Write out the current jalview desktop state as a Jalview XML stream.
181 * Note: the vamsas objects referred to here are primitive versions of the
182 * VAMSAS project schema elements - they are not the same and most likely never
186 * @version $Revision: 1.134 $
188 public class Jalview2XML
190 private static final String VIEWER_PREFIX = "viewer_";
192 private static final String RNA_PREFIX = "rna_";
194 private static final String UTF_8 = "UTF-8";
196 // use this with nextCounter() to make unique names for entities
197 private int counter = 0;
200 * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
201 * of sequence objects are created.
203 IdentityHashMap<SequenceI, String> seqsToIds = null;
206 * jalview XML Sequence ID to jalview sequence object reference (both dataset
207 * and alignment sequences. Populated as XML reps of sequence objects are
210 Map<String, SequenceI> seqRefIds = null;
212 Map<String, SequenceI> incompleteSeqs = null;
214 List<SeqFref> frefedSequence = null;
216 boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
219 * Map of reconstructed AlignFrame objects that appear to have come from
220 * SplitFrame objects (have a dna/protein complement view).
222 private Map<Viewport, AlignFrame> splitFrameCandidates = new HashMap<>();
225 * Map from displayed rna structure models to their saved session state jar
228 private Map<RnaModel, String> rnaSessions = new HashMap<>();
231 * create/return unique hash string for sq
234 * @return new or existing unique string for sq
236 String seqHash(SequenceI sq)
238 if (seqsToIds == null)
242 if (seqsToIds.containsKey(sq))
244 return seqsToIds.get(sq);
248 // create sequential key
249 String key = "sq" + (seqsToIds.size() + 1);
250 key = makeHashCode(sq, key); // check we don't have an external reference
252 seqsToIds.put(sq, key);
259 if (seqsToIds == null)
261 seqsToIds = new IdentityHashMap<>();
263 if (seqRefIds == null)
265 seqRefIds = new HashMap<>();
267 if (incompleteSeqs == null)
269 incompleteSeqs = new HashMap<>();
271 if (frefedSequence == null)
273 frefedSequence = new ArrayList<>();
281 public Jalview2XML(boolean raiseGUI)
283 this.raiseGUI = raiseGUI;
287 * base class for resolving forward references to sequences by their ID
292 abstract class SeqFref
298 public SeqFref(String _sref, String type)
304 public String getSref()
309 public SequenceI getSrefSeq()
311 return seqRefIds.get(sref);
314 public boolean isResolvable()
316 return seqRefIds.get(sref) != null;
319 public SequenceI getSrefDatasetSeq()
321 SequenceI sq = seqRefIds.get(sref);
324 while (sq.getDatasetSequence() != null)
326 sq = sq.getDatasetSequence();
333 * @return true if the forward reference was fully resolved
335 abstract boolean resolve();
338 public String toString()
340 return type + " reference to " + sref;
345 * create forward reference for a mapping
351 public SeqFref newMappingRef(final String sref,
352 final jalview.datamodel.Mapping _jmap)
354 SeqFref fref = new SeqFref(sref, "Mapping")
356 public jalview.datamodel.Mapping jmap = _jmap;
361 SequenceI seq = getSrefDatasetSeq();
373 public SeqFref newAlcodMapRef(final String sref,
374 final AlignedCodonFrame _cf,
375 final jalview.datamodel.Mapping _jmap)
378 SeqFref fref = new SeqFref(sref, "Codon Frame")
380 AlignedCodonFrame cf = _cf;
382 public jalview.datamodel.Mapping mp = _jmap;
385 public boolean isResolvable()
387 return super.isResolvable() && mp.getTo() != null;
393 SequenceI seq = getSrefDatasetSeq();
398 cf.addMap(seq, mp.getTo(), mp.getMap());
405 public void resolveFrefedSequences()
407 Iterator<SeqFref> nextFref = frefedSequence.iterator();
408 int toresolve = frefedSequence.size();
409 int unresolved = 0, failedtoresolve = 0;
410 while (nextFref.hasNext())
412 SeqFref ref = nextFref.next();
413 if (ref.isResolvable())
425 } catch (Exception x)
428 "IMPLEMENTATION ERROR: Failed to resolve forward reference for sequence "
441 System.err.println("Jalview Project Import: There were " + unresolved
442 + " forward references left unresolved on the stack.");
444 if (failedtoresolve > 0)
446 System.err.println("SERIOUS! " + failedtoresolve
447 + " resolvable forward references failed to resolve.");
449 if (incompleteSeqs != null && incompleteSeqs.size() > 0)
452 "Jalview Project Import: There are " + incompleteSeqs.size()
453 + " sequences which may have incomplete metadata.");
454 if (incompleteSeqs.size() < 10)
456 for (SequenceI s : incompleteSeqs.values())
458 System.err.println(s.toString());
464 "Too many to report. Skipping output of incomplete sequences.");
470 * This maintains a map of viewports, the key being the seqSetId. Important to
471 * set historyItem and redoList for multiple views
473 Map<String, AlignViewport> viewportsAdded = new HashMap<>();
475 Map<String, AlignmentAnnotation> annotationIds = new HashMap<>();
477 String uniqueSetSuffix = "";
480 * List of pdbfiles added to Jar
482 List<String> pdbfiles = null;
484 // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
485 public void saveState(File statefile)
487 FileOutputStream fos = null;
490 fos = new FileOutputStream(statefile);
491 JarOutputStream jout = new JarOutputStream(fos);
494 } catch (Exception e)
496 // TODO: inform user of the problem - they need to know if their data was
498 if (errorMessage == null)
500 errorMessage = "Couldn't write Jalview Archive to output file '"
501 + statefile + "' - See console error log for details";
505 errorMessage += "(output file was '" + statefile + "')";
515 } catch (IOException e)
525 * Writes a jalview project archive to the given Jar output stream.
529 public void saveState(JarOutputStream jout)
531 AlignFrame[] frames = Desktop.getAlignFrames();
537 saveAllFrames(Arrays.asList(frames), jout);
541 * core method for storing state for a set of AlignFrames.
544 * - frames involving all data to be exported (including containing
547 * - project output stream
549 private void saveAllFrames(List<AlignFrame> frames, JarOutputStream jout)
551 Hashtable<String, AlignFrame> dsses = new Hashtable<>();
554 * ensure cached data is clear before starting
556 // todo tidy up seqRefIds, seqsToIds initialisation / reset
558 splitFrameCandidates.clear();
563 // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
564 // //////////////////////////////////////////////////
566 List<String> shortNames = new ArrayList<>();
567 List<String> viewIds = new ArrayList<>();
570 for (int i = frames.size() - 1; i > -1; i--)
572 AlignFrame af = frames.get(i);
574 if (skipList != null && skipList
575 .containsKey(af.getViewport().getSequenceSetId()))
580 String shortName = makeFilename(af, shortNames);
582 int ap, apSize = af.alignPanels.size();
584 for (ap = 0; ap < apSize; ap++)
586 AlignmentPanel apanel = af.alignPanels.get(ap);
587 String fileName = apSize == 1 ? shortName : ap + shortName;
588 if (!fileName.endsWith(".xml"))
590 fileName = fileName + ".xml";
593 saveState(apanel, fileName, jout, viewIds);
595 String dssid = getDatasetIdRef(
596 af.getViewport().getAlignment().getDataset());
597 if (!dsses.containsKey(dssid))
599 dsses.put(dssid, af);
604 writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix,
610 } catch (Exception foo)
615 } catch (Exception ex)
617 // TODO: inform user of the problem - they need to know if their data was
619 if (errorMessage == null)
621 errorMessage = "Couldn't write Jalview Archive - see error output for details";
623 ex.printStackTrace();
628 * Generates a distinct file name, based on the title of the AlignFrame, by
629 * appending _n for increasing n until an unused name is generated. The new
630 * name (without its extension) is added to the list.
634 * @return the generated name, with .xml extension
636 protected String makeFilename(AlignFrame af, List<String> namesUsed)
638 String shortName = af.getTitle();
640 if (shortName.indexOf(File.separatorChar) > -1)
642 shortName = shortName
643 .substring(shortName.lastIndexOf(File.separatorChar) + 1);
648 while (namesUsed.contains(shortName))
650 if (shortName.endsWith("_" + (count - 1)))
652 shortName = shortName.substring(0, shortName.lastIndexOf("_"));
655 shortName = shortName.concat("_" + count);
659 namesUsed.add(shortName);
661 if (!shortName.endsWith(".xml"))
663 shortName = shortName + ".xml";
668 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
669 public boolean saveAlignment(AlignFrame af, String jarFile,
674 FileOutputStream fos = new FileOutputStream(jarFile);
675 JarOutputStream jout = new JarOutputStream(fos);
676 List<AlignFrame> frames = new ArrayList<>();
678 // resolve splitframes
679 if (af.getViewport().getCodingComplement() != null)
681 frames = ((SplitFrame) af.getSplitViewContainer()).getAlignFrames();
687 saveAllFrames(frames, jout);
691 } catch (Exception foo)
697 } catch (Exception ex)
699 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
700 ex.printStackTrace();
705 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
706 String fileName, JarOutputStream jout)
709 for (String dssids : dsses.keySet())
711 AlignFrame _af = dsses.get(dssids);
712 String jfileName = fileName + " Dataset for " + _af.getTitle();
713 if (!jfileName.endsWith(".xml"))
715 jfileName = jfileName + ".xml";
717 saveState(_af.alignPanel, jfileName, true, jout, null);
722 * create a JalviewModel from an alignment view and marshall it to a
726 * panel to create jalview model for
728 * name of alignment panel written to output stream
735 public JalviewModel saveState(AlignmentPanel ap, String fileName,
736 JarOutputStream jout, List<String> viewIds)
738 return saveState(ap, fileName, false, jout, viewIds);
742 * create a JalviewModel from an alignment view and marshall it to a
746 * panel to create jalview model for
748 * name of alignment panel written to output stream
750 * when true, only write the dataset for the alignment, not the data
751 * associated with the view.
757 public JalviewModel saveState(AlignmentPanel ap, String fileName,
758 boolean storeDS, JarOutputStream jout, List<String> viewIds)
762 viewIds = new ArrayList<>();
767 List<UserColourScheme> userColours = new ArrayList<>();
769 AlignViewport av = ap.av;
770 ViewportRanges vpRanges = av.getRanges();
772 JalviewModel object = new JalviewModel();
773 object.setVamsasModel(new jalview.schemabinding.version2.VamsasModel());
775 object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
777 jalview.bin.Cache.getDefault("VERSION", "Development Build"));
780 * rjal is full height alignment, jal is actual alignment with full metadata
781 * but excludes hidden sequences.
783 jalview.datamodel.AlignmentI rjal = av.getAlignment(), jal = rjal;
785 if (av.hasHiddenRows())
787 rjal = jal.getHiddenSequences().getFullAlignment();
790 SequenceSet vamsasSet = new SequenceSet();
792 JalviewModelSequence jms = new JalviewModelSequence();
794 vamsasSet.setGapChar(jal.getGapCharacter() + "");
796 if (jal.getDataset() != null)
798 // dataset id is the dataset's hashcode
799 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
802 // switch jal and the dataset
803 jal = jal.getDataset();
807 if (jal.getProperties() != null)
809 Enumeration en = jal.getProperties().keys();
810 while (en.hasMoreElements())
812 String key = en.nextElement().toString();
813 SequenceSetProperties ssp = new SequenceSetProperties();
815 ssp.setValue(jal.getProperties().get(key).toString());
816 vamsasSet.addSequenceSetProperties(ssp);
821 Set<String> calcIdSet = new HashSet<>();
822 // record the set of vamsas sequence XML POJO we create.
823 HashMap<String, Sequence> vamsasSetIds = new HashMap<>();
825 for (final SequenceI jds : rjal.getSequences())
827 final SequenceI jdatasq = jds.getDatasetSequence() == null ? jds
828 : jds.getDatasetSequence();
829 String id = seqHash(jds);
830 if (vamsasSetIds.get(id) == null)
832 if (seqRefIds.get(id) != null && !storeDS)
834 // This happens for two reasons: 1. multiple views are being
836 // 2. the hashCode has collided with another sequence's code. This
838 // HAPPEN! (PF00072.15.stk does this)
839 // JBPNote: Uncomment to debug writing out of files that do not read
840 // back in due to ArrayOutOfBoundExceptions.
841 // System.err.println("vamsasSeq backref: "+id+"");
842 // System.err.println(jds.getName()+"
843 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
844 // System.err.println("Hashcode: "+seqHash(jds));
845 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
846 // System.err.println(rsq.getName()+"
847 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
848 // System.err.println("Hashcode: "+seqHash(rsq));
852 vamsasSeq = createVamsasSequence(id, jds);
853 vamsasSet.addSequence(vamsasSeq);
854 vamsasSetIds.put(id, vamsasSeq);
855 seqRefIds.put(id, jds);
859 jseq.setStart(jds.getStart());
860 jseq.setEnd(jds.getEnd());
861 jseq.setColour(av.getSequenceColour(jds).getRGB());
863 jseq.setId(id); // jseq id should be a string not a number
866 // Store any sequences this sequence represents
867 if (av.hasHiddenRows())
869 // use rjal, contains the full height alignment
871 av.getAlignment().getHiddenSequences().isHidden(jds));
873 if (av.isHiddenRepSequence(jds))
875 jalview.datamodel.SequenceI[] reps = av
876 .getRepresentedSequences(jds).getSequencesInOrder(rjal);
878 for (int h = 0; h < reps.length; h++)
882 jseq.addHiddenSequences(rjal.findIndex(reps[h]));
887 // mark sequence as reference - if it is the reference for this view
890 jseq.setViewreference(jds == jal.getSeqrep());
894 // TODO: omit sequence features from each alignment view's XML dump if we
895 // are storing dataset
896 List<jalview.datamodel.SequenceFeature> sfs = jds
897 .getSequenceFeatures();
898 for (SequenceFeature sf : sfs)
900 Features features = new Features();
902 features.setBegin(sf.getBegin());
903 features.setEnd(sf.getEnd());
904 features.setDescription(sf.getDescription());
905 features.setType(sf.getType());
906 features.setFeatureGroup(sf.getFeatureGroup());
907 features.setScore(sf.getScore());
908 if (sf.links != null)
910 for (int l = 0; l < sf.links.size(); l++)
912 OtherData keyValue = new OtherData();
913 keyValue.setKey("LINK_" + l);
914 keyValue.setValue(sf.links.elementAt(l).toString());
915 features.addOtherData(keyValue);
918 if (sf.otherDetails != null)
921 * save feature attributes, which may be simple strings or
922 * map valued (have sub-attributes)
924 for (Entry<String, Object> entry : sf.otherDetails.entrySet())
926 String key = entry.getKey();
927 Object value = entry.getValue();
928 if (value instanceof Map<?, ?>)
930 for (Entry<String, Object> subAttribute : ((Map<String, Object>) value)
933 OtherData otherData = new OtherData();
934 otherData.setKey(key);
935 otherData.setKey2(subAttribute.getKey());
936 otherData.setValue(subAttribute.getValue().toString());
937 features.addOtherData(otherData);
942 OtherData otherData = new OtherData();
943 otherData.setKey(key);
944 otherData.setValue(value.toString());
945 features.addOtherData(otherData);
950 jseq.addFeatures(features);
953 if (jdatasq.getAllPDBEntries() != null)
955 Enumeration en = jdatasq.getAllPDBEntries().elements();
956 while (en.hasMoreElements())
958 Pdbids pdb = new Pdbids();
959 jalview.datamodel.PDBEntry entry = (jalview.datamodel.PDBEntry) en
962 String pdbId = entry.getId();
964 pdb.setType(entry.getType());
967 * Store any structure views associated with this sequence. This
968 * section copes with duplicate entries in the project, so a dataset
969 * only view *should* be coped with sensibly.
971 // This must have been loaded, is it still visible?
972 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
973 String matchedFile = null;
974 for (int f = frames.length - 1; f > -1; f--)
976 if (frames[f] instanceof StructureViewerBase)
978 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
979 matchedFile = saveStructureState(ap, jds, pdb, entry, viewIds,
980 matchedFile, viewFrame);
982 * Only store each structure viewer's state once in the project
983 * jar. First time through only (storeDS==false)
985 String viewId = viewFrame.getViewId();
986 if (!storeDS && !viewIds.contains(viewId))
991 String viewerState = viewFrame.getStateInfo();
992 writeJarEntry(jout, getViewerJarEntryName(viewId),
993 viewerState.getBytes());
994 } catch (IOException e)
997 "Error saving viewer state: " + e.getMessage());
1003 if (matchedFile != null || entry.getFile() != null)
1005 if (entry.getFile() != null)
1008 matchedFile = entry.getFile();
1010 pdb.setFile(matchedFile); // entry.getFile());
1011 if (pdbfiles == null)
1013 pdbfiles = new ArrayList<>();
1016 if (!pdbfiles.contains(pdbId))
1018 pdbfiles.add(pdbId);
1019 copyFileToJar(jout, matchedFile, pdbId);
1023 Enumeration<String> props = entry.getProperties();
1024 if (props.hasMoreElements())
1026 PdbentryItem item = new PdbentryItem();
1027 while (props.hasMoreElements())
1029 Property prop = new Property();
1030 String key = props.nextElement();
1032 prop.setValue(entry.getProperty(key).toString());
1033 item.addProperty(prop);
1035 pdb.addPdbentryItem(item);
1038 jseq.addPdbids(pdb);
1042 saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
1047 if (!storeDS && av.hasHiddenRows())
1049 jal = av.getAlignment();
1053 if (storeDS && jal.getCodonFrames() != null)
1055 List<AlignedCodonFrame> jac = jal.getCodonFrames();
1056 for (AlignedCodonFrame acf : jac)
1058 AlcodonFrame alc = new AlcodonFrame();
1059 if (acf.getProtMappings() != null
1060 && acf.getProtMappings().length > 0)
1062 boolean hasMap = false;
1063 SequenceI[] dnas = acf.getdnaSeqs();
1064 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1065 for (int m = 0; m < pmaps.length; m++)
1067 AlcodMap alcmap = new AlcodMap();
1068 alcmap.setDnasq(seqHash(dnas[m]));
1070 createVamsasMapping(pmaps[m], dnas[m], null, false));
1071 alc.addAlcodMap(alcmap);
1076 vamsasSet.addAlcodonFrame(alc);
1079 // TODO: delete this ? dead code from 2.8.3->2.9 ?
1081 // AlcodonFrame alc = new AlcodonFrame();
1082 // vamsasSet.addAlcodonFrame(alc);
1083 // for (int p = 0; p < acf.aaWidth; p++)
1085 // Alcodon cmap = new Alcodon();
1086 // if (acf.codons[p] != null)
1088 // // Null codons indicate a gapped column in the translated peptide
1090 // cmap.setPos1(acf.codons[p][0]);
1091 // cmap.setPos2(acf.codons[p][1]);
1092 // cmap.setPos3(acf.codons[p][2]);
1094 // alc.addAlcodon(cmap);
1096 // if (acf.getProtMappings() != null
1097 // && acf.getProtMappings().length > 0)
1099 // SequenceI[] dnas = acf.getdnaSeqs();
1100 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1101 // for (int m = 0; m < pmaps.length; m++)
1103 // AlcodMap alcmap = new AlcodMap();
1104 // alcmap.setDnasq(seqHash(dnas[m]));
1105 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
1107 // alc.addAlcodMap(alcmap);
1114 // /////////////////////////////////
1115 if (!storeDS && av.getCurrentTree() != null)
1117 // FIND ANY ASSOCIATED TREES
1118 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
1119 if (Desktop.desktop != null)
1121 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1123 for (int t = 0; t < frames.length; t++)
1125 if (frames[t] instanceof TreePanel)
1127 TreePanel tp = (TreePanel) frames[t];
1129 if (tp.treeCanvas.av.getAlignment() == jal)
1131 Tree tree = new Tree();
1132 tree.setTitle(tp.getTitle());
1133 tree.setCurrentTree((av.getCurrentTree() == tp.getTree()));
1134 tree.setNewick(tp.getTree().print());
1135 tree.setThreshold(tp.treeCanvas.threshold);
1137 tree.setFitToWindow(tp.fitToWindow.getState());
1138 tree.setFontName(tp.getTreeFont().getName());
1139 tree.setFontSize(tp.getTreeFont().getSize());
1140 tree.setFontStyle(tp.getTreeFont().getStyle());
1141 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
1143 tree.setShowBootstrap(tp.bootstrapMenu.getState());
1144 tree.setShowDistances(tp.distanceMenu.getState());
1146 tree.setHeight(tp.getHeight());
1147 tree.setWidth(tp.getWidth());
1148 tree.setXpos(tp.getX());
1149 tree.setYpos(tp.getY());
1150 tree.setId(makeHashCode(tp, null));
1151 tree.setLinkToAllViews(tp.treeCanvas.applyToAllViews);
1162 if (!storeDS && Desktop.desktop != null)
1164 for (JInternalFrame frame : Desktop.desktop.getAllFrames())
1166 if (frame instanceof PCAPanel)
1168 PCAPanel panel = (PCAPanel) frame;
1169 if (panel.av.getAlignment() == jal)
1171 savePCA(panel, jms);
1179 * store forward refs from an annotationRow to any groups
1181 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<>();
1184 for (SequenceI sq : jal.getSequences())
1186 // Store annotation on dataset sequences only
1187 AlignmentAnnotation[] aa = sq.getAnnotation();
1188 if (aa != null && aa.length > 0)
1190 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1197 if (jal.getAlignmentAnnotation() != null)
1199 // Store the annotation shown on the alignment.
1200 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1201 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1206 if (jal.getGroups() != null)
1208 JGroup[] groups = new JGroup[jal.getGroups().size()];
1210 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1212 JGroup jGroup = new JGroup();
1213 groups[++i] = jGroup;
1215 jGroup.setStart(sg.getStartRes());
1216 jGroup.setEnd(sg.getEndRes());
1217 jGroup.setName(sg.getName());
1218 if (groupRefs.containsKey(sg))
1220 // group has references so set its ID field
1221 jGroup.setId(groupRefs.get(sg));
1223 ColourSchemeI colourScheme = sg.getColourScheme();
1224 if (colourScheme != null)
1226 ResidueShaderI groupColourScheme = sg.getGroupColourScheme();
1227 if (groupColourScheme.conservationApplied())
1229 jGroup.setConsThreshold(groupColourScheme.getConservationInc());
1231 if (colourScheme instanceof jalview.schemes.UserColourScheme)
1234 setUserColourScheme(colourScheme, userColours, jms));
1238 jGroup.setColour(colourScheme.getSchemeName());
1241 else if (colourScheme instanceof jalview.schemes.AnnotationColourGradient)
1243 jGroup.setColour("AnnotationColourGradient");
1244 jGroup.setAnnotationColours(constructAnnotationColours(
1245 (jalview.schemes.AnnotationColourGradient) colourScheme,
1248 else if (colourScheme instanceof jalview.schemes.UserColourScheme)
1251 setUserColourScheme(colourScheme, userColours, jms));
1255 jGroup.setColour(colourScheme.getSchemeName());
1258 jGroup.setPidThreshold(groupColourScheme.getThreshold());
1261 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1262 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1263 jGroup.setDisplayText(sg.getDisplayText());
1264 jGroup.setColourText(sg.getColourText());
1265 jGroup.setTextCol1(sg.textColour.getRGB());
1266 jGroup.setTextCol2(sg.textColour2.getRGB());
1267 jGroup.setTextColThreshold(sg.thresholdTextColour);
1268 jGroup.setShowUnconserved(sg.getShowNonconserved());
1269 jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1270 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1271 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1272 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1273 for (SequenceI seq : sg.getSequences())
1275 jGroup.addSeq(seqHash(seq));
1279 jms.setJGroup(groups);
1283 // /////////SAVE VIEWPORT
1284 Viewport view = new Viewport();
1285 view.setTitle(ap.alignFrame.getTitle());
1286 view.setSequenceSetId(
1287 makeHashCode(av.getSequenceSetId(), av.getSequenceSetId()));
1288 view.setId(av.getViewId());
1289 if (av.getCodingComplement() != null)
1291 view.setComplementId(av.getCodingComplement().getViewId());
1293 view.setViewName(av.viewName);
1294 view.setGatheredViews(av.isGatherViewsHere());
1296 Rectangle size = ap.av.getExplodedGeometry();
1297 Rectangle position = size;
1300 size = ap.alignFrame.getBounds();
1301 if (av.getCodingComplement() != null)
1303 position = ((SplitFrame) ap.alignFrame.getSplitViewContainer())
1311 view.setXpos(position.x);
1312 view.setYpos(position.y);
1314 view.setWidth(size.width);
1315 view.setHeight(size.height);
1317 view.setStartRes(vpRanges.getStartRes());
1318 view.setStartSeq(vpRanges.getStartSeq());
1320 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1322 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1326 .getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1328 AnnotationColours ac = constructAnnotationColours(
1329 (jalview.schemes.AnnotationColourGradient) av
1330 .getGlobalColourScheme(),
1333 view.setAnnotationColours(ac);
1334 view.setBgColour("AnnotationColourGradient");
1338 view.setBgColour(ColourSchemeProperty
1339 .getColourName(av.getGlobalColourScheme()));
1342 ResidueShaderI vcs = av.getResidueShading();
1343 ColourSchemeI cs = av.getGlobalColourScheme();
1347 if (vcs.conservationApplied())
1349 view.setConsThreshold(vcs.getConservationInc());
1350 if (cs instanceof jalview.schemes.UserColourScheme)
1352 view.setBgColour(setUserColourScheme(cs, userColours, jms));
1355 view.setPidThreshold(vcs.getThreshold());
1358 view.setConservationSelected(av.getConservationSelected());
1359 view.setPidSelected(av.getAbovePIDThreshold());
1360 view.setFontName(av.font.getName());
1361 view.setFontSize(av.font.getSize());
1362 view.setFontStyle(av.font.getStyle());
1363 view.setScaleProteinAsCdna(av.getViewStyle().isScaleProteinAsCdna());
1364 view.setRenderGaps(av.isRenderGaps());
1365 view.setShowAnnotation(av.isShowAnnotation());
1366 view.setShowBoxes(av.getShowBoxes());
1367 view.setShowColourText(av.getColourText());
1368 view.setShowFullId(av.getShowJVSuffix());
1369 view.setRightAlignIds(av.isRightAlignIds());
1370 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1371 view.setShowText(av.getShowText());
1372 view.setShowUnconserved(av.getShowUnconserved());
1373 view.setWrapAlignment(av.getWrapAlignment());
1374 view.setTextCol1(av.getTextColour().getRGB());
1375 view.setTextCol2(av.getTextColour2().getRGB());
1376 view.setTextColThreshold(av.getThresholdTextColour());
1377 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1378 view.setShowSequenceLogo(av.isShowSequenceLogo());
1379 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1380 view.setShowGroupConsensus(av.isShowGroupConsensus());
1381 view.setShowGroupConservation(av.isShowGroupConservation());
1382 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1383 view.setShowDbRefTooltip(av.isShowDBRefs());
1384 view.setFollowHighlight(av.isFollowHighlight());
1385 view.setFollowSelection(av.followSelection);
1386 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1387 if (av.getFeaturesDisplayed() != null)
1389 jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
1391 FeatureRenderer fr = ap.getSeqPanel().seqCanvas
1392 .getFeatureRenderer();
1393 String[] renderOrder = fr.getRenderOrder().toArray(new String[0]);
1395 Vector<String> settingsAdded = new Vector<>();
1396 if (renderOrder != null)
1398 for (String featureType : renderOrder)
1400 Setting setting = new Setting();
1401 setting.setType(featureType);
1404 * save any filter for the feature type
1406 FeatureMatcherSetI filter = fr.getFeatureFilter(featureType);
1407 if (filter != null) {
1408 Iterator<FeatureMatcherI> filters = filter.getMatchers().iterator();
1409 FeatureMatcherI firstFilter = filters.next();
1410 setting.setMatcherSet(Jalview2XML.marshalFilter(
1411 firstFilter, filters, filter.isAnded()));
1415 * save colour scheme for the feature type
1417 FeatureColourI fcol = fr.getFeatureStyle(featureType);
1418 if (!fcol.isSimpleColour())
1420 setting.setColour(fcol.getMaxColour().getRGB());
1421 setting.setMincolour(fcol.getMinColour().getRGB());
1422 setting.setMin(fcol.getMin());
1423 setting.setMax(fcol.getMax());
1424 setting.setColourByLabel(fcol.isColourByLabel());
1425 if (fcol.isColourByAttribute())
1427 setting.setAttributeName(fcol.getAttributeName());
1429 setting.setAutoScale(fcol.isAutoScaled());
1430 setting.setThreshold(fcol.getThreshold());
1431 Color noColour = fcol.getNoColour();
1432 if (noColour == null)
1434 setting.setNoValueColour(NoValueColour.NONE);
1436 else if (noColour.equals(fcol.getMaxColour()))
1438 setting.setNoValueColour(NoValueColour.MAX);
1442 setting.setNoValueColour(NoValueColour.MIN);
1444 // -1 = No threshold, 0 = Below, 1 = Above
1445 setting.setThreshstate(fcol.isAboveThreshold() ? 1
1446 : (fcol.isBelowThreshold() ? 0 : -1));
1450 setting.setColour(fcol.getColour().getRGB());
1454 av.getFeaturesDisplayed().isVisible(featureType));
1456 .getOrder(featureType);
1459 setting.setOrder(rorder);
1461 fs.addSetting(setting);
1462 settingsAdded.addElement(featureType);
1466 // is groups actually supposed to be a map here ?
1467 Iterator<String> en = fr.getFeatureGroups().iterator();
1468 Vector<String> groupsAdded = new Vector<>();
1469 while (en.hasNext())
1471 String grp = en.next();
1472 if (groupsAdded.contains(grp))
1476 Group g = new Group();
1478 g.setDisplay(((Boolean) fr.checkGroupVisibility(grp, false))
1481 groupsAdded.addElement(grp);
1483 jms.setFeatureSettings(fs);
1486 if (av.hasHiddenColumns())
1488 jalview.datamodel.HiddenColumns hidden = av.getAlignment()
1489 .getHiddenColumns();
1492 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1496 Iterator<int[]> hiddenRegions = hidden.iterator();
1497 while (hiddenRegions.hasNext())
1499 int[] region = hiddenRegions.next();
1500 HiddenColumns hc = new HiddenColumns();
1501 hc.setStart(region[0]);
1502 hc.setEnd(region[1]);
1503 view.addHiddenColumns(hc);
1507 if (calcIdSet.size() > 0)
1509 for (String calcId : calcIdSet)
1511 if (calcId.trim().length() > 0)
1513 CalcIdParam cidp = createCalcIdParam(calcId, av);
1514 // Some calcIds have no parameters.
1517 view.addCalcIdParam(cidp);
1523 jms.addViewport(view);
1525 object.setJalviewModelSequence(jms);
1526 object.getVamsasModel().addSequenceSet(vamsasSet);
1528 if (jout != null && fileName != null)
1530 // We may not want to write the object to disk,
1531 // eg we can copy the alignViewport to a new view object
1532 // using save and then load
1535 System.out.println("Writing jar entry " + fileName);
1536 JarEntry entry = new JarEntry(fileName);
1537 jout.putNextEntry(entry);
1538 PrintWriter pout = new PrintWriter(
1539 new OutputStreamWriter(jout, UTF_8));
1540 Marshaller marshaller = new Marshaller(pout);
1541 marshaller.marshal(object);
1544 } catch (Exception ex)
1546 // TODO: raise error in GUI if marshalling failed.
1547 ex.printStackTrace();
1554 * Writes PCA viewer attributes and computed values to an XML model object and adds it to the JalviewModel. Any exceptions are reported by logging.
1556 protected void savePCA(PCAPanel panel, JalviewModelSequence jms)
1560 PcaViewer viewer = new PcaViewer();
1561 viewer.setHeight(panel.getHeight());
1562 viewer.setWidth(panel.getWidth());
1563 viewer.setXpos(panel.getX());
1564 viewer.setYpos(panel.getY());
1565 viewer.setTitle(panel.getTitle());
1566 PCAModel pcaModel = panel.pcaModel;
1567 viewer.setScoreModelName(pcaModel.getScoreModelName());
1568 viewer.setXDim(panel.getSelectedDimensionIndex(X));
1569 viewer.setYDim(panel.getSelectedDimensionIndex(Y));
1570 viewer.setZDim(panel.getSelectedDimensionIndex(Z));
1571 viewer.setBgColour(panel.rc.getBackgroundColour().getRGB());
1572 viewer.setScaleFactor(panel.rc.scaleFactor);
1573 float[] spMin = panel.rc.getSeqMin();
1574 SeqPointMin spmin = new SeqPointMin();
1575 spmin.setXPos(spMin[0]);
1576 spmin.setYPos(spMin[1]);
1577 spmin.setZPos(spMin[2]);
1578 viewer.setSeqPointMin(spmin);
1579 float[] spMax = panel.rc.getSeqMax();
1580 SeqPointMax spmax = new SeqPointMax();
1581 spmax.setXPos(spMax[0]);
1582 spmax.setYPos(spMax[1]);
1583 spmax.setZPos(spMax[2]);
1584 viewer.setSeqPointMax(spmax);
1585 viewer.setShowLabels(panel.rc.showLabels);
1586 viewer.setLinkToAllViews(panel.rc.applyToAllViews);
1587 SimilarityParamsI sp = pcaModel.getSimilarityParameters();
1588 viewer.setIncludeGaps(sp.includeGaps());
1589 viewer.setMatchGaps(sp.matchGaps());
1590 viewer.setIncludeGappedColumns(sp.includeGappedColumns());
1591 viewer.setDenominateByShortestLength(sp.denominateByShortestLength());
1594 * sequence points on display
1596 for (jalview.datamodel.SequencePoint spt : pcaModel
1597 .getSequencePoints())
1599 SequencePoint point = new SequencePoint();
1600 point.setSequenceRef(seqHash(spt.getSequence()));
1601 point.setXPos(spt.coord.x);
1602 point.setYPos(spt.coord.y);
1603 point.setZPos(spt.coord.z);
1604 viewer.addSequencePoint(point);
1608 * (end points of) axes on display
1610 for (Point p : panel.rc.axisEndPoints)
1612 Axis axis = new Axis();
1616 viewer.addAxis(axis);
1622 PcaData data = new PcaData();
1623 viewer.setPcaData(data);
1624 PCA pca = pcaModel.getPcaData();
1625 data.setDetails(pca.getDetails());
1626 MatrixI m = pca.getEigenmatrix();
1627 EigenMatrix eigenMatrix = new EigenMatrix();
1628 eigenMatrix.setRows(m.height());
1629 eigenMatrix.setColumns(m.width());
1630 data.setEigenMatrix(eigenMatrix);
1631 for (int i = 0; i < m.height(); i++)
1633 Row row = new Row();
1634 for (int j = 0; j < m.width(); j++)
1636 row.addD(m.getValue(i, j));
1638 eigenMatrix.addRow(row);
1640 EigenMatrixD eigenMatrixD = new EigenMatrixD();
1641 eigenMatrixD.setD(m.getD());
1642 data.setEigenMatrixD(eigenMatrixD);
1643 EigenMatrixE eigenMatrixE = new EigenMatrixE();
1644 eigenMatrixE.setD(m.getE());
1645 data.setEigenMatrixE(eigenMatrixE);
1647 PairwiseMatrix pm = new PairwiseMatrix();
1648 m = pca.getPairwiseScores();
1649 pm.setRows(m.height());
1650 pm.setColumns(m.width());
1651 data.setPairwiseMatrix(pm);
1652 for (int i = 0; i < m.height(); i++)
1654 Row row = new Row();
1655 for (int j = 0; j < m.width(); j++)
1657 row.addD(m.getValue(i, j));
1662 jms.addPcaViewer(viewer);
1663 } catch (Throwable t)
1665 Cache.log.error("Error saving PCA: " + t.getMessage());
1670 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1671 * for each viewer, with
1673 * <li>viewer geometry (position, size, split pane divider location)</li>
1674 * <li>index of the selected structure in the viewer (currently shows gapped
1676 * <li>the id of the annotation holding RNA secondary structure</li>
1677 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1679 * Varna viewer state is also written out (in native Varna XML) to separate
1680 * project jar entries. A separate entry is written for each RNA structure
1681 * displayed, with the naming convention
1683 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
1691 * @param storeDataset
1693 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
1694 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
1695 boolean storeDataset)
1697 if (Desktop.desktop == null)
1701 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1702 for (int f = frames.length - 1; f > -1; f--)
1704 if (frames[f] instanceof AppVarna)
1706 AppVarna varna = (AppVarna) frames[f];
1708 * link the sequence to every viewer that is showing it and is linked to
1709 * its alignment panel
1711 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1713 String viewId = varna.getViewId();
1714 RnaViewer rna = new RnaViewer();
1715 rna.setViewId(viewId);
1716 rna.setTitle(varna.getTitle());
1717 rna.setXpos(varna.getX());
1718 rna.setYpos(varna.getY());
1719 rna.setWidth(varna.getWidth());
1720 rna.setHeight(varna.getHeight());
1721 rna.setDividerLocation(varna.getDividerLocation());
1722 rna.setSelectedRna(varna.getSelectedIndex());
1723 jseq.addRnaViewer(rna);
1726 * Store each Varna panel's state once in the project per sequence.
1727 * First time through only (storeDataset==false)
1729 // boolean storeSessions = false;
1730 // String sequenceViewId = viewId + seqsToIds.get(jds);
1731 // if (!storeDataset && !viewIds.contains(sequenceViewId))
1733 // viewIds.add(sequenceViewId);
1734 // storeSessions = true;
1736 for (RnaModel model : varna.getModels())
1738 if (model.seq == jds)
1741 * VARNA saves each view (sequence or alignment secondary
1742 * structure, gapped or trimmed) as a separate XML file
1744 String jarEntryName = rnaSessions.get(model);
1745 if (jarEntryName == null)
1748 String varnaStateFile = varna.getStateInfo(model.rna);
1749 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
1750 copyFileToJar(jout, varnaStateFile, jarEntryName);
1751 rnaSessions.put(model, jarEntryName);
1753 SecondaryStructure ss = new SecondaryStructure();
1754 String annotationId = varna.getAnnotation(jds).annotationId;
1755 ss.setAnnotationId(annotationId);
1756 ss.setViewerState(jarEntryName);
1757 ss.setGapped(model.gapped);
1758 ss.setTitle(model.title);
1759 rna.addSecondaryStructure(ss);
1768 * Copy the contents of a file to a new entry added to the output jar
1772 * @param jarEntryName
1774 protected void copyFileToJar(JarOutputStream jout, String infilePath,
1775 String jarEntryName)
1777 DataInputStream dis = null;
1780 File file = new File(infilePath);
1781 if (file.exists() && jout != null)
1783 dis = new DataInputStream(new FileInputStream(file));
1784 byte[] data = new byte[(int) file.length()];
1785 dis.readFully(data);
1786 writeJarEntry(jout, jarEntryName, data);
1788 } catch (Exception ex)
1790 ex.printStackTrace();
1798 } catch (IOException e)
1807 * Write the data to a new entry of given name in the output jar file
1810 * @param jarEntryName
1812 * @throws IOException
1814 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
1815 byte[] data) throws IOException
1819 System.out.println("Writing jar entry " + jarEntryName);
1820 jout.putNextEntry(new JarEntry(jarEntryName));
1821 DataOutputStream dout = new DataOutputStream(jout);
1822 dout.write(data, 0, data.length);
1829 * Save the state of a structure viewer
1834 * the archive XML element under which to save the state
1837 * @param matchedFile
1841 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
1842 Pdbids pdb, PDBEntry entry, List<String> viewIds,
1843 String matchedFile, StructureViewerBase viewFrame)
1845 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
1848 * Look for any bindings for this viewer to the PDB file of interest
1849 * (including part matches excluding chain id)
1851 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
1853 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
1854 final String pdbId = pdbentry.getId();
1855 if (!pdbId.equals(entry.getId())
1856 && !(entry.getId().length() > 4 && entry.getId().toLowerCase()
1857 .startsWith(pdbId.toLowerCase())))
1860 * not interested in a binding to a different PDB entry here
1864 if (matchedFile == null)
1866 matchedFile = pdbentry.getFile();
1868 else if (!matchedFile.equals(pdbentry.getFile()))
1871 "Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
1872 + pdbentry.getFile());
1876 // can get at it if the ID
1877 // match is ambiguous (e.g.
1880 for (int smap = 0; smap < viewFrame.getBinding()
1881 .getSequence()[peid].length; smap++)
1883 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
1884 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
1886 StructureState state = new StructureState();
1887 state.setVisible(true);
1888 state.setXpos(viewFrame.getX());
1889 state.setYpos(viewFrame.getY());
1890 state.setWidth(viewFrame.getWidth());
1891 state.setHeight(viewFrame.getHeight());
1892 final String viewId = viewFrame.getViewId();
1893 state.setViewId(viewId);
1894 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
1895 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
1896 state.setColourByJmol(viewFrame.isColouredByViewer());
1897 state.setType(viewFrame.getViewerType().toString());
1898 pdb.addStructureState(state);
1906 * Populates the AnnotationColours xml for save. This captures the settings of
1907 * the options in the 'Colour by Annotation' dialog.
1910 * @param userColours
1914 private AnnotationColours constructAnnotationColours(
1915 AnnotationColourGradient acg, List<UserColourScheme> userColours,
1916 JalviewModelSequence jms)
1918 AnnotationColours ac = new AnnotationColours();
1919 ac.setAboveThreshold(acg.getAboveThreshold());
1920 ac.setThreshold(acg.getAnnotationThreshold());
1921 // 2.10.2 save annotationId (unique) not annotation label
1922 ac.setAnnotation(acg.getAnnotation().annotationId);
1923 if (acg.getBaseColour() instanceof UserColourScheme)
1926 setUserColourScheme(acg.getBaseColour(), userColours, jms));
1931 ColourSchemeProperty.getColourName(acg.getBaseColour()));
1934 ac.setMaxColour(acg.getMaxColour().getRGB());
1935 ac.setMinColour(acg.getMinColour().getRGB());
1936 ac.setPerSequence(acg.isSeqAssociated());
1937 ac.setPredefinedColours(acg.isPredefinedColours());
1941 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
1942 IdentityHashMap<SequenceGroup, String> groupRefs,
1943 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
1944 SequenceSet vamsasSet)
1947 for (int i = 0; i < aa.length; i++)
1949 Annotation an = new Annotation();
1951 AlignmentAnnotation annotation = aa[i];
1952 if (annotation.annotationId != null)
1954 annotationIds.put(annotation.annotationId, annotation);
1957 an.setId(annotation.annotationId);
1959 an.setVisible(annotation.visible);
1961 an.setDescription(annotation.description);
1963 if (annotation.sequenceRef != null)
1965 // 2.9 JAL-1781 xref on sequence id rather than name
1966 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
1968 if (annotation.groupRef != null)
1970 String groupIdr = groupRefs.get(annotation.groupRef);
1971 if (groupIdr == null)
1973 // make a locally unique String
1974 groupRefs.put(annotation.groupRef,
1975 groupIdr = ("" + System.currentTimeMillis()
1976 + annotation.groupRef.getName()
1977 + groupRefs.size()));
1979 an.setGroupRef(groupIdr.toString());
1982 // store all visualization attributes for annotation
1983 an.setGraphHeight(annotation.graphHeight);
1984 an.setCentreColLabels(annotation.centreColLabels);
1985 an.setScaleColLabels(annotation.scaleColLabel);
1986 an.setShowAllColLabels(annotation.showAllColLabels);
1987 an.setBelowAlignment(annotation.belowAlignment);
1989 if (annotation.graph > 0)
1992 an.setGraphType(annotation.graph);
1993 an.setGraphGroup(annotation.graphGroup);
1994 if (annotation.getThreshold() != null)
1996 ThresholdLine line = new ThresholdLine();
1997 line.setLabel(annotation.getThreshold().label);
1998 line.setValue(annotation.getThreshold().value);
1999 line.setColour(annotation.getThreshold().colour.getRGB());
2000 an.setThresholdLine(line);
2008 an.setLabel(annotation.label);
2010 if (annotation == av.getAlignmentQualityAnnot()
2011 || annotation == av.getAlignmentConservationAnnotation()
2012 || annotation == av.getAlignmentConsensusAnnotation()
2013 || annotation.autoCalculated)
2015 // new way of indicating autocalculated annotation -
2016 an.setAutoCalculated(annotation.autoCalculated);
2018 if (annotation.hasScore())
2020 an.setScore(annotation.getScore());
2023 if (annotation.getCalcId() != null)
2025 calcIdSet.add(annotation.getCalcId());
2026 an.setCalcId(annotation.getCalcId());
2028 if (annotation.hasProperties())
2030 for (String pr : annotation.getProperties())
2032 Property prop = new Property();
2034 prop.setValue(annotation.getProperty(pr));
2035 an.addProperty(prop);
2039 AnnotationElement ae;
2040 if (annotation.annotations != null)
2042 an.setScoreOnly(false);
2043 for (int a = 0; a < annotation.annotations.length; a++)
2045 if ((annotation == null) || (annotation.annotations[a] == null))
2050 ae = new AnnotationElement();
2051 if (annotation.annotations[a].description != null)
2053 ae.setDescription(annotation.annotations[a].description);
2055 if (annotation.annotations[a].displayCharacter != null)
2057 ae.setDisplayCharacter(
2058 annotation.annotations[a].displayCharacter);
2061 if (!Float.isNaN(annotation.annotations[a].value))
2063 ae.setValue(annotation.annotations[a].value);
2067 if (annotation.annotations[a].secondaryStructure > ' ')
2069 ae.setSecondaryStructure(
2070 annotation.annotations[a].secondaryStructure + "");
2073 if (annotation.annotations[a].colour != null
2074 && annotation.annotations[a].colour != java.awt.Color.black)
2076 ae.setColour(annotation.annotations[a].colour.getRGB());
2079 an.addAnnotationElement(ae);
2080 if (annotation.autoCalculated)
2082 // only write one non-null entry into the annotation row -
2083 // sufficient to get the visualization attributes necessary to
2091 an.setScoreOnly(true);
2093 if (!storeDS || (storeDS && !annotation.autoCalculated))
2095 // skip autocalculated annotation - these are only provided for
2097 vamsasSet.addAnnotation(an);
2103 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
2105 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
2106 if (settings != null)
2108 CalcIdParam vCalcIdParam = new CalcIdParam();
2109 vCalcIdParam.setCalcId(calcId);
2110 vCalcIdParam.addServiceURL(settings.getServiceURI());
2111 // generic URI allowing a third party to resolve another instance of the
2112 // service used for this calculation
2113 for (String urls : settings.getServiceURLs())
2115 vCalcIdParam.addServiceURL(urls);
2117 vCalcIdParam.setVersion("1.0");
2118 if (settings.getPreset() != null)
2120 WsParamSetI setting = settings.getPreset();
2121 vCalcIdParam.setName(setting.getName());
2122 vCalcIdParam.setDescription(setting.getDescription());
2126 vCalcIdParam.setName("");
2127 vCalcIdParam.setDescription("Last used parameters");
2129 // need to be able to recover 1) settings 2) user-defined presets or
2130 // recreate settings from preset 3) predefined settings provided by
2131 // service - or settings that can be transferred (or discarded)
2132 vCalcIdParam.setParameters(
2133 settings.getWsParamFile().replace("\n", "|\\n|"));
2134 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
2135 // todo - decide if updateImmediately is needed for any projects.
2137 return vCalcIdParam;
2142 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
2145 if (calcIdParam.getVersion().equals("1.0"))
2147 Jws2Instance service = Jws2Discoverer.getDiscoverer()
2148 .getPreferredServiceFor(calcIdParam.getServiceURL());
2149 if (service != null)
2151 WsParamSetI parmSet = null;
2154 parmSet = service.getParamStore().parseServiceParameterFile(
2155 calcIdParam.getName(), calcIdParam.getDescription(),
2156 calcIdParam.getServiceURL(),
2157 calcIdParam.getParameters().replace("|\\n|", "\n"));
2158 } catch (IOException x)
2160 warn("Couldn't parse parameter data for "
2161 + calcIdParam.getCalcId(), x);
2164 List<ArgumentI> argList = null;
2165 if (calcIdParam.getName().length() > 0)
2167 parmSet = service.getParamStore()
2168 .getPreset(calcIdParam.getName());
2169 if (parmSet != null)
2171 // TODO : check we have a good match with settings in AACon -
2172 // otherwise we'll need to create a new preset
2177 argList = parmSet.getArguments();
2180 AAConSettings settings = new AAConSettings(
2181 calcIdParam.isAutoUpdate(), service, parmSet, argList);
2182 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
2183 calcIdParam.isNeedsUpdate());
2188 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
2192 throw new Error(MessageManager.formatMessage(
2193 "error.unsupported_version_calcIdparam", new Object[]
2194 { calcIdParam.toString() }));
2198 * External mapping between jalview objects and objects yielding a valid and
2199 * unique object ID string. This is null for normal Jalview project IO, but
2200 * non-null when a jalview project is being read or written as part of a
2203 IdentityHashMap jv2vobj = null;
2206 * Construct a unique ID for jvobj using either existing bindings or if none
2207 * exist, the result of the hashcode call for the object.
2210 * jalview data object
2211 * @return unique ID for referring to jvobj
2213 private String makeHashCode(Object jvobj, String altCode)
2215 if (jv2vobj != null)
2217 Object id = jv2vobj.get(jvobj);
2220 return id.toString();
2222 // check string ID mappings
2223 if (jvids2vobj != null && jvobj instanceof String)
2225 id = jvids2vobj.get(jvobj);
2229 return id.toString();
2231 // give up and warn that something has gone wrong
2232 warn("Cannot find ID for object in external mapping : " + jvobj);
2238 * return local jalview object mapped to ID, if it exists
2242 * @return null or object bound to idcode
2244 private Object retrieveExistingObj(String idcode)
2246 if (idcode != null && vobj2jv != null)
2248 return vobj2jv.get(idcode);
2254 * binding from ID strings from external mapping table to jalview data model
2257 private Hashtable vobj2jv;
2259 private Sequence createVamsasSequence(String id, SequenceI jds)
2261 return createVamsasSequence(true, id, jds, null);
2264 private Sequence createVamsasSequence(boolean recurse, String id,
2265 SequenceI jds, SequenceI parentseq)
2267 Sequence vamsasSeq = new Sequence();
2268 vamsasSeq.setId(id);
2269 vamsasSeq.setName(jds.getName());
2270 vamsasSeq.setSequence(jds.getSequenceAsString());
2271 vamsasSeq.setDescription(jds.getDescription());
2272 jalview.datamodel.DBRefEntry[] dbrefs = null;
2273 if (jds.getDatasetSequence() != null)
2275 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
2279 // seqId==dsseqid so we can tell which sequences really are
2280 // dataset sequences only
2281 vamsasSeq.setDsseqid(id);
2282 dbrefs = jds.getDBRefs();
2283 if (parentseq == null)
2290 for (int d = 0; d < dbrefs.length; d++)
2292 DBRef dbref = new DBRef();
2293 dbref.setSource(dbrefs[d].getSource());
2294 dbref.setVersion(dbrefs[d].getVersion());
2295 dbref.setAccessionId(dbrefs[d].getAccessionId());
2296 if (dbrefs[d].hasMap())
2298 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
2300 dbref.setMapping(mp);
2302 vamsasSeq.addDBRef(dbref);
2308 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
2309 SequenceI parentseq, SequenceI jds, boolean recurse)
2312 if (jmp.getMap() != null)
2316 jalview.util.MapList mlst = jmp.getMap();
2317 List<int[]> r = mlst.getFromRanges();
2318 for (int[] range : r)
2320 MapListFrom mfrom = new MapListFrom();
2321 mfrom.setStart(range[0]);
2322 mfrom.setEnd(range[1]);
2323 mp.addMapListFrom(mfrom);
2325 r = mlst.getToRanges();
2326 for (int[] range : r)
2328 MapListTo mto = new MapListTo();
2329 mto.setStart(range[0]);
2330 mto.setEnd(range[1]);
2331 mp.addMapListTo(mto);
2333 mp.setMapFromUnit(mlst.getFromRatio());
2334 mp.setMapToUnit(mlst.getToRatio());
2335 if (jmp.getTo() != null)
2337 MappingChoice mpc = new MappingChoice();
2339 // check/create ID for the sequence referenced by getTo()
2342 SequenceI ps = null;
2343 if (parentseq != jmp.getTo()
2344 && parentseq.getDatasetSequence() != jmp.getTo())
2346 // chaining dbref rather than a handshaking one
2347 jmpid = seqHash(ps = jmp.getTo());
2351 jmpid = seqHash(ps = parentseq);
2353 mpc.setDseqFor(jmpid);
2354 if (!seqRefIds.containsKey(mpc.getDseqFor()))
2356 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2357 seqRefIds.put(mpc.getDseqFor(), ps);
2361 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2364 mp.setMappingChoice(mpc);
2370 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2371 List<UserColourScheme> userColours, JalviewModelSequence jms)
2374 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2375 boolean newucs = false;
2376 if (!userColours.contains(ucs))
2378 userColours.add(ucs);
2381 id = "ucs" + userColours.indexOf(ucs);
2384 // actually create the scheme's entry in the XML model
2385 java.awt.Color[] colours = ucs.getColours();
2386 jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
2387 jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
2389 for (int i = 0; i < colours.length; i++)
2391 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2392 col.setName(ResidueProperties.aa[i]);
2393 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2394 jbucs.addColour(col);
2396 if (ucs.getLowerCaseColours() != null)
2398 colours = ucs.getLowerCaseColours();
2399 for (int i = 0; i < colours.length; i++)
2401 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2402 col.setName(ResidueProperties.aa[i].toLowerCase());
2403 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2404 jbucs.addColour(col);
2409 uc.setUserColourScheme(jbucs);
2410 jms.addUserColours(uc);
2416 jalview.schemes.UserColourScheme getUserColourScheme(
2417 JalviewModelSequence jms, String id)
2419 UserColours[] uc = jms.getUserColours();
2420 UserColours colours = null;
2422 for (int i = 0; i < uc.length; i++)
2424 if (uc[i].getId().equals(id))
2432 java.awt.Color[] newColours = new java.awt.Color[24];
2434 for (int i = 0; i < 24; i++)
2436 newColours[i] = new java.awt.Color(Integer.parseInt(
2437 colours.getUserColourScheme().getColour(i).getRGB(), 16));
2440 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2443 if (colours.getUserColourScheme().getColourCount() > 24)
2445 newColours = new java.awt.Color[23];
2446 for (int i = 0; i < 23; i++)
2448 newColours[i] = new java.awt.Color(Integer.parseInt(
2449 colours.getUserColourScheme().getColour(i + 24).getRGB(),
2452 ucs.setLowerCaseColours(newColours);
2459 * contains last error message (if any) encountered by XML loader.
2461 String errorMessage = null;
2464 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2465 * exceptions are raised during project XML parsing
2467 public boolean attemptversion1parse = true;
2470 * Load a jalview project archive from a jar file
2473 * - HTTP URL or filename
2475 public AlignFrame loadJalviewAlign(final String file)
2478 jalview.gui.AlignFrame af = null;
2482 // create list to store references for any new Jmol viewers created
2483 newStructureViewers = new Vector<>();
2484 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2485 // Workaround is to make sure caller implements the JarInputStreamProvider
2487 // so we can re-open the jar input stream for each entry.
2489 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2490 af = loadJalviewAlign(jprovider);
2491 af.setMenusForViewport();
2493 } catch (MalformedURLException e)
2495 errorMessage = "Invalid URL format for '" + file + "'";
2501 SwingUtilities.invokeAndWait(new Runnable()
2506 setLoadingFinishedForNewStructureViewers();
2509 } catch (Exception x)
2511 System.err.println("Error loading alignment: " + x.getMessage());
2517 private jarInputStreamProvider createjarInputStreamProvider(
2518 final String file) throws MalformedURLException
2521 errorMessage = null;
2522 uniqueSetSuffix = null;
2524 viewportsAdded.clear();
2525 frefedSequence = null;
2527 if (file.startsWith("http://"))
2529 url = new URL(file);
2531 final URL _url = url;
2532 return new jarInputStreamProvider()
2536 public JarInputStream getJarInputStream() throws IOException
2540 return new JarInputStream(_url.openStream());
2544 return new JarInputStream(new FileInputStream(file));
2549 public String getFilename()
2557 * Recover jalview session from a jalview project archive. Caller may
2558 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2559 * themselves. Any null fields will be initialised with default values,
2560 * non-null fields are left alone.
2565 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2567 errorMessage = null;
2568 if (uniqueSetSuffix == null)
2570 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2572 if (seqRefIds == null)
2576 AlignFrame af = null, _af = null;
2577 IdentityHashMap<AlignmentI, AlignmentI> importedDatasets = new IdentityHashMap<>();
2578 Map<String, AlignFrame> gatherToThisFrame = new HashMap<>();
2579 final String file = jprovider.getFilename();
2582 JarInputStream jin = null;
2583 JarEntry jarentry = null;
2588 jin = jprovider.getJarInputStream();
2589 for (int i = 0; i < entryCount; i++)
2591 jarentry = jin.getNextJarEntry();
2594 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2596 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2597 JalviewModel object = new JalviewModel();
2599 Unmarshaller unmar = new Unmarshaller(object);
2600 unmar.setValidation(false);
2601 object = (JalviewModel) unmar.unmarshal(in);
2602 if (true) // !skipViewport(object))
2604 _af = loadFromObject(object, file, true, jprovider);
2605 if (_af != null && object.getJalviewModelSequence()
2606 .getViewportCount() > 0)
2610 // store a reference to the first view
2613 if (_af.viewport.isGatherViewsHere())
2615 // if this is a gathered view, keep its reference since
2616 // after gathering views, only this frame will remain
2618 gatherToThisFrame.put(_af.viewport.getSequenceSetId(), _af);
2620 // Save dataset to register mappings once all resolved
2621 importedDatasets.put(af.viewport.getAlignment().getDataset(),
2622 af.viewport.getAlignment().getDataset());
2627 else if (jarentry != null)
2629 // Some other file here.
2632 } while (jarentry != null);
2633 resolveFrefedSequences();
2634 } catch (IOException ex)
2636 ex.printStackTrace();
2637 errorMessage = "Couldn't locate Jalview XML file : " + file;
2639 "Exception whilst loading jalview XML file : " + ex + "\n");
2640 } catch (Exception ex)
2642 System.err.println("Parsing as Jalview Version 2 file failed.");
2643 ex.printStackTrace(System.err);
2644 if (attemptversion1parse)
2646 // Is Version 1 Jar file?
2649 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
2650 } catch (Exception ex2)
2652 System.err.println("Exception whilst loading as jalviewXMLV1:");
2653 ex2.printStackTrace();
2657 if (Desktop.instance != null)
2659 Desktop.instance.stopLoading();
2663 System.out.println("Successfully loaded archive file");
2666 ex.printStackTrace();
2669 "Exception whilst loading jalview XML file : " + ex + "\n");
2670 } catch (OutOfMemoryError e)
2672 // Don't use the OOM Window here
2673 errorMessage = "Out of memory loading jalview XML file";
2674 System.err.println("Out of memory whilst loading jalview XML file");
2675 e.printStackTrace();
2679 * Regather multiple views (with the same sequence set id) to the frame (if
2680 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2681 * views instead of separate frames. Note this doesn't restore a state where
2682 * some expanded views in turn have tabbed views - the last "first tab" read
2683 * in will play the role of gatherer for all.
2685 for (AlignFrame fr : gatherToThisFrame.values())
2687 Desktop.instance.gatherViews(fr);
2690 restoreSplitFrames();
2691 for (AlignmentI ds : importedDatasets.keySet())
2693 if (ds.getCodonFrames() != null)
2695 StructureSelectionManager
2696 .getStructureSelectionManager(Desktop.instance)
2697 .registerMappings(ds.getCodonFrames());
2700 if (errorMessage != null)
2705 if (Desktop.instance != null)
2707 Desktop.instance.stopLoading();
2714 * Try to reconstruct and display SplitFrame windows, where each contains
2715 * complementary dna and protein alignments. Done by pairing up AlignFrame
2716 * objects (created earlier) which have complementary viewport ids associated.
2718 protected void restoreSplitFrames()
2720 List<SplitFrame> gatherTo = new ArrayList<>();
2721 List<AlignFrame> addedToSplitFrames = new ArrayList<>();
2722 Map<String, AlignFrame> dna = new HashMap<>();
2725 * Identify the DNA alignments
2727 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2730 AlignFrame af = candidate.getValue();
2731 if (af.getViewport().getAlignment().isNucleotide())
2733 dna.put(candidate.getKey().getId(), af);
2738 * Try to match up the protein complements
2740 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2743 AlignFrame af = candidate.getValue();
2744 if (!af.getViewport().getAlignment().isNucleotide())
2746 String complementId = candidate.getKey().getComplementId();
2747 // only non-null complements should be in the Map
2748 if (complementId != null && dna.containsKey(complementId))
2750 final AlignFrame dnaFrame = dna.get(complementId);
2751 SplitFrame sf = createSplitFrame(dnaFrame, af);
2752 addedToSplitFrames.add(dnaFrame);
2753 addedToSplitFrames.add(af);
2754 dnaFrame.setMenusForViewport();
2755 af.setMenusForViewport();
2756 if (af.viewport.isGatherViewsHere())
2765 * Open any that we failed to pair up (which shouldn't happen!) as
2766 * standalone AlignFrame's.
2768 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2771 AlignFrame af = candidate.getValue();
2772 if (!addedToSplitFrames.contains(af))
2774 Viewport view = candidate.getKey();
2775 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
2777 af.setMenusForViewport();
2778 System.err.println("Failed to restore view " + view.getTitle()
2779 + " to split frame");
2784 * Gather back into tabbed views as flagged.
2786 for (SplitFrame sf : gatherTo)
2788 Desktop.instance.gatherViews(sf);
2791 splitFrameCandidates.clear();
2795 * Construct and display one SplitFrame holding DNA and protein alignments.
2798 * @param proteinFrame
2801 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
2802 AlignFrame proteinFrame)
2804 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
2805 String title = MessageManager.getString("label.linked_view_title");
2806 int width = (int) dnaFrame.getBounds().getWidth();
2807 int height = (int) (dnaFrame.getBounds().getHeight()
2808 + proteinFrame.getBounds().getHeight() + 50);
2811 * SplitFrame location is saved to both enclosed frames
2813 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
2814 Desktop.addInternalFrame(splitFrame, title, width, height);
2817 * And compute cDNA consensus (couldn't do earlier with consensus as
2818 * mappings were not yet present)
2820 proteinFrame.viewport.alignmentChanged(proteinFrame.alignPanel);
2826 * check errorMessage for a valid error message and raise an error box in the
2827 * GUI or write the current errorMessage to stderr and then clear the error
2830 protected void reportErrors()
2832 reportErrors(false);
2835 protected void reportErrors(final boolean saving)
2837 if (errorMessage != null)
2839 final String finalErrorMessage = errorMessage;
2842 javax.swing.SwingUtilities.invokeLater(new Runnable()
2847 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2849 "Error " + (saving ? "saving" : "loading")
2851 JvOptionPane.WARNING_MESSAGE);
2857 System.err.println("Problem loading Jalview file: " + errorMessage);
2860 errorMessage = null;
2863 Map<String, String> alreadyLoadedPDB = new HashMap<>();
2866 * when set, local views will be updated from view stored in JalviewXML
2867 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2868 * sync if this is set to true.
2870 private final boolean updateLocalViews = false;
2873 * Returns the path to a temporary file holding the PDB file for the given PDB
2874 * id. The first time of asking, searches for a file of that name in the
2875 * Jalview project jar, and copies it to a new temporary file. Any repeat
2876 * requests just return the path to the file previously created.
2882 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId,
2885 if (alreadyLoadedPDB.containsKey(pdbId))
2887 return alreadyLoadedPDB.get(pdbId).toString();
2890 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb",
2892 if (tempFile != null)
2894 alreadyLoadedPDB.put(pdbId, tempFile);
2900 * Copies the jar entry of given name to a new temporary file and returns the
2901 * path to the file, or null if the entry is not found.
2904 * @param jarEntryName
2906 * a prefix for the temporary file name, must be at least three
2909 * null or original file - so new file can be given the same suffix
2913 protected String copyJarEntry(jarInputStreamProvider jprovider,
2914 String jarEntryName, String prefix, String origFile)
2916 BufferedReader in = null;
2917 PrintWriter out = null;
2918 String suffix = ".tmp";
2919 if (origFile == null)
2921 origFile = jarEntryName;
2923 int sfpos = origFile.lastIndexOf(".");
2924 if (sfpos > -1 && sfpos < (origFile.length() - 3))
2926 suffix = "." + origFile.substring(sfpos + 1);
2930 JarInputStream jin = jprovider.getJarInputStream();
2932 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2933 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2934 * FileInputStream(jprovider)); }
2937 JarEntry entry = null;
2940 entry = jin.getNextJarEntry();
2941 } while (entry != null && !entry.getName().equals(jarEntryName));
2944 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
2945 File outFile = File.createTempFile(prefix, suffix);
2946 outFile.deleteOnExit();
2947 out = new PrintWriter(new FileOutputStream(outFile));
2950 while ((data = in.readLine()) != null)
2955 String t = outFile.getAbsolutePath();
2960 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
2962 } catch (Exception ex)
2964 ex.printStackTrace();
2972 } catch (IOException e)
2986 private class JvAnnotRow
2988 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2995 * persisted version of annotation row from which to take vis properties
2997 public jalview.datamodel.AlignmentAnnotation template;
3000 * original position of the annotation row in the alignment
3006 * Load alignment frame from jalview XML DOM object
3011 * filename source string
3012 * @param loadTreesAndStructures
3013 * when false only create Viewport
3015 * data source provider
3016 * @return alignment frame created from view stored in DOM
3018 AlignFrame loadFromObject(JalviewModel object, String file,
3019 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
3021 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
3022 Sequence[] vamsasSeq = vamsasSet.getSequence();
3024 JalviewModelSequence jms = object.getJalviewModelSequence();
3026 Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
3029 // ////////////////////////////////
3032 List<SequenceI> hiddenSeqs = null;
3034 List<SequenceI> tmpseqs = new ArrayList<>();
3036 boolean multipleView = false;
3037 SequenceI referenceseqForView = null;
3038 JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
3039 int vi = 0; // counter in vamsasSeq array
3040 for (int i = 0; i < jseqs.length; i++)
3042 String seqId = jseqs[i].getId();
3044 SequenceI tmpSeq = seqRefIds.get(seqId);
3047 if (!incompleteSeqs.containsKey(seqId))
3049 // may not need this check, but keep it for at least 2.9,1 release
3050 if (tmpSeq.getStart() != jseqs[i].getStart()
3051 || tmpSeq.getEnd() != jseqs[i].getEnd())
3054 "Warning JAL-2154 regression: updating start/end for sequence "
3055 + tmpSeq.toString() + " to " + jseqs[i]);
3060 incompleteSeqs.remove(seqId);
3062 if (vamsasSeq.length > vi && vamsasSeq[vi].getId().equals(seqId))
3064 // most likely we are reading a dataset XML document so
3065 // update from vamsasSeq section of XML for this sequence
3066 tmpSeq.setName(vamsasSeq[vi].getName());
3067 tmpSeq.setDescription(vamsasSeq[vi].getDescription());
3068 tmpSeq.setSequence(vamsasSeq[vi].getSequence());
3073 // reading multiple views, so vamsasSeq set is a subset of JSeq
3074 multipleView = true;
3076 tmpSeq.setStart(jseqs[i].getStart());
3077 tmpSeq.setEnd(jseqs[i].getEnd());
3078 tmpseqs.add(tmpSeq);
3082 tmpSeq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
3083 vamsasSeq[vi].getSequence());
3084 tmpSeq.setDescription(vamsasSeq[vi].getDescription());
3085 tmpSeq.setStart(jseqs[i].getStart());
3086 tmpSeq.setEnd(jseqs[i].getEnd());
3087 tmpSeq.setVamsasId(uniqueSetSuffix + seqId);
3088 seqRefIds.put(vamsasSeq[vi].getId(), tmpSeq);
3089 tmpseqs.add(tmpSeq);
3093 if (jseqs[i].hasViewreference() && jseqs[i].getViewreference())
3095 referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
3098 if (jseqs[i].getHidden())
3100 if (hiddenSeqs == null)
3102 hiddenSeqs = new ArrayList<>();
3105 hiddenSeqs.add(tmpSeq);
3110 // Create the alignment object from the sequence set
3111 // ///////////////////////////////
3112 SequenceI[] orderedSeqs = tmpseqs
3113 .toArray(new SequenceI[tmpseqs.size()]);
3115 AlignmentI al = null;
3116 // so we must create or recover the dataset alignment before going further
3117 // ///////////////////////////////
3118 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
3120 // older jalview projects do not have a dataset - so creat alignment and
3122 al = new Alignment(orderedSeqs);
3123 al.setDataset(null);
3127 boolean isdsal = object.getJalviewModelSequence()
3128 .getViewportCount() == 0;
3131 // we are importing a dataset record, so
3132 // recover reference to an alignment already materialsed as dataset
3133 al = getDatasetFor(vamsasSet.getDatasetId());
3137 // materialse the alignment
3138 al = new Alignment(orderedSeqs);
3142 addDatasetRef(vamsasSet.getDatasetId(), al);
3145 // finally, verify all data in vamsasSet is actually present in al
3146 // passing on flag indicating if it is actually a stored dataset
3147 recoverDatasetFor(vamsasSet, al, isdsal);
3150 if (referenceseqForView != null)
3152 al.setSeqrep(referenceseqForView);
3154 // / Add the alignment properties
3155 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
3157 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
3158 al.setProperty(ssp.getKey(), ssp.getValue());
3161 // ///////////////////////////////
3163 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
3166 // load sequence features, database references and any associated PDB
3167 // structures for the alignment
3169 // prior to 2.10, this part would only be executed the first time a
3170 // sequence was encountered, but not afterwards.
3171 // now, for 2.10 projects, this is also done if the xml doc includes
3172 // dataset sequences not actually present in any particular view.
3174 for (int i = 0; i < vamsasSeq.length; i++)
3176 if (jseqs[i].getFeaturesCount() > 0)
3178 Features[] features = jseqs[i].getFeatures();
3179 for (int f = 0; f < features.length; f++)
3181 SequenceFeature sf = new SequenceFeature(features[f].getType(),
3182 features[f].getDescription(), features[f].getBegin(),
3183 features[f].getEnd(), features[f].getScore(),
3184 features[f].getFeatureGroup());
3185 sf.setStatus(features[f].getStatus());
3188 * load any feature attributes - include map-valued attributes
3190 Map<String, Map<String, String>> mapAttributes = new HashMap<>();
3191 for (int od = 0; od < features[f].getOtherDataCount(); od++)
3193 OtherData keyValue = features[f].getOtherData(od);
3194 String attributeName = keyValue.getKey();
3195 String attributeValue = keyValue.getValue();
3196 if (attributeName.startsWith("LINK"))
3198 sf.addLink(attributeValue);
3202 String subAttribute = keyValue.getKey2();
3203 if (subAttribute == null)
3205 // simple string-valued attribute
3206 sf.setValue(attributeName, attributeValue);
3210 // attribute 'key' has sub-attribute 'key2'
3211 if (!mapAttributes.containsKey(attributeName))
3213 mapAttributes.put(attributeName, new HashMap<>());
3215 mapAttributes.get(attributeName).put(subAttribute,
3220 for (Entry<String, Map<String, String>> mapAttribute : mapAttributes
3223 sf.setValue(mapAttribute.getKey(), mapAttribute.getValue());
3226 // adds feature to datasequence's feature set (since Jalview 2.10)
3227 al.getSequenceAt(i).addSequenceFeature(sf);
3230 if (vamsasSeq[i].getDBRefCount() > 0)
3232 // adds dbrefs to datasequence's set (since Jalview 2.10)
3234 al.getSequenceAt(i).getDatasetSequence() == null
3235 ? al.getSequenceAt(i)
3236 : al.getSequenceAt(i).getDatasetSequence(),
3239 if (jseqs[i].getPdbidsCount() > 0)
3241 Pdbids[] ids = jseqs[i].getPdbids();
3242 for (int p = 0; p < ids.length; p++)
3244 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
3245 entry.setId(ids[p].getId());
3246 if (ids[p].getType() != null)
3248 if (PDBEntry.Type.getType(ids[p].getType()) != null)
3250 entry.setType(PDBEntry.Type.getType(ids[p].getType()));
3254 entry.setType(PDBEntry.Type.FILE);
3257 // jprovider is null when executing 'New View'
3258 if (ids[p].getFile() != null && jprovider != null)
3260 if (!pdbloaded.containsKey(ids[p].getFile()))
3262 entry.setFile(loadPDBFile(jprovider, ids[p].getId(),
3267 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
3270 if (ids[p].getPdbentryItem() != null)
3272 for (PdbentryItem item : ids[p].getPdbentryItem())
3274 for (Property pr : item.getProperty())
3276 entry.setProperty(pr.getName(), pr.getValue());
3280 StructureSelectionManager
3281 .getStructureSelectionManager(Desktop.instance)
3282 .registerPDBEntry(entry);
3283 // adds PDBEntry to datasequence's set (since Jalview 2.10)
3284 if (al.getSequenceAt(i).getDatasetSequence() != null)
3286 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
3290 al.getSequenceAt(i).addPDBId(entry);
3295 } // end !multipleview
3297 // ///////////////////////////////
3298 // LOAD SEQUENCE MAPPINGS
3300 if (vamsasSet.getAlcodonFrameCount() > 0)
3302 // TODO Potentially this should only be done once for all views of an
3304 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
3305 for (int i = 0; i < alc.length; i++)
3307 AlignedCodonFrame cf = new AlignedCodonFrame();
3308 if (alc[i].getAlcodMapCount() > 0)
3310 AlcodMap[] maps = alc[i].getAlcodMap();
3311 for (int m = 0; m < maps.length; m++)
3313 SequenceI dnaseq = seqRefIds.get(maps[m].getDnasq());
3315 jalview.datamodel.Mapping mapping = null;
3316 // attach to dna sequence reference.
3317 if (maps[m].getMapping() != null)
3319 mapping = addMapping(maps[m].getMapping());
3320 if (dnaseq != null && mapping.getTo() != null)
3322 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
3328 newAlcodMapRef(maps[m].getDnasq(), cf, mapping));
3332 al.addCodonFrame(cf);
3337 // ////////////////////////////////
3339 List<JvAnnotRow> autoAlan = new ArrayList<>();
3342 * store any annotations which forward reference a group's ID
3344 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<>();
3346 if (vamsasSet.getAnnotationCount() > 0)
3348 Annotation[] an = vamsasSet.getAnnotation();
3350 for (int i = 0; i < an.length; i++)
3352 Annotation annotation = an[i];
3355 * test if annotation is automatically calculated for this view only
3357 boolean autoForView = false;
3358 if (annotation.getLabel().equals("Quality")
3359 || annotation.getLabel().equals("Conservation")
3360 || annotation.getLabel().equals("Consensus"))
3362 // Kludge for pre 2.5 projects which lacked the autocalculated flag
3364 if (!annotation.hasAutoCalculated())
3366 annotation.setAutoCalculated(true);
3369 if (autoForView || (annotation.hasAutoCalculated()
3370 && annotation.isAutoCalculated()))
3372 // remove ID - we don't recover annotation from other views for
3373 // view-specific annotation
3374 annotation.setId(null);
3377 // set visiblity for other annotation in this view
3378 String annotationId = annotation.getId();
3379 if (annotationId != null && annotationIds.containsKey(annotationId))
3381 AlignmentAnnotation jda = annotationIds.get(annotationId);
3382 // in principle Visible should always be true for annotation displayed
3383 // in multiple views
3384 if (annotation.hasVisible())
3386 jda.visible = annotation.getVisible();
3389 al.addAnnotation(jda);
3393 // Construct new annotation from model.
3394 AnnotationElement[] ae = annotation.getAnnotationElement();
3395 jalview.datamodel.Annotation[] anot = null;
3396 java.awt.Color firstColour = null;
3398 if (!annotation.getScoreOnly())
3400 anot = new jalview.datamodel.Annotation[al.getWidth()];
3401 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
3403 anpos = ae[aa].getPosition();
3405 if (anpos >= anot.length)
3410 anot[anpos] = new jalview.datamodel.Annotation(
3412 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
3413 (ae[aa].getSecondaryStructure() == null
3414 || ae[aa].getSecondaryStructure().length() == 0)
3416 : ae[aa].getSecondaryStructure()
3421 // JBPNote: Consider verifying dataflow for IO of secondary
3422 // structure annotation read from Stockholm files
3423 // this was added to try to ensure that
3424 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
3426 // anot[ae[aa].getPosition()].displayCharacter = "";
3428 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
3429 if (firstColour == null)
3431 firstColour = anot[anpos].colour;
3435 jalview.datamodel.AlignmentAnnotation jaa = null;
3437 if (annotation.getGraph())
3439 float llim = 0, hlim = 0;
3440 // if (autoForView || an[i].isAutoCalculated()) {
3443 jaa = new jalview.datamodel.AlignmentAnnotation(
3444 annotation.getLabel(), annotation.getDescription(), anot,
3445 llim, hlim, annotation.getGraphType());
3447 jaa.graphGroup = annotation.getGraphGroup();
3448 jaa._linecolour = firstColour;
3449 if (annotation.getThresholdLine() != null)
3451 jaa.setThreshold(new jalview.datamodel.GraphLine(
3452 annotation.getThresholdLine().getValue(),
3453 annotation.getThresholdLine().getLabel(),
3455 annotation.getThresholdLine().getColour())));
3458 if (autoForView || annotation.isAutoCalculated())
3460 // Hardwire the symbol display line to ensure that labels for
3461 // histograms are displayed
3467 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
3468 an[i].getDescription(), anot);
3469 jaa._linecolour = firstColour;
3471 // register new annotation
3472 if (an[i].getId() != null)
3474 annotationIds.put(an[i].getId(), jaa);
3475 jaa.annotationId = an[i].getId();
3477 // recover sequence association
3478 String sequenceRef = an[i].getSequenceRef();
3479 if (sequenceRef != null)
3481 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3482 SequenceI sequence = seqRefIds.get(sequenceRef);
3483 if (sequence == null)
3485 // in pre-2.9 projects sequence ref is to sequence name
3486 sequence = al.findName(sequenceRef);
3488 if (sequence != null)
3490 jaa.createSequenceMapping(sequence, 1, true);
3491 sequence.addAlignmentAnnotation(jaa);
3494 // and make a note of any group association
3495 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
3497 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3498 .get(an[i].getGroupRef());
3501 aal = new ArrayList<>();
3502 groupAnnotRefs.put(an[i].getGroupRef(), aal);
3507 if (an[i].hasScore())
3509 jaa.setScore(an[i].getScore());
3511 if (an[i].hasVisible())
3513 jaa.visible = an[i].getVisible();
3516 if (an[i].hasCentreColLabels())
3518 jaa.centreColLabels = an[i].getCentreColLabels();
3521 if (an[i].hasScaleColLabels())
3523 jaa.scaleColLabel = an[i].getScaleColLabels();
3525 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
3527 // newer files have an 'autoCalculated' flag and store calculation
3528 // state in viewport properties
3529 jaa.autoCalculated = true; // means annotation will be marked for
3530 // update at end of load.
3532 if (an[i].hasGraphHeight())
3534 jaa.graphHeight = an[i].getGraphHeight();
3536 if (an[i].hasBelowAlignment())
3538 jaa.belowAlignment = an[i].isBelowAlignment();
3540 jaa.setCalcId(an[i].getCalcId());
3541 if (an[i].getPropertyCount() > 0)
3543 for (jalview.schemabinding.version2.Property prop : an[i]
3546 jaa.setProperty(prop.getName(), prop.getValue());
3549 if (jaa.autoCalculated)
3551 autoAlan.add(new JvAnnotRow(i, jaa));
3554 // if (!autoForView)
3556 // add autocalculated group annotation and any user created annotation
3558 al.addAnnotation(jaa);
3562 // ///////////////////////
3564 // Create alignment markup and styles for this view
3565 if (jms.getJGroupCount() > 0)
3567 JGroup[] groups = jms.getJGroup();
3568 boolean addAnnotSchemeGroup = false;
3569 for (int i = 0; i < groups.length; i++)
3571 JGroup jGroup = groups[i];
3572 ColourSchemeI cs = null;
3573 if (jGroup.getColour() != null)
3575 if (jGroup.getColour().startsWith("ucs"))
3577 cs = getUserColourScheme(jms, jGroup.getColour());
3579 else if (jGroup.getColour().equals("AnnotationColourGradient")
3580 && jGroup.getAnnotationColours() != null)
3582 addAnnotSchemeGroup = true;
3586 cs = ColourSchemeProperty.getColourScheme(al,
3587 jGroup.getColour());
3590 int pidThreshold = jGroup.getPidThreshold();
3592 Vector<SequenceI> seqs = new Vector<>();
3594 for (int s = 0; s < jGroup.getSeqCount(); s++)
3596 String seqId = jGroup.getSeq(s) + "";
3597 SequenceI ts = seqRefIds.get(seqId);
3601 seqs.addElement(ts);
3605 if (seqs.size() < 1)
3610 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3611 jGroup.getDisplayBoxes(), jGroup.getDisplayText(),
3612 jGroup.getColourText(), jGroup.getStart(), jGroup.getEnd());
3613 sg.getGroupColourScheme().setThreshold(pidThreshold, true);
3614 sg.getGroupColourScheme()
3615 .setConservationInc(jGroup.getConsThreshold());
3616 sg.setOutlineColour(new java.awt.Color(jGroup.getOutlineColour()));
3618 sg.textColour = new java.awt.Color(jGroup.getTextCol1());
3619 sg.textColour2 = new java.awt.Color(jGroup.getTextCol2());
3620 sg.setShowNonconserved(
3621 jGroup.hasShowUnconserved() ? jGroup.isShowUnconserved()
3623 sg.thresholdTextColour = jGroup.getTextColThreshold();
3624 if (jGroup.hasShowConsensusHistogram())
3626 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3629 if (jGroup.hasShowSequenceLogo())
3631 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3633 if (jGroup.hasNormaliseSequenceLogo())
3635 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3637 if (jGroup.hasIgnoreGapsinConsensus())
3639 sg.setIgnoreGapsConsensus(jGroup.getIgnoreGapsinConsensus());
3641 if (jGroup.getConsThreshold() != 0)
3643 Conservation c = new Conservation("All", sg.getSequences(null), 0,
3646 c.verdict(false, 25);
3647 sg.cs.setConservation(c);
3650 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3652 // re-instate unique group/annotation row reference
3653 List<AlignmentAnnotation> jaal = groupAnnotRefs
3654 .get(jGroup.getId());
3657 for (AlignmentAnnotation jaa : jaal)
3660 if (jaa.autoCalculated)
3662 // match up and try to set group autocalc alignment row for this
3664 if (jaa.label.startsWith("Consensus for "))
3666 sg.setConsensus(jaa);
3668 // match up and try to set group autocalc alignment row for this
3670 if (jaa.label.startsWith("Conservation for "))
3672 sg.setConservationRow(jaa);
3679 if (addAnnotSchemeGroup)
3681 // reconstruct the annotation colourscheme
3682 sg.setColourScheme(constructAnnotationColour(
3683 jGroup.getAnnotationColours(), null, al, jms, false));
3689 // only dataset in this model, so just return.
3692 // ///////////////////////////////
3695 // If we just load in the same jar file again, the sequenceSetId
3696 // will be the same, and we end up with multiple references
3697 // to the same sequenceSet. We must modify this id on load
3698 // so that each load of the file gives a unique id
3699 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3700 String viewId = (view.getId() == null ? null
3701 : view.getId() + uniqueSetSuffix);
3702 AlignFrame af = null;
3703 AlignViewport av = null;
3704 // now check to see if we really need to create a new viewport.
3705 if (multipleView && viewportsAdded.size() == 0)
3707 // We recovered an alignment for which a viewport already exists.
3708 // TODO: fix up any settings necessary for overlaying stored state onto
3709 // state recovered from another document. (may not be necessary).
3710 // we may need a binding from a viewport in memory to one recovered from
3712 // and then recover its containing af to allow the settings to be applied.
3713 // TODO: fix for vamsas demo
3715 "About to recover a viewport for existing alignment: Sequence set ID is "
3717 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3718 if (seqsetobj != null)
3720 if (seqsetobj instanceof String)
3722 uniqueSeqSetId = (String) seqsetobj;
3724 "Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
3730 "Warning : Collision between sequence set ID string and existing jalview object mapping.");
3736 * indicate that annotation colours are applied across all groups (pre
3737 * Jalview 2.8.1 behaviour)
3739 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan("2.8.1",
3740 object.getVersion());
3742 AlignmentPanel ap = null;
3743 boolean isnewview = true;
3746 // Check to see if this alignment already has a view id == viewId
3747 jalview.gui.AlignmentPanel views[] = Desktop
3748 .getAlignmentPanels(uniqueSeqSetId);
3749 if (views != null && views.length > 0)
3751 for (int v = 0; v < views.length; v++)
3753 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
3755 // recover the existing alignpanel, alignframe, viewport
3756 af = views[v].alignFrame;
3759 // TODO: could even skip resetting view settings if we don't want to
3760 // change the local settings from other jalview processes
3769 af = loadViewport(file, jseqs, hiddenSeqs, al, jms, view,
3770 uniqueSeqSetId, viewId, autoAlan);
3776 * Load any trees, PDB structures and viewers
3778 * Not done if flag is false (when this method is used for New View)
3780 if (loadTreesAndStructures)
3782 loadTrees(jms, view, af, av, ap);
3783 loadPCAViewers(jms, ap);
3784 loadPDBStructures(jprovider, jseqs, af, ap);
3785 loadRnaViewers(jprovider, jseqs, ap);
3787 // and finally return.
3792 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
3793 * panel is restored from separate jar entries, two (gapped and trimmed) per
3794 * sequence and secondary structure.
3796 * Currently each viewer shows just one sequence and structure (gapped and
3797 * trimmed), however this method is designed to support multiple sequences or
3798 * structures in viewers if wanted in future.
3804 private void loadRnaViewers(jarInputStreamProvider jprovider,
3805 JSeq[] jseqs, AlignmentPanel ap)
3808 * scan the sequences for references to viewers; create each one the first
3809 * time it is referenced, add Rna models to existing viewers
3811 for (JSeq jseq : jseqs)
3813 for (int i = 0; i < jseq.getRnaViewerCount(); i++)
3815 RnaViewer viewer = jseq.getRnaViewer(i);
3816 AppVarna appVarna = findOrCreateVarnaViewer(viewer, uniqueSetSuffix,
3819 for (int j = 0; j < viewer.getSecondaryStructureCount(); j++)
3821 SecondaryStructure ss = viewer.getSecondaryStructure(j);
3822 SequenceI seq = seqRefIds.get(jseq.getId());
3823 AlignmentAnnotation ann = this.annotationIds
3824 .get(ss.getAnnotationId());
3827 * add the structure to the Varna display (with session state copied
3828 * from the jar to a temporary file)
3830 boolean gapped = ss.isGapped();
3831 String rnaTitle = ss.getTitle();
3832 String sessionState = ss.getViewerState();
3833 String tempStateFile = copyJarEntry(jprovider, sessionState,
3835 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
3836 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
3838 appVarna.setInitialSelection(viewer.getSelectedRna());
3844 * Locate and return an already instantiated matching AppVarna, or create one
3848 * @param viewIdSuffix
3852 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
3853 String viewIdSuffix, AlignmentPanel ap)
3856 * on each load a suffix is appended to the saved viewId, to avoid conflicts
3857 * if load is repeated
3859 String postLoadId = viewer.getViewId() + viewIdSuffix;
3860 for (JInternalFrame frame : getAllFrames())
3862 if (frame instanceof AppVarna)
3864 AppVarna varna = (AppVarna) frame;
3865 if (postLoadId.equals(varna.getViewId()))
3867 // this viewer is already instantiated
3868 // could in future here add ap as another 'parent' of the
3869 // AppVarna window; currently just 1-to-many
3876 * viewer not found - make it
3878 RnaViewerModel model = new RnaViewerModel(postLoadId, viewer.getTitle(),
3879 viewer.getXpos(), viewer.getYpos(), viewer.getWidth(),
3880 viewer.getHeight(), viewer.getDividerLocation());
3881 AppVarna varna = new AppVarna(model, ap);
3887 * Load any saved trees
3895 protected void loadTrees(JalviewModelSequence jms, Viewport view,
3896 AlignFrame af, AlignViewport av, AlignmentPanel ap)
3898 // TODO result of automated refactoring - are all these parameters needed?
3901 for (int t = 0; t < jms.getTreeCount(); t++)
3904 Tree tree = jms.getTree(t);
3906 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
3909 tp = af.showNewickTree(
3910 new jalview.io.NewickFile(tree.getNewick()),
3911 tree.getTitle(), tree.getWidth(), tree.getHeight(),
3912 tree.getXpos(), tree.getYpos());
3913 if (tree.getId() != null)
3915 // perhaps bind the tree id to something ?
3920 // update local tree attributes ?
3921 // TODO: should check if tp has been manipulated by user - if so its
3922 // settings shouldn't be modified
3923 tp.setTitle(tree.getTitle());
3924 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(),
3925 tree.getWidth(), tree.getHeight()));
3927 tp.treeCanvas.av = av; // af.viewport;
3928 tp.treeCanvas.ap = ap; // af.alignPanel;
3933 warn("There was a problem recovering stored Newick tree: \n"
3934 + tree.getNewick());
3938 tp.fitToWindow.setState(tree.getFitToWindow());
3939 tp.fitToWindow_actionPerformed(null);
3941 if (tree.getFontName() != null)
3943 tp.setTreeFont(new java.awt.Font(tree.getFontName(),
3944 tree.getFontStyle(), tree.getFontSize()));
3948 tp.setTreeFont(new java.awt.Font(view.getFontName(),
3949 view.getFontStyle(), tree.getFontSize()));
3952 tp.showPlaceholders(tree.getMarkUnlinked());
3953 tp.showBootstrap(tree.getShowBootstrap());
3954 tp.showDistances(tree.getShowDistances());
3956 tp.treeCanvas.threshold = tree.getThreshold();
3957 tp.treeCanvas.applyToAllViews = tree.isLinkToAllViews();
3959 if (tree.getCurrentTree())
3961 af.viewport.setCurrentTree(tp.getTree());
3965 } catch (Exception ex)
3967 ex.printStackTrace();
3972 * Load and link any saved structure viewers.
3979 protected void loadPDBStructures(jarInputStreamProvider jprovider,
3980 JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
3983 * Run through all PDB ids on the alignment, and collect mappings between
3984 * distinct view ids and all sequences referring to that view.
3986 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<>();
3988 for (int i = 0; i < jseqs.length; i++)
3990 if (jseqs[i].getPdbidsCount() > 0)
3992 Pdbids[] ids = jseqs[i].getPdbids();
3993 for (int p = 0; p < ids.length; p++)
3995 final int structureStateCount = ids[p].getStructureStateCount();
3996 for (int s = 0; s < structureStateCount; s++)
3998 // check to see if we haven't already created this structure view
3999 final StructureState structureState = ids[p]
4000 .getStructureState(s);
4001 String sviewid = (structureState.getViewId() == null) ? null
4002 : structureState.getViewId() + uniqueSetSuffix;
4003 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
4004 // Originally : ids[p].getFile()
4005 // : TODO: verify external PDB file recovery still works in normal
4006 // jalview project load
4007 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId(),
4009 jpdb.setId(ids[p].getId());
4011 int x = structureState.getXpos();
4012 int y = structureState.getYpos();
4013 int width = structureState.getWidth();
4014 int height = structureState.getHeight();
4016 // Probably don't need to do this anymore...
4017 // Desktop.desktop.getComponentAt(x, y);
4018 // TODO: NOW: check that this recovers the PDB file correctly.
4019 String pdbFile = loadPDBFile(jprovider, ids[p].getId(),
4021 jalview.datamodel.SequenceI seq = seqRefIds
4022 .get(jseqs[i].getId() + "");
4023 if (sviewid == null)
4025 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width + ","
4028 if (!structureViewers.containsKey(sviewid))
4030 structureViewers.put(sviewid,
4031 new StructureViewerModel(x, y, width, height, false,
4032 false, true, structureState.getViewId(),
4033 structureState.getType()));
4034 // Legacy pre-2.7 conversion JAL-823 :
4035 // do not assume any view has to be linked for colour by
4039 // assemble String[] { pdb files }, String[] { id for each
4040 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
4041 // seqs_file 2}, boolean[] {
4042 // linkAlignPanel,superposeWithAlignpanel}} from hash
4043 StructureViewerModel jmoldat = structureViewers.get(sviewid);
4044 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
4045 | (structureState.hasAlignwithAlignPanel()
4046 ? structureState.getAlignwithAlignPanel()
4050 * Default colour by linked panel to false if not specified (e.g.
4051 * for pre-2.7 projects)
4053 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
4054 colourWithAlignPanel |= (structureState
4055 .hasColourwithAlignPanel()
4056 ? structureState.getColourwithAlignPanel()
4058 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
4061 * Default colour by viewer to true if not specified (e.g. for
4064 boolean colourByViewer = jmoldat.isColourByViewer();
4065 colourByViewer &= structureState.hasColourByJmol()
4066 ? structureState.getColourByJmol()
4068 jmoldat.setColourByViewer(colourByViewer);
4070 if (jmoldat.getStateData().length() < structureState
4071 .getContent().length())
4074 jmoldat.setStateData(structureState.getContent());
4077 if (ids[p].getFile() != null)
4079 File mapkey = new File(ids[p].getFile());
4080 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
4081 if (seqstrmaps == null)
4083 jmoldat.getFileData().put(mapkey,
4084 seqstrmaps = jmoldat.new StructureData(pdbFile,
4087 if (!seqstrmaps.getSeqList().contains(seq))
4089 seqstrmaps.getSeqList().add(seq);
4095 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");
4102 // Instantiate the associated structure views
4103 for (Entry<String, StructureViewerModel> entry : structureViewers
4108 createOrLinkStructureViewer(entry, af, ap, jprovider);
4109 } catch (Exception e)
4112 "Error loading structure viewer: " + e.getMessage());
4113 // failed - try the next one
4125 protected void createOrLinkStructureViewer(
4126 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4127 AlignmentPanel ap, jarInputStreamProvider jprovider)
4129 final StructureViewerModel stateData = viewerData.getValue();
4132 * Search for any viewer windows already open from other alignment views
4133 * that exactly match the stored structure state
4135 StructureViewerBase comp = findMatchingViewer(viewerData);
4139 linkStructureViewer(ap, comp, stateData);
4144 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
4145 * "viewer_"+stateData.viewId
4147 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
4149 createChimeraViewer(viewerData, af, jprovider);
4154 * else Jmol (if pre-2.9, stateData contains JMOL state string)
4156 createJmolViewer(viewerData, af, jprovider);
4161 * Create a new Chimera viewer.
4167 protected void createChimeraViewer(
4168 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4169 jarInputStreamProvider jprovider)
4171 StructureViewerModel data = viewerData.getValue();
4172 String chimeraSessionFile = data.getStateData();
4175 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
4177 * NB this is the 'saved' viewId as in the project file XML, _not_ the
4178 * 'uniquified' sviewid used to reconstruct the viewer here
4180 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
4181 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
4184 Set<Entry<File, StructureData>> fileData = data.getFileData()
4186 List<PDBEntry> pdbs = new ArrayList<>();
4187 List<SequenceI[]> allseqs = new ArrayList<>();
4188 for (Entry<File, StructureData> pdb : fileData)
4190 String filePath = pdb.getValue().getFilePath();
4191 String pdbId = pdb.getValue().getPdbId();
4192 // pdbs.add(new PDBEntry(filePath, pdbId));
4193 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
4194 final List<SequenceI> seqList = pdb.getValue().getSeqList();
4195 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
4199 boolean colourByChimera = data.isColourByViewer();
4200 boolean colourBySequence = data.isColourWithAlignPanel();
4202 // TODO use StructureViewer as a factory here, see JAL-1761
4203 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
4204 final SequenceI[][] seqsArray = allseqs
4205 .toArray(new SequenceI[allseqs.size()][]);
4206 String newViewId = viewerData.getKey();
4208 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
4209 af.alignPanel, pdbArray, seqsArray, colourByChimera,
4210 colourBySequence, newViewId);
4211 cvf.setSize(data.getWidth(), data.getHeight());
4212 cvf.setLocation(data.getX(), data.getY());
4216 * Create a new Jmol window. First parse the Jmol state to translate filenames
4217 * loaded into the view, and record the order in which files are shown in the
4218 * Jmol view, so we can add the sequence mappings in same order.
4224 protected void createJmolViewer(
4225 final Entry<String, StructureViewerModel> viewerData,
4226 AlignFrame af, jarInputStreamProvider jprovider)
4228 final StructureViewerModel svattrib = viewerData.getValue();
4229 String state = svattrib.getStateData();
4232 * Pre-2.9: state element value is the Jmol state string
4234 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
4237 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
4239 state = readJarEntry(jprovider,
4240 getViewerJarEntryName(svattrib.getViewId()));
4243 List<String> pdbfilenames = new ArrayList<>();
4244 List<SequenceI[]> seqmaps = new ArrayList<>();
4245 List<String> pdbids = new ArrayList<>();
4246 StringBuilder newFileLoc = new StringBuilder(64);
4247 int cp = 0, ncp, ecp;
4248 Map<File, StructureData> oldFiles = svattrib.getFileData();
4249 while ((ncp = state.indexOf("load ", cp)) > -1)
4253 // look for next filename in load statement
4254 newFileLoc.append(state.substring(cp,
4255 ncp = (state.indexOf("\"", ncp + 1) + 1)));
4256 String oldfilenam = state.substring(ncp,
4257 ecp = state.indexOf("\"", ncp));
4258 // recover the new mapping data for this old filename
4259 // have to normalize filename - since Jmol and jalview do
4261 // translation differently.
4262 StructureData filedat = oldFiles.get(new File(oldfilenam));
4263 if (filedat == null)
4265 String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\");
4266 filedat = oldFiles.get(new File(reformatedOldFilename));
4268 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
4269 pdbfilenames.add(filedat.getFilePath());
4270 pdbids.add(filedat.getPdbId());
4271 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4272 newFileLoc.append("\"");
4273 cp = ecp + 1; // advance beyond last \" and set cursor so we can
4274 // look for next file statement.
4275 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
4279 // just append rest of state
4280 newFileLoc.append(state.substring(cp));
4284 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
4285 newFileLoc = new StringBuilder(state);
4286 newFileLoc.append("; load append ");
4287 for (File id : oldFiles.keySet())
4289 // add this and any other pdb files that should be present in
4291 StructureData filedat = oldFiles.get(id);
4292 newFileLoc.append(filedat.getFilePath());
4293 pdbfilenames.add(filedat.getFilePath());
4294 pdbids.add(filedat.getPdbId());
4295 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4296 newFileLoc.append(" \"");
4297 newFileLoc.append(filedat.getFilePath());
4298 newFileLoc.append("\"");
4301 newFileLoc.append(";");
4304 if (newFileLoc.length() == 0)
4308 int histbug = newFileLoc.indexOf("history = ");
4312 * change "history = [true|false];" to "history = [1|0];"
4315 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
4316 String val = (diff == -1) ? null
4317 : newFileLoc.substring(histbug, diff);
4318 if (val != null && val.length() >= 4)
4320 if (val.contains("e")) // eh? what can it be?
4322 if (val.trim().equals("true"))
4330 newFileLoc.replace(histbug, diff, val);
4335 final String[] pdbf = pdbfilenames
4336 .toArray(new String[pdbfilenames.size()]);
4337 final String[] id = pdbids.toArray(new String[pdbids.size()]);
4338 final SequenceI[][] sq = seqmaps
4339 .toArray(new SequenceI[seqmaps.size()][]);
4340 final String fileloc = newFileLoc.toString();
4341 final String sviewid = viewerData.getKey();
4342 final AlignFrame alf = af;
4343 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
4344 svattrib.getWidth(), svattrib.getHeight());
4347 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
4352 JalviewStructureDisplayI sview = null;
4355 sview = new StructureViewer(
4356 alf.alignPanel.getStructureSelectionManager())
4357 .createView(StructureViewer.ViewerType.JMOL,
4358 pdbf, id, sq, alf.alignPanel, svattrib,
4359 fileloc, rect, sviewid);
4360 addNewStructureViewer(sview);
4361 } catch (OutOfMemoryError ex)
4363 new OOMWarning("restoring structure view for PDB id " + id,
4364 (OutOfMemoryError) ex.getCause());
4365 if (sview != null && sview.isVisible())
4367 sview.closeViewer(false);
4368 sview.setVisible(false);
4374 } catch (InvocationTargetException ex)
4376 warn("Unexpected error when opening Jmol view.", ex);
4378 } catch (InterruptedException e)
4380 // e.printStackTrace();
4386 * Generates a name for the entry in the project jar file to hold state
4387 * information for a structure viewer
4392 protected String getViewerJarEntryName(String viewId)
4394 return VIEWER_PREFIX + viewId;
4398 * Returns any open frame that matches given structure viewer data. The match
4399 * is based on the unique viewId, or (for older project versions) the frame's
4405 protected StructureViewerBase findMatchingViewer(
4406 Entry<String, StructureViewerModel> viewerData)
4408 final String sviewid = viewerData.getKey();
4409 final StructureViewerModel svattrib = viewerData.getValue();
4410 StructureViewerBase comp = null;
4411 JInternalFrame[] frames = getAllFrames();
4412 for (JInternalFrame frame : frames)
4414 if (frame instanceof StructureViewerBase)
4417 * Post jalview 2.4 schema includes structure view id
4419 if (sviewid != null && ((StructureViewerBase) frame).getViewId()
4422 comp = (StructureViewerBase) frame;
4423 break; // break added in 2.9
4426 * Otherwise test for matching position and size of viewer frame
4428 else if (frame.getX() == svattrib.getX()
4429 && frame.getY() == svattrib.getY()
4430 && frame.getHeight() == svattrib.getHeight()
4431 && frame.getWidth() == svattrib.getWidth())
4433 comp = (StructureViewerBase) frame;
4434 // no break in faint hope of an exact match on viewId
4442 * Link an AlignmentPanel to an existing structure viewer.
4447 * @param useinViewerSuperpos
4448 * @param usetoColourbyseq
4449 * @param viewerColouring
4451 protected void linkStructureViewer(AlignmentPanel ap,
4452 StructureViewerBase viewer, StructureViewerModel stateData)
4454 // NOTE: if the jalview project is part of a shared session then
4455 // view synchronization should/could be done here.
4457 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4458 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4459 final boolean viewerColouring = stateData.isColourByViewer();
4460 Map<File, StructureData> oldFiles = stateData.getFileData();
4463 * Add mapping for sequences in this view to an already open viewer
4465 final AAStructureBindingModel binding = viewer.getBinding();
4466 for (File id : oldFiles.keySet())
4468 // add this and any other pdb files that should be present in the
4470 StructureData filedat = oldFiles.get(id);
4471 String pdbFile = filedat.getFilePath();
4472 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4473 binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE,
4475 binding.addSequenceForStructFile(pdbFile, seq);
4477 // and add the AlignmentPanel's reference to the view panel
4478 viewer.addAlignmentPanel(ap);
4479 if (useinViewerSuperpos)
4481 viewer.useAlignmentPanelForSuperposition(ap);
4485 viewer.excludeAlignmentPanelForSuperposition(ap);
4487 if (usetoColourbyseq)
4489 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4493 viewer.excludeAlignmentPanelForColourbyseq(ap);
4498 * Get all frames within the Desktop.
4502 protected JInternalFrame[] getAllFrames()
4504 JInternalFrame[] frames = null;
4505 // TODO is this necessary - is it safe - risk of hanging?
4510 frames = Desktop.desktop.getAllFrames();
4511 } catch (ArrayIndexOutOfBoundsException e)
4513 // occasional No such child exceptions are thrown here...
4517 } catch (InterruptedException f)
4521 } while (frames == null);
4526 * Answers true if 'version' is equal to or later than 'supported', where each
4527 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4528 * changes. Development and test values for 'version' are leniently treated
4532 * - minimum version we are comparing against
4534 * - version of data being processsed
4537 public static boolean isVersionStringLaterThan(String supported,
4540 if (supported == null || version == null
4541 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4542 || version.equalsIgnoreCase("Test")
4543 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4545 System.err.println("Assuming project file with "
4546 + (version == null ? "null" : version)
4547 + " is compatible with Jalview version " + supported);
4552 return StringUtils.compareVersions(version, supported, "b") >= 0;
4556 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4558 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4560 if (newStructureViewers != null)
4562 sview.getBinding().setFinishedLoadingFromArchive(false);
4563 newStructureViewers.add(sview);
4567 protected void setLoadingFinishedForNewStructureViewers()
4569 if (newStructureViewers != null)
4571 for (JalviewStructureDisplayI sview : newStructureViewers)
4573 sview.getBinding().setFinishedLoadingFromArchive(true);
4575 newStructureViewers.clear();
4576 newStructureViewers = null;
4580 AlignFrame loadViewport(String file, JSeq[] JSEQ,
4581 List<SequenceI> hiddenSeqs, AlignmentI al,
4582 JalviewModelSequence jms, Viewport view, String uniqueSeqSetId,
4583 String viewId, List<JvAnnotRow> autoAlan)
4585 AlignFrame af = null;
4586 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
4587 uniqueSeqSetId, viewId);
4589 af.setFileName(file, FileFormat.Jalview);
4591 for (int i = 0; i < JSEQ.length; i++)
4593 af.viewport.setSequenceColour(
4594 af.viewport.getAlignment().getSequenceAt(i),
4595 new java.awt.Color(JSEQ[i].getColour()));
4600 af.getViewport().setColourByReferenceSeq(true);
4601 af.getViewport().setDisplayReferenceSeq(true);
4604 af.viewport.setGatherViewsHere(view.getGatheredViews());
4606 if (view.getSequenceSetId() != null)
4608 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4610 af.viewport.setSequenceSetId(uniqueSeqSetId);
4613 // propagate shared settings to this new view
4614 af.viewport.setHistoryList(av.getHistoryList());
4615 af.viewport.setRedoList(av.getRedoList());
4619 viewportsAdded.put(uniqueSeqSetId, af.viewport);
4621 // TODO: check if this method can be called repeatedly without
4622 // side-effects if alignpanel already registered.
4623 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4625 // apply Hidden regions to view.
4626 if (hiddenSeqs != null)
4628 for (int s = 0; s < JSEQ.length; s++)
4630 SequenceGroup hidden = new SequenceGroup();
4631 boolean isRepresentative = false;
4632 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
4634 isRepresentative = true;
4635 SequenceI sequenceToHide = al
4636 .getSequenceAt(JSEQ[s].getHiddenSequences(r));
4637 hidden.addSequence(sequenceToHide, false);
4638 // remove from hiddenSeqs list so we don't try to hide it twice
4639 hiddenSeqs.remove(sequenceToHide);
4641 if (isRepresentative)
4643 SequenceI representativeSequence = al.getSequenceAt(s);
4644 hidden.addSequence(representativeSequence, false);
4645 af.viewport.hideRepSequences(representativeSequence, hidden);
4649 SequenceI[] hseqs = hiddenSeqs
4650 .toArray(new SequenceI[hiddenSeqs.size()]);
4651 af.viewport.hideSequence(hseqs);
4654 // recover view properties and display parameters
4656 af.viewport.setShowAnnotation(view.getShowAnnotation());
4657 af.viewport.setAbovePIDThreshold(view.getPidSelected());
4658 af.viewport.setThreshold(view.getPidThreshold());
4660 af.viewport.setColourText(view.getShowColourText());
4662 af.viewport.setConservationSelected(view.getConservationSelected());
4663 af.viewport.setIncrement(view.getConsThreshold());
4664 af.viewport.setShowJVSuffix(view.getShowFullId());
4665 af.viewport.setRightAlignIds(view.getRightAlignIds());
4666 af.viewport.setFont(new java.awt.Font(view.getFontName(),
4667 view.getFontStyle(), view.getFontSize()), true);
4668 ViewStyleI vs = af.viewport.getViewStyle();
4669 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
4670 af.viewport.setViewStyle(vs);
4671 // TODO: allow custom charWidth/Heights to be restored by updating them
4672 // after setting font - which means set above to false
4673 af.viewport.setRenderGaps(view.getRenderGaps());
4674 af.viewport.setWrapAlignment(view.getWrapAlignment());
4675 af.viewport.setShowAnnotation(view.getShowAnnotation());
4677 af.viewport.setShowBoxes(view.getShowBoxes());
4679 af.viewport.setShowText(view.getShowText());
4681 af.viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
4682 af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
4683 af.viewport.setThresholdTextColour(view.getTextColThreshold());
4684 af.viewport.setShowUnconserved(
4685 view.hasShowUnconserved() ? view.isShowUnconserved() : false);
4686 af.viewport.getRanges().setStartRes(view.getStartRes());
4688 if (view.getViewName() != null)
4690 af.viewport.viewName = view.getViewName();
4691 af.setInitialTabVisible();
4693 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
4695 // startSeq set in af.alignPanel.updateLayout below
4696 af.alignPanel.updateLayout();
4697 ColourSchemeI cs = null;
4698 // apply colourschemes
4699 if (view.getBgColour() != null)
4701 if (view.getBgColour().startsWith("ucs"))
4703 cs = getUserColourScheme(jms, view.getBgColour());
4705 else if (view.getBgColour().startsWith("Annotation"))
4707 AnnotationColours viewAnnColour = view.getAnnotationColours();
4708 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
4715 cs = ColourSchemeProperty.getColourScheme(al, view.getBgColour());
4719 af.viewport.setGlobalColourScheme(cs);
4720 af.viewport.getResidueShading().setThreshold(view.getPidThreshold(),
4721 view.getIgnoreGapsinConsensus());
4722 af.viewport.getResidueShading()
4723 .setConsensus(af.viewport.getSequenceConsensusHash());
4724 af.viewport.setColourAppliesToAllGroups(false);
4726 if (view.getConservationSelected() && cs != null)
4728 af.viewport.getResidueShading()
4729 .setConservationInc(view.getConsThreshold());
4732 af.changeColour(cs);
4734 af.viewport.setColourAppliesToAllGroups(true);
4736 af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures());
4738 if (view.hasCentreColumnLabels())
4740 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
4742 if (view.hasIgnoreGapsinConsensus())
4744 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
4747 if (view.hasFollowHighlight())
4749 af.viewport.setFollowHighlight(view.getFollowHighlight());
4751 if (view.hasFollowSelection())
4753 af.viewport.followSelection = view.getFollowSelection();
4755 if (view.hasShowConsensusHistogram())
4758 .setShowConsensusHistogram(view.getShowConsensusHistogram());
4762 af.viewport.setShowConsensusHistogram(true);
4764 if (view.hasShowSequenceLogo())
4766 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
4770 af.viewport.setShowSequenceLogo(false);
4772 if (view.hasNormaliseSequenceLogo())
4774 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
4776 if (view.hasShowDbRefTooltip())
4778 af.viewport.setShowDBRefs(view.getShowDbRefTooltip());
4780 if (view.hasShowNPfeatureTooltip())
4782 af.viewport.setShowNPFeats(view.hasShowNPfeatureTooltip());
4784 if (view.hasShowGroupConsensus())
4786 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
4790 af.viewport.setShowGroupConsensus(false);
4792 if (view.hasShowGroupConservation())
4794 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
4798 af.viewport.setShowGroupConservation(false);
4801 // recover feature settings
4802 if (jms.getFeatureSettings() != null)
4804 FeatureRenderer fr = af.alignPanel.getSeqPanel().seqCanvas
4805 .getFeatureRenderer();
4806 FeaturesDisplayed fdi;
4807 af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
4808 String[] renderOrder = new String[jms.getFeatureSettings()
4809 .getSettingCount()];
4810 Map<String, FeatureColourI> featureColours = new Hashtable<>();
4811 Map<String, Float> featureOrder = new Hashtable<>();
4813 for (int fs = 0; fs < jms.getFeatureSettings()
4814 .getSettingCount(); fs++)
4816 Setting setting = jms.getFeatureSettings().getSetting(fs);
4817 String featureType = setting.getType();
4820 * restore feature filters (if any)
4822 MatcherSet filters = setting.getMatcherSet();
4823 if (filters != null)
4825 FeatureMatcherSetI filter = Jalview2XML
4826 .unmarshalFilter(featureType, filters);
4827 if (!filter.isEmpty())
4829 fr.setFeatureFilter(featureType, filter);
4834 * restore feature colour scheme
4836 Color maxColour = new Color(setting.getColour());
4837 if (setting.hasMincolour())
4840 * minColour is always set unless a simple colour
4841 * (including for colour by label though it doesn't use it)
4843 Color minColour = new Color(setting.getMincolour());
4844 Color noValueColour = minColour;
4845 NoValueColour noColour = setting.getNoValueColour();
4846 if (noColour == NoValueColour.NONE)
4848 noValueColour = null;
4850 else if (noColour == NoValueColour.MAX)
4852 noValueColour = maxColour;
4854 float min = setting.hasMin() ? setting.getMin() : 0f;
4855 float max = setting.hasMin() ? setting.getMax() : 1f;
4856 FeatureColourI gc = new FeatureColour(minColour, maxColour,
4857 noValueColour, min, max);
4858 if (setting.getAttributeNameCount() > 0)
4860 gc.setAttributeName(setting.getAttributeName());
4862 if (setting.hasThreshold())
4864 gc.setThreshold(setting.getThreshold());
4865 int threshstate = setting.getThreshstate();
4866 // -1 = None, 0 = Below, 1 = Above threshold
4867 if (threshstate == 0)
4869 gc.setBelowThreshold(true);
4871 else if (threshstate == 1)
4873 gc.setAboveThreshold(true);
4876 gc.setAutoScaled(true); // default
4877 if (setting.hasAutoScale())
4879 gc.setAutoScaled(setting.getAutoScale());
4881 if (setting.hasColourByLabel())
4883 gc.setColourByLabel(setting.getColourByLabel());
4885 // and put in the feature colour table.
4886 featureColours.put(featureType, gc);
4890 featureColours.put(featureType,
4891 new FeatureColour(maxColour));
4893 renderOrder[fs] = featureType;
4894 if (setting.hasOrder())
4896 featureOrder.put(featureType, setting.getOrder());
4900 featureOrder.put(featureType, new Float(
4901 fs / jms.getFeatureSettings().getSettingCount()));
4903 if (setting.getDisplay())
4905 fdi.setVisible(featureType);
4908 Map<String, Boolean> fgtable = new Hashtable<>();
4909 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
4911 Group grp = jms.getFeatureSettings().getGroup(gs);
4912 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
4914 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4915 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
4916 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
4917 FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4918 fgtable, featureColours, 1.0f, featureOrder);
4919 fr.transferSettings(frs);
4922 if (view.getHiddenColumnsCount() > 0)
4924 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
4926 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(),
4927 view.getHiddenColumns(c).getEnd() // +1
4931 if (view.getCalcIdParam() != null)
4933 for (CalcIdParam calcIdParam : view.getCalcIdParam())
4935 if (calcIdParam != null)
4937 if (recoverCalcIdParam(calcIdParam, af.viewport))
4942 warn("Couldn't recover parameters for "
4943 + calcIdParam.getCalcId());
4948 af.setMenusFromViewport(af.viewport);
4949 af.setTitle(view.getTitle());
4950 // TODO: we don't need to do this if the viewport is aready visible.
4952 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
4953 * has a 'cdna/protein complement' view, in which case save it in order to
4954 * populate a SplitFrame once all views have been read in.
4956 String complementaryViewId = view.getComplementId();
4957 if (complementaryViewId == null)
4959 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
4961 // recompute any autoannotation
4962 af.alignPanel.updateAnnotation(false, true);
4963 reorderAutoannotation(af, al, autoAlan);
4964 af.alignPanel.alignmentChanged();
4968 splitFrameCandidates.put(view, af);
4974 * Reads saved data to restore Colour by Annotation settings
4976 * @param viewAnnColour
4980 * @param checkGroupAnnColour
4983 private ColourSchemeI constructAnnotationColour(
4984 AnnotationColours viewAnnColour, AlignFrame af, AlignmentI al,
4985 JalviewModelSequence jms, boolean checkGroupAnnColour)
4987 boolean propagateAnnColour = false;
4988 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
4989 if (checkGroupAnnColour && al.getGroups() != null
4990 && al.getGroups().size() > 0)
4992 // pre 2.8.1 behaviour
4993 // check to see if we should transfer annotation colours
4994 propagateAnnColour = true;
4995 for (SequenceGroup sg : al.getGroups())
4997 if (sg.getColourScheme() instanceof AnnotationColourGradient)
4999 propagateAnnColour = false;
5005 * 2.10.2- : saved annotationId is AlignmentAnnotation.annotationId
5007 String annotationId = viewAnnColour.getAnnotation();
5008 AlignmentAnnotation matchedAnnotation = annotationIds.get(annotationId);
5011 * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
5013 if (matchedAnnotation == null
5014 && annAlignment.getAlignmentAnnotation() != null)
5016 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
5019 .equals(annAlignment.getAlignmentAnnotation()[i].label))
5021 matchedAnnotation = annAlignment.getAlignmentAnnotation()[i];
5026 if (matchedAnnotation == null)
5028 System.err.println("Failed to match annotation colour scheme for "
5032 if (matchedAnnotation.getThreshold() == null)
5034 matchedAnnotation.setThreshold(new GraphLine(
5035 viewAnnColour.getThreshold(), "Threshold", Color.black));
5038 AnnotationColourGradient cs = null;
5039 if (viewAnnColour.getColourScheme().equals("None"))
5041 cs = new AnnotationColourGradient(matchedAnnotation,
5042 new Color(viewAnnColour.getMinColour()),
5043 new Color(viewAnnColour.getMaxColour()),
5044 viewAnnColour.getAboveThreshold());
5046 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
5048 cs = new AnnotationColourGradient(matchedAnnotation,
5049 getUserColourScheme(jms, viewAnnColour.getColourScheme()),
5050 viewAnnColour.getAboveThreshold());
5054 cs = new AnnotationColourGradient(matchedAnnotation,
5055 ColourSchemeProperty.getColourScheme(al,
5056 viewAnnColour.getColourScheme()),
5057 viewAnnColour.getAboveThreshold());
5060 boolean perSequenceOnly = viewAnnColour.isPerSequence();
5061 boolean useOriginalColours = viewAnnColour.isPredefinedColours();
5062 cs.setSeqAssociated(perSequenceOnly);
5063 cs.setPredefinedColours(useOriginalColours);
5065 if (propagateAnnColour && al.getGroups() != null)
5067 // Also use these settings for all the groups
5068 for (int g = 0; g < al.getGroups().size(); g++)
5070 SequenceGroup sg = al.getGroups().get(g);
5071 if (sg.getGroupColourScheme() == null)
5076 AnnotationColourGradient groupScheme = new AnnotationColourGradient(
5077 matchedAnnotation, sg.getColourScheme(),
5078 viewAnnColour.getAboveThreshold());
5079 sg.setColourScheme(groupScheme);
5080 groupScheme.setSeqAssociated(perSequenceOnly);
5081 groupScheme.setPredefinedColours(useOriginalColours);
5087 private void reorderAutoannotation(AlignFrame af, AlignmentI al,
5088 List<JvAnnotRow> autoAlan)
5090 // copy over visualization settings for autocalculated annotation in the
5092 if (al.getAlignmentAnnotation() != null)
5095 * Kludge for magic autoannotation names (see JAL-811)
5097 String[] magicNames = new String[] { "Consensus", "Quality",
5099 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
5100 Hashtable<String, JvAnnotRow> visan = new Hashtable<>();
5101 for (String nm : magicNames)
5103 visan.put(nm, nullAnnot);
5105 for (JvAnnotRow auan : autoAlan)
5107 visan.put(auan.template.label
5108 + (auan.template.getCalcId() == null ? ""
5109 : "\t" + auan.template.getCalcId()),
5112 int hSize = al.getAlignmentAnnotation().length;
5113 List<JvAnnotRow> reorder = new ArrayList<>();
5114 // work through any autoCalculated annotation already on the view
5115 // removing it if it should be placed in a different location on the
5116 // annotation panel.
5117 List<String> remains = new ArrayList<>(visan.keySet());
5118 for (int h = 0; h < hSize; h++)
5120 jalview.datamodel.AlignmentAnnotation jalan = al
5121 .getAlignmentAnnotation()[h];
5122 if (jalan.autoCalculated)
5125 JvAnnotRow valan = visan.get(k = jalan.label);
5126 if (jalan.getCalcId() != null)
5128 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
5133 // delete the auto calculated row from the alignment
5134 al.deleteAnnotation(jalan, false);
5138 if (valan != nullAnnot)
5140 if (jalan != valan.template)
5142 // newly created autoannotation row instance
5143 // so keep a reference to the visible annotation row
5144 // and copy over all relevant attributes
5145 if (valan.template.graphHeight >= 0)
5148 jalan.graphHeight = valan.template.graphHeight;
5150 jalan.visible = valan.template.visible;
5152 reorder.add(new JvAnnotRow(valan.order, jalan));
5157 // Add any (possibly stale) autocalculated rows that were not appended to
5158 // the view during construction
5159 for (String other : remains)
5161 JvAnnotRow othera = visan.get(other);
5162 if (othera != nullAnnot && othera.template.getCalcId() != null
5163 && othera.template.getCalcId().length() > 0)
5165 reorder.add(othera);
5168 // now put the automatic annotation in its correct place
5169 int s = 0, srt[] = new int[reorder.size()];
5170 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
5171 for (JvAnnotRow jvar : reorder)
5174 srt[s++] = jvar.order;
5177 jalview.util.QuickSort.sort(srt, rws);
5178 // and re-insert the annotation at its correct position
5179 for (JvAnnotRow jvar : rws)
5181 al.addAnnotation(jvar.template, jvar.order);
5183 af.alignPanel.adjustAnnotationHeight();
5187 Hashtable skipList = null;
5190 * TODO remove this method
5193 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
5194 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
5195 * throw new Error("Implementation Error. No skipList defined for this
5196 * Jalview2XML instance."); } return (AlignFrame)
5197 * skipList.get(view.getSequenceSetId()); }
5201 * Check if the Jalview view contained in object should be skipped or not.
5204 * @return true if view's sequenceSetId is a key in skipList
5206 private boolean skipViewport(JalviewModel object)
5208 if (skipList == null)
5213 if (skipList.containsKey(
5214 id = object.getJalviewModelSequence().getViewport()[0]
5215 .getSequenceSetId()))
5217 if (Cache.log != null && Cache.log.isDebugEnabled())
5219 Cache.log.debug("Skipping seuqence set id " + id);
5226 public void addToSkipList(AlignFrame af)
5228 if (skipList == null)
5230 skipList = new Hashtable();
5232 skipList.put(af.getViewport().getSequenceSetId(), af);
5235 public void clearSkipList()
5237 if (skipList != null)
5244 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
5245 boolean ignoreUnrefed)
5247 jalview.datamodel.AlignmentI ds = getDatasetFor(
5248 vamsasSet.getDatasetId());
5249 Vector dseqs = null;
5252 // create a list of new dataset sequences
5253 dseqs = new Vector();
5255 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
5257 Sequence vamsasSeq = vamsasSet.getSequence(i);
5258 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
5260 // create a new dataset
5263 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
5264 dseqs.copyInto(dsseqs);
5265 ds = new jalview.datamodel.Alignment(dsseqs);
5266 debug("Created new dataset " + vamsasSet.getDatasetId()
5267 + " for alignment " + System.identityHashCode(al));
5268 addDatasetRef(vamsasSet.getDatasetId(), ds);
5270 // set the dataset for the newly imported alignment.
5271 if (al.getDataset() == null && !ignoreUnrefed)
5280 * sequence definition to create/merge dataset sequence for
5284 * vector to add new dataset sequence to
5285 * @param ignoreUnrefed
5286 * - when true, don't create new sequences from vamsasSeq if it's id
5287 * doesn't already have an asssociated Jalview sequence.
5289 * - used to reorder the sequence in the alignment according to the
5290 * vamsasSeq array ordering, to preserve ordering of dataset
5292 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
5293 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed, int vseqpos)
5295 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
5297 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
5298 boolean reorder = false;
5299 SequenceI dsq = null;
5300 if (sq != null && sq.getDatasetSequence() != null)
5302 dsq = sq.getDatasetSequence();
5308 if (sq == null && ignoreUnrefed)
5312 String sqid = vamsasSeq.getDsseqid();
5315 // need to create or add a new dataset sequence reference to this sequence
5318 dsq = seqRefIds.get(sqid);
5323 // make a new dataset sequence
5324 dsq = sq.createDatasetSequence();
5327 // make up a new dataset reference for this sequence
5328 sqid = seqHash(dsq);
5330 dsq.setVamsasId(uniqueSetSuffix + sqid);
5331 seqRefIds.put(sqid, dsq);
5336 dseqs.addElement(dsq);
5341 ds.addSequence(dsq);
5347 { // make this dataset sequence sq's dataset sequence
5348 sq.setDatasetSequence(dsq);
5349 // and update the current dataset alignment
5354 if (!dseqs.contains(dsq))
5361 if (ds.findIndex(dsq) < 0)
5363 ds.addSequence(dsq);
5370 // TODO: refactor this as a merge dataset sequence function
5371 // now check that sq (the dataset sequence) sequence really is the union of
5372 // all references to it
5373 // boolean pre = sq.getStart() < dsq.getStart();
5374 // boolean post = sq.getEnd() > dsq.getEnd();
5378 // StringBuffer sb = new StringBuffer();
5379 String newres = jalview.analysis.AlignSeq.extractGaps(
5380 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
5381 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
5382 && newres.length() > dsq.getLength())
5384 // Update with the longer sequence.
5388 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
5389 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
5390 * sb.append(newres.substring(newres.length() - sq.getEnd() -
5391 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
5393 dsq.setSequence(newres);
5395 // TODO: merges will never happen if we 'know' we have the real dataset
5396 // sequence - this should be detected when id==dssid
5398 "DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
5399 // + (pre ? "prepended" : "") + " "
5400 // + (post ? "appended" : ""));
5405 // sequence refs are identical. We may need to update the existing dataset
5406 // alignment with this one, though.
5407 if (ds != null && dseqs == null)
5409 int opos = ds.findIndex(dsq);
5410 SequenceI tseq = null;
5411 if (opos != -1 && vseqpos != opos)
5413 // remove from old position
5414 ds.deleteSequence(dsq);
5416 if (vseqpos < ds.getHeight())
5418 if (vseqpos != opos)
5420 // save sequence at destination position
5421 tseq = ds.getSequenceAt(vseqpos);
5422 ds.replaceSequenceAt(vseqpos, dsq);
5423 ds.addSequence(tseq);
5428 ds.addSequence(dsq);
5435 * TODO use AlignmentI here and in related methods - needs
5436 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
5438 Hashtable<String, AlignmentI> datasetIds = null;
5440 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
5442 private AlignmentI getDatasetFor(String datasetId)
5444 if (datasetIds == null)
5446 datasetIds = new Hashtable<>();
5449 if (datasetIds.containsKey(datasetId))
5451 return datasetIds.get(datasetId);
5456 private void addDatasetRef(String datasetId, AlignmentI dataset)
5458 if (datasetIds == null)
5460 datasetIds = new Hashtable<>();
5462 datasetIds.put(datasetId, dataset);
5466 * make a new dataset ID for this jalview dataset alignment
5471 private String getDatasetIdRef(AlignmentI dataset)
5473 if (dataset.getDataset() != null)
5475 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
5477 String datasetId = makeHashCode(dataset, null);
5478 if (datasetId == null)
5480 // make a new datasetId and record it
5481 if (dataset2Ids == null)
5483 dataset2Ids = new IdentityHashMap<>();
5487 datasetId = dataset2Ids.get(dataset);
5489 if (datasetId == null)
5491 datasetId = "ds" + dataset2Ids.size() + 1;
5492 dataset2Ids.put(dataset, datasetId);
5498 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5500 for (int d = 0; d < sequence.getDBRefCount(); d++)
5502 DBRef dr = sequence.getDBRef(d);
5503 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
5504 sequence.getDBRef(d).getSource(),
5505 sequence.getDBRef(d).getVersion(),
5506 sequence.getDBRef(d).getAccessionId());
5507 if (dr.getMapping() != null)
5509 entry.setMap(addMapping(dr.getMapping()));
5511 datasetSequence.addDBRef(entry);
5515 private jalview.datamodel.Mapping addMapping(Mapping m)
5517 SequenceI dsto = null;
5518 // Mapping m = dr.getMapping();
5519 int fr[] = new int[m.getMapListFromCount() * 2];
5520 Enumeration f = m.enumerateMapListFrom();
5521 for (int _i = 0; f.hasMoreElements(); _i += 2)
5523 MapListFrom mf = (MapListFrom) f.nextElement();
5524 fr[_i] = mf.getStart();
5525 fr[_i + 1] = mf.getEnd();
5527 int fto[] = new int[m.getMapListToCount() * 2];
5528 f = m.enumerateMapListTo();
5529 for (int _i = 0; f.hasMoreElements(); _i += 2)
5531 MapListTo mf = (MapListTo) f.nextElement();
5532 fto[_i] = mf.getStart();
5533 fto[_i + 1] = mf.getEnd();
5535 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto, fr,
5536 fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
5537 if (m.getMappingChoice() != null)
5539 MappingChoice mc = m.getMappingChoice();
5540 if (mc.getDseqFor() != null)
5542 String dsfor = "" + mc.getDseqFor();
5543 if (seqRefIds.containsKey(dsfor))
5548 jmap.setTo(seqRefIds.get(dsfor));
5552 frefedSequence.add(newMappingRef(dsfor, jmap));
5558 * local sequence definition
5560 Sequence ms = mc.getSequence();
5561 SequenceI djs = null;
5562 String sqid = ms.getDsseqid();
5563 if (sqid != null && sqid.length() > 0)
5566 * recover dataset sequence
5568 djs = seqRefIds.get(sqid);
5573 "Warning - making up dataset sequence id for DbRef sequence map reference");
5574 sqid = ((Object) ms).toString(); // make up a new hascode for
5575 // undefined dataset sequence hash
5576 // (unlikely to happen)
5582 * make a new dataset sequence and add it to refIds hash
5584 djs = new jalview.datamodel.Sequence(ms.getName(),
5586 djs.setStart(jmap.getMap().getToLowest());
5587 djs.setEnd(jmap.getMap().getToHighest());
5588 djs.setVamsasId(uniqueSetSuffix + sqid);
5590 incompleteSeqs.put(sqid, djs);
5591 seqRefIds.put(sqid, djs);
5594 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5604 * Provides a 'copy' of an alignment view (on action New View) by 'saving' the
5605 * view as XML (but not to file), and then reloading it
5610 public AlignmentPanel copyAlignPanel(AlignmentPanel ap)
5613 JalviewModel jm = saveState(ap, null, null, null);
5615 uniqueSetSuffix = "";
5616 jm.getJalviewModelSequence().getViewport(0).setId(null);
5617 // we don't overwrite the view we just copied
5619 if (this.frefedSequence == null)
5621 frefedSequence = new Vector<>();
5624 viewportsAdded.clear();
5626 AlignFrame af = loadFromObject(jm, null, false, null);
5627 af.alignPanels.clear();
5628 af.closeMenuItem_actionPerformed(true);
5631 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5632 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5633 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5634 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5635 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5638 return af.alignPanel;
5641 private Hashtable jvids2vobj;
5643 private void warn(String msg)
5648 private void warn(String msg, Exception e)
5650 if (Cache.log != null)
5654 Cache.log.warn(msg, e);
5658 Cache.log.warn(msg);
5663 System.err.println("Warning: " + msg);
5666 e.printStackTrace();
5671 private void debug(String string)
5673 debug(string, null);
5676 private void debug(String msg, Exception e)
5678 if (Cache.log != null)
5682 Cache.log.debug(msg, e);
5686 Cache.log.debug(msg);
5691 System.err.println("Warning: " + msg);
5694 e.printStackTrace();
5700 * set the object to ID mapping tables used to write/recover objects and XML
5701 * ID strings for the jalview project. If external tables are provided then
5702 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
5703 * object goes out of scope. - also populates the datasetIds hashtable with
5704 * alignment objects containing dataset sequences
5707 * Map from ID strings to jalview datamodel
5709 * Map from jalview datamodel to ID strings
5713 public void setObjectMappingTables(Hashtable vobj2jv,
5714 IdentityHashMap jv2vobj)
5716 this.jv2vobj = jv2vobj;
5717 this.vobj2jv = vobj2jv;
5718 Iterator ds = jv2vobj.keySet().iterator();
5720 while (ds.hasNext())
5722 Object jvobj = ds.next();
5723 id = jv2vobj.get(jvobj).toString();
5724 if (jvobj instanceof jalview.datamodel.Alignment)
5726 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
5728 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
5731 else if (jvobj instanceof jalview.datamodel.Sequence)
5733 // register sequence object so the XML parser can recover it.
5734 if (seqRefIds == null)
5736 seqRefIds = new HashMap<>();
5738 if (seqsToIds == null)
5740 seqsToIds = new IdentityHashMap<>();
5742 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
5743 seqsToIds.put((SequenceI) jvobj, id);
5745 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
5748 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
5749 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
5750 if (jvann.annotationId == null)
5752 jvann.annotationId = anid;
5754 if (!jvann.annotationId.equals(anid))
5756 // TODO verify that this is the correct behaviour
5757 this.warn("Overriding Annotation ID for " + anid
5758 + " from different id : " + jvann.annotationId);
5759 jvann.annotationId = anid;
5762 else if (jvobj instanceof String)
5764 if (jvids2vobj == null)
5766 jvids2vobj = new Hashtable();
5767 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
5772 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
5778 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
5779 * objects created from the project archive. If string is null (default for
5780 * construction) then suffix will be set automatically.
5784 public void setUniqueSetSuffix(String string)
5786 uniqueSetSuffix = string;
5791 * uses skipList2 as the skipList for skipping views on sequence sets
5792 * associated with keys in the skipList
5796 public void setSkipList(Hashtable skipList2)
5798 skipList = skipList2;
5802 * Reads the jar entry of given name and returns its contents, or null if the
5803 * entry is not found.
5806 * @param jarEntryName
5809 protected String readJarEntry(jarInputStreamProvider jprovider,
5810 String jarEntryName)
5812 String result = null;
5813 BufferedReader in = null;
5818 * Reopen the jar input stream and traverse its entries to find a matching
5821 JarInputStream jin = jprovider.getJarInputStream();
5822 JarEntry entry = null;
5825 entry = jin.getNextJarEntry();
5826 } while (entry != null && !entry.getName().equals(jarEntryName));
5830 StringBuilder out = new StringBuilder(256);
5831 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
5834 while ((data = in.readLine()) != null)
5838 result = out.toString();
5842 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
5844 } catch (Exception ex)
5846 ex.printStackTrace();
5854 } catch (IOException e)
5865 * Returns an incrementing counter (0, 1, 2...)
5869 private synchronized int nextCounter()
5875 * Loads any saved PCA viewers
5880 protected void loadPCAViewers(JalviewModelSequence jms, AlignmentPanel ap)
5884 for (int t = 0; t < jms.getPcaViewerCount(); t++)
5886 PcaViewer viewer = jms.getPcaViewer(t);
5887 String modelName = viewer.getScoreModelName();
5888 SimilarityParamsI params = new SimilarityParams(
5889 viewer.isIncludeGappedColumns(),
5890 viewer.isMatchGaps(), viewer.isIncludeGaps(),
5891 viewer.isDenominateByShortestLength());
5894 * create the panel (without computing the PCA)
5896 PCAPanel panel = new PCAPanel(ap, modelName, params);
5898 panel.setTitle(viewer.getTitle());
5899 panel.setBounds(new Rectangle(viewer.getXpos(), viewer.getYpos(),
5900 viewer.getWidth(), viewer.getHeight()));
5902 boolean showLabels = viewer.isShowLabels();
5903 panel.setShowLabels(showLabels);
5904 panel.rc.showLabels = showLabels;
5905 panel.rc.bgColour = new Color(viewer.getBgColour());
5906 panel.rc.applyToAllViews = viewer.isLinkToAllViews();
5909 * load PCA output data
5911 ScoreModelI scoreModel = ScoreModels.getInstance()
5912 .getScoreModel(modelName, ap);
5913 PCA pca = new PCA(null, scoreModel, params);
5914 PcaData pcaData = viewer.getPcaData();
5915 pca.setDetails(pcaData.getDetails());
5916 MatrixI pairwise = loadMatrix(pcaData.getPairwiseMatrix());
5917 pca.setPairwiseScores(pairwise);
5918 MatrixI result = loadMatrix(pcaData.getEigenMatrix());
5919 result.setD(pcaData.getEigenMatrixD().getD());
5920 result.setE(pcaData.getEigenMatrixE().getD());
5921 pca.setEigenmatrix(result);
5922 panel.pcaModel.setPCA(pca);
5925 * add the sequence points for the PCA display
5927 List<jalview.datamodel.SequencePoint> seqPoints = new ArrayList<>();
5928 for (SequencePoint sp : viewer.getSequencePoint())
5930 String seqId = sp.getSequenceRef();
5931 SequenceI seq = seqRefIds.get(seqId);
5934 throw new IllegalStateException(
5935 "Unmatched seqref for PCA: " + seqId);
5937 Point pt = new Point(sp.getXPos(), sp.getYPos(), sp.getZPos());
5938 jalview.datamodel.SequencePoint seqPoint = new jalview.datamodel.SequencePoint(
5940 seqPoints.add(seqPoint);
5942 panel.rc.setPoints(seqPoints, seqPoints.size());
5945 * set min-max ranges and scale after setPoints (which recomputes them)
5947 panel.rc.scaleFactor = viewer.getScaleFactor();
5948 SeqPointMin spMin = viewer.getSeqPointMin();
5949 float[] min = new float[] { spMin.getXPos(), spMin.getYPos(),
5951 SeqPointMax spMax = viewer.getSeqPointMax();
5952 float[] max = new float[] { spMax.getXPos(), spMax.getYPos(),
5954 panel.rc.setSeqMinMax(min, max);
5956 // todo: hold points list in PCAModel only
5957 panel.pcaModel.setSequencePoints(seqPoints);
5959 panel.setSelectedDimensionIndex(viewer.getXDim(), X);
5960 panel.setSelectedDimensionIndex(viewer.getYDim(), Y);
5961 panel.setSelectedDimensionIndex(viewer.getZDim(), Z);
5963 // is this duplication needed?
5964 panel.top = seqPoints.size() - 1;
5965 panel.pcaModel.setTop(seqPoints.size() - 1);
5968 * add the axes' end points for the display
5970 for (int i = 0; i < 3; i++)
5972 Axis axis = viewer.getAxis(i);
5973 panel.rc.axisEndPoints[i] = new Point(axis.getXPos(),
5974 axis.getYPos(), axis.getZPos());
5977 Desktop.addInternalFrame(panel, MessageManager.formatMessage(
5978 "label.calc_title", "PCA", modelName), 475, 450);
5980 } catch (Exception ex)
5982 Cache.log.error("Error loading PCA: " + ex.toString());
5987 * Loads XML matrix data into a new Matrix object
5992 protected MatrixI loadMatrix(DoubleMatrix mData)
5994 int rows = mData.getRows();
5995 double[][] vals = new double[rows][];
5997 for (int i = 0; i < rows; i++)
5999 vals[i] = mData.getRow(i).getD();
6002 MatrixI m = new Matrix(vals);
6007 * Populates an XML model of the feature colour scheme for one feature type
6009 * @param featureType
6013 protected static jalview.schemabinding.version2.Colour marshalColour(
6014 String featureType, FeatureColourI fcol)
6016 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
6017 if (fcol.isSimpleColour())
6019 col.setRGB(Format.getHexString(fcol.getColour()));
6023 col.setRGB(Format.getHexString(fcol.getMaxColour()));
6024 col.setMin(fcol.getMin());
6025 col.setMax(fcol.getMax());
6026 col.setMinRGB(jalview.util.Format.getHexString(fcol.getMinColour()));
6027 col.setAutoScale(fcol.isAutoScaled());
6028 col.setThreshold(fcol.getThreshold());
6029 col.setColourByLabel(fcol.isColourByLabel());
6030 col.setThreshType(fcol.isAboveThreshold() ? ColourThreshTypeType.ABOVE
6031 : (fcol.isBelowThreshold() ? ColourThreshTypeType.BELOW
6032 : ColourThreshTypeType.NONE));
6033 if (fcol.isColourByAttribute())
6035 col.setAttributeName(fcol.getAttributeName());
6037 Color noColour = fcol.getNoColour();
6038 if (noColour == null)
6040 col.setNoValueColour(NoValueColour.NONE);
6042 else if (noColour == fcol.getMaxColour())
6044 col.setNoValueColour(NoValueColour.MAX);
6048 col.setNoValueColour(NoValueColour.MIN);
6051 col.setName(featureType);
6056 * Populates an XML model of the feature filter(s) for one feature type
6058 * @param firstMatcher
6059 * the first (or only) match condition)
6061 * remaining match conditions (if any)
6063 * if true, conditions are and-ed, else or-ed
6065 protected static MatcherSet marshalFilter(FeatureMatcherI firstMatcher,
6066 Iterator<FeatureMatcherI> filters, boolean and)
6068 MatcherSet result = new MatcherSet();
6070 if (filters.hasNext())
6075 CompoundMatcher compound = new CompoundMatcher();
6076 compound.setAnd(and);
6077 MatcherSet matcher1 = marshalFilter(firstMatcher,
6078 Collections.emptyIterator(), and);
6079 compound.addMatcherSet(matcher1);
6080 FeatureMatcherI nextMatcher = filters.next();
6081 MatcherSet matcher2 = marshalFilter(nextMatcher, filters, and);
6082 compound.addMatcherSet(matcher2);
6083 result.setCompoundMatcher(compound);
6088 * single condition matcher
6090 MatchCondition matcherModel = new MatchCondition();
6091 matcherModel.setCondition(
6092 firstMatcher.getMatcher().getCondition().getStableName());
6093 matcherModel.setValue(firstMatcher.getMatcher().getPattern());
6094 if (firstMatcher.isByAttribute())
6096 matcherModel.setBy(FeatureMatcherByType.BYATTRIBUTE);
6097 matcherModel.setAttributeName(firstMatcher.getAttribute());
6099 else if (firstMatcher.isByLabel())
6101 matcherModel.setBy(FeatureMatcherByType.BYLABEL);
6103 else if (firstMatcher.isByScore())
6105 matcherModel.setBy(FeatureMatcherByType.BYSCORE);
6107 result.setMatchCondition(matcherModel);
6114 * Loads one XML model of a feature filter to a Jalview object
6116 * @param featureType
6117 * @param matcherSetModel
6120 protected static FeatureMatcherSetI unmarshalFilter(
6121 String featureType, MatcherSet matcherSetModel)
6123 FeatureMatcherSetI result = new FeatureMatcherSet();
6126 unmarshalFilterConditions(result, matcherSetModel, true);
6127 } catch (IllegalStateException e)
6129 // mixing AND and OR conditions perhaps
6131 String.format("Error reading filter conditions for '%s': %s",
6132 featureType, e.getMessage()));
6133 // return as much as was parsed up to the error
6140 * Adds feature match conditions to matcherSet as unmarshalled from XML
6141 * (possibly recursively for compound conditions)
6144 * @param matcherSetModel
6146 * if true, multiple conditions are AND-ed, else they are OR-ed
6147 * @throws IllegalStateException
6148 * if AND and OR conditions are mixed
6150 protected static void unmarshalFilterConditions(
6151 FeatureMatcherSetI matcherSet, MatcherSet matcherSetModel,
6154 MatchCondition mc = matcherSetModel.getMatchCondition();
6160 FeatureMatcherByType filterBy = mc.getBy();
6161 Condition cond = Condition.fromString(mc.getCondition());
6162 String pattern = mc.getValue();
6163 FeatureMatcherI matchCondition = null;
6164 if (filterBy == FeatureMatcherByType.BYLABEL)
6166 matchCondition = FeatureMatcher.byLabel(cond, pattern);
6168 else if (filterBy == FeatureMatcherByType.BYSCORE)
6170 matchCondition = FeatureMatcher.byScore(cond, pattern);
6173 else if (filterBy == FeatureMatcherByType.BYATTRIBUTE)
6175 String[] attNames = mc.getAttributeName();
6176 matchCondition = FeatureMatcher.byAttribute(cond, pattern,
6181 * note this throws IllegalStateException if AND-ing to a
6182 * previously OR-ed compound condition, or vice versa
6186 matcherSet.and(matchCondition);
6190 matcherSet.or(matchCondition);
6196 * compound condition
6198 MatcherSet[] matchers = matcherSetModel.getCompoundMatcher()
6200 boolean anded = matcherSetModel.getCompoundMatcher().getAnd();
6201 if (matchers.length == 2)
6203 unmarshalFilterConditions(matcherSet, matchers[0], anded);
6204 unmarshalFilterConditions(matcherSet, matchers[1], anded);
6208 System.err.println("Malformed compound filter condition");
6214 * Loads one XML model of a feature colour to a Jalview object
6216 * @param colourModel
6219 protected static FeatureColourI unmarshalColour(
6220 jalview.schemabinding.version2.Colour colourModel)
6222 FeatureColourI colour = null;
6224 if (colourModel.hasMax())
6226 Color mincol = null;
6227 Color maxcol = null;
6228 Color noValueColour = null;
6232 mincol = new Color(Integer.parseInt(colourModel.getMinRGB(), 16));
6233 maxcol = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6234 } catch (Exception e)
6236 Cache.log.warn("Couldn't parse out graduated feature color.", e);
6239 NoValueColour noCol = colourModel.getNoValueColour();
6240 if (noCol == NoValueColour.MIN)
6242 noValueColour = mincol;
6244 else if (noCol == NoValueColour.MAX)
6246 noValueColour = maxcol;
6249 colour = new FeatureColour(mincol, maxcol, noValueColour,
6250 colourModel.getMin(),
6251 colourModel.getMax());
6252 String[] attributes = colourModel.getAttributeName();
6253 if (attributes != null && attributes.length > 0)
6255 colour.setAttributeName(attributes);
6257 if (colourModel.hasAutoScale())
6259 colour.setAutoScaled(colourModel.getAutoScale());
6261 if (colourModel.hasColourByLabel())
6263 colour.setColourByLabel(colourModel.getColourByLabel());
6265 if (colourModel.hasThreshold())
6267 colour.setThreshold(colourModel.getThreshold());
6269 ColourThreshTypeType ttyp = colourModel.getThreshType();
6272 if (ttyp == ColourThreshTypeType.ABOVE)
6274 colour.setAboveThreshold(true);
6276 else if (ttyp == ColourThreshTypeType.BELOW)
6278 colour.setBelowThreshold(true);
6284 Color color = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6285 colour = new FeatureColour(color);