2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
21 package jalview.project;
23 import jalview.analysis.Conservation;
24 import jalview.api.FeatureColourI;
25 import jalview.api.ViewStyleI;
26 import jalview.api.structures.JalviewStructureDisplayI;
27 import jalview.bin.Cache;
28 import jalview.datamodel.AlignedCodonFrame;
29 import jalview.datamodel.Alignment;
30 import jalview.datamodel.AlignmentAnnotation;
31 import jalview.datamodel.AlignmentI;
32 import jalview.datamodel.GraphLine;
33 import jalview.datamodel.PDBEntry;
34 import jalview.datamodel.RnaViewerModel;
35 import jalview.datamodel.SequenceFeature;
36 import jalview.datamodel.SequenceGroup;
37 import jalview.datamodel.SequenceI;
38 import jalview.datamodel.StructureViewerModel;
39 import jalview.datamodel.StructureViewerModel.StructureData;
40 import jalview.datamodel.features.FeatureMatcher;
41 import jalview.datamodel.features.FeatureMatcherI;
42 import jalview.datamodel.features.FeatureMatcherSet;
43 import jalview.datamodel.features.FeatureMatcherSetI;
44 import jalview.ext.varna.RnaModel;
45 import jalview.gui.AlignFrame;
46 import jalview.gui.AlignViewport;
47 import jalview.gui.AlignmentPanel;
48 import jalview.gui.AppVarna;
49 import jalview.gui.ChimeraViewFrame;
50 import jalview.gui.Desktop;
51 import jalview.gui.FeatureRenderer;
52 import jalview.gui.Jalview2XML_V1;
53 import jalview.gui.JvOptionPane;
54 import jalview.gui.OOMWarning;
55 import jalview.gui.PaintRefresher;
56 import jalview.gui.SplitFrame;
57 import jalview.gui.StructureViewer;
58 import jalview.gui.StructureViewer.ViewerType;
59 import jalview.gui.StructureViewerBase;
60 import jalview.gui.TreePanel;
61 import jalview.io.DataSourceType;
62 import jalview.io.FileFormat;
63 import jalview.renderer.ResidueShaderI;
64 import jalview.schemes.AnnotationColourGradient;
65 import jalview.schemes.ColourSchemeI;
66 import jalview.schemes.ColourSchemeProperty;
67 import jalview.schemes.FeatureColour;
68 import jalview.schemes.ResidueProperties;
69 import jalview.schemes.UserColourScheme;
70 import jalview.structure.StructureSelectionManager;
71 import jalview.structures.models.AAStructureBindingModel;
72 import jalview.util.Format;
73 import jalview.util.MessageManager;
74 import jalview.util.Platform;
75 import jalview.util.StringUtils;
76 import jalview.util.jarInputStreamProvider;
77 import jalview.util.matcher.Condition;
78 import jalview.viewmodel.AlignmentViewport;
79 import jalview.viewmodel.ViewportRanges;
80 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
81 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
82 import jalview.ws.jws2.Jws2Discoverer;
83 import jalview.ws.jws2.dm.AAConSettings;
84 import jalview.ws.jws2.jabaws2.Jws2Instance;
85 import jalview.ws.params.ArgumentI;
86 import jalview.ws.params.AutoCalcSetting;
87 import jalview.ws.params.WsParamSetI;
88 import jalview.xml.binding.jalview.AlcodonFrame;
89 import jalview.xml.binding.jalview.AlcodonFrame.AlcodMap;
90 import jalview.xml.binding.jalview.Annotation;
91 import jalview.xml.binding.jalview.Annotation.ThresholdLine;
92 import jalview.xml.binding.jalview.AnnotationColourScheme;
93 import jalview.xml.binding.jalview.AnnotationElement;
94 import jalview.xml.binding.jalview.Feature;
95 import jalview.xml.binding.jalview.Feature.OtherData;
96 import jalview.xml.binding.jalview.FeatureMatcherSet.CompoundMatcher;
97 import jalview.xml.binding.jalview.FilterBy;
98 import jalview.xml.binding.jalview.JalviewModel;
99 import jalview.xml.binding.jalview.JalviewModel.FeatureSettings;
100 import jalview.xml.binding.jalview.JalviewModel.FeatureSettings.Group;
101 import jalview.xml.binding.jalview.JalviewModel.FeatureSettings.Setting;
102 import jalview.xml.binding.jalview.JalviewModel.JGroup;
103 import jalview.xml.binding.jalview.JalviewModel.JSeq;
104 import jalview.xml.binding.jalview.JalviewModel.JSeq.Pdbids;
105 import jalview.xml.binding.jalview.JalviewModel.JSeq.Pdbids.StructureState;
106 import jalview.xml.binding.jalview.JalviewModel.JSeq.RnaViewer;
107 import jalview.xml.binding.jalview.JalviewModel.JSeq.RnaViewer.SecondaryStructure;
108 import jalview.xml.binding.jalview.JalviewModel.Tree;
109 import jalview.xml.binding.jalview.JalviewModel.UserColours;
110 import jalview.xml.binding.jalview.JalviewModel.Viewport;
111 import jalview.xml.binding.jalview.JalviewModel.Viewport.CalcIdParam;
112 import jalview.xml.binding.jalview.JalviewModel.Viewport.HiddenColumns;
113 import jalview.xml.binding.jalview.JalviewUserColours;
114 import jalview.xml.binding.jalview.JalviewUserColours.Colour;
115 import jalview.xml.binding.jalview.MapListType.MapListFrom;
116 import jalview.xml.binding.jalview.MapListType.MapListTo;
117 import jalview.xml.binding.jalview.Mapping;
118 import jalview.xml.binding.jalview.NoValueColour;
119 import jalview.xml.binding.jalview.ObjectFactory;
120 import jalview.xml.binding.jalview.Pdbentry.Property;
121 import jalview.xml.binding.jalview.Sequence;
122 import jalview.xml.binding.jalview.Sequence.DBRef;
123 import jalview.xml.binding.jalview.SequenceSet;
124 import jalview.xml.binding.jalview.SequenceSet.SequenceSetProperties;
125 import jalview.xml.binding.jalview.ThresholdType;
126 import jalview.xml.binding.jalview.VAMSAS;
128 import java.awt.Color;
129 import java.awt.Font;
130 import java.awt.Rectangle;
131 import java.io.BufferedReader;
132 import java.io.DataInputStream;
133 import java.io.DataOutputStream;
135 import java.io.FileInputStream;
136 import java.io.FileOutputStream;
137 import java.io.IOException;
138 import java.io.InputStreamReader;
139 import java.io.OutputStreamWriter;
140 import java.io.PrintWriter;
141 import java.lang.reflect.InvocationTargetException;
142 import java.math.BigInteger;
143 import java.net.MalformedURLException;
145 import java.util.ArrayList;
146 import java.util.Arrays;
147 import java.util.Collections;
148 import java.util.Enumeration;
149 import java.util.GregorianCalendar;
150 import java.util.HashMap;
151 import java.util.HashSet;
152 import java.util.Hashtable;
153 import java.util.IdentityHashMap;
154 import java.util.Iterator;
155 import java.util.LinkedHashMap;
156 import java.util.List;
157 import java.util.Map;
158 import java.util.Map.Entry;
159 import java.util.Set;
160 import java.util.Vector;
161 import java.util.jar.JarEntry;
162 import java.util.jar.JarInputStream;
163 import java.util.jar.JarOutputStream;
165 import javax.swing.JInternalFrame;
166 import javax.swing.SwingUtilities;
167 import javax.xml.bind.JAXBContext;
168 import javax.xml.bind.JAXBElement;
169 import javax.xml.bind.Marshaller;
170 import javax.xml.datatype.DatatypeConfigurationException;
171 import javax.xml.datatype.DatatypeFactory;
172 import javax.xml.datatype.XMLGregorianCalendar;
173 import javax.xml.stream.XMLInputFactory;
174 import javax.xml.stream.XMLStreamReader;
177 * Write out the current jalview desktop state as a Jalview XML stream.
179 * Note: the vamsas objects referred to here are primitive versions of the
180 * VAMSAS project schema elements - they are not the same and most likely never
184 * @version $Revision: 1.134 $
186 public class Jalview2XML
188 private static final String VIEWER_PREFIX = "viewer_";
190 private static final String RNA_PREFIX = "rna_";
192 private static final String UTF_8 = "UTF-8";
194 // use this with nextCounter() to make unique names for entities
195 private int counter = 0;
198 * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
199 * of sequence objects are created.
201 IdentityHashMap<SequenceI, String> seqsToIds = null;
204 * jalview XML Sequence ID to jalview sequence object reference (both dataset
205 * and alignment sequences. Populated as XML reps of sequence objects are
208 Map<String, SequenceI> seqRefIds = null;
210 Map<String, SequenceI> incompleteSeqs = null;
212 List<SeqFref> frefedSequence = null;
214 boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
217 * Map of reconstructed AlignFrame objects that appear to have come from
218 * SplitFrame objects (have a dna/protein complement view).
220 private Map<Viewport, AlignFrame> splitFrameCandidates = new HashMap<>();
223 * Map from displayed rna structure models to their saved session state jar
226 private Map<RnaModel, String> rnaSessions = new HashMap<>();
229 * create/return unique hash string for sq
232 * @return new or existing unique string for sq
234 String seqHash(SequenceI sq)
236 if (seqsToIds == null)
240 if (seqsToIds.containsKey(sq))
242 return seqsToIds.get(sq);
246 // create sequential key
247 String key = "sq" + (seqsToIds.size() + 1);
248 key = makeHashCode(sq, key); // check we don't have an external reference
250 seqsToIds.put(sq, key);
257 if (seqsToIds == null)
259 seqsToIds = new IdentityHashMap<>();
261 if (seqRefIds == null)
263 seqRefIds = new HashMap<>();
265 if (incompleteSeqs == null)
267 incompleteSeqs = new HashMap<>();
269 if (frefedSequence == null)
271 frefedSequence = new ArrayList<>();
279 public Jalview2XML(boolean raiseGUI)
281 this.raiseGUI = raiseGUI;
285 * base class for resolving forward references to sequences by their ID
290 abstract class SeqFref
296 public SeqFref(String _sref, String type)
302 public String getSref()
307 public SequenceI getSrefSeq()
309 return seqRefIds.get(sref);
312 public boolean isResolvable()
314 return seqRefIds.get(sref) != null;
317 public SequenceI getSrefDatasetSeq()
319 SequenceI sq = seqRefIds.get(sref);
322 while (sq.getDatasetSequence() != null)
324 sq = sq.getDatasetSequence();
331 * @return true if the forward reference was fully resolved
333 abstract boolean resolve();
336 public String toString()
338 return type + " reference to " + sref;
343 * create forward reference for a mapping
349 public SeqFref newMappingRef(final String sref,
350 final jalview.datamodel.Mapping _jmap)
352 SeqFref fref = new SeqFref(sref, "Mapping")
354 public jalview.datamodel.Mapping jmap = _jmap;
359 SequenceI seq = getSrefDatasetSeq();
371 public SeqFref newAlcodMapRef(final String sref,
372 final AlignedCodonFrame _cf,
373 final jalview.datamodel.Mapping _jmap)
376 SeqFref fref = new SeqFref(sref, "Codon Frame")
378 AlignedCodonFrame cf = _cf;
380 public jalview.datamodel.Mapping mp = _jmap;
383 public boolean isResolvable()
385 return super.isResolvable() && mp.getTo() != null;
391 SequenceI seq = getSrefDatasetSeq();
396 cf.addMap(seq, mp.getTo(), mp.getMap());
403 public void resolveFrefedSequences()
405 Iterator<SeqFref> nextFref = frefedSequence.iterator();
406 int toresolve = frefedSequence.size();
407 int unresolved = 0, failedtoresolve = 0;
408 while (nextFref.hasNext())
410 SeqFref ref = nextFref.next();
411 if (ref.isResolvable())
423 } catch (Exception x)
426 "IMPLEMENTATION ERROR: Failed to resolve forward reference for sequence "
439 System.err.println("Jalview Project Import: There were " + unresolved
440 + " forward references left unresolved on the stack.");
442 if (failedtoresolve > 0)
444 System.err.println("SERIOUS! " + failedtoresolve
445 + " resolvable forward references failed to resolve.");
447 if (incompleteSeqs != null && incompleteSeqs.size() > 0)
450 "Jalview Project Import: There are " + incompleteSeqs.size()
451 + " sequences which may have incomplete metadata.");
452 if (incompleteSeqs.size() < 10)
454 for (SequenceI s : incompleteSeqs.values())
456 System.err.println(s.toString());
462 "Too many to report. Skipping output of incomplete sequences.");
468 * This maintains a map of viewports, the key being the seqSetId. Important to
469 * set historyItem and redoList for multiple views
471 Map<String, AlignViewport> viewportsAdded = new HashMap<>();
473 Map<String, AlignmentAnnotation> annotationIds = new HashMap<>();
475 String uniqueSetSuffix = "";
478 * List of pdbfiles added to Jar
480 List<String> pdbfiles = null;
482 // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
483 public void saveState(File statefile)
485 FileOutputStream fos = null;
488 fos = new FileOutputStream(statefile);
489 JarOutputStream jout = new JarOutputStream(fos);
492 } catch (Exception e)
494 // TODO: inform user of the problem - they need to know if their data was
496 if (errorMessage == null)
498 errorMessage = "Couldn't write Jalview Archive to output file '"
499 + statefile + "' - See console error log for details";
503 errorMessage += "(output file was '" + statefile + "')";
513 } catch (IOException e)
523 * Writes a jalview project archive to the given Jar output stream.
527 public void saveState(JarOutputStream jout)
529 AlignFrame[] frames = Desktop.getAlignFrames();
535 saveAllFrames(Arrays.asList(frames), jout);
539 * core method for storing state for a set of AlignFrames.
542 * - frames involving all data to be exported (including containing
545 * - project output stream
547 private void saveAllFrames(List<AlignFrame> frames, JarOutputStream jout)
549 Hashtable<String, AlignFrame> dsses = new Hashtable<>();
552 * ensure cached data is clear before starting
554 // todo tidy up seqRefIds, seqsToIds initialisation / reset
556 splitFrameCandidates.clear();
561 // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
562 // //////////////////////////////////////////////////
564 List<String> shortNames = new ArrayList<>();
565 List<String> viewIds = new ArrayList<>();
568 for (int i = frames.size() - 1; i > -1; i--)
570 AlignFrame af = frames.get(i);
572 if (skipList != null && skipList
573 .containsKey(af.getViewport().getSequenceSetId()))
578 String shortName = makeFilename(af, shortNames);
580 int apSize = af.getAlignPanels().size();
582 for (int ap = 0; ap < apSize; ap++)
584 AlignmentPanel apanel = (AlignmentPanel) af.getAlignPanels()
586 String fileName = apSize == 1 ? shortName : ap + shortName;
587 if (!fileName.endsWith(".xml"))
589 fileName = fileName + ".xml";
592 saveState(apanel, fileName, jout, viewIds);
594 String dssid = getDatasetIdRef(
595 af.getViewport().getAlignment().getDataset());
596 if (!dsses.containsKey(dssid))
598 dsses.put(dssid, af);
603 writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix,
609 } catch (Exception foo)
614 } catch (Exception ex)
616 // TODO: inform user of the problem - they need to know if their data was
618 if (errorMessage == null)
620 errorMessage = "Couldn't write Jalview Archive - see error output for details";
622 ex.printStackTrace();
627 * Generates a distinct file name, based on the title of the AlignFrame, by
628 * appending _n for increasing n until an unused name is generated. The new
629 * name (without its extension) is added to the list.
633 * @return the generated name, with .xml extension
635 protected String makeFilename(AlignFrame af, List<String> namesUsed)
637 String shortName = af.getTitle();
639 if (shortName.indexOf(File.separatorChar) > -1)
641 shortName = shortName
642 .substring(shortName.lastIndexOf(File.separatorChar) + 1);
647 while (namesUsed.contains(shortName))
649 if (shortName.endsWith("_" + (count - 1)))
651 shortName = shortName.substring(0, shortName.lastIndexOf("_"));
654 shortName = shortName.concat("_" + count);
658 namesUsed.add(shortName);
660 if (!shortName.endsWith(".xml"))
662 shortName = shortName + ".xml";
667 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
668 public boolean saveAlignment(AlignFrame af, String jarFile,
673 FileOutputStream fos = new FileOutputStream(jarFile);
674 JarOutputStream jout = new JarOutputStream(fos);
675 List<AlignFrame> frames = new ArrayList<>();
677 // resolve splitframes
678 if (af.getViewport().getCodingComplement() != null)
680 frames = ((SplitFrame) af.getSplitViewContainer()).getAlignFrames();
686 saveAllFrames(frames, jout);
690 } catch (Exception foo)
696 } catch (Exception ex)
698 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
699 ex.printStackTrace();
704 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
705 String fileName, JarOutputStream jout)
708 for (String dssids : dsses.keySet())
710 AlignFrame _af = dsses.get(dssids);
711 String jfileName = fileName + " Dataset for " + _af.getTitle();
712 if (!jfileName.endsWith(".xml"))
714 jfileName = jfileName + ".xml";
716 saveState(_af.alignPanel, jfileName, true, jout, null);
721 * create a JalviewModel from an alignment view and marshall it to a
725 * panel to create jalview model for
727 * name of alignment panel written to output stream
734 public JalviewModel saveState(AlignmentPanel ap, String fileName,
735 JarOutputStream jout, List<String> viewIds)
737 return saveState(ap, fileName, false, jout, viewIds);
741 * create a JalviewModel from an alignment view and marshall it to a
745 * panel to create jalview model for
747 * name of alignment panel written to output stream
749 * when true, only write the dataset for the alignment, not the data
750 * associated with the view.
756 public JalviewModel saveState(AlignmentPanel ap, String fileName,
757 boolean storeDS, JarOutputStream jout, List<String> viewIds)
761 viewIds = new ArrayList<>();
766 List<UserColourScheme> userColours = new ArrayList<>();
768 AlignViewport av = ap.av;
769 ViewportRanges vpRanges = av.getRanges();
771 final ObjectFactory objectFactory = new ObjectFactory();
772 JalviewModel object = objectFactory.createJalviewModel();
773 object.setVamsasModel(new VAMSAS());
775 // object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
778 GregorianCalendar c = new GregorianCalendar();
779 DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
780 XMLGregorianCalendar now = datatypeFactory.newXMLGregorianCalendar(c);// gregorianCalendar);
781 object.setCreationDate(now);
782 } catch (DatatypeConfigurationException e)
784 System.err.println("error writing date: " + e.toString());
787 jalview.bin.Cache.getDefault("VERSION", "Development Build"));
790 * rjal is full height alignment, jal is actual alignment with full metadata
791 * but excludes hidden sequences.
793 jalview.datamodel.AlignmentI rjal = av.getAlignment(), jal = rjal;
795 if (av.hasHiddenRows())
797 rjal = jal.getHiddenSequences().getFullAlignment();
800 SequenceSet vamsasSet = new SequenceSet();
802 // JalviewModelSequence jms = new JalviewModelSequence();
804 vamsasSet.setGapChar(jal.getGapCharacter() + "");
806 if (jal.getDataset() != null)
808 // dataset id is the dataset's hashcode
809 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
812 // switch jal and the dataset
813 jal = jal.getDataset();
817 if (jal.getProperties() != null)
819 Enumeration en = jal.getProperties().keys();
820 while (en.hasMoreElements())
822 String key = en.nextElement().toString();
823 SequenceSetProperties ssp = new SequenceSetProperties();
825 ssp.setValue(jal.getProperties().get(key).toString());
826 // vamsasSet.addSequenceSetProperties(ssp);
827 vamsasSet.getSequenceSetProperties().add(ssp);
832 Set<String> calcIdSet = new HashSet<>();
833 // record the set of vamsas sequence XML POJO we create.
834 HashMap<String, Sequence> vamsasSetIds = new HashMap<>();
836 for (final SequenceI jds : rjal.getSequences())
838 final SequenceI jdatasq = jds.getDatasetSequence() == null ? jds
839 : jds.getDatasetSequence();
840 String id = seqHash(jds);
841 if (vamsasSetIds.get(id) == null)
843 if (seqRefIds.get(id) != null && !storeDS)
845 // This happens for two reasons: 1. multiple views are being
847 // 2. the hashCode has collided with another sequence's code. This
849 // HAPPEN! (PF00072.15.stk does this)
850 // JBPNote: Uncomment to debug writing out of files that do not read
851 // back in due to ArrayOutOfBoundExceptions.
852 // System.err.println("vamsasSeq backref: "+id+"");
853 // System.err.println(jds.getName()+"
854 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
855 // System.err.println("Hashcode: "+seqHash(jds));
856 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
857 // System.err.println(rsq.getName()+"
858 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
859 // System.err.println("Hashcode: "+seqHash(rsq));
863 vamsasSeq = createVamsasSequence(id, jds);
864 // vamsasSet.addSequence(vamsasSeq);
865 vamsasSet.getSequence().add(vamsasSeq);
866 vamsasSetIds.put(id, vamsasSeq);
867 seqRefIds.put(id, jds);
871 jseq.setStart(jds.getStart());
872 jseq.setEnd(jds.getEnd());
873 jseq.setColour(av.getSequenceColour(jds).getRGB());
875 jseq.setId(id); // jseq id should be a string not a number
878 // Store any sequences this sequence represents
879 if (av.hasHiddenRows())
881 // use rjal, contains the full height alignment
883 av.getAlignment().getHiddenSequences().isHidden(jds));
885 if (av.isHiddenRepSequence(jds))
887 jalview.datamodel.SequenceI[] reps = av
888 .getRepresentedSequences(jds).getSequencesInOrder(rjal);
890 for (int h = 0; h < reps.length; h++)
894 // jseq.addHiddenSequences(rjal.findIndex(reps[h]));
895 jseq.getHiddenSequences().add(rjal.findIndex(reps[h]));
900 // mark sequence as reference - if it is the reference for this view
903 jseq.setViewreference(jds == jal.getSeqrep());
907 // TODO: omit sequence features from each alignment view's XML dump if we
908 // are storing dataset
909 List<SequenceFeature> sfs = jds.getSequenceFeatures();
910 for (SequenceFeature sf : sfs)
912 // Features features = new Features();
913 Feature features = new Feature();
915 features.setBegin(sf.getBegin());
916 features.setEnd(sf.getEnd());
917 features.setDescription(sf.getDescription());
918 features.setType(sf.getType());
919 features.setFeatureGroup(sf.getFeatureGroup());
920 features.setScore(sf.getScore());
921 if (sf.links != null)
923 for (int l = 0; l < sf.links.size(); l++)
925 OtherData keyValue = new OtherData();
926 keyValue.setKey("LINK_" + l);
927 keyValue.setValue(sf.links.elementAt(l).toString());
928 // features.addOtherData(keyValue);
929 features.getOtherData().add(keyValue);
932 if (sf.otherDetails != null)
935 * save feature attributes, which may be simple strings or
936 * map valued (have sub-attributes)
938 for (Entry<String, Object> entry : sf.otherDetails.entrySet())
940 String key = entry.getKey();
941 Object value = entry.getValue();
942 if (value instanceof Map<?, ?>)
944 for (Entry<String, Object> subAttribute : ((Map<String, Object>) value)
947 OtherData otherData = new OtherData();
948 otherData.setKey(key);
949 otherData.setKey2(subAttribute.getKey());
950 otherData.setValue(subAttribute.getValue().toString());
951 // features.addOtherData(otherData);
952 features.getOtherData().add(otherData);
957 OtherData otherData = new OtherData();
958 otherData.setKey(key);
959 otherData.setValue(value.toString());
960 // features.addOtherData(otherData);
961 features.getOtherData().add(otherData);
966 // jseq.addFeatures(features);
967 jseq.getFeatures().add(features);
970 if (jdatasq.getAllPDBEntries() != null)
972 Enumeration<PDBEntry> en = jdatasq.getAllPDBEntries().elements();
973 while (en.hasMoreElements())
975 Pdbids pdb = new Pdbids();
976 jalview.datamodel.PDBEntry entry = en.nextElement();
978 String pdbId = entry.getId();
980 pdb.setType(entry.getType());
983 * Store any structure views associated with this sequence. This
984 * section copes with duplicate entries in the project, so a dataset
985 * only view *should* be coped with sensibly.
987 // This must have been loaded, is it still visible?
988 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
989 String matchedFile = null;
990 for (int f = frames.length - 1; f > -1; f--)
992 if (frames[f] instanceof StructureViewerBase)
994 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
995 matchedFile = saveStructureState(ap, jds, pdb, entry, viewIds,
996 matchedFile, viewFrame);
998 * Only store each structure viewer's state once in the project
999 * jar. First time through only (storeDS==false)
1001 String viewId = viewFrame.getViewId();
1002 if (!storeDS && !viewIds.contains(viewId))
1004 viewIds.add(viewId);
1007 String viewerState = viewFrame.getStateInfo();
1008 writeJarEntry(jout, getViewerJarEntryName(viewId),
1009 viewerState.getBytes());
1010 } catch (IOException e)
1013 "Error saving viewer state: " + e.getMessage());
1019 if (matchedFile != null || entry.getFile() != null)
1021 if (entry.getFile() != null)
1024 matchedFile = entry.getFile();
1026 pdb.setFile(matchedFile); // entry.getFile());
1027 if (pdbfiles == null)
1029 pdbfiles = new ArrayList<>();
1032 if (!pdbfiles.contains(pdbId))
1034 pdbfiles.add(pdbId);
1035 copyFileToJar(jout, matchedFile, pdbId);
1039 Enumeration<String> props = entry.getProperties();
1040 if (props.hasMoreElements())
1042 // PdbentryItem item = new PdbentryItem();
1043 while (props.hasMoreElements())
1045 Property prop = new Property();
1046 String key = props.nextElement();
1048 prop.setValue(entry.getProperty(key).toString());
1049 // item.addProperty(prop);
1050 pdb.getProperty().add(prop);
1052 // pdb.addPdbentryItem(item);
1055 // jseq.addPdbids(pdb);
1056 jseq.getPdbids().add(pdb);
1060 saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
1062 // jms.addJSeq(jseq);
1063 object.getJSeq().add(jseq);
1066 if (!storeDS && av.hasHiddenRows())
1068 jal = av.getAlignment();
1072 if (storeDS && jal.getCodonFrames() != null)
1074 List<AlignedCodonFrame> jac = jal.getCodonFrames();
1075 for (AlignedCodonFrame acf : jac)
1077 AlcodonFrame alc = new AlcodonFrame();
1078 if (acf.getProtMappings() != null
1079 && acf.getProtMappings().length > 0)
1081 boolean hasMap = false;
1082 SequenceI[] dnas = acf.getdnaSeqs();
1083 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1084 for (int m = 0; m < pmaps.length; m++)
1086 AlcodMap alcmap = new AlcodMap();
1087 alcmap.setDnasq(seqHash(dnas[m]));
1089 createVamsasMapping(pmaps[m], dnas[m], null, false));
1090 // alc.addAlcodMap(alcmap);
1091 alc.getAlcodMap().add(alcmap);
1096 // vamsasSet.addAlcodonFrame(alc);
1097 vamsasSet.getAlcodonFrame().add(alc);
1100 // TODO: delete this ? dead code from 2.8.3->2.9 ?
1102 // AlcodonFrame alc = new AlcodonFrame();
1103 // vamsasSet.addAlcodonFrame(alc);
1104 // for (int p = 0; p < acf.aaWidth; p++)
1106 // Alcodon cmap = new Alcodon();
1107 // if (acf.codons[p] != null)
1109 // // Null codons indicate a gapped column in the translated peptide
1111 // cmap.setPos1(acf.codons[p][0]);
1112 // cmap.setPos2(acf.codons[p][1]);
1113 // cmap.setPos3(acf.codons[p][2]);
1115 // alc.addAlcodon(cmap);
1117 // if (acf.getProtMappings() != null
1118 // && acf.getProtMappings().length > 0)
1120 // SequenceI[] dnas = acf.getdnaSeqs();
1121 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1122 // for (int m = 0; m < pmaps.length; m++)
1124 // AlcodMap alcmap = new AlcodMap();
1125 // alcmap.setDnasq(seqHash(dnas[m]));
1126 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
1128 // alc.addAlcodMap(alcmap);
1135 // /////////////////////////////////
1136 if (!storeDS && av.getCurrentTree() != null)
1138 // FIND ANY ASSOCIATED TREES
1139 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
1140 if (Desktop.desktop != null)
1142 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1144 for (int t = 0; t < frames.length; t++)
1146 if (frames[t] instanceof TreePanel)
1148 TreePanel tp = (TreePanel) frames[t];
1150 if (tp.getTreeCanvas().getViewport().getAlignment() == jal)
1152 JalviewModel.Tree tree = new JalviewModel.Tree();
1153 tree.setTitle(tp.getTitle());
1154 tree.setCurrentTree((av.getCurrentTree() == tp.getTree()));
1155 tree.setNewick(tp.getTree().print());
1156 tree.setThreshold(tp.getTreeCanvas().getThreshold());
1158 tree.setFitToWindow(tp.fitToWindow.getState());
1159 tree.setFontName(tp.getTreeFont().getName());
1160 tree.setFontSize(tp.getTreeFont().getSize());
1161 tree.setFontStyle(tp.getTreeFont().getStyle());
1162 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
1164 tree.setShowBootstrap(tp.bootstrapMenu.getState());
1165 tree.setShowDistances(tp.distanceMenu.getState());
1167 tree.setHeight(tp.getHeight());
1168 tree.setWidth(tp.getWidth());
1169 tree.setXpos(tp.getX());
1170 tree.setYpos(tp.getY());
1171 tree.setId(makeHashCode(tp, null));
1172 // jms.addTree(tree);
1173 object.getTree().add(tree);
1182 * store forward refs from an annotationRow to any groups
1184 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<>();
1187 for (SequenceI sq : jal.getSequences())
1189 // Store annotation on dataset sequences only
1190 AlignmentAnnotation[] aa = sq.getAnnotation();
1191 if (aa != null && aa.length > 0)
1193 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1200 if (jal.getAlignmentAnnotation() != null)
1202 // Store the annotation shown on the alignment.
1203 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1204 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1209 if (jal.getGroups() != null)
1211 JGroup[] groups = new JGroup[jal.getGroups().size()];
1213 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1215 JGroup jGroup = new JGroup();
1216 groups[++i] = jGroup;
1218 jGroup.setStart(sg.getStartRes());
1219 jGroup.setEnd(sg.getEndRes());
1220 jGroup.setName(sg.getName());
1221 if (groupRefs.containsKey(sg))
1223 // group has references so set its ID field
1224 jGroup.setId(groupRefs.get(sg));
1226 ColourSchemeI colourScheme = sg.getColourScheme();
1227 if (colourScheme != null)
1229 ResidueShaderI groupColourScheme = sg.getGroupColourScheme();
1230 if (groupColourScheme.conservationApplied())
1232 jGroup.setConsThreshold(groupColourScheme.getConservationInc());
1234 if (colourScheme instanceof jalview.schemes.UserColourScheme)
1237 setUserColourScheme(colourScheme, userColours,
1242 jGroup.setColour(colourScheme.getSchemeName());
1245 else if (colourScheme instanceof jalview.schemes.AnnotationColourGradient)
1247 jGroup.setColour("AnnotationColourGradient");
1248 jGroup.setAnnotationColours(constructAnnotationColours(
1249 (jalview.schemes.AnnotationColourGradient) colourScheme,
1250 userColours, object));
1252 else if (colourScheme instanceof jalview.schemes.UserColourScheme)
1255 setUserColourScheme(colourScheme, userColours, object));
1259 jGroup.setColour(colourScheme.getSchemeName());
1262 jGroup.setPidThreshold(groupColourScheme.getThreshold());
1265 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1266 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1267 jGroup.setDisplayText(sg.getDisplayText());
1268 jGroup.setColourText(sg.getColourText());
1269 jGroup.setTextCol1(sg.textColour.getRGB());
1270 jGroup.setTextCol2(sg.textColour2.getRGB());
1271 jGroup.setTextColThreshold(sg.thresholdTextColour);
1272 jGroup.setShowUnconserved(sg.getShowNonconserved());
1273 jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1274 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1275 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1276 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1277 for (SequenceI seq : sg.getSequences())
1279 // jGroup.addSeq(seqHash(seq));
1280 jGroup.getSeq().add(seqHash(seq));
1284 //jms.setJGroup(groups);
1286 for (JGroup grp : groups)
1288 object.getJGroup().add(grp);
1293 // /////////SAVE VIEWPORT
1294 Viewport view = new Viewport();
1295 view.setTitle(ap.alignFrame.getTitle());
1296 view.setSequenceSetId(
1297 makeHashCode(av.getSequenceSetId(), av.getSequenceSetId()));
1298 view.setId(av.getViewId());
1299 if (av.getCodingComplement() != null)
1301 view.setComplementId(av.getCodingComplement().getViewId());
1303 view.setViewName(av.getViewName());
1304 view.setGatheredViews(av.isGatherViewsHere());
1306 Rectangle size = ap.av.getExplodedGeometry();
1307 Rectangle position = size;
1310 size = ap.alignFrame.getBounds();
1311 if (av.getCodingComplement() != null)
1313 position = ((SplitFrame) ap.alignFrame.getSplitViewContainer())
1321 view.setXpos(position.x);
1322 view.setYpos(position.y);
1324 view.setWidth(size.width);
1325 view.setHeight(size.height);
1327 view.setStartRes(vpRanges.getStartRes());
1328 view.setStartSeq(vpRanges.getStartSeq());
1330 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1332 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1333 userColours, object));
1336 .getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1338 AnnotationColourScheme ac = constructAnnotationColours(
1339 (jalview.schemes.AnnotationColourGradient) av
1340 .getGlobalColourScheme(),
1341 userColours, object);
1343 view.setAnnotationColours(ac);
1344 view.setBgColour("AnnotationColourGradient");
1348 view.setBgColour(ColourSchemeProperty
1349 .getColourName(av.getGlobalColourScheme()));
1352 ResidueShaderI vcs = av.getResidueShading();
1353 ColourSchemeI cs = av.getGlobalColourScheme();
1357 if (vcs.conservationApplied())
1359 view.setConsThreshold(vcs.getConservationInc());
1360 if (cs instanceof jalview.schemes.UserColourScheme)
1362 view.setBgColour(setUserColourScheme(cs, userColours, object));
1365 view.setPidThreshold(vcs.getThreshold());
1368 view.setConservationSelected(av.getConservationSelected());
1369 view.setPidSelected(av.getAbovePIDThreshold());
1370 final Font font = av.getFont();
1371 view.setFontName(font.getName());
1372 view.setFontSize(font.getSize());
1373 view.setFontStyle(font.getStyle());
1374 view.setScaleProteinAsCdna(av.getViewStyle().isScaleProteinAsCdna());
1375 view.setRenderGaps(av.isRenderGaps());
1376 view.setShowAnnotation(av.isShowAnnotation());
1377 view.setShowBoxes(av.getShowBoxes());
1378 view.setShowColourText(av.getColourText());
1379 view.setShowFullId(av.getShowJVSuffix());
1380 view.setRightAlignIds(av.isRightAlignIds());
1381 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1382 view.setShowText(av.getShowText());
1383 view.setShowUnconserved(av.getShowUnconserved());
1384 view.setWrapAlignment(av.getWrapAlignment());
1385 view.setTextCol1(av.getTextColour().getRGB());
1386 view.setTextCol2(av.getTextColour2().getRGB());
1387 view.setTextColThreshold(av.getThresholdTextColour());
1388 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1389 view.setShowSequenceLogo(av.isShowSequenceLogo());
1390 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1391 view.setShowGroupConsensus(av.isShowGroupConsensus());
1392 view.setShowGroupConservation(av.isShowGroupConservation());
1393 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1394 view.setShowDbRefTooltip(av.isShowDBRefs());
1395 view.setFollowHighlight(av.isFollowHighlight());
1396 view.setFollowSelection(av.followSelection);
1397 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1398 if (av.getFeaturesDisplayed() != null)
1400 FeatureSettings fs = new FeatureSettings();
1402 FeatureRenderer fr = ap.getSeqPanel().seqCanvas
1403 .getFeatureRenderer();
1404 String[] renderOrder = fr.getRenderOrder().toArray(new String[0]);
1406 Vector<String> settingsAdded = new Vector<>();
1407 if (renderOrder != null)
1409 for (String featureType : renderOrder)
1411 FeatureSettings.Setting setting = new FeatureSettings.Setting();
1412 setting.setType(featureType);
1415 * save any filter for the feature type
1417 FeatureMatcherSetI filter = fr.getFeatureFilter(featureType);
1418 if (filter != null) {
1419 Iterator<FeatureMatcherI> filters = filter.getMatchers().iterator();
1420 FeatureMatcherI firstFilter = filters.next();
1421 setting.setMatcherSet(Jalview2XML.marshalFilter(
1422 firstFilter, filters, filter.isAnded()));
1426 * save colour scheme for the feature type
1428 FeatureColourI fcol = fr.getFeatureStyle(featureType);
1429 if (!fcol.isSimpleColour())
1431 setting.setColour(fcol.getMaxColour().getRGB());
1432 setting.setMincolour(fcol.getMinColour().getRGB());
1433 setting.setMin(fcol.getMin());
1434 setting.setMax(fcol.getMax());
1435 setting.setColourByLabel(fcol.isColourByLabel());
1436 if (fcol.isColourByAttribute())
1438 String[] attName = fcol.getAttributeName();
1439 setting.getAttributeName().add(attName[0]);
1440 if (attName.length > 1)
1442 setting.getAttributeName().add(attName[1]);
1445 setting.setAutoScale(fcol.isAutoScaled());
1446 setting.setThreshold(fcol.getThreshold());
1447 Color noColour = fcol.getNoColour();
1448 if (noColour == null)
1450 setting.setNoValueColour(NoValueColour.NONE);
1452 else if (noColour.equals(fcol.getMaxColour()))
1454 setting.setNoValueColour(NoValueColour.MAX);
1458 setting.setNoValueColour(NoValueColour.MIN);
1460 // -1 = No threshold, 0 = Below, 1 = Above
1461 setting.setThreshstate(fcol.isAboveThreshold() ? 1
1462 : (fcol.isBelowThreshold() ? 0 : -1));
1466 setting.setColour(fcol.getColour().getRGB());
1470 av.getFeaturesDisplayed().isVisible(featureType));
1472 .getOrder(featureType);
1475 setting.setOrder(rorder);
1477 /// fs.addSetting(setting);
1478 fs.getSetting().add(setting);
1479 settingsAdded.addElement(featureType);
1483 // is groups actually supposed to be a map here ?
1484 Iterator<String> en = fr.getFeatureGroups().iterator();
1485 Vector<String> groupsAdded = new Vector<>();
1486 while (en.hasNext())
1488 String grp = en.next();
1489 if (groupsAdded.contains(grp))
1493 Group g = new Group();
1495 g.setDisplay(((Boolean) fr.checkGroupVisibility(grp, false))
1498 fs.getGroup().add(g);
1499 groupsAdded.addElement(grp);
1501 // jms.setFeatureSettings(fs);
1502 object.setFeatureSettings(fs);
1505 if (av.hasHiddenColumns())
1507 jalview.datamodel.HiddenColumns hidden = av.getAlignment()
1508 .getHiddenColumns();
1511 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1515 Iterator<int[]> hiddenRegions = hidden.iterator();
1516 while (hiddenRegions.hasNext())
1518 int[] region = hiddenRegions.next();
1519 HiddenColumns hc = new HiddenColumns();
1520 hc.setStart(region[0]);
1521 hc.setEnd(region[1]);
1522 // view.addHiddenColumns(hc);
1523 view.getHiddenColumns().add(hc);
1527 if (calcIdSet.size() > 0)
1529 for (String calcId : calcIdSet)
1531 if (calcId.trim().length() > 0)
1533 CalcIdParam cidp = createCalcIdParam(calcId, av);
1534 // Some calcIds have no parameters.
1537 // view.addCalcIdParam(cidp);
1538 view.getCalcIdParam().add(cidp);
1544 // jms.addViewport(view);
1545 object.getViewport().add(view);
1547 // object.setJalviewModelSequence(jms);
1548 // object.getVamsasModel().addSequenceSet(vamsasSet);
1549 object.getVamsasModel().getSequenceSet().add(vamsasSet);
1551 if (jout != null && fileName != null)
1553 // We may not want to write the object to disk,
1554 // eg we can copy the alignViewport to a new view object
1555 // using save and then load
1558 System.out.println("Writing jar entry " + fileName);
1559 JarEntry entry = new JarEntry(fileName);
1560 jout.putNextEntry(entry);
1561 PrintWriter pout = new PrintWriter(
1562 new OutputStreamWriter(jout, UTF_8));
1563 JAXBContext jaxbContext = JAXBContext
1564 .newInstance(JalviewModel.class);
1565 Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
1567 // output pretty printed
1568 // jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
1569 jaxbMarshaller.marshal(
1570 new ObjectFactory().createJalviewModel(object), pout);
1572 // jaxbMarshaller.marshal(object, pout);
1573 // marshaller.marshal(object);
1576 } catch (Exception ex)
1578 // TODO: raise error in GUI if marshalling failed.
1579 System.err.println("Error writing Jalview project");
1580 ex.printStackTrace();
1587 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1588 * for each viewer, with
1590 * <li>viewer geometry (position, size, split pane divider location)</li>
1591 * <li>index of the selected structure in the viewer (currently shows gapped
1593 * <li>the id of the annotation holding RNA secondary structure</li>
1594 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1596 * Varna viewer state is also written out (in native Varna XML) to separate
1597 * project jar entries. A separate entry is written for each RNA structure
1598 * displayed, with the naming convention
1600 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
1608 * @param storeDataset
1610 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
1611 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
1612 boolean storeDataset)
1614 if (Desktop.desktop == null)
1618 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1619 for (int f = frames.length - 1; f > -1; f--)
1621 if (frames[f] instanceof AppVarna)
1623 AppVarna varna = (AppVarna) frames[f];
1625 * link the sequence to every viewer that is showing it and is linked to
1626 * its alignment panel
1628 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1630 String viewId = varna.getViewId();
1631 RnaViewer rna = new RnaViewer();
1632 rna.setViewId(viewId);
1633 rna.setTitle(varna.getTitle());
1634 rna.setXpos(varna.getX());
1635 rna.setYpos(varna.getY());
1636 rna.setWidth(varna.getWidth());
1637 rna.setHeight(varna.getHeight());
1638 rna.setDividerLocation(varna.getDividerLocation());
1639 rna.setSelectedRna(varna.getSelectedIndex());
1640 // jseq.addRnaViewer(rna);
1641 jseq.getRnaViewer().add(rna);
1644 * Store each Varna panel's state once in the project per sequence.
1645 * First time through only (storeDataset==false)
1647 // boolean storeSessions = false;
1648 // String sequenceViewId = viewId + seqsToIds.get(jds);
1649 // if (!storeDataset && !viewIds.contains(sequenceViewId))
1651 // viewIds.add(sequenceViewId);
1652 // storeSessions = true;
1654 for (RnaModel model : varna.getModels())
1656 if (model.seq == jds)
1659 * VARNA saves each view (sequence or alignment secondary
1660 * structure, gapped or trimmed) as a separate XML file
1662 String jarEntryName = rnaSessions.get(model);
1663 if (jarEntryName == null)
1666 String varnaStateFile = varna.getStateInfo(model.rna);
1667 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
1668 copyFileToJar(jout, varnaStateFile, jarEntryName);
1669 rnaSessions.put(model, jarEntryName);
1671 SecondaryStructure ss = new SecondaryStructure();
1672 String annotationId = varna.getAnnotation(jds).annotationId;
1673 ss.setAnnotationId(annotationId);
1674 ss.setViewerState(jarEntryName);
1675 ss.setGapped(model.gapped);
1676 ss.setTitle(model.title);
1677 // rna.addSecondaryStructure(ss);
1678 rna.getSecondaryStructure().add(ss);
1687 * Copy the contents of a file to a new entry added to the output jar
1691 * @param jarEntryName
1693 protected void copyFileToJar(JarOutputStream jout, String infilePath,
1694 String jarEntryName)
1696 DataInputStream dis = null;
1699 File file = new File(infilePath);
1700 if (file.exists() && jout != null)
1702 dis = new DataInputStream(new FileInputStream(file));
1703 byte[] data = new byte[(int) file.length()];
1704 dis.readFully(data);
1705 writeJarEntry(jout, jarEntryName, data);
1707 } catch (Exception ex)
1709 ex.printStackTrace();
1717 } catch (IOException e)
1726 * Write the data to a new entry of given name in the output jar file
1729 * @param jarEntryName
1731 * @throws IOException
1733 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
1734 byte[] data) throws IOException
1738 System.out.println("Writing jar entry " + jarEntryName);
1739 jout.putNextEntry(new JarEntry(jarEntryName));
1740 DataOutputStream dout = new DataOutputStream(jout);
1741 dout.write(data, 0, data.length);
1748 * Save the state of a structure viewer
1753 * the archive XML element under which to save the state
1756 * @param matchedFile
1760 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
1761 Pdbids pdb, PDBEntry entry, List<String> viewIds,
1762 String matchedFile, StructureViewerBase viewFrame)
1764 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
1767 * Look for any bindings for this viewer to the PDB file of interest
1768 * (including part matches excluding chain id)
1770 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
1772 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
1773 final String pdbId = pdbentry.getId();
1774 if (!pdbId.equals(entry.getId())
1775 && !(entry.getId().length() > 4 && entry.getId().toLowerCase()
1776 .startsWith(pdbId.toLowerCase())))
1779 * not interested in a binding to a different PDB entry here
1783 if (matchedFile == null)
1785 matchedFile = pdbentry.getFile();
1787 else if (!matchedFile.equals(pdbentry.getFile()))
1790 "Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
1791 + pdbentry.getFile());
1795 // can get at it if the ID
1796 // match is ambiguous (e.g.
1799 for (int smap = 0; smap < viewFrame.getBinding()
1800 .getSequence()[peid].length; smap++)
1802 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
1803 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
1805 StructureState state = new StructureState();
1806 state.setVisible(true);
1807 state.setXpos(viewFrame.getX());
1808 state.setYpos(viewFrame.getY());
1809 state.setWidth(viewFrame.getWidth());
1810 state.setHeight(viewFrame.getHeight());
1811 final String viewId = viewFrame.getViewId();
1812 state.setViewId(viewId);
1813 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
1814 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
1815 state.setColourByJmol(viewFrame.isColouredByViewer());
1816 state.setType(viewFrame.getViewerType().toString());
1817 // pdb.addStructureState(state);
1818 pdb.getStructureState().add(state);
1826 * Populates the AnnotationColourScheme xml for save. This captures the
1827 * settings of the options in the 'Colour by Annotation' dialog.
1830 * @param userColours
1834 private AnnotationColourScheme constructAnnotationColours(
1835 AnnotationColourGradient acg, List<UserColourScheme> userColours,
1838 AnnotationColourScheme ac = new AnnotationColourScheme();
1839 ac.setAboveThreshold(acg.getAboveThreshold());
1840 ac.setThreshold(acg.getAnnotationThreshold());
1841 // 2.10.2 save annotationId (unique) not annotation label
1842 ac.setAnnotation(acg.getAnnotation().annotationId);
1843 if (acg.getBaseColour() instanceof UserColourScheme)
1846 setUserColourScheme(acg.getBaseColour(), userColours, jm));
1851 ColourSchemeProperty.getColourName(acg.getBaseColour()));
1854 ac.setMaxColour(acg.getMaxColour().getRGB());
1855 ac.setMinColour(acg.getMinColour().getRGB());
1856 ac.setPerSequence(acg.isSeqAssociated());
1857 ac.setPredefinedColours(acg.isPredefinedColours());
1861 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
1862 IdentityHashMap<SequenceGroup, String> groupRefs,
1863 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
1864 SequenceSet vamsasSet)
1867 for (int i = 0; i < aa.length; i++)
1869 Annotation an = new Annotation();
1871 AlignmentAnnotation annotation = aa[i];
1872 if (annotation.annotationId != null)
1874 annotationIds.put(annotation.annotationId, annotation);
1877 an.setId(annotation.annotationId);
1879 an.setVisible(annotation.visible);
1881 an.setDescription(annotation.description);
1883 if (annotation.sequenceRef != null)
1885 // 2.9 JAL-1781 xref on sequence id rather than name
1886 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
1888 if (annotation.groupRef != null)
1890 String groupIdr = groupRefs.get(annotation.groupRef);
1891 if (groupIdr == null)
1893 // make a locally unique String
1894 groupRefs.put(annotation.groupRef,
1895 groupIdr = ("" + System.currentTimeMillis()
1896 + annotation.groupRef.getName()
1897 + groupRefs.size()));
1899 an.setGroupRef(groupIdr.toString());
1902 // store all visualization attributes for annotation
1903 an.setGraphHeight(annotation.graphHeight);
1904 an.setCentreColLabels(annotation.centreColLabels);
1905 an.setScaleColLabels(annotation.scaleColLabel);
1906 an.setShowAllColLabels(annotation.showAllColLabels);
1907 an.setBelowAlignment(annotation.belowAlignment);
1909 if (annotation.graph > 0)
1912 an.setGraphType(annotation.graph);
1913 an.setGraphGroup(annotation.graphGroup);
1914 if (annotation.getThreshold() != null)
1916 ThresholdLine line = new ThresholdLine();
1917 line.setLabel(annotation.getThreshold().label);
1918 line.setValue(annotation.getThreshold().value);
1919 line.setColour(annotation.getThreshold().colour.getRGB());
1920 an.setThresholdLine(line);
1928 an.setLabel(annotation.label);
1930 if (annotation == av.getAlignmentQualityAnnot()
1931 || annotation == av.getAlignmentConservationAnnotation()
1932 || annotation == av.getAlignmentConsensusAnnotation()
1933 || annotation.autoCalculated)
1935 // new way of indicating autocalculated annotation -
1936 an.setAutoCalculated(annotation.autoCalculated);
1938 if (annotation.hasScore())
1940 an.setScore(annotation.getScore());
1943 if (annotation.getCalcId() != null)
1945 calcIdSet.add(annotation.getCalcId());
1946 an.setCalcId(annotation.getCalcId());
1948 if (annotation.hasProperties())
1950 for (String pr : annotation.getProperties())
1952 jalview.xml.binding.jalview.Annotation.Property prop = new jalview.xml.binding.jalview.Annotation.Property();
1954 prop.setValue(annotation.getProperty(pr));
1955 // an.addProperty(prop);
1956 an.getProperty().add(prop);
1960 AnnotationElement ae;
1961 if (annotation.annotations != null)
1963 an.setScoreOnly(false);
1964 for (int a = 0; a < annotation.annotations.length; a++)
1966 if ((annotation == null) || (annotation.annotations[a] == null))
1971 ae = new AnnotationElement();
1972 if (annotation.annotations[a].description != null)
1974 ae.setDescription(annotation.annotations[a].description);
1976 if (annotation.annotations[a].displayCharacter != null)
1978 ae.setDisplayCharacter(
1979 annotation.annotations[a].displayCharacter);
1982 if (!Float.isNaN(annotation.annotations[a].value))
1984 ae.setValue(annotation.annotations[a].value);
1988 if (annotation.annotations[a].secondaryStructure > ' ')
1990 ae.setSecondaryStructure(
1991 annotation.annotations[a].secondaryStructure + "");
1994 if (annotation.annotations[a].colour != null
1995 && annotation.annotations[a].colour != java.awt.Color.black)
1997 ae.setColour(annotation.annotations[a].colour.getRGB());
2000 // an.addAnnotationElement(ae);
2001 an.getAnnotationElement().add(ae);
2002 if (annotation.autoCalculated)
2004 // only write one non-null entry into the annotation row -
2005 // sufficient to get the visualization attributes necessary to
2013 an.setScoreOnly(true);
2015 if (!storeDS || (storeDS && !annotation.autoCalculated))
2017 // skip autocalculated annotation - these are only provided for
2019 // vamsasSet.addAnnotation(an);
2020 vamsasSet.getAnnotation().add(an);
2026 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
2028 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
2029 if (settings != null)
2031 CalcIdParam vCalcIdParam = new CalcIdParam();
2032 vCalcIdParam.setCalcId(calcId);
2033 // vCalcIdParam.addServiceURL(settings.getServiceURI());
2034 vCalcIdParam.getServiceURL().add(settings.getServiceURI());
2035 // generic URI allowing a third party to resolve another instance of the
2036 // service used for this calculation
2037 for (String url : settings.getServiceURLs())
2039 // vCalcIdParam.addServiceURL(urls);
2040 vCalcIdParam.getServiceURL().add(url);
2042 vCalcIdParam.setVersion("1.0");
2043 if (settings.getPreset() != null)
2045 WsParamSetI setting = settings.getPreset();
2046 vCalcIdParam.setName(setting.getName());
2047 vCalcIdParam.setDescription(setting.getDescription());
2051 vCalcIdParam.setName("");
2052 vCalcIdParam.setDescription("Last used parameters");
2054 // need to be able to recover 1) settings 2) user-defined presets or
2055 // recreate settings from preset 3) predefined settings provided by
2056 // service - or settings that can be transferred (or discarded)
2057 vCalcIdParam.setParameters(
2058 settings.getWsParamFile().replace("\n", "|\\n|"));
2059 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
2060 // todo - decide if updateImmediately is needed for any projects.
2062 return vCalcIdParam;
2067 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
2070 if (calcIdParam.getVersion().equals("1.0"))
2072 final String[] calcIds = calcIdParam.getServiceURL().toArray(new String[0]);
2073 Jws2Instance service = Jws2Discoverer.getDiscoverer()
2074 .getPreferredServiceFor(calcIds);
2075 if (service != null)
2077 WsParamSetI parmSet = null;
2080 parmSet = service.getParamStore().parseServiceParameterFile(
2081 calcIdParam.getName(), calcIdParam.getDescription(),
2083 calcIdParam.getParameters().replace("|\\n|", "\n"));
2084 } catch (IOException x)
2086 warn("Couldn't parse parameter data for "
2087 + calcIdParam.getCalcId(), x);
2090 List<ArgumentI> argList = null;
2091 if (calcIdParam.getName().length() > 0)
2093 parmSet = service.getParamStore()
2094 .getPreset(calcIdParam.getName());
2095 if (parmSet != null)
2097 // TODO : check we have a good match with settings in AACon -
2098 // otherwise we'll need to create a new preset
2103 argList = parmSet.getArguments();
2106 AAConSettings settings = new AAConSettings(
2107 calcIdParam.isAutoUpdate(), service, parmSet, argList);
2108 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
2109 calcIdParam.isNeedsUpdate());
2114 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
2118 throw new Error(MessageManager.formatMessage(
2119 "error.unsupported_version_calcIdparam", new Object[]
2120 { calcIdParam.toString() }));
2124 * External mapping between jalview objects and objects yielding a valid and
2125 * unique object ID string. This is null for normal Jalview project IO, but
2126 * non-null when a jalview project is being read or written as part of a
2129 IdentityHashMap jv2vobj = null;
2132 * Construct a unique ID for jvobj using either existing bindings or if none
2133 * exist, the result of the hashcode call for the object.
2136 * jalview data object
2137 * @return unique ID for referring to jvobj
2139 private String makeHashCode(Object jvobj, String altCode)
2141 if (jv2vobj != null)
2143 Object id = jv2vobj.get(jvobj);
2146 return id.toString();
2148 // check string ID mappings
2149 if (jvids2vobj != null && jvobj instanceof String)
2151 id = jvids2vobj.get(jvobj);
2155 return id.toString();
2157 // give up and warn that something has gone wrong
2158 warn("Cannot find ID for object in external mapping : " + jvobj);
2164 * return local jalview object mapped to ID, if it exists
2168 * @return null or object bound to idcode
2170 private Object retrieveExistingObj(String idcode)
2172 if (idcode != null && vobj2jv != null)
2174 return vobj2jv.get(idcode);
2180 * binding from ID strings from external mapping table to jalview data model
2183 private Hashtable vobj2jv;
2185 private Sequence createVamsasSequence(String id, SequenceI jds)
2187 return createVamsasSequence(true, id, jds, null);
2190 private Sequence createVamsasSequence(boolean recurse, String id,
2191 SequenceI jds, SequenceI parentseq)
2193 Sequence vamsasSeq = new Sequence();
2194 vamsasSeq.setId(id);
2195 vamsasSeq.setName(jds.getName());
2196 vamsasSeq.setSequence(jds.getSequenceAsString());
2197 vamsasSeq.setDescription(jds.getDescription());
2198 jalview.datamodel.DBRefEntry[] dbrefs = null;
2199 if (jds.getDatasetSequence() != null)
2201 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
2205 // seqId==dsseqid so we can tell which sequences really are
2206 // dataset sequences only
2207 vamsasSeq.setDsseqid(id);
2208 dbrefs = jds.getDBRefs();
2209 if (parentseq == null)
2216 for (int d = 0; d < dbrefs.length; d++)
2218 DBRef dbref = new DBRef();
2219 dbref.setSource(dbrefs[d].getSource());
2220 dbref.setVersion(dbrefs[d].getVersion());
2221 dbref.setAccessionId(dbrefs[d].getAccessionId());
2222 if (dbrefs[d].hasMap())
2224 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
2226 dbref.setMapping(mp);
2228 // vamsasSeq.addDBRef(dbref);
2229 vamsasSeq.getDBRef().add(dbref);
2235 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
2236 SequenceI parentseq, SequenceI jds, boolean recurse)
2239 if (jmp.getMap() != null)
2243 jalview.util.MapList mlst = jmp.getMap();
2244 List<int[]> r = mlst.getFromRanges();
2245 for (int[] range : r)
2247 MapListFrom mfrom = new MapListFrom();
2248 mfrom.setStart(range[0]);
2249 mfrom.setEnd(range[1]);
2250 // mp.addMapListFrom(mfrom);
2251 mp.getMapListFrom().add(mfrom);
2253 r = mlst.getToRanges();
2254 for (int[] range : r)
2256 MapListTo mto = new MapListTo();
2257 mto.setStart(range[0]);
2258 mto.setEnd(range[1]);
2259 // mp.addMapListTo(mto);
2260 mp.getMapListTo().add(mto);
2262 mp.setMapFromUnit(BigInteger.valueOf(mlst.getFromRatio()));
2263 mp.setMapToUnit(BigInteger.valueOf(mlst.getToRatio()));
2264 if (jmp.getTo() != null)
2266 // MappingChoice mpc = new MappingChoice();
2268 // check/create ID for the sequence referenced by getTo()
2271 SequenceI ps = null;
2272 if (parentseq != jmp.getTo()
2273 && parentseq.getDatasetSequence() != jmp.getTo())
2275 // chaining dbref rather than a handshaking one
2276 jmpid = seqHash(ps = jmp.getTo());
2280 jmpid = seqHash(ps = parentseq);
2282 // mpc.setDseqFor(jmpid);
2283 mp.setDseqFor(jmpid);
2284 if (!seqRefIds.containsKey(jmpid))
2286 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2287 seqRefIds.put(jmpid, ps);
2291 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2294 // mp.setMappingChoice(mpc);
2300 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2301 List<UserColourScheme> userColours, JalviewModel jm)
2304 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2305 boolean newucs = false;
2306 if (!userColours.contains(ucs))
2308 userColours.add(ucs);
2311 id = "ucs" + userColours.indexOf(ucs);
2314 // actually create the scheme's entry in the XML model
2315 java.awt.Color[] colours = ucs.getColours();
2316 UserColours uc = new UserColours();
2317 // UserColourScheme jbucs = new UserColourScheme();
2318 JalviewUserColours jbucs = new JalviewUserColours();
2320 for (int i = 0; i < colours.length; i++)
2322 Colour col = new Colour();
2323 col.setName(ResidueProperties.aa[i]);
2324 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2325 // jbucs.addColour(col);
2326 jbucs.getColour().add(col);
2328 if (ucs.getLowerCaseColours() != null)
2330 colours = ucs.getLowerCaseColours();
2331 for (int i = 0; i < colours.length; i++)
2333 Colour col = new Colour();
2334 col.setName(ResidueProperties.aa[i].toLowerCase());
2335 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2336 // jbucs.addColour(col);
2337 jbucs.getColour().add(col);
2342 uc.setUserColourScheme(jbucs);
2343 // jm.addUserColours(uc);
2344 jm.getUserColours().add(uc);
2350 jalview.schemes.UserColourScheme getUserColourScheme(
2351 JalviewModel jm, String id)
2353 List<UserColours> uc = jm.getUserColours();
2354 UserColours colours = null;
2356 for (int i = 0; i < uc.length; i++)
2358 if (uc[i].getId().equals(id))
2365 for (UserColours c : uc)
2367 if (c.getId().equals(id))
2374 java.awt.Color[] newColours = new java.awt.Color[24];
2376 for (int i = 0; i < 24; i++)
2378 newColours[i] = new java.awt.Color(Integer.parseInt(
2379 // colours.getUserColourScheme().getColour(i).getRGB(), 16));
2380 colours.getUserColourScheme().getColour().get(i).getRGB(),
2384 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2387 if (colours.getUserColourScheme().getColour().size()/*Count()*/ > 24)
2389 newColours = new java.awt.Color[23];
2390 for (int i = 0; i < 23; i++)
2392 newColours[i] = new java.awt.Color(Integer.parseInt(
2393 colours.getUserColourScheme().getColour().get(i + 24)
2397 ucs.setLowerCaseColours(newColours);
2404 * contains last error message (if any) encountered by XML loader.
2406 String errorMessage = null;
2409 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2410 * exceptions are raised during project XML parsing
2412 public boolean attemptversion1parse = false;
2415 * Load a jalview project archive from a jar file
2418 * - HTTP URL or filename
2420 public AlignFrame loadJalviewAlign(final String file)
2423 jalview.gui.AlignFrame af = null;
2427 // create list to store references for any new Jmol viewers created
2428 newStructureViewers = new Vector<>();
2429 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2430 // Workaround is to make sure caller implements the JarInputStreamProvider
2432 // so we can re-open the jar input stream for each entry.
2434 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2435 af = loadJalviewAlign(jprovider);
2438 af.setMenusForViewport();
2440 } catch (MalformedURLException e)
2442 errorMessage = "Invalid URL format for '" + file + "'";
2448 SwingUtilities.invokeAndWait(new Runnable()
2453 setLoadingFinishedForNewStructureViewers();
2456 } catch (Exception x)
2458 System.err.println("Error loading alignment: " + x.getMessage());
2464 private jarInputStreamProvider createjarInputStreamProvider(
2465 final String file) throws MalformedURLException
2468 errorMessage = null;
2469 uniqueSetSuffix = null;
2471 viewportsAdded.clear();
2472 frefedSequence = null;
2474 if (file.startsWith("http://"))
2476 url = new URL(file);
2478 final URL _url = url;
2479 return new jarInputStreamProvider()
2483 public JarInputStream getJarInputStream() throws IOException
2487 return new JarInputStream(_url.openStream());
2491 return new JarInputStream(new FileInputStream(file));
2496 public String getFilename()
2504 * Recover jalview session from a jalview project archive. Caller may
2505 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2506 * themselves. Any null fields will be initialised with default values,
2507 * non-null fields are left alone.
2512 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2514 errorMessage = null;
2515 if (uniqueSetSuffix == null)
2517 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2519 if (seqRefIds == null)
2523 AlignFrame af = null, _af = null;
2524 IdentityHashMap<AlignmentI, AlignmentI> importedDatasets = new IdentityHashMap<>();
2525 Map<String, AlignFrame> gatherToThisFrame = new HashMap<>();
2526 final String file = jprovider.getFilename();
2529 JarInputStream jin = null;
2530 JarEntry jarentry = null;
2535 jin = jprovider.getJarInputStream();
2536 for (int i = 0; i < entryCount; i++)
2538 jarentry = jin.getNextJarEntry();
2541 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2543 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2544 // JalviewModel object = new JalviewModel();
2546 JAXBContext jc = JAXBContext
2547 .newInstance("jalview.xml.binding.jalview");
2548 XMLStreamReader streamReader = XMLInputFactory.newInstance()
2549 .createXMLStreamReader(jin);
2550 javax.xml.bind.Unmarshaller um = jc.createUnmarshaller();
2551 JAXBElement<JalviewModel> jbe = um
2552 .unmarshal(streamReader, JalviewModel.class);
2553 JalviewModel object = jbe.getValue();
2556 Unmarshaller unmar = new Unmarshaller(object);
2557 unmar.setValidation(false);
2558 object = (JalviewModel) unmar.unmarshal(in);
2560 if (true) // !skipViewport(object))
2562 _af = loadFromObject(object, file, true, jprovider);
2563 if (_af != null && object.getViewport().size() > 0)
2564 // getJalviewModelSequence().getViewportCount() > 0)
2568 // store a reference to the first view
2571 if (_af.getViewport().isGatherViewsHere())
2573 // if this is a gathered view, keep its reference since
2574 // after gathering views, only this frame will remain
2576 gatherToThisFrame.put(_af.getViewport().getSequenceSetId(),
2579 // Save dataset to register mappings once all resolved
2580 importedDatasets.put(
2581 af.getViewport().getAlignment().getDataset(),
2582 af.getViewport().getAlignment().getDataset());
2587 else if (jarentry != null)
2589 // Some other file here.
2592 } while (jarentry != null);
2593 resolveFrefedSequences();
2594 } catch (IOException ex)
2596 ex.printStackTrace();
2597 errorMessage = "Couldn't locate Jalview XML file : " + file;
2599 "Exception whilst loading jalview XML file : " + ex + "\n");
2600 } catch (Exception ex)
2602 System.err.println("Parsing as Jalview Version 2 file failed.");
2603 ex.printStackTrace(System.err);
2604 if (attemptversion1parse)
2606 // Is Version 1 Jar file?
2609 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
2610 } catch (Exception ex2)
2612 System.err.println("Exception whilst loading as jalviewXMLV1:");
2613 ex2.printStackTrace();
2617 if (Desktop.instance != null)
2619 Desktop.instance.stopLoading();
2623 System.out.println("Successfully loaded archive file");
2626 ex.printStackTrace();
2629 "Exception whilst loading jalview XML file : " + ex + "\n");
2630 } catch (OutOfMemoryError e)
2632 // Don't use the OOM Window here
2633 errorMessage = "Out of memory loading jalview XML file";
2634 System.err.println("Out of memory whilst loading jalview XML file");
2635 e.printStackTrace();
2639 * Regather multiple views (with the same sequence set id) to the frame (if
2640 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2641 * views instead of separate frames. Note this doesn't restore a state where
2642 * some expanded views in turn have tabbed views - the last "first tab" read
2643 * in will play the role of gatherer for all.
2645 for (AlignFrame fr : gatherToThisFrame.values())
2647 Desktop.instance.gatherViews(fr);
2650 restoreSplitFrames();
2651 for (AlignmentI ds : importedDatasets.keySet())
2653 if (ds.getCodonFrames() != null)
2655 StructureSelectionManager
2656 .getStructureSelectionManager(Desktop.instance)
2657 .registerMappings(ds.getCodonFrames());
2660 if (errorMessage != null)
2665 if (Desktop.instance != null)
2667 Desktop.instance.stopLoading();
2674 * Try to reconstruct and display SplitFrame windows, where each contains
2675 * complementary dna and protein alignments. Done by pairing up AlignFrame
2676 * objects (created earlier) which have complementary viewport ids associated.
2678 protected void restoreSplitFrames()
2680 List<SplitFrame> gatherTo = new ArrayList<>();
2681 List<AlignFrame> addedToSplitFrames = new ArrayList<>();
2682 Map<String, AlignFrame> dna = new HashMap<>();
2685 * Identify the DNA alignments
2687 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2690 AlignFrame af = candidate.getValue();
2691 if (af.getViewport().getAlignment().isNucleotide())
2693 dna.put(candidate.getKey().getId(), af);
2698 * Try to match up the protein complements
2700 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2703 AlignFrame af = candidate.getValue();
2704 if (!af.getViewport().getAlignment().isNucleotide())
2706 String complementId = candidate.getKey().getComplementId();
2707 // only non-null complements should be in the Map
2708 if (complementId != null && dna.containsKey(complementId))
2710 final AlignFrame dnaFrame = dna.get(complementId);
2711 SplitFrame sf = createSplitFrame(dnaFrame, af);
2712 addedToSplitFrames.add(dnaFrame);
2713 addedToSplitFrames.add(af);
2714 dnaFrame.setMenusForViewport();
2715 af.setMenusForViewport();
2716 if (af.getViewport().isGatherViewsHere())
2725 * Open any that we failed to pair up (which shouldn't happen!) as
2726 * standalone AlignFrame's.
2728 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2731 AlignFrame af = candidate.getValue();
2732 if (!addedToSplitFrames.contains(af))
2734 Viewport view = candidate.getKey();
2735 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
2737 af.setMenusForViewport();
2738 System.err.println("Failed to restore view " + view.getTitle()
2739 + " to split frame");
2744 * Gather back into tabbed views as flagged.
2746 for (SplitFrame sf : gatherTo)
2748 Desktop.instance.gatherViews(sf);
2751 splitFrameCandidates.clear();
2755 * Construct and display one SplitFrame holding DNA and protein alignments.
2758 * @param proteinFrame
2761 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
2762 AlignFrame proteinFrame)
2764 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
2765 String title = MessageManager.getString("label.linked_view_title");
2766 int width = (int) dnaFrame.getBounds().getWidth();
2767 int height = (int) (dnaFrame.getBounds().getHeight()
2768 + proteinFrame.getBounds().getHeight() + 50);
2771 * SplitFrame location is saved to both enclosed frames
2773 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
2774 Desktop.addInternalFrame(splitFrame, title, width, height);
2777 * And compute cDNA consensus (couldn't do earlier with consensus as
2778 * mappings were not yet present)
2780 proteinFrame.getViewport().alignmentChanged(proteinFrame.alignPanel);
2786 * check errorMessage for a valid error message and raise an error box in the
2787 * GUI or write the current errorMessage to stderr and then clear the error
2790 protected void reportErrors()
2792 reportErrors(false);
2795 protected void reportErrors(final boolean saving)
2797 if (errorMessage != null)
2799 final String finalErrorMessage = errorMessage;
2802 javax.swing.SwingUtilities.invokeLater(new Runnable()
2807 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2809 "Error " + (saving ? "saving" : "loading")
2811 JvOptionPane.WARNING_MESSAGE);
2817 System.err.println("Problem loading Jalview file: " + errorMessage);
2820 errorMessage = null;
2823 Map<String, String> alreadyLoadedPDB = new HashMap<>();
2826 * when set, local views will be updated from view stored in JalviewXML
2827 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2828 * sync if this is set to true.
2830 private final boolean updateLocalViews = false;
2833 * Returns the path to a temporary file holding the PDB file for the given PDB
2834 * id. The first time of asking, searches for a file of that name in the
2835 * Jalview project jar, and copies it to a new temporary file. Any repeat
2836 * requests just return the path to the file previously created.
2842 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId,
2845 if (alreadyLoadedPDB.containsKey(pdbId))
2847 return alreadyLoadedPDB.get(pdbId).toString();
2850 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb",
2852 if (tempFile != null)
2854 alreadyLoadedPDB.put(pdbId, tempFile);
2860 * Copies the jar entry of given name to a new temporary file and returns the
2861 * path to the file, or null if the entry is not found.
2864 * @param jarEntryName
2866 * a prefix for the temporary file name, must be at least three
2869 * null or original file - so new file can be given the same suffix
2873 protected String copyJarEntry(jarInputStreamProvider jprovider,
2874 String jarEntryName, String prefix, String origFile)
2876 BufferedReader in = null;
2877 PrintWriter out = null;
2878 String suffix = ".tmp";
2879 if (origFile == null)
2881 origFile = jarEntryName;
2883 int sfpos = origFile.lastIndexOf(".");
2884 if (sfpos > -1 && sfpos < (origFile.length() - 3))
2886 suffix = "." + origFile.substring(sfpos + 1);
2890 JarInputStream jin = jprovider.getJarInputStream();
2892 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2893 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2894 * FileInputStream(jprovider)); }
2897 JarEntry entry = null;
2900 entry = jin.getNextJarEntry();
2901 } while (entry != null && !entry.getName().equals(jarEntryName));
2904 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
2905 File outFile = File.createTempFile(prefix, suffix);
2906 outFile.deleteOnExit();
2907 out = new PrintWriter(new FileOutputStream(outFile));
2910 while ((data = in.readLine()) != null)
2915 String t = outFile.getAbsolutePath();
2920 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
2922 } catch (Exception ex)
2924 ex.printStackTrace();
2932 } catch (IOException e)
2946 private class JvAnnotRow
2948 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2955 * persisted version of annotation row from which to take vis properties
2957 public jalview.datamodel.AlignmentAnnotation template;
2960 * original position of the annotation row in the alignment
2966 * Load alignment frame from jalview XML DOM object
2968 * @param jalviewModel
2971 * filename source string
2972 * @param loadTreesAndStructures
2973 * when false only create Viewport
2975 * data source provider
2976 * @return alignment frame created from view stored in DOM
2978 AlignFrame loadFromObject(JalviewModel jalviewModel, String file,
2979 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
2981 SequenceSet vamsasSet = jalviewModel.getVamsasModel().getSequenceSet().get(0);
2982 List<Sequence> vamsasSeqs = vamsasSet.getSequence();
2984 // JalviewModelSequence jms = object.getJalviewModelSequence();
2986 // Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
2988 Viewport view = (jalviewModel.getViewport().size() > 0)
2989 ? jalviewModel.getViewport().get(0)
2992 // ////////////////////////////////
2995 List<SequenceI> hiddenSeqs = null;
2997 List<SequenceI> tmpseqs = new ArrayList<>();
2999 boolean multipleView = false;
3000 SequenceI referenceseqForView = null;
3001 // JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
3002 List<JSeq> jseqs = jalviewModel.getJSeq();
3003 int vi = 0; // counter in vamsasSeq array
3004 for (int i = 0; i < jseqs.size(); i++)
3006 JSeq jseq = jseqs.get(i);
3007 String seqId = jseq.getId();
3009 SequenceI tmpSeq = seqRefIds.get(seqId);
3012 if (!incompleteSeqs.containsKey(seqId))
3014 // may not need this check, but keep it for at least 2.9,1 release
3015 if (tmpSeq.getStart() != jseq.getStart()
3016 || tmpSeq.getEnd() != jseq.getEnd())
3019 "Warning JAL-2154 regression: updating start/end for sequence "
3020 + tmpSeq.toString() + " to " + jseq);
3025 incompleteSeqs.remove(seqId);
3027 if (vamsasSeqs.size() > vi
3028 && vamsasSeqs.get(vi).getId().equals(seqId))
3030 // most likely we are reading a dataset XML document so
3031 // update from vamsasSeq section of XML for this sequence
3032 tmpSeq.setName(vamsasSeqs.get(vi).getName());
3033 tmpSeq.setDescription(vamsasSeqs.get(vi).getDescription());
3034 tmpSeq.setSequence(vamsasSeqs.get(vi).getSequence());
3039 // reading multiple views, so vamsasSeq set is a subset of JSeq
3040 multipleView = true;
3042 tmpSeq.setStart(jseq.getStart());
3043 tmpSeq.setEnd(jseq.getEnd());
3044 tmpseqs.add(tmpSeq);
3048 Sequence vamsasSeq = vamsasSeqs.get(vi);
3049 tmpSeq = new jalview.datamodel.Sequence(vamsasSeq.getName(),
3050 vamsasSeq.getSequence());
3051 tmpSeq.setDescription(vamsasSeq.getDescription());
3052 tmpSeq.setStart(jseq.getStart());
3053 tmpSeq.setEnd(jseq.getEnd());
3054 tmpSeq.setVamsasId(uniqueSetSuffix + seqId);
3055 seqRefIds.put(vamsasSeq.getId(), tmpSeq);
3056 tmpseqs.add(tmpSeq);
3060 if (jseq.isViewreference() != null
3061 && jseq.isViewreference().booleanValue())
3063 referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
3066 if (jseq.isHidden() != null && jseq.isHidden().booleanValue())
3068 if (hiddenSeqs == null)
3070 hiddenSeqs = new ArrayList<>();
3073 hiddenSeqs.add(tmpSeq);
3078 // Create the alignment object from the sequence set
3079 // ///////////////////////////////
3080 SequenceI[] orderedSeqs = tmpseqs
3081 .toArray(new SequenceI[tmpseqs.size()]);
3083 AlignmentI al = null;
3084 // so we must create or recover the dataset alignment before going further
3085 // ///////////////////////////////
3086 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
3088 // older jalview projects do not have a dataset - so creat alignment and
3090 al = new Alignment(orderedSeqs);
3091 al.setDataset(null);
3095 boolean isdsal = jalviewModel.getViewport().isEmpty();
3098 // we are importing a dataset record, so
3099 // recover reference to an alignment already materialsed as dataset
3100 al = getDatasetFor(vamsasSet.getDatasetId());
3104 // materialse the alignment
3105 al = new Alignment(orderedSeqs);
3109 addDatasetRef(vamsasSet.getDatasetId(), al);
3112 // finally, verify all data in vamsasSet is actually present in al
3113 // passing on flag indicating if it is actually a stored dataset
3114 recoverDatasetFor(vamsasSet, al, isdsal);
3117 if (referenceseqForView != null)
3119 al.setSeqrep(referenceseqForView);
3121 // / Add the alignment properties
3122 for (int i = 0; i < vamsasSet.getSequenceSetProperties().size(); i++)
3124 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties()
3126 al.setProperty(ssp.getKey(), ssp.getValue());
3129 // ///////////////////////////////
3131 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
3134 // load sequence features, database references and any associated PDB
3135 // structures for the alignment
3137 // prior to 2.10, this part would only be executed the first time a
3138 // sequence was encountered, but not afterwards.
3139 // now, for 2.10 projects, this is also done if the xml doc includes
3140 // dataset sequences not actually present in any particular view.
3142 for (int i = 0; i < vamsasSeqs.size(); i++)
3144 JSeq jseq = jseqs.get(i);
3145 if (jseq.getFeatures().size() > 0)
3147 List<Feature> features = jseq.getFeatures();
3148 for (int f = 0; f < features.size(); f++)
3150 Feature feat = features.get(f);
3151 SequenceFeature sf = new SequenceFeature(feat.getType(),
3152 feat.getDescription(), feat.getBegin(), feat.getEnd(),
3153 feat.getScore(), feat.getFeatureGroup());
3154 sf.setStatus(feat.getStatus());
3157 * load any feature attributes - include map-valued attributes
3159 Map<String, Map<String, String>> mapAttributes = new HashMap<>();
3160 for (int od = 0; od < feat.getOtherData().size(); od++)
3162 OtherData keyValue = feat.getOtherData().get(od);
3163 String attributeName = keyValue.getKey();
3164 String attributeValue = keyValue.getValue();
3165 if (attributeName.startsWith("LINK"))
3167 sf.addLink(attributeValue);
3171 String subAttribute = keyValue.getKey2();
3172 if (subAttribute == null)
3174 // simple string-valued attribute
3175 sf.setValue(attributeName, attributeValue);
3179 // attribute 'key' has sub-attribute 'key2'
3180 if (!mapAttributes.containsKey(attributeName))
3182 mapAttributes.put(attributeName, new HashMap<>());
3184 mapAttributes.get(attributeName).put(subAttribute,
3189 for (Entry<String, Map<String, String>> mapAttribute : mapAttributes
3192 sf.setValue(mapAttribute.getKey(), mapAttribute.getValue());
3195 // adds feature to datasequence's feature set (since Jalview 2.10)
3196 al.getSequenceAt(i).addSequenceFeature(sf);
3199 if (vamsasSeqs.get(i).getDBRef().size() > 0)
3201 // adds dbrefs to datasequence's set (since Jalview 2.10)
3203 al.getSequenceAt(i).getDatasetSequence() == null
3204 ? al.getSequenceAt(i)
3205 : al.getSequenceAt(i).getDatasetSequence(),
3208 if (jseq.getPdbids().size() > 0)
3210 List<Pdbids> ids = jseq.getPdbids();
3211 for (int p = 0; p < ids.size(); p++)
3213 Pdbids pdbid = ids.get(p);
3214 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
3215 entry.setId(pdbid.getId());
3216 if (pdbid.getType() != null)
3218 if (PDBEntry.Type.getType(pdbid.getType()) != null)
3220 entry.setType(PDBEntry.Type.getType(pdbid.getType()));
3224 entry.setType(PDBEntry.Type.FILE);
3227 // jprovider is null when executing 'New View'
3228 if (pdbid.getFile() != null && jprovider != null)
3230 if (!pdbloaded.containsKey(pdbid.getFile()))
3232 entry.setFile(loadPDBFile(jprovider, pdbid.getId(),
3237 entry.setFile(pdbloaded.get(pdbid.getId()).toString());
3241 if (pdbid.getPdbentryItem() != null)
3243 for (PdbentryItem item : pdbid.getPdbentryItem())
3245 for (Property pr : item.getProperty())
3247 entry.setProperty(pr.getName(), pr.getValue());
3252 for (Property prop : pdbid.getProperty())
3254 entry.setProperty(prop.getName(), prop.getValue());
3256 StructureSelectionManager
3257 .getStructureSelectionManager(Desktop.instance)
3258 .registerPDBEntry(entry);
3259 // adds PDBEntry to datasequence's set (since Jalview 2.10)
3260 if (al.getSequenceAt(i).getDatasetSequence() != null)
3262 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
3266 al.getSequenceAt(i).addPDBId(entry);
3271 } // end !multipleview
3273 // ///////////////////////////////
3274 // LOAD SEQUENCE MAPPINGS
3276 if (vamsasSet.getAlcodonFrame().size() > 0)
3278 // TODO Potentially this should only be done once for all views of an
3280 List<AlcodonFrame> alc = vamsasSet.getAlcodonFrame();
3281 for (int i = 0; i < alc.size(); i++)
3283 AlignedCodonFrame cf = new AlignedCodonFrame();
3284 if (alc.get(i).getAlcodMap().size() > 0)
3286 List<AlcodMap> maps = alc.get(i).getAlcodMap();
3287 for (int m = 0; m < maps.size(); m++)
3289 AlcodMap map = maps.get(m);
3290 SequenceI dnaseq = seqRefIds.get(map.getDnasq());
3292 jalview.datamodel.Mapping mapping = null;
3293 // attach to dna sequence reference.
3294 if (map.getMapping() != null)
3296 mapping = addMapping(map.getMapping());
3297 if (dnaseq != null && mapping.getTo() != null)
3299 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
3305 newAlcodMapRef(map.getDnasq(), cf, mapping));
3309 al.addCodonFrame(cf);
3314 // ////////////////////////////////
3316 List<JvAnnotRow> autoAlan = new ArrayList<>();
3319 * store any annotations which forward reference a group's ID
3321 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<>();
3323 if (vamsasSet.getAnnotation().size()/*Count()*/ > 0)
3325 List<Annotation> an = vamsasSet.getAnnotation();
3327 for (int i = 0; i < an.size(); i++)
3329 Annotation annotation = an.get(i);
3332 * test if annotation is automatically calculated for this view only
3334 boolean autoForView = false;
3335 if (annotation.getLabel().equals("Quality")
3336 || annotation.getLabel().equals("Conservation")
3337 || annotation.getLabel().equals("Consensus"))
3339 // Kludge for pre 2.5 projects which lacked the autocalculated flag
3341 // JAXB has no has() test; schema defaults value to false
3342 // if (!annotation.hasAutoCalculated())
3344 // annotation.setAutoCalculated(true);
3347 if (autoForView || // (annotation.hasAutoCalculated() &&
3348 annotation.isAutoCalculated())
3350 // remove ID - we don't recover annotation from other views for
3351 // view-specific annotation
3352 annotation.setId(null);
3355 // set visiblity for other annotation in this view
3356 String annotationId = annotation.getId();
3357 if (annotationId != null && annotationIds.containsKey(annotationId))
3359 AlignmentAnnotation jda = annotationIds.get(annotationId);
3360 // in principle Visible should always be true for annotation displayed
3361 // in multiple views
3362 if (annotation.isVisible() != null) // annotation.hasVisible())
3364 jda.visible = annotation.isVisible();
3367 al.addAnnotation(jda);
3371 // Construct new annotation from model.
3372 List<AnnotationElement> ae = annotation.getAnnotationElement();
3373 jalview.datamodel.Annotation[] anot = null;
3374 java.awt.Color firstColour = null;
3376 if (!annotation.isScoreOnly())
3378 anot = new jalview.datamodel.Annotation[al.getWidth()];
3379 for (int aa = 0; aa < ae.size() && aa < anot.length; aa++)
3381 AnnotationElement annElement = ae.get(aa);
3382 anpos = annElement.getPosition();
3384 if (anpos >= anot.length)
3389 float value = annElement.getValue() == null ? 0f
3390 : annElement.getValue().floatValue();
3391 anot[anpos] = new jalview.datamodel.Annotation(
3392 annElement.getDisplayCharacter(),
3393 annElement.getDescription(),
3394 (annElement.getSecondaryStructure() == null
3395 || annElement.getSecondaryStructure()
3399 .getSecondaryStructure()
3402 // JBPNote: Consider verifying dataflow for IO of secondary
3403 // structure annotation read from Stockholm files
3404 // this was added to try to ensure that
3405 // if (anot[ annElement.getPosition()].secondaryStructure>' ')
3407 // anot[ annElement.getPosition()].displayCharacter = "";
3409 final int colourValue = annElement.getColour() == null ? 0
3410 : annElement.getColour().intValue();
3411 anot[anpos].colour = new java.awt.Color(colourValue);
3412 if (firstColour == null)
3414 firstColour = anot[anpos].colour;
3418 jalview.datamodel.AlignmentAnnotation jaa = null;
3420 if (annotation.isGraph())
3422 float llim = 0, hlim = 0;
3423 // if (autoForView || an[i].isAutoCalculated()) {
3426 jaa = new jalview.datamodel.AlignmentAnnotation(
3427 annotation.getLabel(), annotation.getDescription(), anot,
3428 llim, hlim, annotation.getGraphType());
3430 jaa.graphGroup = annotation.getGraphGroup();
3431 jaa._linecolour = firstColour;
3432 if (annotation.getThresholdLine() != null)
3434 jaa.setThreshold(new jalview.datamodel.GraphLine(
3435 annotation.getThresholdLine().getValue(),
3436 annotation.getThresholdLine().getLabel(),
3438 annotation.getThresholdLine().getColour())));
3441 if (autoForView || annotation.isAutoCalculated())
3443 // Hardwire the symbol display line to ensure that labels for
3444 // histograms are displayed
3450 jaa = new jalview.datamodel.AlignmentAnnotation(
3451 annotation.getLabel(), annotation.getDescription(), anot);
3452 jaa._linecolour = firstColour;
3454 // register new annotation
3455 if (annotation.getId() != null)
3457 annotationIds.put(annotation.getId(), jaa);
3458 jaa.annotationId = annotation.getId();
3460 // recover sequence association
3461 String sequenceRef = annotation.getSequenceRef();
3462 if (sequenceRef != null)
3464 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3465 SequenceI sequence = seqRefIds.get(sequenceRef);
3466 if (sequence == null)
3468 // in pre-2.9 projects sequence ref is to sequence name
3469 sequence = al.findName(sequenceRef);
3471 if (sequence != null)
3473 jaa.createSequenceMapping(sequence, 1, true);
3474 sequence.addAlignmentAnnotation(jaa);
3477 // and make a note of any group association
3478 if (annotation.getGroupRef() != null
3479 && annotation.getGroupRef().length() > 0)
3481 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3482 .get(annotation.getGroupRef());
3485 aal = new ArrayList<>();
3486 groupAnnotRefs.put(annotation.getGroupRef(), aal);
3491 if (annotation.getScore() != null)
3493 jaa.setScore(annotation.getScore());
3495 if (annotation.isVisible() != null)
3497 jaa.visible = annotation.isVisible().booleanValue();
3500 if (annotation.isCentreColLabels() != null)
3502 jaa.centreColLabels = annotation.isCentreColLabels()
3506 if (annotation.isScaleColLabels() != null)
3508 jaa.scaleColLabel = annotation.isScaleColLabels().booleanValue();
3510 if (/*annotation.hasAutoCalculated() && */annotation
3511 .isAutoCalculated())
3513 // newer files have an 'autoCalculated' flag and store calculation
3514 // state in viewport properties
3515 jaa.autoCalculated = true; // means annotation will be marked for
3516 // update at end of load.
3518 if (annotation.getGraphHeight() != null)
3520 jaa.graphHeight = annotation.getGraphHeight().intValue();
3522 // if (annotation.hasBelowAlignment())
3524 // schema specifies default for optional attribute
3525 jaa.belowAlignment = annotation.isBelowAlignment();
3527 jaa.setCalcId(annotation.getCalcId());
3528 if (annotation.getProperty().size() > 0)
3530 for (Annotation.Property prop : annotation
3533 jaa.setProperty(prop.getName(), prop.getValue());
3536 if (jaa.autoCalculated)
3538 autoAlan.add(new JvAnnotRow(i, jaa));
3541 // if (!autoForView)
3543 // add autocalculated group annotation and any user created annotation
3545 al.addAnnotation(jaa);
3549 // ///////////////////////
3551 // Create alignment markup and styles for this view
3552 if (jalviewModel.getJGroup().size() > 0)
3554 List<JGroup> groups = jalviewModel.getJGroup();
3555 boolean addAnnotSchemeGroup = false;
3556 for (int i = 0; i < groups.size(); i++)
3558 JGroup jGroup = groups.get(i);
3559 ColourSchemeI cs = null;
3560 if (jGroup.getColour() != null)
3562 if (jGroup.getColour().startsWith("ucs"))
3564 cs = getUserColourScheme(jalviewModel, jGroup.getColour());
3566 else if (jGroup.getColour().equals("AnnotationColourGradient")
3567 && jGroup.getAnnotationColours() != null)
3569 addAnnotSchemeGroup = true;
3573 cs = ColourSchemeProperty.getColourScheme(al,
3574 jGroup.getColour());
3577 int pidThreshold = jGroup.getPidThreshold() == null ? 0
3578 : jGroup.getPidThreshold().intValue();
3580 Vector<SequenceI> seqs = new Vector<>();
3582 for (int s = 0; s < jGroup.getSeq().size(); s++)
3584 String seqId = jGroup.getSeq().get(s);
3585 SequenceI ts = seqRefIds.get(seqId);
3589 seqs.addElement(ts);
3593 if (seqs.size() < 1)
3598 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3599 jGroup.isDisplayBoxes(), jGroup.isDisplayText(),
3600 jGroup.isColourText(), jGroup.getStart(), jGroup.getEnd());
3601 sg.getGroupColourScheme().setThreshold(pidThreshold, true);
3602 sg.getGroupColourScheme()
3603 .setConservationInc(jGroup.getConsThreshold() == null ? 0
3604 : jGroup.getConsThreshold().intValue());
3605 sg.setOutlineColour(
3606 new java.awt.Color(jGroup.getOutlineColour() == null ? 0
3607 : jGroup.getOutlineColour().intValue()));
3609 sg.textColour = new java.awt.Color(jGroup.getTextCol1());
3610 sg.textColour2 = new java.awt.Color(jGroup.getTextCol2());
3611 sg.setShowNonconserved(
3612 jGroup.isShowUnconserved() != null
3613 ? jGroup.isShowUnconserved().booleanValue()
3615 sg.thresholdTextColour = jGroup.getTextColThreshold();
3616 // attributes with a default in the schema are never null
3617 // if (jGroup.hasShowConsensusHistogram())
3619 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3621 // if (jGroup.hasShowSequenceLogo())
3623 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3625 // if (jGroup.hasNormaliseSequenceLogo())
3627 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3629 // if (jGroup.hasIgnoreGapsinConsensus())
3631 sg.setIgnoreGapsConsensus(jGroup.isIgnoreGapsinConsensus());
3633 if (jGroup.getConsThreshold() != null
3634 && jGroup.getConsThreshold().intValue() != 0)
3636 Conservation c = new Conservation("All", sg.getSequences(null), 0,
3639 c.verdict(false, 25);
3640 sg.cs.setConservation(c);
3643 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3645 // re-instate unique group/annotation row reference
3646 List<AlignmentAnnotation> jaal = groupAnnotRefs
3647 .get(jGroup.getId());
3650 for (AlignmentAnnotation jaa : jaal)
3653 if (jaa.autoCalculated)
3655 // match up and try to set group autocalc alignment row for this
3657 if (jaa.label.startsWith("Consensus for "))
3659 sg.setConsensus(jaa);
3661 // match up and try to set group autocalc alignment row for this
3663 if (jaa.label.startsWith("Conservation for "))
3665 sg.setConservationRow(jaa);
3672 if (addAnnotSchemeGroup)
3674 // reconstruct the annotation colourscheme
3675 sg.setColourScheme(constructAnnotationColour(
3676 jGroup.getAnnotationColours(), null, al, jalviewModel, false));
3682 // only dataset in this model, so just return.
3685 // ///////////////////////////////
3688 // If we just load in the same jar file again, the sequenceSetId
3689 // will be the same, and we end up with multiple references
3690 // to the same sequenceSet. We must modify this id on load
3691 // so that each load of the file gives a unique id
3692 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3693 String viewId = (view.getId() == null ? null
3694 : view.getId() + uniqueSetSuffix);
3695 AlignFrame af = null;
3696 AlignViewport av = null;
3697 // now check to see if we really need to create a new viewport.
3698 if (multipleView && viewportsAdded.size() == 0)
3700 // We recovered an alignment for which a viewport already exists.
3701 // TODO: fix up any settings necessary for overlaying stored state onto
3702 // state recovered from another document. (may not be necessary).
3703 // we may need a binding from a viewport in memory to one recovered from
3705 // and then recover its containing af to allow the settings to be applied.
3706 // TODO: fix for vamsas demo
3708 "About to recover a viewport for existing alignment: Sequence set ID is "
3710 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3711 if (seqsetobj != null)
3713 if (seqsetobj instanceof String)
3715 uniqueSeqSetId = (String) seqsetobj;
3717 "Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
3723 "Warning : Collision between sequence set ID string and existing jalview object mapping.");
3729 * indicate that annotation colours are applied across all groups (pre
3730 * Jalview 2.8.1 behaviour)
3732 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan("2.8.1",
3733 jalviewModel.getVersion());
3735 AlignmentPanel ap = null;
3736 boolean isnewview = true;
3739 // Check to see if this alignment already has a view id == viewId
3740 jalview.gui.AlignmentPanel views[] = Desktop
3741 .getAlignmentPanels(uniqueSeqSetId);
3742 if (views != null && views.length > 0)
3744 for (int v = 0; v < views.length; v++)
3746 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
3748 // recover the existing alignpanel, alignframe, viewport
3749 af = views[v].alignFrame;
3752 // TODO: could even skip resetting view settings if we don't want to
3753 // change the local settings from other jalview processes
3762 af = loadViewport(file, jseqs, hiddenSeqs, al, jalviewModel, view,
3763 uniqueSeqSetId, viewId, autoAlan);
3764 av = af.getViewport();
3769 * Load any trees, PDB structures and viewers
3771 * Not done if flag is false (when this method is used for New View)
3773 if (loadTreesAndStructures)
3775 loadTrees(jalviewModel, view, af, av, ap);
3776 loadPDBStructures(jprovider, jseqs, af, ap);
3777 loadRnaViewers(jprovider, jseqs, ap);
3779 // and finally return.
3784 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
3785 * panel is restored from separate jar entries, two (gapped and trimmed) per
3786 * sequence and secondary structure.
3788 * Currently each viewer shows just one sequence and structure (gapped and
3789 * trimmed), however this method is designed to support multiple sequences or
3790 * structures in viewers if wanted in future.
3796 private void loadRnaViewers(jarInputStreamProvider jprovider,
3797 List<JSeq> jseqs, AlignmentPanel ap)
3800 * scan the sequences for references to viewers; create each one the first
3801 * time it is referenced, add Rna models to existing viewers
3803 for (JSeq jseq : jseqs)
3805 for (int i = 0; i < jseq.getRnaViewer().size(); i++)
3807 RnaViewer viewer = jseq.getRnaViewer().get(i);
3808 AppVarna appVarna = findOrCreateVarnaViewer(viewer, uniqueSetSuffix,
3811 for (int j = 0; j < viewer.getSecondaryStructure().size(); j++)
3813 SecondaryStructure ss = viewer.getSecondaryStructure().get(j);
3814 SequenceI seq = seqRefIds.get(jseq.getId());
3815 AlignmentAnnotation ann = this.annotationIds
3816 .get(ss.getAnnotationId());
3819 * add the structure to the Varna display (with session state copied
3820 * from the jar to a temporary file)
3822 boolean gapped = ss.isGapped();
3823 String rnaTitle = ss.getTitle();
3824 String sessionState = ss.getViewerState();
3825 String tempStateFile = copyJarEntry(jprovider, sessionState,
3827 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
3828 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
3830 appVarna.setInitialSelection(viewer.getSelectedRna());
3836 * Locate and return an already instantiated matching AppVarna, or create one
3840 * @param viewIdSuffix
3844 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
3845 String viewIdSuffix, AlignmentPanel ap)
3848 * on each load a suffix is appended to the saved viewId, to avoid conflicts
3849 * if load is repeated
3851 String postLoadId = viewer.getViewId() + viewIdSuffix;
3852 for (JInternalFrame frame : getAllFrames())
3854 if (frame instanceof AppVarna)
3856 AppVarna varna = (AppVarna) frame;
3857 if (postLoadId.equals(varna.getViewId()))
3859 // this viewer is already instantiated
3860 // could in future here add ap as another 'parent' of the
3861 // AppVarna window; currently just 1-to-many
3868 * viewer not found - make it
3870 RnaViewerModel model = new RnaViewerModel(postLoadId, viewer.getTitle(),
3871 viewer.getXpos(), viewer.getYpos(), viewer.getWidth(),
3872 viewer.getHeight(), viewer.getDividerLocation());
3873 AppVarna varna = new AppVarna(model, ap);
3879 * Load any saved trees
3887 protected void loadTrees(JalviewModel jm, Viewport view,
3888 AlignFrame af, AlignViewport av, AlignmentPanel ap)
3890 // TODO result of automated refactoring - are all these parameters needed?
3893 for (int t = 0; t < jm.getTree().size(); t++)
3896 Tree tree = jm.getTree().get(t);
3898 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
3901 tp = af.showNewickTree(
3902 new jalview.io.NewickFile(tree.getNewick()),
3903 tree.getTitle(), tree.getWidth(), tree.getHeight(),
3904 tree.getXpos(), tree.getYpos());
3905 if (tree.getId() != null)
3907 // perhaps bind the tree id to something ?
3912 // update local tree attributes ?
3913 // TODO: should check if tp has been manipulated by user - if so its
3914 // settings shouldn't be modified
3915 tp.setTitle(tree.getTitle());
3916 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(),
3917 tree.getWidth(), tree.getHeight()));
3918 tp.setViewport(av); // af.viewport; // TODO: verify 'associate with all
3921 tp.getTreeCanvas().setViewport(av); // af.viewport;
3922 tp.getTreeCanvas().setAssociatedPanel(ap); // af.alignPanel;
3927 warn("There was a problem recovering stored Newick tree: \n"
3928 + tree.getNewick());
3932 tp.fitToWindow.setState(tree.isFitToWindow());
3933 tp.fitToWindow_actionPerformed(null);
3935 if (tree.getFontName() != null)
3937 tp.setTreeFont(new java.awt.Font(tree.getFontName(),
3938 tree.getFontStyle(), tree.getFontSize()));
3942 tp.setTreeFont(new java.awt.Font(view.getFontName(),
3943 view.getFontStyle(), tree.getFontSize()));
3946 tp.showPlaceholders(tree.isMarkUnlinked());
3947 tp.showBootstrap(tree.isShowBootstrap());
3948 tp.showDistances(tree.isShowDistances());
3950 tp.getTreeCanvas().setThreshold(tree.getThreshold());
3952 if (tree.isCurrentTree())
3954 af.getViewport().setCurrentTree(tp.getTree());
3958 } catch (Exception ex)
3960 ex.printStackTrace();
3965 * Load and link any saved structure viewers.
3972 protected void loadPDBStructures(jarInputStreamProvider jprovider,
3973 List<JSeq> jseqs, AlignFrame af, AlignmentPanel ap)
3976 * Run through all PDB ids on the alignment, and collect mappings between
3977 * distinct view ids and all sequences referring to that view.
3979 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<>();
3981 for (int i = 0; i < jseqs.size(); i++)
3983 JSeq jseq = jseqs.get(i);
3984 if (jseq.getPdbids().size() > 0)
3986 List<Pdbids> ids = jseq.getPdbids();
3987 for (int p = 0; p < ids.size(); p++)
3989 Pdbids pdbid = ids.get(p);
3990 final int structureStateCount = pdbid.getStructureState().size();
3991 for (int s = 0; s < structureStateCount; s++)
3993 // check to see if we haven't already created this structure view
3994 final StructureState structureState = pdbid
3995 .getStructureState().get(s);
3996 String sviewid = (structureState.getViewId() == null) ? null
3997 : structureState.getViewId() + uniqueSetSuffix;
3998 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
3999 // Originally : pdbid.getFile()
4000 // : TODO: verify external PDB file recovery still works in normal
4001 // jalview project load
4003 loadPDBFile(jprovider, pdbid.getId(), pdbid.getFile()));
4004 jpdb.setId(pdbid.getId());
4006 int x = structureState.getXpos();
4007 int y = structureState.getYpos();
4008 int width = structureState.getWidth();
4009 int height = structureState.getHeight();
4011 // Probably don't need to do this anymore...
4012 // Desktop.desktop.getComponentAt(x, y);
4013 // TODO: NOW: check that this recovers the PDB file correctly.
4014 String pdbFile = loadPDBFile(jprovider, pdbid.getId(),
4016 jalview.datamodel.SequenceI seq = seqRefIds
4017 .get(jseq.getId() + "");
4018 if (sviewid == null)
4020 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width + ","
4023 if (!structureViewers.containsKey(sviewid))
4025 structureViewers.put(sviewid,
4026 new StructureViewerModel(x, y, width, height, false,
4027 false, true, structureState.getViewId(),
4028 structureState.getType()));
4029 // Legacy pre-2.7 conversion JAL-823 :
4030 // do not assume any view has to be linked for colour by
4034 // assemble String[] { pdb files }, String[] { id for each
4035 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
4036 // seqs_file 2}, boolean[] {
4037 // linkAlignPanel,superposeWithAlignpanel}} from hash
4038 StructureViewerModel jmoldat = structureViewers.get(sviewid);
4039 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
4040 || structureState.isAlignwithAlignPanel());
4043 * Default colour by linked panel to false if not specified (e.g.
4044 * for pre-2.7 projects)
4046 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
4047 colourWithAlignPanel |= structureState.isColourwithAlignPanel();
4048 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
4051 * Default colour by viewer to true if not specified (e.g. for
4054 boolean colourByViewer = jmoldat.isColourByViewer();
4055 colourByViewer &= structureState.isColourByJmol();
4056 jmoldat.setColourByViewer(colourByViewer);
4058 if (jmoldat.getStateData().length() < structureState
4059 .getValue()/*Content()*/.length())
4061 jmoldat.setStateData(structureState.getValue());// Content());
4063 if (pdbid.getFile() != null)
4065 File mapkey = new File(pdbid.getFile());
4066 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
4067 if (seqstrmaps == null)
4069 jmoldat.getFileData().put(mapkey,
4070 seqstrmaps = jmoldat.new StructureData(pdbFile,
4073 if (!seqstrmaps.getSeqList().contains(seq))
4075 seqstrmaps.getSeqList().add(seq);
4081 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");
4088 // Instantiate the associated structure views
4089 for (Entry<String, StructureViewerModel> entry : structureViewers
4094 createOrLinkStructureViewer(entry, af, ap, jprovider);
4095 } catch (Exception e)
4098 "Error loading structure viewer: " + e.getMessage());
4099 // failed - try the next one
4111 protected void createOrLinkStructureViewer(
4112 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4113 AlignmentPanel ap, jarInputStreamProvider jprovider)
4115 final StructureViewerModel stateData = viewerData.getValue();
4118 * Search for any viewer windows already open from other alignment views
4119 * that exactly match the stored structure state
4121 StructureViewerBase comp = findMatchingViewer(viewerData);
4125 linkStructureViewer(ap, comp, stateData);
4130 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
4131 * "viewer_"+stateData.viewId
4133 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
4135 createChimeraViewer(viewerData, af, jprovider);
4140 * else Jmol (if pre-2.9, stateData contains JMOL state string)
4142 createJmolViewer(viewerData, af, jprovider);
4147 * Create a new Chimera viewer.
4153 protected void createChimeraViewer(
4154 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
4155 jarInputStreamProvider jprovider)
4157 StructureViewerModel data = viewerData.getValue();
4158 String chimeraSessionFile = data.getStateData();
4161 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
4163 * NB this is the 'saved' viewId as in the project file XML, _not_ the
4164 * 'uniquified' sviewid used to reconstruct the viewer here
4166 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
4167 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
4170 Set<Entry<File, StructureData>> fileData = data.getFileData()
4172 List<PDBEntry> pdbs = new ArrayList<>();
4173 List<SequenceI[]> allseqs = new ArrayList<>();
4174 for (Entry<File, StructureData> pdb : fileData)
4176 String filePath = pdb.getValue().getFilePath();
4177 String pdbId = pdb.getValue().getPdbId();
4178 // pdbs.add(new PDBEntry(filePath, pdbId));
4179 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
4180 final List<SequenceI> seqList = pdb.getValue().getSeqList();
4181 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
4185 boolean colourByChimera = data.isColourByViewer();
4186 boolean colourBySequence = data.isColourWithAlignPanel();
4188 // TODO use StructureViewer as a factory here, see JAL-1761
4189 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
4190 final SequenceI[][] seqsArray = allseqs
4191 .toArray(new SequenceI[allseqs.size()][]);
4192 String newViewId = viewerData.getKey();
4194 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
4195 af.alignPanel, pdbArray, seqsArray, colourByChimera,
4196 colourBySequence, newViewId);
4197 cvf.setSize(data.getWidth(), data.getHeight());
4198 cvf.setLocation(data.getX(), data.getY());
4202 * Create a new Jmol window. First parse the Jmol state to translate filenames
4203 * loaded into the view, and record the order in which files are shown in the
4204 * Jmol view, so we can add the sequence mappings in same order.
4210 protected void createJmolViewer(
4211 final Entry<String, StructureViewerModel> viewerData,
4212 AlignFrame af, jarInputStreamProvider jprovider)
4214 final StructureViewerModel svattrib = viewerData.getValue();
4215 String state = svattrib.getStateData();
4218 * Pre-2.9: state element value is the Jmol state string
4220 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
4223 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
4225 state = readJarEntry(jprovider,
4226 getViewerJarEntryName(svattrib.getViewId()));
4229 List<String> pdbfilenames = new ArrayList<>();
4230 List<SequenceI[]> seqmaps = new ArrayList<>();
4231 List<String> pdbids = new ArrayList<>();
4232 StringBuilder newFileLoc = new StringBuilder(64);
4233 int cp = 0, ncp, ecp;
4234 Map<File, StructureData> oldFiles = svattrib.getFileData();
4235 while ((ncp = state.indexOf("load ", cp)) > -1)
4239 // look for next filename in load statement
4240 newFileLoc.append(state.substring(cp,
4241 ncp = (state.indexOf("\"", ncp + 1) + 1)));
4242 String oldfilenam = state.substring(ncp,
4243 ecp = state.indexOf("\"", ncp));
4244 // recover the new mapping data for this old filename
4245 // have to normalize filename - since Jmol and jalview do
4247 // translation differently.
4248 StructureData filedat = oldFiles.get(new File(oldfilenam));
4249 if (filedat == null)
4251 String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\");
4252 filedat = oldFiles.get(new File(reformatedOldFilename));
4254 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
4255 pdbfilenames.add(filedat.getFilePath());
4256 pdbids.add(filedat.getPdbId());
4257 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4258 newFileLoc.append("\"");
4259 cp = ecp + 1; // advance beyond last \" and set cursor so we can
4260 // look for next file statement.
4261 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
4265 // just append rest of state
4266 newFileLoc.append(state.substring(cp));
4270 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
4271 newFileLoc = new StringBuilder(state);
4272 newFileLoc.append("; load append ");
4273 for (File id : oldFiles.keySet())
4275 // add this and any other pdb files that should be present in
4277 StructureData filedat = oldFiles.get(id);
4278 newFileLoc.append(filedat.getFilePath());
4279 pdbfilenames.add(filedat.getFilePath());
4280 pdbids.add(filedat.getPdbId());
4281 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4282 newFileLoc.append(" \"");
4283 newFileLoc.append(filedat.getFilePath());
4284 newFileLoc.append("\"");
4287 newFileLoc.append(";");
4290 if (newFileLoc.length() == 0)
4294 int histbug = newFileLoc.indexOf("history = ");
4298 * change "history = [true|false];" to "history = [1|0];"
4301 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
4302 String val = (diff == -1) ? null
4303 : newFileLoc.substring(histbug, diff);
4304 if (val != null && val.length() >= 4)
4306 if (val.contains("e")) // eh? what can it be?
4308 if (val.trim().equals("true"))
4316 newFileLoc.replace(histbug, diff, val);
4321 final String[] pdbf = pdbfilenames
4322 .toArray(new String[pdbfilenames.size()]);
4323 final String[] id = pdbids.toArray(new String[pdbids.size()]);
4324 final SequenceI[][] sq = seqmaps
4325 .toArray(new SequenceI[seqmaps.size()][]);
4326 final String fileloc = newFileLoc.toString();
4327 final String sviewid = viewerData.getKey();
4328 final AlignFrame alf = af;
4329 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
4330 svattrib.getWidth(), svattrib.getHeight());
4333 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
4338 JalviewStructureDisplayI sview = null;
4341 sview = new StructureViewer(
4342 alf.alignPanel.getStructureSelectionManager())
4343 .createView(StructureViewer.ViewerType.JMOL,
4344 pdbf, id, sq, alf.alignPanel, svattrib,
4345 fileloc, rect, sviewid);
4346 addNewStructureViewer(sview);
4347 } catch (OutOfMemoryError ex)
4349 new OOMWarning("restoring structure view for PDB id " + id,
4350 (OutOfMemoryError) ex.getCause());
4351 if (sview != null && sview.isVisible())
4353 sview.closeViewer(false);
4354 sview.setVisible(false);
4360 } catch (InvocationTargetException ex)
4362 warn("Unexpected error when opening Jmol view.", ex);
4364 } catch (InterruptedException e)
4366 // e.printStackTrace();
4372 * Generates a name for the entry in the project jar file to hold state
4373 * information for a structure viewer
4378 protected String getViewerJarEntryName(String viewId)
4380 return VIEWER_PREFIX + viewId;
4384 * Returns any open frame that matches given structure viewer data. The match
4385 * is based on the unique viewId, or (for older project versions) the frame's
4391 protected StructureViewerBase findMatchingViewer(
4392 Entry<String, StructureViewerModel> viewerData)
4394 final String sviewid = viewerData.getKey();
4395 final StructureViewerModel svattrib = viewerData.getValue();
4396 StructureViewerBase comp = null;
4397 JInternalFrame[] frames = getAllFrames();
4398 for (JInternalFrame frame : frames)
4400 if (frame instanceof StructureViewerBase)
4403 * Post jalview 2.4 schema includes structure view id
4405 if (sviewid != null && ((StructureViewerBase) frame).getViewId()
4408 comp = (StructureViewerBase) frame;
4409 break; // break added in 2.9
4412 * Otherwise test for matching position and size of viewer frame
4414 else if (frame.getX() == svattrib.getX()
4415 && frame.getY() == svattrib.getY()
4416 && frame.getHeight() == svattrib.getHeight()
4417 && frame.getWidth() == svattrib.getWidth())
4419 comp = (StructureViewerBase) frame;
4420 // no break in faint hope of an exact match on viewId
4428 * Link an AlignmentPanel to an existing structure viewer.
4433 * @param useinViewerSuperpos
4434 * @param usetoColourbyseq
4435 * @param viewerColouring
4437 protected void linkStructureViewer(AlignmentPanel ap,
4438 StructureViewerBase viewer, StructureViewerModel stateData)
4440 // NOTE: if the jalview project is part of a shared session then
4441 // view synchronization should/could be done here.
4443 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4444 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4445 final boolean viewerColouring = stateData.isColourByViewer();
4446 Map<File, StructureData> oldFiles = stateData.getFileData();
4449 * Add mapping for sequences in this view to an already open viewer
4451 final AAStructureBindingModel binding = viewer.getBinding();
4452 for (File id : oldFiles.keySet())
4454 // add this and any other pdb files that should be present in the
4456 StructureData filedat = oldFiles.get(id);
4457 String pdbFile = filedat.getFilePath();
4458 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4459 binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE,
4461 binding.addSequenceForStructFile(pdbFile, seq);
4463 // and add the AlignmentPanel's reference to the view panel
4464 viewer.addAlignmentPanel(ap);
4465 if (useinViewerSuperpos)
4467 viewer.useAlignmentPanelForSuperposition(ap);
4471 viewer.excludeAlignmentPanelForSuperposition(ap);
4473 if (usetoColourbyseq)
4475 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4479 viewer.excludeAlignmentPanelForColourbyseq(ap);
4484 * Get all frames within the Desktop.
4488 protected JInternalFrame[] getAllFrames()
4490 JInternalFrame[] frames = null;
4491 // TODO is this necessary - is it safe - risk of hanging?
4496 frames = Desktop.desktop.getAllFrames();
4497 } catch (ArrayIndexOutOfBoundsException e)
4499 // occasional No such child exceptions are thrown here...
4503 } catch (InterruptedException f)
4507 } while (frames == null);
4512 * Answers true if 'version' is equal to or later than 'supported', where each
4513 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4514 * changes. Development and test values for 'version' are leniently treated
4518 * - minimum version we are comparing against
4520 * - version of data being processsed
4523 public static boolean isVersionStringLaterThan(String supported,
4526 if (supported == null || version == null
4527 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4528 || version.equalsIgnoreCase("Test")
4529 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4531 System.err.println("Assuming project file with "
4532 + (version == null ? "null" : version)
4533 + " is compatible with Jalview version " + supported);
4538 return StringUtils.compareVersions(version, supported, "b") >= 0;
4542 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4544 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4546 if (newStructureViewers != null)
4548 sview.getBinding().setFinishedLoadingFromArchive(false);
4549 newStructureViewers.add(sview);
4553 protected void setLoadingFinishedForNewStructureViewers()
4555 if (newStructureViewers != null)
4557 for (JalviewStructureDisplayI sview : newStructureViewers)
4559 sview.getBinding().setFinishedLoadingFromArchive(true);
4561 newStructureViewers.clear();
4562 newStructureViewers = null;
4566 AlignFrame loadViewport(String file, List<JSeq> JSEQ,
4567 List<SequenceI> hiddenSeqs, AlignmentI al,
4568 JalviewModel jm, Viewport view, String uniqueSeqSetId,
4569 String viewId, List<JvAnnotRow> autoAlan)
4571 AlignFrame af = null;
4572 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
4573 uniqueSeqSetId, viewId);
4575 af.setFileName(file, FileFormat.Jalview);
4577 final AlignViewport viewport = af.getViewport();
4578 for (int i = 0; i < JSEQ.size(); i++)
4580 viewport.setSequenceColour(
4581 viewport.getAlignment().getSequenceAt(i),
4582 new java.awt.Color(JSEQ.get(i).getColour()));
4587 viewport.setColourByReferenceSeq(true);
4588 viewport.setDisplayReferenceSeq(true);
4591 viewport.setGatherViewsHere(view.isGatheredViews());
4593 if (view.getSequenceSetId() != null)
4595 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4597 viewport.setSequenceSetId(uniqueSeqSetId);
4600 // propagate shared settings to this new view
4601 viewport.setHistoryList(av.getHistoryList());
4602 viewport.setRedoList(av.getRedoList());
4606 viewportsAdded.put(uniqueSeqSetId, viewport);
4608 // TODO: check if this method can be called repeatedly without
4609 // side-effects if alignpanel already registered.
4610 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4612 // apply Hidden regions to view.
4613 if (hiddenSeqs != null)
4615 for (int s = 0; s < JSEQ.size(); s++)
4617 SequenceGroup hidden = new SequenceGroup();
4618 boolean isRepresentative = false;
4619 for (int r = 0; r < JSEQ.get(s).getHiddenSequences().size(); r++)
4621 isRepresentative = true;
4622 SequenceI sequenceToHide = al
4623 .getSequenceAt(JSEQ.get(s).getHiddenSequences().get(r));
4624 hidden.addSequence(sequenceToHide, false);
4625 // remove from hiddenSeqs list so we don't try to hide it twice
4626 hiddenSeqs.remove(sequenceToHide);
4628 if (isRepresentative)
4630 SequenceI representativeSequence = al.getSequenceAt(s);
4631 hidden.addSequence(representativeSequence, false);
4632 viewport.hideRepSequences(representativeSequence, hidden);
4636 SequenceI[] hseqs = hiddenSeqs
4637 .toArray(new SequenceI[hiddenSeqs.size()]);
4638 viewport.hideSequence(hseqs);
4641 // recover view properties and display parameters
4643 viewport.setShowAnnotation(view.isShowAnnotation());
4644 viewport.setAbovePIDThreshold(view.isPidSelected());
4645 final int pidThreshold = view.getPidThreshold() == null ? 0
4646 : view.getPidThreshold().intValue();
4647 viewport.setThreshold(pidThreshold);
4649 viewport.setColourText(view.isShowColourText());
4652 .setConservationSelected(view.isConservationSelected());
4653 viewport.setIncrement(view.getConsThreshold() == null ? 0
4654 : view.getConsThreshold().intValue());
4655 viewport.setShowJVSuffix(view.isShowFullId());
4656 viewport.setRightAlignIds(view.isRightAlignIds());
4657 viewport.setFont(new java.awt.Font(view.getFontName(),
4658 view.getFontStyle(), view.getFontSize()), true);
4659 ViewStyleI vs = viewport.getViewStyle();
4660 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
4661 viewport.setViewStyle(vs);
4662 // TODO: allow custom charWidth/Heights to be restored by updating them
4663 // after setting font - which means set above to false
4664 viewport.setRenderGaps(view.isRenderGaps());
4665 viewport.setWrapAlignment(view.isWrapAlignment());
4666 viewport.setShowAnnotation(view.isShowAnnotation());
4668 viewport.setShowBoxes(view.isShowBoxes());
4670 viewport.setShowText(view.isShowText());
4672 viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
4673 viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
4674 viewport.setThresholdTextColour(view.getTextColThreshold());
4675 viewport.setShowUnconserved(
4676 view.isShowUnconserved() ? view.isShowUnconserved() : false);
4677 viewport.getRanges().setStartRes(view.getStartRes());
4679 if (view.getViewName() != null)
4681 viewport.setViewName(view.getViewName());
4682 af.setInitialTabVisible();
4684 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
4686 // startSeq set in af.alignPanel.updateLayout below
4687 af.alignPanel.updateLayout();
4688 ColourSchemeI cs = null;
4689 // apply colourschemes
4690 if (view.getBgColour() != null)
4692 if (view.getBgColour().startsWith("ucs"))
4694 cs = getUserColourScheme(jm, view.getBgColour());
4696 else if (view.getBgColour().startsWith("Annotation"))
4698 AnnotationColourScheme viewAnnColour = view.getAnnotationColours();
4699 cs = constructAnnotationColour(viewAnnColour, af, al, jm, true);
4706 cs = ColourSchemeProperty.getColourScheme(al, view.getBgColour());
4710 viewport.setGlobalColourScheme(cs);
4711 viewport.getResidueShading().setThreshold(pidThreshold,
4712 view.isIgnoreGapsinConsensus());
4713 viewport.getResidueShading()
4714 .setConsensus(viewport.getSequenceConsensusHash());
4715 viewport.setColourAppliesToAllGroups(false);
4717 if (view.isConservationSelected() && cs != null)
4719 viewport.getResidueShading()
4720 .setConservationInc(view.getConsThreshold());
4723 af.changeColour(cs);
4725 viewport.setColourAppliesToAllGroups(true);
4728 .setShowSequenceFeatures(view.isShowSequenceFeatures());
4730 // if (view.hasCentreColumnLabels())
4732 viewport.setCentreColumnLabels(view.isCentreColumnLabels());
4734 // if (view.hasIgnoreGapsinConsensus())
4736 viewport.setIgnoreGapsConsensus(view.isIgnoreGapsinConsensus(), null);
4738 // if (view.hasFollowHighlight())
4741 viewport.setFollowHighlight(view.isFollowHighlight());
4743 // if (view.hasFollowSelection())
4745 viewport.followSelection = view.isFollowSelection();
4747 // if (view.hasShowConsensusHistogram())
4749 viewport.setShowConsensusHistogram(view.isShowConsensusHistogram());
4753 // viewport.setShowConsensusHistogram(true);
4755 // if (view.hasShowSequenceLogo())
4757 viewport.setShowSequenceLogo(view.isShowSequenceLogo());
4761 // viewport.setShowSequenceLogo(false);
4763 // if (view.hasNormaliseSequenceLogo())
4765 viewport.setNormaliseSequenceLogo(view.isNormaliseSequenceLogo());
4767 if (view.isShowDbRefTooltip() != null)
4769 viewport.setShowDBRefs(view.isShowDbRefTooltip());
4771 if (view.isShowNPfeatureTooltip() != null)
4773 viewport.setShowNPFeats(view.isShowNPfeatureTooltip());
4775 // if (view.hasShowGroupConsensus())
4777 viewport.setShowGroupConsensus(view.isShowGroupConsensus());
4781 // viewport.setShowGroupConsensus(false);
4783 // if (view.hasShowGroupConservation())
4785 viewport.setShowGroupConservation(view.isShowGroupConservation());
4789 // viewport.setShowGroupConservation(false);
4792 // recover feature settings
4793 if (jm.getFeatureSettings() != null)
4795 FeatureRenderer fr = af.alignPanel.getSeqPanel().seqCanvas
4796 .getFeatureRenderer();
4797 FeaturesDisplayed fdi;
4798 viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
4799 String[] renderOrder = new String[jm.getFeatureSettings()
4800 .getSetting().size()];
4801 Map<String, FeatureColourI> featureColours = new Hashtable<>();
4802 Map<String, Float> featureOrder = new Hashtable<>();
4804 for (int fs = 0; fs < jm.getFeatureSettings()
4805 .getSetting().size(); fs++)
4807 Setting setting = jm.getFeatureSettings().getSetting().get(fs);
4808 String featureType = setting.getType();
4811 * restore feature filters (if any)
4813 jalview.xml.binding.jalview.FeatureMatcherSet filters = setting
4815 if (filters != null)
4817 FeatureMatcherSetI filter = Jalview2XML
4818 .parseFilter(featureType, filters);
4819 if (!filter.isEmpty())
4821 fr.setFeatureFilter(featureType, filter);
4826 * restore feature colour scheme
4828 Color maxColour = new Color(setting.getColour());
4829 if (setting.getMincolour() != null)
4832 * minColour is always set unless a simple colour
4833 * (including for colour by label though it doesn't use it)
4835 Color minColour = new Color(setting.getMincolour().intValue());
4836 Color noValueColour = minColour;
4837 NoValueColour noColour = setting.getNoValueColour();
4838 if (noColour == NoValueColour.NONE)
4840 noValueColour = null;
4842 else if (noColour == NoValueColour.MAX)
4844 noValueColour = maxColour;
4846 float min = setting.getMin() != null
4847 ? setting.getMin().floatValue()
4849 float max = setting.getMin() != null
4850 ? setting.getMax().floatValue()
4852 FeatureColourI gc = new FeatureColour(minColour, maxColour,
4853 noValueColour, min, max);
4854 if (setting.getAttributeName().size() > 0)
4856 gc.setAttributeName(setting.getAttributeName().toArray(
4857 new String[setting.getAttributeName().size()]));
4859 if (setting.getThreshold() != null)
4861 gc.setThreshold(setting.getThreshold().floatValue());
4862 int threshstate = setting.getThreshstate().intValue();
4863 // -1 = None, 0 = Below, 1 = Above threshold
4864 if (threshstate == 0)
4866 gc.setBelowThreshold(true);
4868 else if (threshstate == 1)
4870 gc.setAboveThreshold(true);
4873 gc.setAutoScaled(true); // default
4874 if (setting.isAutoScale() != null)
4876 gc.setAutoScaled(setting.isAutoScale());
4878 if (setting.isColourByLabel() != null)
4880 gc.setColourByLabel(setting.isColourByLabel());
4882 // and put in the feature colour table.
4883 featureColours.put(featureType, gc);
4887 featureColours.put(featureType,
4888 new FeatureColour(maxColour));
4890 renderOrder[fs] = featureType;
4891 if (setting.getOrder() != null)
4893 featureOrder.put(featureType, setting.getOrder().floatValue());
4897 featureOrder.put(featureType, new Float(
4898 fs / jm.getFeatureSettings().getSetting().size()));
4900 if (setting.isDisplay())
4902 fdi.setVisible(featureType);
4905 Map<String, Boolean> fgtable = new Hashtable<>();
4906 for (int gs = 0; gs < jm.getFeatureSettings().getGroup().size(); gs++)
4908 Group grp = jm.getFeatureSettings().getGroup().get(gs);
4909 fgtable.put(grp.getName(), new Boolean(grp.isDisplay()));
4911 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4912 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
4913 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
4914 FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4915 fgtable, featureColours, 1.0f, featureOrder);
4916 fr.transferSettings(frs);
4919 if (view.getHiddenColumns().size() > 0)
4921 for (int c = 0; c < view.getHiddenColumns().size(); c++)
4923 viewport.hideColumns(view.getHiddenColumns().get(c).getStart(),
4924 view.getHiddenColumns().get(c).getEnd() // +1
4928 if (view.getCalcIdParam() != null)
4930 for (CalcIdParam calcIdParam : view.getCalcIdParam())
4932 if (calcIdParam != null)
4934 if (recoverCalcIdParam(calcIdParam, viewport))
4939 warn("Couldn't recover parameters for "
4940 + calcIdParam.getCalcId());
4945 af.setMenusFromViewport(viewport);
4946 af.setTitle(view.getTitle());
4947 // TODO: we don't need to do this if the viewport is aready visible.
4949 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
4950 * has a 'cdna/protein complement' view, in which case save it in order to
4951 * populate a SplitFrame once all views have been read in.
4953 String complementaryViewId = view.getComplementId();
4954 if (complementaryViewId == null)
4956 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
4958 // recompute any autoannotation
4959 af.alignPanel.updateAnnotation(false, true);
4960 reorderAutoannotation(af, al, autoAlan);
4961 af.alignPanel.alignmentChanged();
4965 splitFrameCandidates.put(view, af);
4971 * Reads saved data to restore Colour by Annotation settings
4973 * @param viewAnnColour
4977 * @param checkGroupAnnColour
4980 private ColourSchemeI constructAnnotationColour(
4981 AnnotationColourScheme viewAnnColour, AlignFrame af,
4982 AlignmentI al, JalviewModel model, boolean checkGroupAnnColour)
4984 boolean propagateAnnColour = false;
4985 AlignmentI annAlignment = af != null ? af.getViewport().getAlignment()
4987 if (checkGroupAnnColour && al.getGroups() != null
4988 && al.getGroups().size() > 0)
4990 // pre 2.8.1 behaviour
4991 // check to see if we should transfer annotation colours
4992 propagateAnnColour = true;
4993 for (SequenceGroup sg : al.getGroups())
4995 if (sg.getColourScheme() instanceof AnnotationColourGradient)
4997 propagateAnnColour = false;
5003 * 2.10.2- : saved annotationId is AlignmentAnnotation.annotationId
5005 String annotationId = viewAnnColour.getAnnotation();
5006 AlignmentAnnotation matchedAnnotation = annotationIds.get(annotationId);
5009 * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
5011 if (matchedAnnotation == null
5012 && annAlignment.getAlignmentAnnotation() != null)
5014 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
5017 .equals(annAlignment.getAlignmentAnnotation()[i].label))
5019 matchedAnnotation = annAlignment.getAlignmentAnnotation()[i];
5024 if (matchedAnnotation == null)
5026 System.err.println("Failed to match annotation colour scheme for "
5030 if (matchedAnnotation.getThreshold() == null)
5032 matchedAnnotation.setThreshold(new GraphLine(
5033 viewAnnColour.getThreshold(), "Threshold", Color.black));
5036 AnnotationColourGradient cs = null;
5037 if (viewAnnColour.getColourScheme().equals("None"))
5039 cs = new AnnotationColourGradient(matchedAnnotation,
5040 new Color(viewAnnColour.getMinColour()),
5041 new Color(viewAnnColour.getMaxColour()),
5042 viewAnnColour.getAboveThreshold());
5044 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
5046 cs = new AnnotationColourGradient(matchedAnnotation,
5047 getUserColourScheme(model, viewAnnColour.getColourScheme()),
5048 viewAnnColour.getAboveThreshold());
5052 cs = new AnnotationColourGradient(matchedAnnotation,
5053 ColourSchemeProperty.getColourScheme(al,
5054 viewAnnColour.getColourScheme()),
5055 viewAnnColour.getAboveThreshold());
5058 boolean perSequenceOnly = viewAnnColour.isPerSequence();
5059 boolean useOriginalColours = viewAnnColour.isPredefinedColours();
5060 cs.setSeqAssociated(perSequenceOnly);
5061 cs.setPredefinedColours(useOriginalColours);
5063 if (propagateAnnColour && al.getGroups() != null)
5065 // Also use these settings for all the groups
5066 for (int g = 0; g < al.getGroups().size(); g++)
5068 SequenceGroup sg = al.getGroups().get(g);
5069 if (sg.getGroupColourScheme() == null)
5074 AnnotationColourGradient groupScheme = new AnnotationColourGradient(
5075 matchedAnnotation, sg.getColourScheme(),
5076 viewAnnColour.getAboveThreshold());
5077 sg.setColourScheme(groupScheme);
5078 groupScheme.setSeqAssociated(perSequenceOnly);
5079 groupScheme.setPredefinedColours(useOriginalColours);
5085 private void reorderAutoannotation(AlignFrame af, AlignmentI al,
5086 List<JvAnnotRow> autoAlan)
5088 // copy over visualization settings for autocalculated annotation in the
5090 if (al.getAlignmentAnnotation() != null)
5093 * Kludge for magic autoannotation names (see JAL-811)
5095 String[] magicNames = new String[] { "Consensus", "Quality",
5097 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
5098 Hashtable<String, JvAnnotRow> visan = new Hashtable<>();
5099 for (String nm : magicNames)
5101 visan.put(nm, nullAnnot);
5103 for (JvAnnotRow auan : autoAlan)
5105 visan.put(auan.template.label
5106 + (auan.template.getCalcId() == null ? ""
5107 : "\t" + auan.template.getCalcId()),
5110 int hSize = al.getAlignmentAnnotation().length;
5111 List<JvAnnotRow> reorder = new ArrayList<>();
5112 // work through any autoCalculated annotation already on the view
5113 // removing it if it should be placed in a different location on the
5114 // annotation panel.
5115 List<String> remains = new ArrayList<>(visan.keySet());
5116 for (int h = 0; h < hSize; h++)
5118 jalview.datamodel.AlignmentAnnotation jalan = al
5119 .getAlignmentAnnotation()[h];
5120 if (jalan.autoCalculated)
5123 JvAnnotRow valan = visan.get(k = jalan.label);
5124 if (jalan.getCalcId() != null)
5126 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
5131 // delete the auto calculated row from the alignment
5132 al.deleteAnnotation(jalan, false);
5136 if (valan != nullAnnot)
5138 if (jalan != valan.template)
5140 // newly created autoannotation row instance
5141 // so keep a reference to the visible annotation row
5142 // and copy over all relevant attributes
5143 if (valan.template.graphHeight >= 0)
5146 jalan.graphHeight = valan.template.graphHeight;
5148 jalan.visible = valan.template.visible;
5150 reorder.add(new JvAnnotRow(valan.order, jalan));
5155 // Add any (possibly stale) autocalculated rows that were not appended to
5156 // the view during construction
5157 for (String other : remains)
5159 JvAnnotRow othera = visan.get(other);
5160 if (othera != nullAnnot && othera.template.getCalcId() != null
5161 && othera.template.getCalcId().length() > 0)
5163 reorder.add(othera);
5166 // now put the automatic annotation in its correct place
5167 int s = 0, srt[] = new int[reorder.size()];
5168 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
5169 for (JvAnnotRow jvar : reorder)
5172 srt[s++] = jvar.order;
5175 jalview.util.QuickSort.sort(srt, rws);
5176 // and re-insert the annotation at its correct position
5177 for (JvAnnotRow jvar : rws)
5179 al.addAnnotation(jvar.template, jvar.order);
5181 af.alignPanel.adjustAnnotationHeight();
5185 Hashtable skipList = null;
5188 * TODO remove this method
5191 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
5192 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
5193 * throw new Error("Implementation Error. No skipList defined for this
5194 * Jalview2XML instance."); } return (AlignFrame)
5195 * skipList.get(view.getSequenceSetId()); }
5199 * Check if the Jalview view contained in object should be skipped or not.
5202 * @return true if view's sequenceSetId is a key in skipList
5204 private boolean skipViewport(JalviewModel object)
5206 if (skipList == null)
5210 String id = object.getViewport().get(0).getSequenceSetId();
5211 if (skipList.containsKey(id))
5213 if (Cache.log != null && Cache.log.isDebugEnabled())
5215 Cache.log.debug("Skipping seuqence set id " + id);
5222 public void addToSkipList(AlignFrame af)
5224 if (skipList == null)
5226 skipList = new Hashtable();
5228 skipList.put(af.getViewport().getSequenceSetId(), af);
5231 public void clearSkipList()
5233 if (skipList != null)
5240 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
5241 boolean ignoreUnrefed)
5243 jalview.datamodel.AlignmentI ds = getDatasetFor(
5244 vamsasSet.getDatasetId());
5245 Vector dseqs = null;
5248 // create a list of new dataset sequences
5249 dseqs = new Vector();
5251 for (int i = 0, iSize = vamsasSet.getSequence().size(); i < iSize; i++)
5253 Sequence vamsasSeq = vamsasSet.getSequence().get(i);
5254 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
5256 // create a new dataset
5259 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
5260 dseqs.copyInto(dsseqs);
5261 ds = new jalview.datamodel.Alignment(dsseqs);
5262 debug("Created new dataset " + vamsasSet.getDatasetId()
5263 + " for alignment " + System.identityHashCode(al));
5264 addDatasetRef(vamsasSet.getDatasetId(), ds);
5266 // set the dataset for the newly imported alignment.
5267 if (al.getDataset() == null && !ignoreUnrefed)
5276 * sequence definition to create/merge dataset sequence for
5280 * vector to add new dataset sequence to
5281 * @param ignoreUnrefed
5282 * - when true, don't create new sequences from vamsasSeq if it's id
5283 * doesn't already have an asssociated Jalview sequence.
5285 * - used to reorder the sequence in the alignment according to the
5286 * vamsasSeq array ordering, to preserve ordering of dataset
5288 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
5289 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed, int vseqpos)
5291 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
5293 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
5294 boolean reorder = false;
5295 SequenceI dsq = null;
5296 if (sq != null && sq.getDatasetSequence() != null)
5298 dsq = sq.getDatasetSequence();
5304 if (sq == null && ignoreUnrefed)
5308 String sqid = vamsasSeq.getDsseqid();
5311 // need to create or add a new dataset sequence reference to this sequence
5314 dsq = seqRefIds.get(sqid);
5319 // make a new dataset sequence
5320 dsq = sq.createDatasetSequence();
5323 // make up a new dataset reference for this sequence
5324 sqid = seqHash(dsq);
5326 dsq.setVamsasId(uniqueSetSuffix + sqid);
5327 seqRefIds.put(sqid, dsq);
5332 dseqs.addElement(dsq);
5337 ds.addSequence(dsq);
5343 { // make this dataset sequence sq's dataset sequence
5344 sq.setDatasetSequence(dsq);
5345 // and update the current dataset alignment
5350 if (!dseqs.contains(dsq))
5357 if (ds.findIndex(dsq) < 0)
5359 ds.addSequence(dsq);
5366 // TODO: refactor this as a merge dataset sequence function
5367 // now check that sq (the dataset sequence) sequence really is the union of
5368 // all references to it
5369 // boolean pre = sq.getStart() < dsq.getStart();
5370 // boolean post = sq.getEnd() > dsq.getEnd();
5374 // StringBuffer sb = new StringBuffer();
5375 String newres = jalview.analysis.AlignSeq.extractGaps(
5376 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
5377 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
5378 && newres.length() > dsq.getLength())
5380 // Update with the longer sequence.
5384 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
5385 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
5386 * sb.append(newres.substring(newres.length() - sq.getEnd() -
5387 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
5389 dsq.setSequence(newres);
5391 // TODO: merges will never happen if we 'know' we have the real dataset
5392 // sequence - this should be detected when id==dssid
5394 "DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
5395 // + (pre ? "prepended" : "") + " "
5396 // + (post ? "appended" : ""));
5401 // sequence refs are identical. We may need to update the existing dataset
5402 // alignment with this one, though.
5403 if (ds != null && dseqs == null)
5405 int opos = ds.findIndex(dsq);
5406 SequenceI tseq = null;
5407 if (opos != -1 && vseqpos != opos)
5409 // remove from old position
5410 ds.deleteSequence(dsq);
5412 if (vseqpos < ds.getHeight())
5414 if (vseqpos != opos)
5416 // save sequence at destination position
5417 tseq = ds.getSequenceAt(vseqpos);
5418 ds.replaceSequenceAt(vseqpos, dsq);
5419 ds.addSequence(tseq);
5424 ds.addSequence(dsq);
5431 * TODO use AlignmentI here and in related methods - needs
5432 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
5434 Hashtable<String, AlignmentI> datasetIds = null;
5436 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
5438 private AlignmentI getDatasetFor(String datasetId)
5440 if (datasetIds == null)
5442 datasetIds = new Hashtable<>();
5445 if (datasetIds.containsKey(datasetId))
5447 return datasetIds.get(datasetId);
5452 private void addDatasetRef(String datasetId, AlignmentI dataset)
5454 if (datasetIds == null)
5456 datasetIds = new Hashtable<>();
5458 datasetIds.put(datasetId, dataset);
5462 * make a new dataset ID for this jalview dataset alignment
5467 private String getDatasetIdRef(AlignmentI dataset)
5469 if (dataset.getDataset() != null)
5471 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
5473 String datasetId = makeHashCode(dataset, null);
5474 if (datasetId == null)
5476 // make a new datasetId and record it
5477 if (dataset2Ids == null)
5479 dataset2Ids = new IdentityHashMap<>();
5483 datasetId = dataset2Ids.get(dataset);
5485 if (datasetId == null)
5487 datasetId = "ds" + dataset2Ids.size() + 1;
5488 dataset2Ids.put(dataset, datasetId);
5494 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5496 for (int d = 0; d < sequence.getDBRef().size(); d++)
5498 DBRef dr = sequence.getDBRef().get(d);
5499 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
5500 dr.getSource(), dr.getVersion(), dr.getAccessionId());
5501 if (dr.getMapping() != null)
5503 entry.setMap(addMapping(dr.getMapping()));
5505 datasetSequence.addDBRef(entry);
5509 private jalview.datamodel.Mapping addMapping(Mapping m)
5511 SequenceI dsto = null;
5512 // Mapping m = dr.getMapping();
5513 int fr[] = new int[m.getMapListFrom().size() * 2];
5514 Iterator<MapListFrom> from = m.getMapListFrom().iterator();// enumerateMapListFrom();
5515 for (int _i = 0; from.hasNext(); _i += 2)
5517 MapListFrom mf = from.next();
5518 fr[_i] = mf.getStart();
5519 fr[_i + 1] = mf.getEnd();
5521 int fto[] = new int[m.getMapListTo().size() * 2];
5522 Iterator<MapListTo> to = m.getMapListTo().iterator();// enumerateMapListTo();
5523 for (int _i = 0; to.hasNext(); _i += 2)
5525 MapListTo mf = to.next();
5526 fto[_i] = mf.getStart();
5527 fto[_i + 1] = mf.getEnd();
5529 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto, fr,
5530 fto, m.getMapFromUnit().intValue(),
5531 m.getMapToUnit().intValue());
5532 // if (m.getMappingChoice() != null)
5534 // MappingChoice mc = m.getMappingChoice();
5535 if (m.getDseqFor() != null)
5537 String dsfor = m.getDseqFor();
5538 if (seqRefIds.containsKey(dsfor))
5543 jmap.setTo(seqRefIds.get(dsfor));
5547 frefedSequence.add(newMappingRef(dsfor, jmap));
5553 * local sequence definition
5555 Sequence ms = m.getSequence();
5556 SequenceI djs = null;
5557 String sqid = ms.getDsseqid();
5558 if (sqid != null && sqid.length() > 0)
5561 * recover dataset sequence
5563 djs = seqRefIds.get(sqid);
5568 "Warning - making up dataset sequence id for DbRef sequence map reference");
5569 sqid = ((Object) ms).toString(); // make up a new hascode for
5570 // undefined dataset sequence hash
5571 // (unlikely to happen)
5577 * make a new dataset sequence and add it to refIds hash
5579 djs = new jalview.datamodel.Sequence(ms.getName(),
5581 djs.setStart(jmap.getMap().getToLowest());
5582 djs.setEnd(jmap.getMap().getToHighest());
5583 djs.setVamsasId(uniqueSetSuffix + sqid);
5585 incompleteSeqs.put(sqid, djs);
5586 seqRefIds.put(sqid, djs);
5589 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5598 * Provides a 'copy' of an alignment view (on action New View) by 'saving' the
5599 * view as XML (but not to file), and then reloading it
5604 public AlignmentPanel copyAlignPanel(AlignmentPanel ap)
5607 JalviewModel jm = saveState(ap, null, null, null);
5609 uniqueSetSuffix = "";
5610 // jm.getJalviewModelSequence().getViewport(0).setId(null);
5611 jm.getViewport().get(0).setId(null);
5612 // we don't overwrite the view we just copied
5614 if (this.frefedSequence == null)
5616 frefedSequence = new Vector<>();
5619 viewportsAdded.clear();
5621 AlignFrame af = loadFromObject(jm, null, false, null);
5622 af.getAlignPanels().clear();
5623 af.closeMenuItem_actionPerformed(true);
5626 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5627 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5628 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5629 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5630 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5633 return af.alignPanel;
5636 private Hashtable jvids2vobj;
5638 private void warn(String msg)
5643 private void warn(String msg, Exception e)
5645 if (Cache.log != null)
5649 Cache.log.warn(msg, e);
5653 Cache.log.warn(msg);
5658 System.err.println("Warning: " + msg);
5661 e.printStackTrace();
5666 private void debug(String string)
5668 debug(string, null);
5671 private void debug(String msg, Exception e)
5673 if (Cache.log != null)
5677 Cache.log.debug(msg, e);
5681 Cache.log.debug(msg);
5686 System.err.println("Warning: " + msg);
5689 e.printStackTrace();
5695 * set the object to ID mapping tables used to write/recover objects and XML
5696 * ID strings for the jalview project. If external tables are provided then
5697 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
5698 * object goes out of scope. - also populates the datasetIds hashtable with
5699 * alignment objects containing dataset sequences
5702 * Map from ID strings to jalview datamodel
5704 * Map from jalview datamodel to ID strings
5708 public void setObjectMappingTables(Hashtable vobj2jv,
5709 IdentityHashMap jv2vobj)
5711 this.jv2vobj = jv2vobj;
5712 this.vobj2jv = vobj2jv;
5713 Iterator ds = jv2vobj.keySet().iterator();
5715 while (ds.hasNext())
5717 Object jvobj = ds.next();
5718 id = jv2vobj.get(jvobj).toString();
5719 if (jvobj instanceof jalview.datamodel.Alignment)
5721 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
5723 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
5726 else if (jvobj instanceof jalview.datamodel.Sequence)
5728 // register sequence object so the XML parser can recover it.
5729 if (seqRefIds == null)
5731 seqRefIds = new HashMap<>();
5733 if (seqsToIds == null)
5735 seqsToIds = new IdentityHashMap<>();
5737 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
5738 seqsToIds.put((SequenceI) jvobj, id);
5740 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
5743 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
5744 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
5745 if (jvann.annotationId == null)
5747 jvann.annotationId = anid;
5749 if (!jvann.annotationId.equals(anid))
5751 // TODO verify that this is the correct behaviour
5752 this.warn("Overriding Annotation ID for " + anid
5753 + " from different id : " + jvann.annotationId);
5754 jvann.annotationId = anid;
5757 else if (jvobj instanceof String)
5759 if (jvids2vobj == null)
5761 jvids2vobj = new Hashtable();
5762 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
5767 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
5773 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
5774 * objects created from the project archive. If string is null (default for
5775 * construction) then suffix will be set automatically.
5779 public void setUniqueSetSuffix(String string)
5781 uniqueSetSuffix = string;
5786 * uses skipList2 as the skipList for skipping views on sequence sets
5787 * associated with keys in the skipList
5791 public void setSkipList(Hashtable skipList2)
5793 skipList = skipList2;
5797 * Reads the jar entry of given name and returns its contents, or null if the
5798 * entry is not found.
5801 * @param jarEntryName
5804 protected String readJarEntry(jarInputStreamProvider jprovider,
5805 String jarEntryName)
5807 String result = null;
5808 BufferedReader in = null;
5813 * Reopen the jar input stream and traverse its entries to find a matching
5816 JarInputStream jin = jprovider.getJarInputStream();
5817 JarEntry entry = null;
5820 entry = jin.getNextJarEntry();
5821 } while (entry != null && !entry.getName().equals(jarEntryName));
5825 StringBuilder out = new StringBuilder(256);
5826 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
5829 while ((data = in.readLine()) != null)
5833 result = out.toString();
5837 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
5839 } catch (Exception ex)
5841 ex.printStackTrace();
5849 } catch (IOException e)
5860 * Returns an incrementing counter (0, 1, 2...)
5864 private synchronized int nextCounter()
5870 * Populates an XML model of the feature colour scheme for one feature type
5872 * @param featureType
5876 public static Colour marshalColour(
5877 String featureType, FeatureColourI fcol)
5879 Colour col = new Colour();
5880 if (fcol.isSimpleColour())
5882 col.setRGB(Format.getHexString(fcol.getColour()));
5886 col.setRGB(Format.getHexString(fcol.getMaxColour()));
5887 col.setMin(fcol.getMin());
5888 col.setMax(fcol.getMax());
5889 col.setMinRGB(jalview.util.Format.getHexString(fcol.getMinColour()));
5890 col.setAutoScale(fcol.isAutoScaled());
5891 col.setThreshold(fcol.getThreshold());
5892 col.setColourByLabel(fcol.isColourByLabel());
5893 col.setThreshType(fcol.isAboveThreshold() ? ThresholdType.ABOVE
5894 : (fcol.isBelowThreshold() ? ThresholdType.BELOW
5895 : ThresholdType.NONE));
5896 if (fcol.isColourByAttribute())
5898 final String[] attName = fcol.getAttributeName();
5899 col.getAttributeName().add(attName[0]);
5900 if (attName.length > 1)
5902 col.getAttributeName().add(attName[1]);
5905 Color noColour = fcol.getNoColour();
5906 if (noColour == null)
5908 col.setNoValueColour(NoValueColour.NONE);
5910 else if (noColour == fcol.getMaxColour())
5912 col.setNoValueColour(NoValueColour.MAX);
5916 col.setNoValueColour(NoValueColour.MIN);
5919 col.setName(featureType);
5924 * Populates an XML model of the feature filter(s) for one feature type
5926 * @param firstMatcher
5927 * the first (or only) match condition)
5929 * remaining match conditions (if any)
5931 * if true, conditions are and-ed, else or-ed
5933 public static jalview.xml.binding.jalview.FeatureMatcherSet marshalFilter(
5934 FeatureMatcherI firstMatcher, Iterator<FeatureMatcherI> filters,
5937 jalview.xml.binding.jalview.FeatureMatcherSet result = new jalview.xml.binding.jalview.FeatureMatcherSet();
5939 if (filters.hasNext())
5944 CompoundMatcher compound = new CompoundMatcher();
5945 compound.setAnd(and);
5946 jalview.xml.binding.jalview.FeatureMatcherSet matcher1 = marshalFilter(
5947 firstMatcher, Collections.emptyIterator(), and);
5948 // compound.addMatcherSet(matcher1);
5949 compound.getMatcherSet().add(matcher1);
5950 FeatureMatcherI nextMatcher = filters.next();
5951 jalview.xml.binding.jalview.FeatureMatcherSet matcher2 = marshalFilter(
5952 nextMatcher, filters, and);
5953 // compound.addMatcherSet(matcher2);
5954 compound.getMatcherSet().add(matcher2);
5955 result.setCompoundMatcher(compound);
5960 * single condition matcher
5962 // MatchCondition matcherModel = new MatchCondition();
5963 jalview.xml.binding.jalview.FeatureMatcher matcherModel = new jalview.xml.binding.jalview.FeatureMatcher();
5964 matcherModel.setCondition(
5965 firstMatcher.getMatcher().getCondition().getStableName());
5966 matcherModel.setValue(firstMatcher.getMatcher().getPattern());
5967 if (firstMatcher.isByAttribute())
5969 matcherModel.setBy(FilterBy.BY_ATTRIBUTE);
5970 // matcherModel.setAttributeName(firstMatcher.getAttribute());
5971 String[] attName = firstMatcher.getAttribute();
5972 matcherModel.getAttributeName().add(attName[0]); // attribute
5973 if (attName.length > 1)
5975 matcherModel.getAttributeName().add(attName[1]); // sub-attribute
5978 else if (firstMatcher.isByLabel())
5980 matcherModel.setBy(FilterBy.BY_LABEL);
5982 else if (firstMatcher.isByScore())
5984 matcherModel.setBy(FilterBy.BY_SCORE);
5986 result.setMatchCondition(matcherModel);
5993 * Loads one XML model of a feature filter to a Jalview object
5995 * @param featureType
5996 * @param matcherSetModel
5999 public static FeatureMatcherSetI parseFilter(
6001 jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel)
6003 FeatureMatcherSetI result = new FeatureMatcherSet();
6006 parseFilterConditions(result, matcherSetModel, true);
6007 } catch (IllegalStateException e)
6009 // mixing AND and OR conditions perhaps
6011 String.format("Error reading filter conditions for '%s': %s",
6012 featureType, e.getMessage()));
6013 // return as much as was parsed up to the error
6020 * Adds feature match conditions to matcherSet as unmarshalled from XML
6021 * (possibly recursively for compound conditions)
6024 * @param matcherSetModel
6026 * if true, multiple conditions are AND-ed, else they are OR-ed
6027 * @throws IllegalStateException
6028 * if AND and OR conditions are mixed
6030 protected static void parseFilterConditions(
6031 FeatureMatcherSetI matcherSet,
6032 jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel,
6035 jalview.xml.binding.jalview.FeatureMatcher mc = matcherSetModel
6036 .getMatchCondition();
6042 FilterBy filterBy = mc.getBy();
6043 Condition cond = Condition.fromString(mc.getCondition());
6044 String pattern = mc.getValue();
6045 FeatureMatcherI matchCondition = null;
6046 if (filterBy == FilterBy.BY_LABEL)
6048 matchCondition = FeatureMatcher.byLabel(cond, pattern);
6050 else if (filterBy == FilterBy.BY_SCORE)
6052 matchCondition = FeatureMatcher.byScore(cond, pattern);
6055 else if (filterBy == FilterBy.BY_ATTRIBUTE)
6057 final List<String> attributeName = mc.getAttributeName();
6058 String[] attNames = attributeName
6059 .toArray(new String[attributeName.size()]);
6060 matchCondition = FeatureMatcher.byAttribute(cond, pattern,
6065 * note this throws IllegalStateException if AND-ing to a
6066 * previously OR-ed compound condition, or vice versa
6070 matcherSet.and(matchCondition);
6074 matcherSet.or(matchCondition);
6080 * compound condition
6082 List<jalview.xml.binding.jalview.FeatureMatcherSet> matchers = matcherSetModel
6083 .getCompoundMatcher().getMatcherSet();
6084 boolean anded = matcherSetModel.getCompoundMatcher().isAnd();
6085 if (matchers.size() == 2)
6087 parseFilterConditions(matcherSet, matchers.get(0), anded);
6088 parseFilterConditions(matcherSet, matchers.get(1), anded);
6092 System.err.println("Malformed compound filter condition");
6098 * Loads one XML model of a feature colour to a Jalview object
6100 * @param colourModel
6103 public static FeatureColourI parseColour(Colour colourModel)
6105 FeatureColourI colour = null;
6107 if (colourModel.getMax() != null)
6109 Color mincol = null;
6110 Color maxcol = null;
6111 Color noValueColour = null;
6115 mincol = new Color(Integer.parseInt(colourModel.getMinRGB(), 16));
6116 maxcol = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6117 } catch (Exception e)
6119 Cache.log.warn("Couldn't parse out graduated feature color.", e);
6122 NoValueColour noCol = colourModel.getNoValueColour();
6123 if (noCol == NoValueColour.MIN)
6125 noValueColour = mincol;
6127 else if (noCol == NoValueColour.MAX)
6129 noValueColour = maxcol;
6132 colour = new FeatureColour(mincol, maxcol, noValueColour,
6133 colourModel.getMin(),
6134 colourModel.getMax());
6135 final List<String> attributeName = colourModel.getAttributeName();
6136 String[] attributes = attributeName
6137 .toArray(new String[attributeName.size()]);
6138 if (attributes != null && attributes.length > 0)
6140 colour.setAttributeName(attributes);
6142 if (colourModel.isAutoScale() != null)
6144 colour.setAutoScaled(colourModel.isAutoScale().booleanValue());
6146 if (colourModel.isColourByLabel() != null)
6148 colour.setColourByLabel(
6149 colourModel.isColourByLabel().booleanValue());
6151 if (colourModel.getThreshold() != null)
6153 colour.setThreshold(colourModel.getThreshold().floatValue());
6155 ThresholdType ttyp = colourModel.getThreshType();
6156 if (ttyp == ThresholdType.ABOVE)
6158 colour.setAboveThreshold(true);
6160 else if (ttyp == ThresholdType.BELOW)
6162 colour.setBelowThreshold(true);
6167 Color color = new Color(Integer.parseInt(colourModel.getRGB(), 16));
6168 colour = new FeatureColour(color);