2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import 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.ext.varna.RnaModel;
41 import jalview.gui.StructureViewer.ViewerType;
42 import jalview.io.DataSourceType;
43 import jalview.io.FileFormat;
44 import jalview.renderer.ResidueShaderI;
45 import jalview.schemabinding.version2.AlcodMap;
46 import jalview.schemabinding.version2.AlcodonFrame;
47 import jalview.schemabinding.version2.Annotation;
48 import jalview.schemabinding.version2.AnnotationColours;
49 import jalview.schemabinding.version2.AnnotationElement;
50 import jalview.schemabinding.version2.CalcIdParam;
51 import jalview.schemabinding.version2.DBRef;
52 import jalview.schemabinding.version2.Features;
53 import jalview.schemabinding.version2.Group;
54 import jalview.schemabinding.version2.HiddenColumns;
55 import jalview.schemabinding.version2.JGroup;
56 import jalview.schemabinding.version2.JSeq;
57 import jalview.schemabinding.version2.JalviewModel;
58 import jalview.schemabinding.version2.JalviewModelSequence;
59 import jalview.schemabinding.version2.MapListFrom;
60 import jalview.schemabinding.version2.MapListTo;
61 import jalview.schemabinding.version2.Mapping;
62 import jalview.schemabinding.version2.MappingChoice;
63 import jalview.schemabinding.version2.OtherData;
64 import jalview.schemabinding.version2.PdbentryItem;
65 import jalview.schemabinding.version2.Pdbids;
66 import jalview.schemabinding.version2.Property;
67 import jalview.schemabinding.version2.RnaViewer;
68 import jalview.schemabinding.version2.SecondaryStructure;
69 import jalview.schemabinding.version2.Sequence;
70 import jalview.schemabinding.version2.SequenceSet;
71 import jalview.schemabinding.version2.SequenceSetProperties;
72 import jalview.schemabinding.version2.Setting;
73 import jalview.schemabinding.version2.StructureState;
74 import jalview.schemabinding.version2.ThresholdLine;
75 import jalview.schemabinding.version2.Tree;
76 import jalview.schemabinding.version2.UserColours;
77 import jalview.schemabinding.version2.Viewport;
78 import jalview.schemes.AnnotationColourGradient;
79 import jalview.schemes.ColourSchemeI;
80 import jalview.schemes.ColourSchemeProperty;
81 import jalview.schemes.FeatureColour;
82 import jalview.schemes.ResidueProperties;
83 import jalview.schemes.UserColourScheme;
84 import jalview.structure.StructureSelectionManager;
85 import jalview.structures.models.AAStructureBindingModel;
86 import jalview.util.MessageManager;
87 import jalview.util.Platform;
88 import jalview.util.StringUtils;
89 import jalview.util.jarInputStreamProvider;
90 import jalview.viewmodel.AlignmentViewport;
91 import jalview.viewmodel.ViewportRanges;
92 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
93 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
94 import jalview.ws.jws2.Jws2Discoverer;
95 import jalview.ws.jws2.dm.AAConSettings;
96 import jalview.ws.jws2.jabaws2.Jws2Instance;
97 import jalview.ws.params.ArgumentI;
98 import jalview.ws.params.AutoCalcSetting;
99 import jalview.ws.params.WsParamSetI;
101 import java.awt.Color;
102 import java.awt.Rectangle;
103 import java.io.BufferedReader;
104 import java.io.DataInputStream;
105 import java.io.DataOutputStream;
107 import java.io.FileInputStream;
108 import java.io.FileOutputStream;
109 import java.io.IOException;
110 import java.io.InputStreamReader;
111 import java.io.OutputStreamWriter;
112 import java.io.PrintWriter;
113 import java.lang.reflect.InvocationTargetException;
114 import java.net.MalformedURLException;
116 import java.util.ArrayList;
117 import java.util.Arrays;
118 import java.util.Enumeration;
119 import java.util.HashMap;
120 import java.util.HashSet;
121 import java.util.Hashtable;
122 import java.util.IdentityHashMap;
123 import java.util.Iterator;
124 import java.util.LinkedHashMap;
125 import java.util.List;
126 import java.util.Map;
127 import java.util.Map.Entry;
128 import java.util.Set;
129 import java.util.Vector;
130 import java.util.jar.JarEntry;
131 import java.util.jar.JarInputStream;
132 import java.util.jar.JarOutputStream;
134 import javax.swing.JInternalFrame;
135 import javax.swing.SwingUtilities;
137 import org.exolab.castor.xml.Marshaller;
138 import org.exolab.castor.xml.Unmarshaller;
141 * Write out the current jalview desktop state as a Jalview XML stream.
143 * Note: the vamsas objects referred to here are primitive versions of the
144 * VAMSAS project schema elements - they are not the same and most likely never
148 * @version $Revision: 1.134 $
150 public class Jalview2XML
152 private static final String VIEWER_PREFIX = "viewer_";
154 private static final String RNA_PREFIX = "rna_";
156 private static final String UTF_8 = "UTF-8";
158 // use this with nextCounter() to make unique names for entities
159 private int counter = 0;
162 * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
163 * of sequence objects are created.
165 IdentityHashMap<SequenceI, String> seqsToIds = null;
168 * jalview XML Sequence ID to jalview sequence object reference (both dataset
169 * and alignment sequences. Populated as XML reps of sequence objects are
172 Map<String, SequenceI> seqRefIds = null;
174 Map<String, SequenceI> incompleteSeqs = null;
176 List<SeqFref> frefedSequence = null;
178 boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
181 * Map of reconstructed AlignFrame objects that appear to have come from
182 * SplitFrame objects (have a dna/protein complement view).
184 private Map<Viewport, AlignFrame> splitFrameCandidates = new HashMap<>();
187 * Map from displayed rna structure models to their saved session state jar
190 private Map<RnaModel, String> rnaSessions = new HashMap<>();
193 * create/return unique hash string for sq
196 * @return new or existing unique string for sq
198 String seqHash(SequenceI sq)
200 if (seqsToIds == null)
204 if (seqsToIds.containsKey(sq))
206 return seqsToIds.get(sq);
210 // create sequential key
211 String key = "sq" + (seqsToIds.size() + 1);
212 key = makeHashCode(sq, key); // check we don't have an external reference
214 seqsToIds.put(sq, key);
221 if (seqsToIds == null)
223 seqsToIds = new IdentityHashMap<>();
225 if (seqRefIds == null)
227 seqRefIds = new HashMap<>();
229 if (incompleteSeqs == null)
231 incompleteSeqs = new HashMap<>();
233 if (frefedSequence == null)
235 frefedSequence = new ArrayList<>();
243 public Jalview2XML(boolean raiseGUI)
245 this.raiseGUI = raiseGUI;
249 * base class for resolving forward references to sequences by their ID
254 abstract class SeqFref
260 public SeqFref(String _sref, String type)
266 public String getSref()
271 public SequenceI getSrefSeq()
273 return seqRefIds.get(sref);
276 public boolean isResolvable()
278 return seqRefIds.get(sref) != null;
281 public SequenceI getSrefDatasetSeq()
283 SequenceI sq = seqRefIds.get(sref);
286 while (sq.getDatasetSequence() != null)
288 sq = sq.getDatasetSequence();
295 * @return true if the forward reference was fully resolved
297 abstract boolean resolve();
300 public String toString()
302 return type + " reference to " + sref;
307 * create forward reference for a mapping
313 public SeqFref newMappingRef(final String sref,
314 final jalview.datamodel.Mapping _jmap)
316 SeqFref fref = new SeqFref(sref, "Mapping")
318 public jalview.datamodel.Mapping jmap = _jmap;
323 SequenceI seq = getSrefDatasetSeq();
335 public SeqFref newAlcodMapRef(final String sref,
336 final AlignedCodonFrame _cf,
337 final jalview.datamodel.Mapping _jmap)
340 SeqFref fref = new SeqFref(sref, "Codon Frame")
342 AlignedCodonFrame cf = _cf;
344 public jalview.datamodel.Mapping mp = _jmap;
347 public boolean isResolvable()
349 return super.isResolvable() && mp.getTo() != null;
355 SequenceI seq = getSrefDatasetSeq();
360 cf.addMap(seq, mp.getTo(), mp.getMap());
367 public void resolveFrefedSequences()
369 Iterator<SeqFref> nextFref = frefedSequence.iterator();
370 int toresolve = frefedSequence.size();
371 int unresolved = 0, failedtoresolve = 0;
372 while (nextFref.hasNext())
374 SeqFref ref = nextFref.next();
375 if (ref.isResolvable())
387 } catch (Exception x)
390 "IMPLEMENTATION ERROR: Failed to resolve forward reference for sequence "
403 System.err.println("Jalview Project Import: There were " + unresolved
404 + " forward references left unresolved on the stack.");
406 if (failedtoresolve > 0)
408 System.err.println("SERIOUS! " + failedtoresolve
409 + " resolvable forward references failed to resolve.");
411 if (incompleteSeqs != null && incompleteSeqs.size() > 0)
414 "Jalview Project Import: There are " + incompleteSeqs.size()
415 + " sequences which may have incomplete metadata.");
416 if (incompleteSeqs.size() < 10)
418 for (SequenceI s : incompleteSeqs.values())
420 System.err.println(s.toString());
426 "Too many to report. Skipping output of incomplete sequences.");
432 * This maintains a map of viewports, the key being the seqSetId. Important to
433 * set historyItem and redoList for multiple views
435 Map<String, AlignViewport> viewportsAdded = new HashMap<>();
437 Map<String, AlignmentAnnotation> annotationIds = new HashMap<>();
439 String uniqueSetSuffix = "";
442 * List of pdbfiles added to Jar
444 List<String> pdbfiles = null;
446 // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
447 public void saveState(File statefile)
449 FileOutputStream fos = null;
452 fos = new FileOutputStream(statefile);
453 JarOutputStream jout = new JarOutputStream(fos);
456 } catch (Exception e)
458 // TODO: inform user of the problem - they need to know if their data was
460 if (errorMessage == null)
462 errorMessage = "Couldn't write Jalview Archive to output file '"
463 + statefile + "' - See console error log for details";
467 errorMessage += "(output file was '" + statefile + "')";
477 } catch (IOException e)
487 * Writes a jalview project archive to the given Jar output stream.
491 public void saveState(JarOutputStream jout)
493 AlignFrame[] frames = Desktop.getAlignFrames();
499 saveAllFrames(Arrays.asList(frames), jout);
503 * core method for storing state for a set of AlignFrames.
506 * - frames involving all data to be exported (including containing
509 * - project output stream
511 private void saveAllFrames(List<AlignFrame> frames, JarOutputStream jout)
513 Hashtable<String, AlignFrame> dsses = new Hashtable<>();
516 * ensure cached data is clear before starting
518 // todo tidy up seqRefIds, seqsToIds initialisation / reset
520 splitFrameCandidates.clear();
525 // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
526 // //////////////////////////////////////////////////
528 List<String> shortNames = new ArrayList<>();
529 List<String> viewIds = new ArrayList<>();
532 for (int i = frames.size() - 1; i > -1; i--)
534 AlignFrame af = frames.get(i);
536 if (skipList != null && skipList
537 .containsKey(af.getViewport().getSequenceSetId()))
542 String shortName = makeFilename(af, shortNames);
544 int ap, apSize = af.alignPanels.size();
546 for (ap = 0; ap < apSize; ap++)
548 AlignmentPanel apanel = af.alignPanels.get(ap);
549 String fileName = apSize == 1 ? shortName : ap + shortName;
550 if (!fileName.endsWith(".xml"))
552 fileName = fileName + ".xml";
555 saveState(apanel, fileName, jout, viewIds);
557 String dssid = getDatasetIdRef(
558 af.getViewport().getAlignment().getDataset());
559 if (!dsses.containsKey(dssid))
561 dsses.put(dssid, af);
566 writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix,
572 } catch (Exception foo)
577 } catch (Exception ex)
579 // TODO: inform user of the problem - they need to know if their data was
581 if (errorMessage == null)
583 errorMessage = "Couldn't write Jalview Archive - see error output for details";
585 ex.printStackTrace();
590 * Generates a distinct file name, based on the title of the AlignFrame, by
591 * appending _n for increasing n until an unused name is generated. The new
592 * name (without its extension) is added to the list.
596 * @return the generated name, with .xml extension
598 protected String makeFilename(AlignFrame af, List<String> namesUsed)
600 String shortName = af.getTitle();
602 if (shortName.indexOf(File.separatorChar) > -1)
604 shortName = shortName
605 .substring(shortName.lastIndexOf(File.separatorChar) + 1);
610 while (namesUsed.contains(shortName))
612 if (shortName.endsWith("_" + (count - 1)))
614 shortName = shortName.substring(0, shortName.lastIndexOf("_"));
617 shortName = shortName.concat("_" + count);
621 namesUsed.add(shortName);
623 if (!shortName.endsWith(".xml"))
625 shortName = shortName + ".xml";
630 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
631 public boolean saveAlignment(AlignFrame af, String jarFile,
636 FileOutputStream fos = new FileOutputStream(jarFile);
637 JarOutputStream jout = new JarOutputStream(fos);
638 List<AlignFrame> frames = new ArrayList<>();
640 // resolve splitframes
641 if (af.getViewport().getCodingComplement() != null)
643 frames = ((SplitFrame) af.getSplitViewContainer()).getAlignFrames();
649 saveAllFrames(frames, jout);
653 } catch (Exception foo)
659 } catch (Exception ex)
661 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
662 ex.printStackTrace();
667 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
668 String fileName, JarOutputStream jout)
671 for (String dssids : dsses.keySet())
673 AlignFrame _af = dsses.get(dssids);
674 String jfileName = fileName + " Dataset for " + _af.getTitle();
675 if (!jfileName.endsWith(".xml"))
677 jfileName = jfileName + ".xml";
679 saveState(_af.alignPanel, jfileName, true, jout, null);
684 * create a JalviewModel from an alignment view and marshall it to a
688 * panel to create jalview model for
690 * name of alignment panel written to output stream
697 public JalviewModel saveState(AlignmentPanel ap, String fileName,
698 JarOutputStream jout, List<String> viewIds)
700 return saveState(ap, fileName, false, jout, viewIds);
704 * create a JalviewModel from an alignment view and marshall it to a
708 * panel to create jalview model for
710 * name of alignment panel written to output stream
712 * when true, only write the dataset for the alignment, not the data
713 * associated with the view.
719 public JalviewModel saveState(AlignmentPanel ap, String fileName,
720 boolean storeDS, JarOutputStream jout, List<String> viewIds)
724 viewIds = new ArrayList<>();
729 List<UserColourScheme> userColours = new ArrayList<>();
731 AlignViewport av = ap.av;
732 ViewportRanges vpRanges = av.getRanges();
734 JalviewModel object = new JalviewModel();
735 object.setVamsasModel(new jalview.schemabinding.version2.VamsasModel());
737 object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
739 jalview.bin.Cache.getDefault("VERSION", "Development Build"));
742 * rjal is full height alignment, jal is actual alignment with full metadata
743 * but excludes hidden sequences.
745 jalview.datamodel.AlignmentI rjal = av.getAlignment(), jal = rjal;
747 if (av.hasHiddenRows())
749 rjal = jal.getHiddenSequences().getFullAlignment();
752 SequenceSet vamsasSet = new SequenceSet();
754 JalviewModelSequence jms = new JalviewModelSequence();
756 vamsasSet.setGapChar(jal.getGapCharacter() + "");
758 if (jal.getDataset() != null)
760 // dataset id is the dataset's hashcode
761 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
764 // switch jal and the dataset
765 jal = jal.getDataset();
769 if (jal.getProperties() != null)
771 Enumeration en = jal.getProperties().keys();
772 while (en.hasMoreElements())
774 String key = en.nextElement().toString();
775 SequenceSetProperties ssp = new SequenceSetProperties();
777 ssp.setValue(jal.getProperties().get(key).toString());
778 vamsasSet.addSequenceSetProperties(ssp);
783 Set<String> calcIdSet = new HashSet<>();
784 // record the set of vamsas sequence XML POJO we create.
785 HashMap<String, Sequence> vamsasSetIds = new HashMap<>();
787 for (final SequenceI jds : rjal.getSequences())
789 final SequenceI jdatasq = jds.getDatasetSequence() == null ? jds
790 : jds.getDatasetSequence();
791 String id = seqHash(jds);
792 if (vamsasSetIds.get(id) == null)
794 if (seqRefIds.get(id) != null && !storeDS)
796 // This happens for two reasons: 1. multiple views are being
798 // 2. the hashCode has collided with another sequence's code. This
800 // HAPPEN! (PF00072.15.stk does this)
801 // JBPNote: Uncomment to debug writing out of files that do not read
802 // back in due to ArrayOutOfBoundExceptions.
803 // System.err.println("vamsasSeq backref: "+id+"");
804 // System.err.println(jds.getName()+"
805 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
806 // System.err.println("Hashcode: "+seqHash(jds));
807 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
808 // System.err.println(rsq.getName()+"
809 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
810 // System.err.println("Hashcode: "+seqHash(rsq));
814 vamsasSeq = createVamsasSequence(id, jds);
815 vamsasSet.addSequence(vamsasSeq);
816 vamsasSetIds.put(id, vamsasSeq);
817 seqRefIds.put(id, jds);
821 jseq.setStart(jds.getStart());
822 jseq.setEnd(jds.getEnd());
823 jseq.setColour(av.getSequenceColour(jds).getRGB());
825 jseq.setId(id); // jseq id should be a string not a number
828 // Store any sequences this sequence represents
829 if (av.hasHiddenRows())
831 // use rjal, contains the full height alignment
833 av.getAlignment().getHiddenSequences().isHidden(jds));
835 if (av.isHiddenRepSequence(jds))
837 jalview.datamodel.SequenceI[] reps = av
838 .getRepresentedSequences(jds).getSequencesInOrder(rjal);
840 for (int h = 0; h < reps.length; h++)
844 jseq.addHiddenSequences(rjal.findIndex(reps[h]));
849 // mark sequence as reference - if it is the reference for this view
852 jseq.setViewreference(jds == jal.getSeqrep());
856 // TODO: omit sequence features from each alignment view's XML dump if we
857 // are storing dataset
858 List<jalview.datamodel.SequenceFeature> sfs = jds
859 .getSequenceFeatures();
860 for (SequenceFeature sf : sfs)
862 Features features = new Features();
864 features.setBegin(sf.getBegin());
865 features.setEnd(sf.getEnd());
866 features.setDescription(sf.getDescription());
867 features.setType(sf.getType());
868 features.setFeatureGroup(sf.getFeatureGroup());
869 features.setScore(sf.getScore());
870 if (sf.links != null)
872 for (int l = 0; l < sf.links.size(); l++)
874 OtherData keyValue = new OtherData();
875 keyValue.setKey("LINK_" + l);
876 keyValue.setValue(sf.links.elementAt(l).toString());
877 features.addOtherData(keyValue);
880 if (sf.otherDetails != null)
883 * save feature attributes, which may be simple strings or
884 * map valued (have sub-attributes)
886 for (Entry<String, Object> entry : sf.otherDetails.entrySet())
888 String key = entry.getKey();
889 Object value = entry.getValue();
890 if (value instanceof Map<?, ?>)
892 for (Entry<String, Object> subAttribute : ((Map<String, Object>) value)
895 OtherData otherData = new OtherData();
896 otherData.setKey(key);
897 otherData.setKey2(subAttribute.getKey());
898 otherData.setValue(subAttribute.getValue().toString());
899 features.addOtherData(otherData);
904 OtherData otherData = new OtherData();
905 otherData.setKey(key);
906 otherData.setValue(value.toString());
907 features.addOtherData(otherData);
912 jseq.addFeatures(features);
915 if (jdatasq.getAllPDBEntries() != null)
917 Enumeration en = jdatasq.getAllPDBEntries().elements();
918 while (en.hasMoreElements())
920 Pdbids pdb = new Pdbids();
921 jalview.datamodel.PDBEntry entry = (jalview.datamodel.PDBEntry) en
924 String pdbId = entry.getId();
926 pdb.setType(entry.getType());
929 * Store any structure views associated with this sequence. This
930 * section copes with duplicate entries in the project, so a dataset
931 * only view *should* be coped with sensibly.
933 // This must have been loaded, is it still visible?
934 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
935 String matchedFile = null;
936 for (int f = frames.length - 1; f > -1; f--)
938 if (frames[f] instanceof StructureViewerBase)
940 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
941 matchedFile = saveStructureState(ap, jds, pdb, entry, viewIds,
942 matchedFile, viewFrame);
944 * Only store each structure viewer's state once in the project
945 * jar. First time through only (storeDS==false)
947 String viewId = viewFrame.getViewId();
948 if (!storeDS && !viewIds.contains(viewId))
953 String viewerState = viewFrame.getStateInfo();
954 writeJarEntry(jout, getViewerJarEntryName(viewId),
955 viewerState.getBytes());
956 } catch (IOException e)
959 "Error saving viewer state: " + e.getMessage());
965 if (matchedFile != null || entry.getFile() != null)
967 if (entry.getFile() != null)
970 matchedFile = entry.getFile();
972 pdb.setFile(matchedFile); // entry.getFile());
973 if (pdbfiles == null)
975 pdbfiles = new ArrayList<>();
978 if (!pdbfiles.contains(pdbId))
981 copyFileToJar(jout, matchedFile, pdbId);
985 Enumeration<String> props = entry.getProperties();
986 if (props.hasMoreElements())
988 PdbentryItem item = new PdbentryItem();
989 while (props.hasMoreElements())
991 Property prop = new Property();
992 String key = props.nextElement();
994 prop.setValue(entry.getProperty(key).toString());
995 item.addProperty(prop);
997 pdb.addPdbentryItem(item);
1000 jseq.addPdbids(pdb);
1004 saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
1009 if (!storeDS && av.hasHiddenRows())
1011 jal = av.getAlignment();
1015 if (storeDS && jal.getCodonFrames() != null)
1017 List<AlignedCodonFrame> jac = jal.getCodonFrames();
1018 for (AlignedCodonFrame acf : jac)
1020 AlcodonFrame alc = new AlcodonFrame();
1021 if (acf.getProtMappings() != null
1022 && acf.getProtMappings().length > 0)
1024 boolean hasMap = false;
1025 SequenceI[] dnas = acf.getdnaSeqs();
1026 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1027 for (int m = 0; m < pmaps.length; m++)
1029 AlcodMap alcmap = new AlcodMap();
1030 alcmap.setDnasq(seqHash(dnas[m]));
1032 createVamsasMapping(pmaps[m], dnas[m], null, false));
1033 alc.addAlcodMap(alcmap);
1038 vamsasSet.addAlcodonFrame(alc);
1041 // TODO: delete this ? dead code from 2.8.3->2.9 ?
1043 // AlcodonFrame alc = new AlcodonFrame();
1044 // vamsasSet.addAlcodonFrame(alc);
1045 // for (int p = 0; p < acf.aaWidth; p++)
1047 // Alcodon cmap = new Alcodon();
1048 // if (acf.codons[p] != null)
1050 // // Null codons indicate a gapped column in the translated peptide
1052 // cmap.setPos1(acf.codons[p][0]);
1053 // cmap.setPos2(acf.codons[p][1]);
1054 // cmap.setPos3(acf.codons[p][2]);
1056 // alc.addAlcodon(cmap);
1058 // if (acf.getProtMappings() != null
1059 // && acf.getProtMappings().length > 0)
1061 // SequenceI[] dnas = acf.getdnaSeqs();
1062 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1063 // for (int m = 0; m < pmaps.length; m++)
1065 // AlcodMap alcmap = new AlcodMap();
1066 // alcmap.setDnasq(seqHash(dnas[m]));
1067 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
1069 // alc.addAlcodMap(alcmap);
1076 // /////////////////////////////////
1077 if (!storeDS && av.getCurrentTree() != null)
1079 // FIND ANY ASSOCIATED TREES
1080 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
1081 if (Desktop.desktop != null)
1083 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1085 for (int t = 0; t < frames.length; t++)
1087 if (frames[t] instanceof TreePanel)
1089 TreePanel tp = (TreePanel) frames[t];
1091 if (tp.treeCanvas.av.getAlignment() == jal)
1093 Tree tree = new Tree();
1094 tree.setTitle(tp.getTitle());
1095 tree.setCurrentTree((av.getCurrentTree() == tp.getTree()));
1096 tree.setNewick(tp.getTree().print());
1097 tree.setThreshold(tp.treeCanvas.threshold);
1099 tree.setFitToWindow(tp.fitToWindow.getState());
1100 tree.setFontName(tp.getTreeFont().getName());
1101 tree.setFontSize(tp.getTreeFont().getSize());
1102 tree.setFontStyle(tp.getTreeFont().getStyle());
1103 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
1105 tree.setShowBootstrap(tp.bootstrapMenu.getState());
1106 tree.setShowDistances(tp.distanceMenu.getState());
1108 tree.setHeight(tp.getHeight());
1109 tree.setWidth(tp.getWidth());
1110 tree.setXpos(tp.getX());
1111 tree.setYpos(tp.getY());
1112 tree.setId(makeHashCode(tp, null));
1122 * store forward refs from an annotationRow to any groups
1124 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<>();
1127 for (SequenceI sq : jal.getSequences())
1129 // Store annotation on dataset sequences only
1130 AlignmentAnnotation[] aa = sq.getAnnotation();
1131 if (aa != null && aa.length > 0)
1133 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1140 if (jal.getAlignmentAnnotation() != null)
1142 // Store the annotation shown on the alignment.
1143 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1144 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1149 if (jal.getGroups() != null)
1151 JGroup[] groups = new JGroup[jal.getGroups().size()];
1153 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1155 JGroup jGroup = new JGroup();
1156 groups[++i] = jGroup;
1158 jGroup.setStart(sg.getStartRes());
1159 jGroup.setEnd(sg.getEndRes());
1160 jGroup.setName(sg.getName());
1161 if (groupRefs.containsKey(sg))
1163 // group has references so set its ID field
1164 jGroup.setId(groupRefs.get(sg));
1166 ColourSchemeI colourScheme = sg.getColourScheme();
1167 if (colourScheme != null)
1169 ResidueShaderI groupColourScheme = sg.getGroupColourScheme();
1170 if (groupColourScheme.conservationApplied())
1172 jGroup.setConsThreshold(groupColourScheme.getConservationInc());
1174 if (colourScheme instanceof jalview.schemes.UserColourScheme)
1177 setUserColourScheme(colourScheme, userColours, jms));
1181 jGroup.setColour(colourScheme.getSchemeName());
1184 else if (colourScheme instanceof jalview.schemes.AnnotationColourGradient)
1186 jGroup.setColour("AnnotationColourGradient");
1187 jGroup.setAnnotationColours(constructAnnotationColours(
1188 (jalview.schemes.AnnotationColourGradient) colourScheme,
1191 else if (colourScheme instanceof jalview.schemes.UserColourScheme)
1194 setUserColourScheme(colourScheme, userColours, jms));
1198 jGroup.setColour(colourScheme.getSchemeName());
1201 jGroup.setPidThreshold(groupColourScheme.getThreshold());
1204 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1205 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1206 jGroup.setDisplayText(sg.getDisplayText());
1207 jGroup.setColourText(sg.getColourText());
1208 jGroup.setTextCol1(sg.textColour.getRGB());
1209 jGroup.setTextCol2(sg.textColour2.getRGB());
1210 jGroup.setTextColThreshold(sg.thresholdTextColour);
1211 jGroup.setShowUnconserved(sg.getShowNonconserved());
1212 jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1213 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1214 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1215 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1216 for (SequenceI seq : sg.getSequences())
1218 jGroup.addSeq(seqHash(seq));
1222 jms.setJGroup(groups);
1226 // /////////SAVE VIEWPORT
1227 Viewport view = new Viewport();
1228 view.setTitle(ap.alignFrame.getTitle());
1229 view.setSequenceSetId(
1230 makeHashCode(av.getSequenceSetId(), av.getSequenceSetId()));
1231 view.setId(av.getViewId());
1232 if (av.getCodingComplement() != null)
1234 view.setComplementId(av.getCodingComplement().getViewId());
1236 view.setViewName(av.viewName);
1237 view.setGatheredViews(av.isGatherViewsHere());
1239 Rectangle size = ap.av.getExplodedGeometry();
1240 Rectangle position = size;
1243 size = ap.alignFrame.getBounds();
1244 if (av.getCodingComplement() != null)
1246 position = ((SplitFrame) ap.alignFrame.getSplitViewContainer())
1254 view.setXpos(position.x);
1255 view.setYpos(position.y);
1257 view.setWidth(size.width);
1258 view.setHeight(size.height);
1260 view.setStartRes(vpRanges.getStartRes());
1261 view.setStartSeq(vpRanges.getStartSeq());
1263 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1265 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1269 .getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1271 AnnotationColours ac = constructAnnotationColours(
1272 (jalview.schemes.AnnotationColourGradient) av
1273 .getGlobalColourScheme(),
1276 view.setAnnotationColours(ac);
1277 view.setBgColour("AnnotationColourGradient");
1281 view.setBgColour(ColourSchemeProperty
1282 .getColourName(av.getGlobalColourScheme()));
1285 ResidueShaderI vcs = av.getResidueShading();
1286 ColourSchemeI cs = av.getGlobalColourScheme();
1290 if (vcs.conservationApplied())
1292 view.setConsThreshold(vcs.getConservationInc());
1293 if (cs instanceof jalview.schemes.UserColourScheme)
1295 view.setBgColour(setUserColourScheme(cs, userColours, jms));
1298 view.setPidThreshold(vcs.getThreshold());
1301 view.setConservationSelected(av.getConservationSelected());
1302 view.setPidSelected(av.getAbovePIDThreshold());
1303 view.setFontName(av.font.getName());
1304 view.setFontSize(av.font.getSize());
1305 view.setFontStyle(av.font.getStyle());
1306 view.setScaleProteinAsCdna(av.getViewStyle().isScaleProteinAsCdna());
1307 view.setRenderGaps(av.isRenderGaps());
1308 view.setShowAnnotation(av.isShowAnnotation());
1309 view.setShowBoxes(av.getShowBoxes());
1310 view.setShowColourText(av.getColourText());
1311 view.setShowFullId(av.getShowJVSuffix());
1312 view.setRightAlignIds(av.isRightAlignIds());
1313 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1314 view.setShowText(av.getShowText());
1315 view.setShowUnconserved(av.getShowUnconserved());
1316 view.setWrapAlignment(av.getWrapAlignment());
1317 view.setTextCol1(av.getTextColour().getRGB());
1318 view.setTextCol2(av.getTextColour2().getRGB());
1319 view.setTextColThreshold(av.getThresholdTextColour());
1320 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1321 view.setShowSequenceLogo(av.isShowSequenceLogo());
1322 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1323 view.setShowGroupConsensus(av.isShowGroupConsensus());
1324 view.setShowGroupConservation(av.isShowGroupConservation());
1325 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1326 view.setShowDbRefTooltip(av.isShowDBRefs());
1327 view.setFollowHighlight(av.isFollowHighlight());
1328 view.setFollowSelection(av.followSelection);
1329 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1330 if (av.getFeaturesDisplayed() != null)
1332 jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
1334 String[] renderOrder = ap.getSeqPanel().seqCanvas
1335 .getFeatureRenderer().getRenderOrder()
1336 .toArray(new String[0]);
1338 Vector<String> settingsAdded = new Vector<>();
1339 if (renderOrder != null)
1341 for (String featureType : renderOrder)
1343 FeatureColourI fcol = ap.getSeqPanel().seqCanvas
1344 .getFeatureRenderer().getFeatureStyle(featureType);
1345 Setting setting = new Setting();
1346 setting.setType(featureType);
1347 if (!fcol.isSimpleColour())
1349 setting.setColour(fcol.getMaxColour().getRGB());
1350 setting.setMincolour(fcol.getMinColour().getRGB());
1351 setting.setMin(fcol.getMin());
1352 setting.setMax(fcol.getMax());
1353 setting.setColourByLabel(fcol.isColourByLabel());
1354 setting.setAutoScale(fcol.isAutoScaled());
1355 setting.setThreshold(fcol.getThreshold());
1356 // -1 = No threshold, 0 = Below, 1 = Above
1357 setting.setThreshstate(fcol.isAboveThreshold() ? 1
1358 : (fcol.isBelowThreshold() ? 0 : -1));
1362 setting.setColour(fcol.getColour().getRGB());
1366 av.getFeaturesDisplayed().isVisible(featureType));
1367 float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1368 .getOrder(featureType);
1371 setting.setOrder(rorder);
1373 fs.addSetting(setting);
1374 settingsAdded.addElement(featureType);
1378 // is groups actually supposed to be a map here ?
1379 Iterator<String> en = ap.getSeqPanel().seqCanvas
1380 .getFeatureRenderer().getFeatureGroups().iterator();
1381 Vector<String> groupsAdded = new Vector<>();
1382 while (en.hasNext())
1384 String grp = en.next();
1385 if (groupsAdded.contains(grp))
1389 Group g = new Group();
1391 g.setDisplay(((Boolean) ap.getSeqPanel().seqCanvas
1392 .getFeatureRenderer().checkGroupVisibility(grp, false))
1395 groupsAdded.addElement(grp);
1397 jms.setFeatureSettings(fs);
1400 if (av.hasHiddenColumns())
1402 jalview.datamodel.HiddenColumns hidden = av.getAlignment()
1403 .getHiddenColumns();
1406 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1410 ArrayList<int[]> hiddenRegions = hidden.getHiddenColumnsCopy();
1411 for (int[] region : hiddenRegions)
1413 HiddenColumns hc = new HiddenColumns();
1414 hc.setStart(region[0]);
1415 hc.setEnd(region[1]);
1416 view.addHiddenColumns(hc);
1420 if (calcIdSet.size() > 0)
1422 for (String calcId : calcIdSet)
1424 if (calcId.trim().length() > 0)
1426 CalcIdParam cidp = createCalcIdParam(calcId, av);
1427 // Some calcIds have no parameters.
1430 view.addCalcIdParam(cidp);
1436 jms.addViewport(view);
1438 object.setJalviewModelSequence(jms);
1439 object.getVamsasModel().addSequenceSet(vamsasSet);
1441 if (jout != null && fileName != null)
1443 // We may not want to write the object to disk,
1444 // eg we can copy the alignViewport to a new view object
1445 // using save and then load
1448 System.out.println("Writing jar entry " + fileName);
1449 JarEntry entry = new JarEntry(fileName);
1450 jout.putNextEntry(entry);
1451 PrintWriter pout = new PrintWriter(
1452 new OutputStreamWriter(jout, UTF_8));
1453 Marshaller marshaller = new Marshaller(pout);
1454 marshaller.marshal(object);
1457 } catch (Exception ex)
1459 // TODO: raise error in GUI if marshalling failed.
1460 ex.printStackTrace();
1467 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1468 * for each viewer, with
1470 * <li>viewer geometry (position, size, split pane divider location)</li>
1471 * <li>index of the selected structure in the viewer (currently shows gapped
1473 * <li>the id of the annotation holding RNA secondary structure</li>
1474 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1476 * Varna viewer state is also written out (in native Varna XML) to separate
1477 * project jar entries. A separate entry is written for each RNA structure
1478 * displayed, with the naming convention
1480 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
1488 * @param storeDataset
1490 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
1491 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
1492 boolean storeDataset)
1494 if (Desktop.desktop == null)
1498 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1499 for (int f = frames.length - 1; f > -1; f--)
1501 if (frames[f] instanceof AppVarna)
1503 AppVarna varna = (AppVarna) frames[f];
1505 * link the sequence to every viewer that is showing it and is linked to
1506 * its alignment panel
1508 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1510 String viewId = varna.getViewId();
1511 RnaViewer rna = new RnaViewer();
1512 rna.setViewId(viewId);
1513 rna.setTitle(varna.getTitle());
1514 rna.setXpos(varna.getX());
1515 rna.setYpos(varna.getY());
1516 rna.setWidth(varna.getWidth());
1517 rna.setHeight(varna.getHeight());
1518 rna.setDividerLocation(varna.getDividerLocation());
1519 rna.setSelectedRna(varna.getSelectedIndex());
1520 jseq.addRnaViewer(rna);
1523 * Store each Varna panel's state once in the project per sequence.
1524 * First time through only (storeDataset==false)
1526 // boolean storeSessions = false;
1527 // String sequenceViewId = viewId + seqsToIds.get(jds);
1528 // if (!storeDataset && !viewIds.contains(sequenceViewId))
1530 // viewIds.add(sequenceViewId);
1531 // storeSessions = true;
1533 for (RnaModel model : varna.getModels())
1535 if (model.seq == jds)
1538 * VARNA saves each view (sequence or alignment secondary
1539 * structure, gapped or trimmed) as a separate XML file
1541 String jarEntryName = rnaSessions.get(model);
1542 if (jarEntryName == null)
1545 String varnaStateFile = varna.getStateInfo(model.rna);
1546 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
1547 copyFileToJar(jout, varnaStateFile, jarEntryName);
1548 rnaSessions.put(model, jarEntryName);
1550 SecondaryStructure ss = new SecondaryStructure();
1551 String annotationId = varna.getAnnotation(jds).annotationId;
1552 ss.setAnnotationId(annotationId);
1553 ss.setViewerState(jarEntryName);
1554 ss.setGapped(model.gapped);
1555 ss.setTitle(model.title);
1556 rna.addSecondaryStructure(ss);
1565 * Copy the contents of a file to a new entry added to the output jar
1569 * @param jarEntryName
1571 protected void copyFileToJar(JarOutputStream jout, String infilePath,
1572 String jarEntryName)
1574 DataInputStream dis = null;
1577 File file = new File(infilePath);
1578 if (file.exists() && jout != null)
1580 dis = new DataInputStream(new FileInputStream(file));
1581 byte[] data = new byte[(int) file.length()];
1582 dis.readFully(data);
1583 writeJarEntry(jout, jarEntryName, data);
1585 } catch (Exception ex)
1587 ex.printStackTrace();
1595 } catch (IOException e)
1604 * Write the data to a new entry of given name in the output jar file
1607 * @param jarEntryName
1609 * @throws IOException
1611 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
1612 byte[] data) throws IOException
1616 System.out.println("Writing jar entry " + jarEntryName);
1617 jout.putNextEntry(new JarEntry(jarEntryName));
1618 DataOutputStream dout = new DataOutputStream(jout);
1619 dout.write(data, 0, data.length);
1626 * Save the state of a structure viewer
1631 * the archive XML element under which to save the state
1634 * @param matchedFile
1638 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
1639 Pdbids pdb, PDBEntry entry, List<String> viewIds,
1640 String matchedFile, StructureViewerBase viewFrame)
1642 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
1645 * Look for any bindings for this viewer to the PDB file of interest
1646 * (including part matches excluding chain id)
1648 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
1650 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
1651 final String pdbId = pdbentry.getId();
1652 if (!pdbId.equals(entry.getId())
1653 && !(entry.getId().length() > 4 && entry.getId().toLowerCase()
1654 .startsWith(pdbId.toLowerCase())))
1657 * not interested in a binding to a different PDB entry here
1661 if (matchedFile == null)
1663 matchedFile = pdbentry.getFile();
1665 else if (!matchedFile.equals(pdbentry.getFile()))
1668 "Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
1669 + pdbentry.getFile());
1673 // can get at it if the ID
1674 // match is ambiguous (e.g.
1677 for (int smap = 0; smap < viewFrame.getBinding()
1678 .getSequence()[peid].length; smap++)
1680 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
1681 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
1683 StructureState state = new StructureState();
1684 state.setVisible(true);
1685 state.setXpos(viewFrame.getX());
1686 state.setYpos(viewFrame.getY());
1687 state.setWidth(viewFrame.getWidth());
1688 state.setHeight(viewFrame.getHeight());
1689 final String viewId = viewFrame.getViewId();
1690 state.setViewId(viewId);
1691 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
1692 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
1693 state.setColourByJmol(viewFrame.isColouredByViewer());
1694 state.setType(viewFrame.getViewerType().toString());
1695 pdb.addStructureState(state);
1703 * Populates the AnnotationColours xml for save. This captures the settings of
1704 * the options in the 'Colour by Annotation' dialog.
1707 * @param userColours
1711 private AnnotationColours constructAnnotationColours(
1712 AnnotationColourGradient acg, List<UserColourScheme> userColours,
1713 JalviewModelSequence jms)
1715 AnnotationColours ac = new AnnotationColours();
1716 ac.setAboveThreshold(acg.getAboveThreshold());
1717 ac.setThreshold(acg.getAnnotationThreshold());
1718 // 2.10.2 save annotationId (unique) not annotation label
1719 ac.setAnnotation(acg.getAnnotation().annotationId);
1720 if (acg.getBaseColour() instanceof UserColourScheme)
1723 setUserColourScheme(acg.getBaseColour(), userColours, jms));
1728 ColourSchemeProperty.getColourName(acg.getBaseColour()));
1731 ac.setMaxColour(acg.getMaxColour().getRGB());
1732 ac.setMinColour(acg.getMinColour().getRGB());
1733 ac.setPerSequence(acg.isSeqAssociated());
1734 ac.setPredefinedColours(acg.isPredefinedColours());
1738 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
1739 IdentityHashMap<SequenceGroup, String> groupRefs,
1740 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
1741 SequenceSet vamsasSet)
1744 for (int i = 0; i < aa.length; i++)
1746 Annotation an = new Annotation();
1748 AlignmentAnnotation annotation = aa[i];
1749 if (annotation.annotationId != null)
1751 annotationIds.put(annotation.annotationId, annotation);
1754 an.setId(annotation.annotationId);
1756 an.setVisible(annotation.visible);
1758 an.setDescription(annotation.description);
1760 if (annotation.sequenceRef != null)
1762 // 2.9 JAL-1781 xref on sequence id rather than name
1763 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
1765 if (annotation.groupRef != null)
1767 String groupIdr = groupRefs.get(annotation.groupRef);
1768 if (groupIdr == null)
1770 // make a locally unique String
1771 groupRefs.put(annotation.groupRef,
1772 groupIdr = ("" + System.currentTimeMillis()
1773 + annotation.groupRef.getName()
1774 + groupRefs.size()));
1776 an.setGroupRef(groupIdr.toString());
1779 // store all visualization attributes for annotation
1780 an.setGraphHeight(annotation.graphHeight);
1781 an.setCentreColLabels(annotation.centreColLabels);
1782 an.setScaleColLabels(annotation.scaleColLabel);
1783 an.setShowAllColLabels(annotation.showAllColLabels);
1784 an.setBelowAlignment(annotation.belowAlignment);
1786 if (annotation.graph > 0)
1789 an.setGraphType(annotation.graph);
1790 an.setGraphGroup(annotation.graphGroup);
1791 if (annotation.getThreshold() != null)
1793 ThresholdLine line = new ThresholdLine();
1794 line.setLabel(annotation.getThreshold().label);
1795 line.setValue(annotation.getThreshold().value);
1796 line.setColour(annotation.getThreshold().colour.getRGB());
1797 an.setThresholdLine(line);
1805 an.setLabel(annotation.label);
1807 if (annotation == av.getAlignmentQualityAnnot()
1808 || annotation == av.getAlignmentConservationAnnotation()
1809 || annotation == av.getAlignmentConsensusAnnotation()
1810 || annotation.autoCalculated)
1812 // new way of indicating autocalculated annotation -
1813 an.setAutoCalculated(annotation.autoCalculated);
1815 if (annotation.hasScore())
1817 an.setScore(annotation.getScore());
1820 if (annotation.getCalcId() != null)
1822 calcIdSet.add(annotation.getCalcId());
1823 an.setCalcId(annotation.getCalcId());
1825 if (annotation.hasProperties())
1827 for (String pr : annotation.getProperties())
1829 Property prop = new Property();
1831 prop.setValue(annotation.getProperty(pr));
1832 an.addProperty(prop);
1836 AnnotationElement ae;
1837 if (annotation.annotations != null)
1839 an.setScoreOnly(false);
1840 for (int a = 0; a < annotation.annotations.length; a++)
1842 if ((annotation == null) || (annotation.annotations[a] == null))
1847 ae = new AnnotationElement();
1848 if (annotation.annotations[a].description != null)
1850 ae.setDescription(annotation.annotations[a].description);
1852 if (annotation.annotations[a].displayCharacter != null)
1854 ae.setDisplayCharacter(
1855 annotation.annotations[a].displayCharacter);
1858 if (!Float.isNaN(annotation.annotations[a].value))
1860 ae.setValue(annotation.annotations[a].value);
1864 if (annotation.annotations[a].secondaryStructure > ' ')
1866 ae.setSecondaryStructure(
1867 annotation.annotations[a].secondaryStructure + "");
1870 if (annotation.annotations[a].colour != null
1871 && annotation.annotations[a].colour != java.awt.Color.black)
1873 ae.setColour(annotation.annotations[a].colour.getRGB());
1876 an.addAnnotationElement(ae);
1877 if (annotation.autoCalculated)
1879 // only write one non-null entry into the annotation row -
1880 // sufficient to get the visualization attributes necessary to
1888 an.setScoreOnly(true);
1890 if (!storeDS || (storeDS && !annotation.autoCalculated))
1892 // skip autocalculated annotation - these are only provided for
1894 vamsasSet.addAnnotation(an);
1900 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
1902 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
1903 if (settings != null)
1905 CalcIdParam vCalcIdParam = new CalcIdParam();
1906 vCalcIdParam.setCalcId(calcId);
1907 vCalcIdParam.addServiceURL(settings.getServiceURI());
1908 // generic URI allowing a third party to resolve another instance of the
1909 // service used for this calculation
1910 for (String urls : settings.getServiceURLs())
1912 vCalcIdParam.addServiceURL(urls);
1914 vCalcIdParam.setVersion("1.0");
1915 if (settings.getPreset() != null)
1917 WsParamSetI setting = settings.getPreset();
1918 vCalcIdParam.setName(setting.getName());
1919 vCalcIdParam.setDescription(setting.getDescription());
1923 vCalcIdParam.setName("");
1924 vCalcIdParam.setDescription("Last used parameters");
1926 // need to be able to recover 1) settings 2) user-defined presets or
1927 // recreate settings from preset 3) predefined settings provided by
1928 // service - or settings that can be transferred (or discarded)
1929 vCalcIdParam.setParameters(
1930 settings.getWsParamFile().replace("\n", "|\\n|"));
1931 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
1932 // todo - decide if updateImmediately is needed for any projects.
1934 return vCalcIdParam;
1939 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
1942 if (calcIdParam.getVersion().equals("1.0"))
1944 Jws2Instance service = Jws2Discoverer.getDiscoverer()
1945 .getPreferredServiceFor(calcIdParam.getServiceURL());
1946 if (service != null)
1948 WsParamSetI parmSet = null;
1951 parmSet = service.getParamStore().parseServiceParameterFile(
1952 calcIdParam.getName(), calcIdParam.getDescription(),
1953 calcIdParam.getServiceURL(),
1954 calcIdParam.getParameters().replace("|\\n|", "\n"));
1955 } catch (IOException x)
1957 warn("Couldn't parse parameter data for "
1958 + calcIdParam.getCalcId(), x);
1961 List<ArgumentI> argList = null;
1962 if (calcIdParam.getName().length() > 0)
1964 parmSet = service.getParamStore()
1965 .getPreset(calcIdParam.getName());
1966 if (parmSet != null)
1968 // TODO : check we have a good match with settings in AACon -
1969 // otherwise we'll need to create a new preset
1974 argList = parmSet.getArguments();
1977 AAConSettings settings = new AAConSettings(
1978 calcIdParam.isAutoUpdate(), service, parmSet, argList);
1979 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
1980 calcIdParam.isNeedsUpdate());
1985 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
1989 throw new Error(MessageManager.formatMessage(
1990 "error.unsupported_version_calcIdparam", new Object[]
1991 { calcIdParam.toString() }));
1995 * External mapping between jalview objects and objects yielding a valid and
1996 * unique object ID string. This is null for normal Jalview project IO, but
1997 * non-null when a jalview project is being read or written as part of a
2000 IdentityHashMap jv2vobj = null;
2003 * Construct a unique ID for jvobj using either existing bindings or if none
2004 * exist, the result of the hashcode call for the object.
2007 * jalview data object
2008 * @return unique ID for referring to jvobj
2010 private String makeHashCode(Object jvobj, String altCode)
2012 if (jv2vobj != null)
2014 Object id = jv2vobj.get(jvobj);
2017 return id.toString();
2019 // check string ID mappings
2020 if (jvids2vobj != null && jvobj instanceof String)
2022 id = jvids2vobj.get(jvobj);
2026 return id.toString();
2028 // give up and warn that something has gone wrong
2029 warn("Cannot find ID for object in external mapping : " + jvobj);
2035 * return local jalview object mapped to ID, if it exists
2039 * @return null or object bound to idcode
2041 private Object retrieveExistingObj(String idcode)
2043 if (idcode != null && vobj2jv != null)
2045 return vobj2jv.get(idcode);
2051 * binding from ID strings from external mapping table to jalview data model
2054 private Hashtable vobj2jv;
2056 private Sequence createVamsasSequence(String id, SequenceI jds)
2058 return createVamsasSequence(true, id, jds, null);
2061 private Sequence createVamsasSequence(boolean recurse, String id,
2062 SequenceI jds, SequenceI parentseq)
2064 Sequence vamsasSeq = new Sequence();
2065 vamsasSeq.setId(id);
2066 vamsasSeq.setName(jds.getName());
2067 vamsasSeq.setSequence(jds.getSequenceAsString());
2068 vamsasSeq.setDescription(jds.getDescription());
2069 jalview.datamodel.DBRefEntry[] dbrefs = null;
2070 if (jds.getDatasetSequence() != null)
2072 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
2076 // seqId==dsseqid so we can tell which sequences really are
2077 // dataset sequences only
2078 vamsasSeq.setDsseqid(id);
2079 dbrefs = jds.getDBRefs();
2080 if (parentseq == null)
2087 for (int d = 0; d < dbrefs.length; d++)
2089 DBRef dbref = new DBRef();
2090 dbref.setSource(dbrefs[d].getSource());
2091 dbref.setVersion(dbrefs[d].getVersion());
2092 dbref.setAccessionId(dbrefs[d].getAccessionId());
2093 if (dbrefs[d].hasMap())
2095 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
2097 dbref.setMapping(mp);
2099 vamsasSeq.addDBRef(dbref);
2105 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
2106 SequenceI parentseq, SequenceI jds, boolean recurse)
2109 if (jmp.getMap() != null)
2113 jalview.util.MapList mlst = jmp.getMap();
2114 List<int[]> r = mlst.getFromRanges();
2115 for (int[] range : r)
2117 MapListFrom mfrom = new MapListFrom();
2118 mfrom.setStart(range[0]);
2119 mfrom.setEnd(range[1]);
2120 mp.addMapListFrom(mfrom);
2122 r = mlst.getToRanges();
2123 for (int[] range : r)
2125 MapListTo mto = new MapListTo();
2126 mto.setStart(range[0]);
2127 mto.setEnd(range[1]);
2128 mp.addMapListTo(mto);
2130 mp.setMapFromUnit(mlst.getFromRatio());
2131 mp.setMapToUnit(mlst.getToRatio());
2132 if (jmp.getTo() != null)
2134 MappingChoice mpc = new MappingChoice();
2136 // check/create ID for the sequence referenced by getTo()
2139 SequenceI ps = null;
2140 if (parentseq != jmp.getTo()
2141 && parentseq.getDatasetSequence() != jmp.getTo())
2143 // chaining dbref rather than a handshaking one
2144 jmpid = seqHash(ps = jmp.getTo());
2148 jmpid = seqHash(ps = parentseq);
2150 mpc.setDseqFor(jmpid);
2151 if (!seqRefIds.containsKey(mpc.getDseqFor()))
2153 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2154 seqRefIds.put(mpc.getDseqFor(), ps);
2158 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2161 mp.setMappingChoice(mpc);
2167 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2168 List<UserColourScheme> userColours, JalviewModelSequence jms)
2171 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2172 boolean newucs = false;
2173 if (!userColours.contains(ucs))
2175 userColours.add(ucs);
2178 id = "ucs" + userColours.indexOf(ucs);
2181 // actually create the scheme's entry in the XML model
2182 java.awt.Color[] colours = ucs.getColours();
2183 jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
2184 jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
2186 for (int i = 0; i < colours.length; i++)
2188 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2189 col.setName(ResidueProperties.aa[i]);
2190 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2191 jbucs.addColour(col);
2193 if (ucs.getLowerCaseColours() != null)
2195 colours = ucs.getLowerCaseColours();
2196 for (int i = 0; i < colours.length; i++)
2198 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2199 col.setName(ResidueProperties.aa[i].toLowerCase());
2200 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2201 jbucs.addColour(col);
2206 uc.setUserColourScheme(jbucs);
2207 jms.addUserColours(uc);
2213 jalview.schemes.UserColourScheme getUserColourScheme(
2214 JalviewModelSequence jms, String id)
2216 UserColours[] uc = jms.getUserColours();
2217 UserColours colours = null;
2219 for (int i = 0; i < uc.length; i++)
2221 if (uc[i].getId().equals(id))
2229 java.awt.Color[] newColours = new java.awt.Color[24];
2231 for (int i = 0; i < 24; i++)
2233 newColours[i] = new java.awt.Color(Integer.parseInt(
2234 colours.getUserColourScheme().getColour(i).getRGB(), 16));
2237 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2240 if (colours.getUserColourScheme().getColourCount() > 24)
2242 newColours = new java.awt.Color[23];
2243 for (int i = 0; i < 23; i++)
2245 newColours[i] = new java.awt.Color(Integer.parseInt(
2246 colours.getUserColourScheme().getColour(i + 24).getRGB(),
2249 ucs.setLowerCaseColours(newColours);
2256 * contains last error message (if any) encountered by XML loader.
2258 String errorMessage = null;
2261 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2262 * exceptions are raised during project XML parsing
2264 public boolean attemptversion1parse = true;
2267 * Load a jalview project archive from a jar file
2270 * - HTTP URL or filename
2272 public AlignFrame loadJalviewAlign(final String file)
2275 jalview.gui.AlignFrame af = null;
2279 // create list to store references for any new Jmol viewers created
2280 newStructureViewers = new Vector<>();
2281 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2282 // Workaround is to make sure caller implements the JarInputStreamProvider
2284 // so we can re-open the jar input stream for each entry.
2286 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2287 af = loadJalviewAlign(jprovider);
2288 af.setMenusForViewport();
2290 } catch (MalformedURLException e)
2292 errorMessage = "Invalid URL format for '" + file + "'";
2298 SwingUtilities.invokeAndWait(new Runnable()
2303 setLoadingFinishedForNewStructureViewers();
2306 } catch (Exception x)
2308 System.err.println("Error loading alignment: " + x.getMessage());
2314 private jarInputStreamProvider createjarInputStreamProvider(
2315 final String file) throws MalformedURLException
2318 errorMessage = null;
2319 uniqueSetSuffix = null;
2321 viewportsAdded.clear();
2322 frefedSequence = null;
2324 if (file.startsWith("http://"))
2326 url = new URL(file);
2328 final URL _url = url;
2329 return new jarInputStreamProvider()
2333 public JarInputStream getJarInputStream() throws IOException
2337 return new JarInputStream(_url.openStream());
2341 return new JarInputStream(new FileInputStream(file));
2346 public String getFilename()
2354 * Recover jalview session from a jalview project archive. Caller may
2355 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2356 * themselves. Any null fields will be initialised with default values,
2357 * non-null fields are left alone.
2362 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2364 errorMessage = null;
2365 if (uniqueSetSuffix == null)
2367 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2369 if (seqRefIds == null)
2373 AlignFrame af = null, _af = null;
2374 IdentityHashMap<AlignmentI, AlignmentI> importedDatasets = new IdentityHashMap<>();
2375 Map<String, AlignFrame> gatherToThisFrame = new HashMap<>();
2376 final String file = jprovider.getFilename();
2379 JarInputStream jin = null;
2380 JarEntry jarentry = null;
2385 jin = jprovider.getJarInputStream();
2386 for (int i = 0; i < entryCount; i++)
2388 jarentry = jin.getNextJarEntry();
2391 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2393 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2394 JalviewModel object = new JalviewModel();
2396 Unmarshaller unmar = new Unmarshaller(object);
2397 unmar.setValidation(false);
2398 object = (JalviewModel) unmar.unmarshal(in);
2399 if (true) // !skipViewport(object))
2401 _af = loadFromObject(object, file, true, jprovider);
2402 if (_af != null && object.getJalviewModelSequence()
2403 .getViewportCount() > 0)
2407 // store a reference to the first view
2410 if (_af.viewport.isGatherViewsHere())
2412 // if this is a gathered view, keep its reference since
2413 // after gathering views, only this frame will remain
2415 gatherToThisFrame.put(_af.viewport.getSequenceSetId(), _af);
2417 // Save dataset to register mappings once all resolved
2418 importedDatasets.put(af.viewport.getAlignment().getDataset(),
2419 af.viewport.getAlignment().getDataset());
2424 else if (jarentry != null)
2426 // Some other file here.
2429 } while (jarentry != null);
2430 resolveFrefedSequences();
2431 } catch (IOException ex)
2433 ex.printStackTrace();
2434 errorMessage = "Couldn't locate Jalview XML file : " + file;
2436 "Exception whilst loading jalview XML file : " + ex + "\n");
2437 } catch (Exception ex)
2439 System.err.println("Parsing as Jalview Version 2 file failed.");
2440 ex.printStackTrace(System.err);
2441 if (attemptversion1parse)
2443 // Is Version 1 Jar file?
2446 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
2447 } catch (Exception ex2)
2449 System.err.println("Exception whilst loading as jalviewXMLV1:");
2450 ex2.printStackTrace();
2454 if (Desktop.instance != null)
2456 Desktop.instance.stopLoading();
2460 System.out.println("Successfully loaded archive file");
2463 ex.printStackTrace();
2466 "Exception whilst loading jalview XML file : " + ex + "\n");
2467 } catch (OutOfMemoryError e)
2469 // Don't use the OOM Window here
2470 errorMessage = "Out of memory loading jalview XML file";
2471 System.err.println("Out of memory whilst loading jalview XML file");
2472 e.printStackTrace();
2476 * Regather multiple views (with the same sequence set id) to the frame (if
2477 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2478 * views instead of separate frames. Note this doesn't restore a state where
2479 * some expanded views in turn have tabbed views - the last "first tab" read
2480 * in will play the role of gatherer for all.
2482 for (AlignFrame fr : gatherToThisFrame.values())
2484 Desktop.instance.gatherViews(fr);
2487 restoreSplitFrames();
2488 for (AlignmentI ds : importedDatasets.keySet())
2490 if (ds.getCodonFrames() != null)
2492 StructureSelectionManager
2493 .getStructureSelectionManager(Desktop.instance)
2494 .registerMappings(ds.getCodonFrames());
2497 if (errorMessage != null)
2502 if (Desktop.instance != null)
2504 Desktop.instance.stopLoading();
2511 * Try to reconstruct and display SplitFrame windows, where each contains
2512 * complementary dna and protein alignments. Done by pairing up AlignFrame
2513 * objects (created earlier) which have complementary viewport ids associated.
2515 protected void restoreSplitFrames()
2517 List<SplitFrame> gatherTo = new ArrayList<>();
2518 List<AlignFrame> addedToSplitFrames = new ArrayList<>();
2519 Map<String, AlignFrame> dna = new HashMap<>();
2522 * Identify the DNA alignments
2524 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2527 AlignFrame af = candidate.getValue();
2528 if (af.getViewport().getAlignment().isNucleotide())
2530 dna.put(candidate.getKey().getId(), af);
2535 * Try to match up the protein complements
2537 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2540 AlignFrame af = candidate.getValue();
2541 if (!af.getViewport().getAlignment().isNucleotide())
2543 String complementId = candidate.getKey().getComplementId();
2544 // only non-null complements should be in the Map
2545 if (complementId != null && dna.containsKey(complementId))
2547 final AlignFrame dnaFrame = dna.get(complementId);
2548 SplitFrame sf = createSplitFrame(dnaFrame, af);
2549 addedToSplitFrames.add(dnaFrame);
2550 addedToSplitFrames.add(af);
2551 dnaFrame.setMenusForViewport();
2552 af.setMenusForViewport();
2553 if (af.viewport.isGatherViewsHere())
2562 * Open any that we failed to pair up (which shouldn't happen!) as
2563 * standalone AlignFrame's.
2565 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2568 AlignFrame af = candidate.getValue();
2569 if (!addedToSplitFrames.contains(af))
2571 Viewport view = candidate.getKey();
2572 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
2574 af.setMenusForViewport();
2575 System.err.println("Failed to restore view " + view.getTitle()
2576 + " to split frame");
2581 * Gather back into tabbed views as flagged.
2583 for (SplitFrame sf : gatherTo)
2585 Desktop.instance.gatherViews(sf);
2588 splitFrameCandidates.clear();
2592 * Construct and display one SplitFrame holding DNA and protein alignments.
2595 * @param proteinFrame
2598 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
2599 AlignFrame proteinFrame)
2601 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
2602 String title = MessageManager.getString("label.linked_view_title");
2603 int width = (int) dnaFrame.getBounds().getWidth();
2604 int height = (int) (dnaFrame.getBounds().getHeight()
2605 + proteinFrame.getBounds().getHeight() + 50);
2608 * SplitFrame location is saved to both enclosed frames
2610 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
2611 Desktop.addInternalFrame(splitFrame, title, width, height);
2614 * And compute cDNA consensus (couldn't do earlier with consensus as
2615 * mappings were not yet present)
2617 proteinFrame.viewport.alignmentChanged(proteinFrame.alignPanel);
2623 * check errorMessage for a valid error message and raise an error box in the
2624 * GUI or write the current errorMessage to stderr and then clear the error
2627 protected void reportErrors()
2629 reportErrors(false);
2632 protected void reportErrors(final boolean saving)
2634 if (errorMessage != null)
2636 final String finalErrorMessage = errorMessage;
2639 javax.swing.SwingUtilities.invokeLater(new Runnable()
2644 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2646 "Error " + (saving ? "saving" : "loading")
2648 JvOptionPane.WARNING_MESSAGE);
2654 System.err.println("Problem loading Jalview file: " + errorMessage);
2657 errorMessage = null;
2660 Map<String, String> alreadyLoadedPDB = new HashMap<>();
2663 * when set, local views will be updated from view stored in JalviewXML
2664 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2665 * sync if this is set to true.
2667 private final boolean updateLocalViews = false;
2670 * Returns the path to a temporary file holding the PDB file for the given PDB
2671 * id. The first time of asking, searches for a file of that name in the
2672 * Jalview project jar, and copies it to a new temporary file. Any repeat
2673 * requests just return the path to the file previously created.
2679 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId,
2682 if (alreadyLoadedPDB.containsKey(pdbId))
2684 return alreadyLoadedPDB.get(pdbId).toString();
2687 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb",
2689 if (tempFile != null)
2691 alreadyLoadedPDB.put(pdbId, tempFile);
2697 * Copies the jar entry of given name to a new temporary file and returns the
2698 * path to the file, or null if the entry is not found.
2701 * @param jarEntryName
2703 * a prefix for the temporary file name, must be at least three
2706 * null or original file - so new file can be given the same suffix
2710 protected String copyJarEntry(jarInputStreamProvider jprovider,
2711 String jarEntryName, String prefix, String origFile)
2713 BufferedReader in = null;
2714 PrintWriter out = null;
2715 String suffix = ".tmp";
2716 if (origFile == null)
2718 origFile = jarEntryName;
2720 int sfpos = origFile.lastIndexOf(".");
2721 if (sfpos > -1 && sfpos < (origFile.length() - 3))
2723 suffix = "." + origFile.substring(sfpos + 1);
2727 JarInputStream jin = jprovider.getJarInputStream();
2729 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2730 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2731 * FileInputStream(jprovider)); }
2734 JarEntry entry = null;
2737 entry = jin.getNextJarEntry();
2738 } while (entry != null && !entry.getName().equals(jarEntryName));
2741 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
2742 File outFile = File.createTempFile(prefix, suffix);
2743 outFile.deleteOnExit();
2744 out = new PrintWriter(new FileOutputStream(outFile));
2747 while ((data = in.readLine()) != null)
2752 String t = outFile.getAbsolutePath();
2757 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
2759 } catch (Exception ex)
2761 ex.printStackTrace();
2769 } catch (IOException e)
2783 private class JvAnnotRow
2785 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2792 * persisted version of annotation row from which to take vis properties
2794 public jalview.datamodel.AlignmentAnnotation template;
2797 * original position of the annotation row in the alignment
2803 * Load alignment frame from jalview XML DOM object
2808 * filename source string
2809 * @param loadTreesAndStructures
2810 * when false only create Viewport
2812 * data source provider
2813 * @return alignment frame created from view stored in DOM
2815 AlignFrame loadFromObject(JalviewModel object, String file,
2816 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
2818 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
2819 Sequence[] vamsasSeq = vamsasSet.getSequence();
2821 JalviewModelSequence jms = object.getJalviewModelSequence();
2823 Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
2826 // ////////////////////////////////
2829 List<SequenceI> hiddenSeqs = null;
2831 List<SequenceI> tmpseqs = new ArrayList<>();
2833 boolean multipleView = false;
2834 SequenceI referenceseqForView = null;
2835 JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
2836 int vi = 0; // counter in vamsasSeq array
2837 for (int i = 0; i < jseqs.length; i++)
2839 String seqId = jseqs[i].getId();
2841 SequenceI tmpSeq = seqRefIds.get(seqId);
2844 if (!incompleteSeqs.containsKey(seqId))
2846 // may not need this check, but keep it for at least 2.9,1 release
2847 if (tmpSeq.getStart() != jseqs[i].getStart()
2848 || tmpSeq.getEnd() != jseqs[i].getEnd())
2851 "Warning JAL-2154 regression: updating start/end for sequence "
2852 + tmpSeq.toString() + " to " + jseqs[i]);
2857 incompleteSeqs.remove(seqId);
2859 if (vamsasSeq.length > vi && vamsasSeq[vi].getId().equals(seqId))
2861 // most likely we are reading a dataset XML document so
2862 // update from vamsasSeq section of XML for this sequence
2863 tmpSeq.setName(vamsasSeq[vi].getName());
2864 tmpSeq.setDescription(vamsasSeq[vi].getDescription());
2865 tmpSeq.setSequence(vamsasSeq[vi].getSequence());
2870 // reading multiple views, so vamsasSeq set is a subset of JSeq
2871 multipleView = true;
2873 tmpSeq.setStart(jseqs[i].getStart());
2874 tmpSeq.setEnd(jseqs[i].getEnd());
2875 tmpseqs.add(tmpSeq);
2879 tmpSeq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
2880 vamsasSeq[vi].getSequence());
2881 tmpSeq.setDescription(vamsasSeq[vi].getDescription());
2882 tmpSeq.setStart(jseqs[i].getStart());
2883 tmpSeq.setEnd(jseqs[i].getEnd());
2884 tmpSeq.setVamsasId(uniqueSetSuffix + seqId);
2885 seqRefIds.put(vamsasSeq[vi].getId(), tmpSeq);
2886 tmpseqs.add(tmpSeq);
2890 if (jseqs[i].hasViewreference() && jseqs[i].getViewreference())
2892 referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
2895 if (jseqs[i].getHidden())
2897 if (hiddenSeqs == null)
2899 hiddenSeqs = new ArrayList<>();
2902 hiddenSeqs.add(tmpSeq);
2907 // Create the alignment object from the sequence set
2908 // ///////////////////////////////
2909 SequenceI[] orderedSeqs = tmpseqs
2910 .toArray(new SequenceI[tmpseqs.size()]);
2912 AlignmentI al = null;
2913 // so we must create or recover the dataset alignment before going further
2914 // ///////////////////////////////
2915 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
2917 // older jalview projects do not have a dataset - so creat alignment and
2919 al = new Alignment(orderedSeqs);
2920 al.setDataset(null);
2924 boolean isdsal = object.getJalviewModelSequence()
2925 .getViewportCount() == 0;
2928 // we are importing a dataset record, so
2929 // recover reference to an alignment already materialsed as dataset
2930 al = getDatasetFor(vamsasSet.getDatasetId());
2934 // materialse the alignment
2935 al = new Alignment(orderedSeqs);
2939 addDatasetRef(vamsasSet.getDatasetId(), al);
2942 // finally, verify all data in vamsasSet is actually present in al
2943 // passing on flag indicating if it is actually a stored dataset
2944 recoverDatasetFor(vamsasSet, al, isdsal);
2947 if (referenceseqForView != null)
2949 al.setSeqrep(referenceseqForView);
2951 // / Add the alignment properties
2952 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
2954 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
2955 al.setProperty(ssp.getKey(), ssp.getValue());
2958 // ///////////////////////////////
2960 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
2963 // load sequence features, database references and any associated PDB
2964 // structures for the alignment
2966 // prior to 2.10, this part would only be executed the first time a
2967 // sequence was encountered, but not afterwards.
2968 // now, for 2.10 projects, this is also done if the xml doc includes
2969 // dataset sequences not actually present in any particular view.
2971 for (int i = 0; i < vamsasSeq.length; i++)
2973 if (jseqs[i].getFeaturesCount() > 0)
2975 Features[] features = jseqs[i].getFeatures();
2976 for (int f = 0; f < features.length; f++)
2978 SequenceFeature sf = new SequenceFeature(features[f].getType(),
2979 features[f].getDescription(), features[f].getBegin(),
2980 features[f].getEnd(), features[f].getScore(),
2981 features[f].getFeatureGroup());
2982 sf.setStatus(features[f].getStatus());
2985 * load any feature attributes - include map-valued attributes
2987 Map<String, Map<String, String>> mapAttributes = new HashMap<>();
2988 for (int od = 0; od < features[f].getOtherDataCount(); od++)
2990 OtherData keyValue = features[f].getOtherData(od);
2991 String attributeName = keyValue.getKey();
2992 String attributeValue = keyValue.getValue();
2993 if (attributeName.startsWith("LINK"))
2995 sf.addLink(attributeValue);
2999 String subAttribute = keyValue.getKey2();
3000 if (subAttribute == null)
3002 // simple string-valued attribute
3003 sf.setValue(attributeName, attributeValue);
3007 // attribute 'key' has sub-attribute 'key2'
3008 if (!mapAttributes.containsKey(attributeName))
3010 mapAttributes.put(attributeName, new HashMap<>());
3012 mapAttributes.get(attributeName).put(subAttribute,
3017 for (Entry<String, Map<String, String>> mapAttribute : mapAttributes
3020 sf.setValue(mapAttribute.getKey(), mapAttribute.getValue());
3023 // adds feature to datasequence's feature set (since Jalview 2.10)
3024 al.getSequenceAt(i).addSequenceFeature(sf);
3027 if (vamsasSeq[i].getDBRefCount() > 0)
3029 // adds dbrefs to datasequence's set (since Jalview 2.10)
3031 al.getSequenceAt(i).getDatasetSequence() == null
3032 ? al.getSequenceAt(i)
3033 : al.getSequenceAt(i).getDatasetSequence(),
3036 if (jseqs[i].getPdbidsCount() > 0)
3038 Pdbids[] ids = jseqs[i].getPdbids();
3039 for (int p = 0; p < ids.length; p++)
3041 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
3042 entry.setId(ids[p].getId());
3043 if (ids[p].getType() != null)
3045 if (PDBEntry.Type.getType(ids[p].getType()) != null)
3047 entry.setType(PDBEntry.Type.getType(ids[p].getType()));
3051 entry.setType(PDBEntry.Type.FILE);
3054 // jprovider is null when executing 'New View'
3055 if (ids[p].getFile() != null && jprovider != null)
3057 if (!pdbloaded.containsKey(ids[p].getFile()))
3059 entry.setFile(loadPDBFile(jprovider, ids[p].getId(),
3064 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
3067 if (ids[p].getPdbentryItem() != null)
3069 for (PdbentryItem item : ids[p].getPdbentryItem())
3071 for (Property pr : item.getProperty())
3073 entry.setProperty(pr.getName(), pr.getValue());
3077 StructureSelectionManager
3078 .getStructureSelectionManager(Desktop.instance)
3079 .registerPDBEntry(entry);
3080 // adds PDBEntry to datasequence's set (since Jalview 2.10)
3081 if (al.getSequenceAt(i).getDatasetSequence() != null)
3083 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
3087 al.getSequenceAt(i).addPDBId(entry);
3092 } // end !multipleview
3094 // ///////////////////////////////
3095 // LOAD SEQUENCE MAPPINGS
3097 if (vamsasSet.getAlcodonFrameCount() > 0)
3099 // TODO Potentially this should only be done once for all views of an
3101 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
3102 for (int i = 0; i < alc.length; i++)
3104 AlignedCodonFrame cf = new AlignedCodonFrame();
3105 if (alc[i].getAlcodMapCount() > 0)
3107 AlcodMap[] maps = alc[i].getAlcodMap();
3108 for (int m = 0; m < maps.length; m++)
3110 SequenceI dnaseq = seqRefIds.get(maps[m].getDnasq());
3112 jalview.datamodel.Mapping mapping = null;
3113 // attach to dna sequence reference.
3114 if (maps[m].getMapping() != null)
3116 mapping = addMapping(maps[m].getMapping());
3117 if (dnaseq != null && mapping.getTo() != null)
3119 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
3125 newAlcodMapRef(maps[m].getDnasq(), cf, mapping));
3129 al.addCodonFrame(cf);
3134 // ////////////////////////////////
3136 List<JvAnnotRow> autoAlan = new ArrayList<>();
3139 * store any annotations which forward reference a group's ID
3141 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<>();
3143 if (vamsasSet.getAnnotationCount() > 0)
3145 Annotation[] an = vamsasSet.getAnnotation();
3147 for (int i = 0; i < an.length; i++)
3149 Annotation annotation = an[i];
3152 * test if annotation is automatically calculated for this view only
3154 boolean autoForView = false;
3155 if (annotation.getLabel().equals("Quality")
3156 || annotation.getLabel().equals("Conservation")
3157 || annotation.getLabel().equals("Consensus"))
3159 // Kludge for pre 2.5 projects which lacked the autocalculated flag
3161 if (!annotation.hasAutoCalculated())
3163 annotation.setAutoCalculated(true);
3166 if (autoForView || (annotation.hasAutoCalculated()
3167 && annotation.isAutoCalculated()))
3169 // remove ID - we don't recover annotation from other views for
3170 // view-specific annotation
3171 annotation.setId(null);
3174 // set visiblity for other annotation in this view
3175 String annotationId = annotation.getId();
3176 if (annotationId != null && annotationIds.containsKey(annotationId))
3178 AlignmentAnnotation jda = annotationIds.get(annotationId);
3179 // in principle Visible should always be true for annotation displayed
3180 // in multiple views
3181 if (annotation.hasVisible())
3183 jda.visible = annotation.getVisible();
3186 al.addAnnotation(jda);
3190 // Construct new annotation from model.
3191 AnnotationElement[] ae = annotation.getAnnotationElement();
3192 jalview.datamodel.Annotation[] anot = null;
3193 java.awt.Color firstColour = null;
3195 if (!annotation.getScoreOnly())
3197 anot = new jalview.datamodel.Annotation[al.getWidth()];
3198 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
3200 anpos = ae[aa].getPosition();
3202 if (anpos >= anot.length)
3207 anot[anpos] = new jalview.datamodel.Annotation(
3209 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
3210 (ae[aa].getSecondaryStructure() == null
3211 || ae[aa].getSecondaryStructure().length() == 0)
3213 : ae[aa].getSecondaryStructure()
3218 // JBPNote: Consider verifying dataflow for IO of secondary
3219 // structure annotation read from Stockholm files
3220 // this was added to try to ensure that
3221 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
3223 // anot[ae[aa].getPosition()].displayCharacter = "";
3225 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
3226 if (firstColour == null)
3228 firstColour = anot[anpos].colour;
3232 jalview.datamodel.AlignmentAnnotation jaa = null;
3234 if (annotation.getGraph())
3236 float llim = 0, hlim = 0;
3237 // if (autoForView || an[i].isAutoCalculated()) {
3240 jaa = new jalview.datamodel.AlignmentAnnotation(
3241 annotation.getLabel(), annotation.getDescription(), anot,
3242 llim, hlim, annotation.getGraphType());
3244 jaa.graphGroup = annotation.getGraphGroup();
3245 jaa._linecolour = firstColour;
3246 if (annotation.getThresholdLine() != null)
3248 jaa.setThreshold(new jalview.datamodel.GraphLine(
3249 annotation.getThresholdLine().getValue(),
3250 annotation.getThresholdLine().getLabel(),
3252 annotation.getThresholdLine().getColour())));
3255 if (autoForView || annotation.isAutoCalculated())
3257 // Hardwire the symbol display line to ensure that labels for
3258 // histograms are displayed
3264 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
3265 an[i].getDescription(), anot);
3266 jaa._linecolour = firstColour;
3268 // register new annotation
3269 if (an[i].getId() != null)
3271 annotationIds.put(an[i].getId(), jaa);
3272 jaa.annotationId = an[i].getId();
3274 // recover sequence association
3275 String sequenceRef = an[i].getSequenceRef();
3276 if (sequenceRef != null)
3278 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3279 SequenceI sequence = seqRefIds.get(sequenceRef);
3280 if (sequence == null)
3282 // in pre-2.9 projects sequence ref is to sequence name
3283 sequence = al.findName(sequenceRef);
3285 if (sequence != null)
3287 jaa.createSequenceMapping(sequence, 1, true);
3288 sequence.addAlignmentAnnotation(jaa);
3291 // and make a note of any group association
3292 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
3294 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3295 .get(an[i].getGroupRef());
3298 aal = new ArrayList<>();
3299 groupAnnotRefs.put(an[i].getGroupRef(), aal);
3304 if (an[i].hasScore())
3306 jaa.setScore(an[i].getScore());
3308 if (an[i].hasVisible())
3310 jaa.visible = an[i].getVisible();
3313 if (an[i].hasCentreColLabels())
3315 jaa.centreColLabels = an[i].getCentreColLabels();
3318 if (an[i].hasScaleColLabels())
3320 jaa.scaleColLabel = an[i].getScaleColLabels();
3322 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
3324 // newer files have an 'autoCalculated' flag and store calculation
3325 // state in viewport properties
3326 jaa.autoCalculated = true; // means annotation will be marked for
3327 // update at end of load.
3329 if (an[i].hasGraphHeight())
3331 jaa.graphHeight = an[i].getGraphHeight();
3333 if (an[i].hasBelowAlignment())
3335 jaa.belowAlignment = an[i].isBelowAlignment();
3337 jaa.setCalcId(an[i].getCalcId());
3338 if (an[i].getPropertyCount() > 0)
3340 for (jalview.schemabinding.version2.Property prop : an[i]
3343 jaa.setProperty(prop.getName(), prop.getValue());
3346 if (jaa.autoCalculated)
3348 autoAlan.add(new JvAnnotRow(i, jaa));
3351 // if (!autoForView)
3353 // add autocalculated group annotation and any user created annotation
3355 al.addAnnotation(jaa);
3359 // ///////////////////////
3361 // Create alignment markup and styles for this view
3362 if (jms.getJGroupCount() > 0)
3364 JGroup[] groups = jms.getJGroup();
3365 boolean addAnnotSchemeGroup = false;
3366 for (int i = 0; i < groups.length; i++)
3368 JGroup jGroup = groups[i];
3369 ColourSchemeI cs = null;
3370 if (jGroup.getColour() != null)
3372 if (jGroup.getColour().startsWith("ucs"))
3374 cs = getUserColourScheme(jms, jGroup.getColour());
3376 else if (jGroup.getColour().equals("AnnotationColourGradient")
3377 && jGroup.getAnnotationColours() != null)
3379 addAnnotSchemeGroup = true;
3383 cs = ColourSchemeProperty.getColourScheme(al,
3384 jGroup.getColour());
3387 int pidThreshold = jGroup.getPidThreshold();
3389 Vector<SequenceI> seqs = new Vector<>();
3391 for (int s = 0; s < jGroup.getSeqCount(); s++)
3393 String seqId = jGroup.getSeq(s) + "";
3394 SequenceI ts = seqRefIds.get(seqId);
3398 seqs.addElement(ts);
3402 if (seqs.size() < 1)
3407 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3408 jGroup.getDisplayBoxes(), jGroup.getDisplayText(),
3409 jGroup.getColourText(), jGroup.getStart(), jGroup.getEnd());
3410 sg.getGroupColourScheme().setThreshold(pidThreshold, true);
3411 sg.getGroupColourScheme()
3412 .setConservationInc(jGroup.getConsThreshold());
3413 sg.setOutlineColour(new java.awt.Color(jGroup.getOutlineColour()));
3415 sg.textColour = new java.awt.Color(jGroup.getTextCol1());
3416 sg.textColour2 = new java.awt.Color(jGroup.getTextCol2());
3417 sg.setShowNonconserved(
3418 jGroup.hasShowUnconserved() ? jGroup.isShowUnconserved()
3420 sg.thresholdTextColour = jGroup.getTextColThreshold();
3421 if (jGroup.hasShowConsensusHistogram())
3423 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3426 if (jGroup.hasShowSequenceLogo())
3428 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3430 if (jGroup.hasNormaliseSequenceLogo())
3432 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3434 if (jGroup.hasIgnoreGapsinConsensus())
3436 sg.setIgnoreGapsConsensus(jGroup.getIgnoreGapsinConsensus());
3438 if (jGroup.getConsThreshold() != 0)
3440 Conservation c = new Conservation("All", sg.getSequences(null), 0,
3443 c.verdict(false, 25);
3444 sg.cs.setConservation(c);
3447 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3449 // re-instate unique group/annotation row reference
3450 List<AlignmentAnnotation> jaal = groupAnnotRefs
3451 .get(jGroup.getId());
3454 for (AlignmentAnnotation jaa : jaal)
3457 if (jaa.autoCalculated)
3459 // match up and try to set group autocalc alignment row for this
3461 if (jaa.label.startsWith("Consensus for "))
3463 sg.setConsensus(jaa);
3465 // match up and try to set group autocalc alignment row for this
3467 if (jaa.label.startsWith("Conservation for "))
3469 sg.setConservationRow(jaa);
3476 if (addAnnotSchemeGroup)
3478 // reconstruct the annotation colourscheme
3479 sg.setColourScheme(constructAnnotationColour(
3480 jGroup.getAnnotationColours(), null, al, jms, false));
3486 // only dataset in this model, so just return.
3489 // ///////////////////////////////
3492 // If we just load in the same jar file again, the sequenceSetId
3493 // will be the same, and we end up with multiple references
3494 // to the same sequenceSet. We must modify this id on load
3495 // so that each load of the file gives a unique id
3496 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3497 String viewId = (view.getId() == null ? null
3498 : view.getId() + uniqueSetSuffix);
3499 AlignFrame af = null;
3500 AlignViewport av = null;
3501 // now check to see if we really need to create a new viewport.
3502 if (multipleView && viewportsAdded.size() == 0)
3504 // We recovered an alignment for which a viewport already exists.
3505 // TODO: fix up any settings necessary for overlaying stored state onto
3506 // state recovered from another document. (may not be necessary).
3507 // we may need a binding from a viewport in memory to one recovered from
3509 // and then recover its containing af to allow the settings to be applied.
3510 // TODO: fix for vamsas demo
3512 "About to recover a viewport for existing alignment: Sequence set ID is "
3514 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3515 if (seqsetobj != null)
3517 if (seqsetobj instanceof String)
3519 uniqueSeqSetId = (String) seqsetobj;
3521 "Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
3527 "Warning : Collision between sequence set ID string and existing jalview object mapping.");
3533 * indicate that annotation colours are applied across all groups (pre
3534 * Jalview 2.8.1 behaviour)
3536 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan("2.8.1",
3537 object.getVersion());
3539 AlignmentPanel ap = null;
3540 boolean isnewview = true;
3543 // Check to see if this alignment already has a view id == viewId
3544 jalview.gui.AlignmentPanel views[] = Desktop
3545 .getAlignmentPanels(uniqueSeqSetId);
3546 if (views != null && views.length > 0)
3548 for (int v = 0; v < views.length; v++)
3550 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
3552 // recover the existing alignpanel, alignframe, viewport
3553 af = views[v].alignFrame;
3556 // TODO: could even skip resetting view settings if we don't want to
3557 // change the local settings from other jalview processes
3566 af = loadViewport(file, jseqs, hiddenSeqs, al, jms, view,
3567 uniqueSeqSetId, viewId, autoAlan);
3573 * Load any trees, PDB structures and viewers
3575 * Not done if flag is false (when this method is used for New View)
3577 if (loadTreesAndStructures)
3579 loadTrees(jms, view, af, av, ap);
3580 loadPDBStructures(jprovider, jseqs, af, ap);
3581 loadRnaViewers(jprovider, jseqs, ap);
3583 // and finally return.
3588 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
3589 * panel is restored from separate jar entries, two (gapped and trimmed) per
3590 * sequence and secondary structure.
3592 * Currently each viewer shows just one sequence and structure (gapped and
3593 * trimmed), however this method is designed to support multiple sequences or
3594 * structures in viewers if wanted in future.
3600 private void loadRnaViewers(jarInputStreamProvider jprovider,
3601 JSeq[] jseqs, AlignmentPanel ap)
3604 * scan the sequences for references to viewers; create each one the first
3605 * time it is referenced, add Rna models to existing viewers
3607 for (JSeq jseq : jseqs)
3609 for (int i = 0; i < jseq.getRnaViewerCount(); i++)
3611 RnaViewer viewer = jseq.getRnaViewer(i);
3612 AppVarna appVarna = findOrCreateVarnaViewer(viewer, uniqueSetSuffix,
3615 for (int j = 0; j < viewer.getSecondaryStructureCount(); j++)
3617 SecondaryStructure ss = viewer.getSecondaryStructure(j);
3618 SequenceI seq = seqRefIds.get(jseq.getId());
3619 AlignmentAnnotation ann = this.annotationIds
3620 .get(ss.getAnnotationId());
3623 * add the structure to the Varna display (with session state copied
3624 * from the jar to a temporary file)
3626 boolean gapped = ss.isGapped();
3627 String rnaTitle = ss.getTitle();
3628 String sessionState = ss.getViewerState();
3629 String tempStateFile = copyJarEntry(jprovider, sessionState,
3631 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
3632 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
3634 appVarna.setInitialSelection(viewer.getSelectedRna());
3640 * Locate and return an already instantiated matching AppVarna, or create one
3644 * @param viewIdSuffix
3648 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
3649 String viewIdSuffix, AlignmentPanel ap)
3652 * on each load a suffix is appended to the saved viewId, to avoid conflicts
3653 * if load is repeated
3655 String postLoadId = viewer.getViewId() + viewIdSuffix;
3656 for (JInternalFrame frame : getAllFrames())
3658 if (frame instanceof AppVarna)
3660 AppVarna varna = (AppVarna) frame;
3661 if (postLoadId.equals(varna.getViewId()))
3663 // this viewer is already instantiated
3664 // could in future here add ap as another 'parent' of the
3665 // AppVarna window; currently just 1-to-many
3672 * viewer not found - make it
3674 RnaViewerModel model = new RnaViewerModel(postLoadId, viewer.getTitle(),
3675 viewer.getXpos(), viewer.getYpos(), viewer.getWidth(),
3676 viewer.getHeight(), viewer.getDividerLocation());
3677 AppVarna varna = new AppVarna(model, ap);
3683 * Load any saved trees
3691 protected void loadTrees(JalviewModelSequence jms, Viewport view,
3692 AlignFrame af, AlignViewport av, AlignmentPanel ap)
3694 // TODO result of automated refactoring - are all these parameters needed?
3697 for (int t = 0; t < jms.getTreeCount(); t++)
3700 Tree tree = jms.getTree(t);
3702 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
3705 tp = af.showNewickTree(
3706 new jalview.io.NewickFile(tree.getNewick()),
3707 tree.getTitle(), tree.getWidth(), tree.getHeight(),
3708 tree.getXpos(), tree.getYpos());
3709 if (tree.getId() != null)
3711 // perhaps bind the tree id to something ?
3716 // update local tree attributes ?
3717 // TODO: should check if tp has been manipulated by user - if so its
3718 // settings shouldn't be modified
3719 tp.setTitle(tree.getTitle());
3720 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(),
3721 tree.getWidth(), tree.getHeight()));
3722 tp.av = av; // af.viewport; // TODO: verify 'associate with all
3725 tp.treeCanvas.av = av; // af.viewport;
3726 tp.treeCanvas.ap = ap; // af.alignPanel;
3731 warn("There was a problem recovering stored Newick tree: \n"
3732 + tree.getNewick());
3736 tp.fitToWindow.setState(tree.getFitToWindow());
3737 tp.fitToWindow_actionPerformed(null);
3739 if (tree.getFontName() != null)
3741 tp.setTreeFont(new java.awt.Font(tree.getFontName(),
3742 tree.getFontStyle(), tree.getFontSize()));
3746 tp.setTreeFont(new java.awt.Font(view.getFontName(),
3747 view.getFontStyle(), tree.getFontSize()));
3750 tp.showPlaceholders(tree.getMarkUnlinked());
3751 tp.showBootstrap(tree.getShowBootstrap());
3752 tp.showDistances(tree.getShowDistances());
3754 tp.treeCanvas.threshold = tree.getThreshold();
3756 if (tree.getCurrentTree())
3758 af.viewport.setCurrentTree(tp.getTree());
3762 } catch (Exception ex)
3764 ex.printStackTrace();
3769 * Load and link any saved structure viewers.
3776 protected void loadPDBStructures(jarInputStreamProvider jprovider,
3777 JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
3780 * Run through all PDB ids on the alignment, and collect mappings between
3781 * distinct view ids and all sequences referring to that view.
3783 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<>();
3785 for (int i = 0; i < jseqs.length; i++)
3787 if (jseqs[i].getPdbidsCount() > 0)
3789 Pdbids[] ids = jseqs[i].getPdbids();
3790 for (int p = 0; p < ids.length; p++)
3792 final int structureStateCount = ids[p].getStructureStateCount();
3793 for (int s = 0; s < structureStateCount; s++)
3795 // check to see if we haven't already created this structure view
3796 final StructureState structureState = ids[p]
3797 .getStructureState(s);
3798 String sviewid = (structureState.getViewId() == null) ? null
3799 : structureState.getViewId() + uniqueSetSuffix;
3800 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
3801 // Originally : ids[p].getFile()
3802 // : TODO: verify external PDB file recovery still works in normal
3803 // jalview project load
3804 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId(),
3806 jpdb.setId(ids[p].getId());
3808 int x = structureState.getXpos();
3809 int y = structureState.getYpos();
3810 int width = structureState.getWidth();
3811 int height = structureState.getHeight();
3813 // Probably don't need to do this anymore...
3814 // Desktop.desktop.getComponentAt(x, y);
3815 // TODO: NOW: check that this recovers the PDB file correctly.
3816 String pdbFile = loadPDBFile(jprovider, ids[p].getId(),
3818 jalview.datamodel.SequenceI seq = seqRefIds
3819 .get(jseqs[i].getId() + "");
3820 if (sviewid == null)
3822 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width + ","
3825 if (!structureViewers.containsKey(sviewid))
3827 structureViewers.put(sviewid,
3828 new StructureViewerModel(x, y, width, height, false,
3829 false, true, structureState.getViewId(),
3830 structureState.getType()));
3831 // Legacy pre-2.7 conversion JAL-823 :
3832 // do not assume any view has to be linked for colour by
3836 // assemble String[] { pdb files }, String[] { id for each
3837 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3838 // seqs_file 2}, boolean[] {
3839 // linkAlignPanel,superposeWithAlignpanel}} from hash
3840 StructureViewerModel jmoldat = structureViewers.get(sviewid);
3841 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
3842 | (structureState.hasAlignwithAlignPanel()
3843 ? structureState.getAlignwithAlignPanel()
3847 * Default colour by linked panel to false if not specified (e.g.
3848 * for pre-2.7 projects)
3850 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
3851 colourWithAlignPanel |= (structureState
3852 .hasColourwithAlignPanel()
3853 ? structureState.getColourwithAlignPanel()
3855 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
3858 * Default colour by viewer to true if not specified (e.g. for
3861 boolean colourByViewer = jmoldat.isColourByViewer();
3862 colourByViewer &= structureState.hasColourByJmol()
3863 ? structureState.getColourByJmol()
3865 jmoldat.setColourByViewer(colourByViewer);
3867 if (jmoldat.getStateData().length() < structureState
3868 .getContent().length())
3871 jmoldat.setStateData(structureState.getContent());
3874 if (ids[p].getFile() != null)
3876 File mapkey = new File(ids[p].getFile());
3877 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
3878 if (seqstrmaps == null)
3880 jmoldat.getFileData().put(mapkey,
3881 seqstrmaps = jmoldat.new StructureData(pdbFile,
3884 if (!seqstrmaps.getSeqList().contains(seq))
3886 seqstrmaps.getSeqList().add(seq);
3892 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");
3899 // Instantiate the associated structure views
3900 for (Entry<String, StructureViewerModel> entry : structureViewers
3905 createOrLinkStructureViewer(entry, af, ap, jprovider);
3906 } catch (Exception e)
3909 "Error loading structure viewer: " + e.getMessage());
3910 // failed - try the next one
3922 protected void createOrLinkStructureViewer(
3923 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3924 AlignmentPanel ap, jarInputStreamProvider jprovider)
3926 final StructureViewerModel stateData = viewerData.getValue();
3929 * Search for any viewer windows already open from other alignment views
3930 * that exactly match the stored structure state
3932 StructureViewerBase comp = findMatchingViewer(viewerData);
3936 linkStructureViewer(ap, comp, stateData);
3941 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
3942 * "viewer_"+stateData.viewId
3944 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
3946 createChimeraViewer(viewerData, af, jprovider);
3951 * else Jmol (if pre-2.9, stateData contains JMOL state string)
3953 createJmolViewer(viewerData, af, jprovider);
3958 * Create a new Chimera viewer.
3964 protected void createChimeraViewer(
3965 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3966 jarInputStreamProvider jprovider)
3968 StructureViewerModel data = viewerData.getValue();
3969 String chimeraSessionFile = data.getStateData();
3972 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
3974 * NB this is the 'saved' viewId as in the project file XML, _not_ the
3975 * 'uniquified' sviewid used to reconstruct the viewer here
3977 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
3978 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
3981 Set<Entry<File, StructureData>> fileData = data.getFileData()
3983 List<PDBEntry> pdbs = new ArrayList<>();
3984 List<SequenceI[]> allseqs = new ArrayList<>();
3985 for (Entry<File, StructureData> pdb : fileData)
3987 String filePath = pdb.getValue().getFilePath();
3988 String pdbId = pdb.getValue().getPdbId();
3989 // pdbs.add(new PDBEntry(filePath, pdbId));
3990 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
3991 final List<SequenceI> seqList = pdb.getValue().getSeqList();
3992 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
3996 boolean colourByChimera = data.isColourByViewer();
3997 boolean colourBySequence = data.isColourWithAlignPanel();
3999 // TODO use StructureViewer as a factory here, see JAL-1761
4000 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
4001 final SequenceI[][] seqsArray = allseqs
4002 .toArray(new SequenceI[allseqs.size()][]);
4003 String newViewId = viewerData.getKey();
4005 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
4006 af.alignPanel, pdbArray, seqsArray, colourByChimera,
4007 colourBySequence, newViewId);
4008 cvf.setSize(data.getWidth(), data.getHeight());
4009 cvf.setLocation(data.getX(), data.getY());
4013 * Create a new Jmol window. First parse the Jmol state to translate filenames
4014 * loaded into the view, and record the order in which files are shown in the
4015 * Jmol view, so we can add the sequence mappings in same order.
4021 protected void createJmolViewer(
4022 final Entry<String, StructureViewerModel> viewerData,
4023 AlignFrame af, jarInputStreamProvider jprovider)
4025 final StructureViewerModel svattrib = viewerData.getValue();
4026 String state = svattrib.getStateData();
4029 * Pre-2.9: state element value is the Jmol state string
4031 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
4034 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
4036 state = readJarEntry(jprovider,
4037 getViewerJarEntryName(svattrib.getViewId()));
4040 List<String> pdbfilenames = new ArrayList<>();
4041 List<SequenceI[]> seqmaps = new ArrayList<>();
4042 List<String> pdbids = new ArrayList<>();
4043 StringBuilder newFileLoc = new StringBuilder(64);
4044 int cp = 0, ncp, ecp;
4045 Map<File, StructureData> oldFiles = svattrib.getFileData();
4046 while ((ncp = state.indexOf("load ", cp)) > -1)
4050 // look for next filename in load statement
4051 newFileLoc.append(state.substring(cp,
4052 ncp = (state.indexOf("\"", ncp + 1) + 1)));
4053 String oldfilenam = state.substring(ncp,
4054 ecp = state.indexOf("\"", ncp));
4055 // recover the new mapping data for this old filename
4056 // have to normalize filename - since Jmol and jalview do
4058 // translation differently.
4059 StructureData filedat = oldFiles.get(new File(oldfilenam));
4060 if (filedat == null)
4062 String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\");
4063 filedat = oldFiles.get(new File(reformatedOldFilename));
4065 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
4066 pdbfilenames.add(filedat.getFilePath());
4067 pdbids.add(filedat.getPdbId());
4068 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4069 newFileLoc.append("\"");
4070 cp = ecp + 1; // advance beyond last \" and set cursor so we can
4071 // look for next file statement.
4072 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
4076 // just append rest of state
4077 newFileLoc.append(state.substring(cp));
4081 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
4082 newFileLoc = new StringBuilder(state);
4083 newFileLoc.append("; load append ");
4084 for (File id : oldFiles.keySet())
4086 // add this and any other pdb files that should be present in
4088 StructureData filedat = oldFiles.get(id);
4089 newFileLoc.append(filedat.getFilePath());
4090 pdbfilenames.add(filedat.getFilePath());
4091 pdbids.add(filedat.getPdbId());
4092 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4093 newFileLoc.append(" \"");
4094 newFileLoc.append(filedat.getFilePath());
4095 newFileLoc.append("\"");
4098 newFileLoc.append(";");
4101 if (newFileLoc.length() == 0)
4105 int histbug = newFileLoc.indexOf("history = ");
4109 * change "history = [true|false];" to "history = [1|0];"
4112 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
4113 String val = (diff == -1) ? null
4114 : newFileLoc.substring(histbug, diff);
4115 if (val != null && val.length() >= 4)
4117 if (val.contains("e")) // eh? what can it be?
4119 if (val.trim().equals("true"))
4127 newFileLoc.replace(histbug, diff, val);
4132 final String[] pdbf = pdbfilenames
4133 .toArray(new String[pdbfilenames.size()]);
4134 final String[] id = pdbids.toArray(new String[pdbids.size()]);
4135 final SequenceI[][] sq = seqmaps
4136 .toArray(new SequenceI[seqmaps.size()][]);
4137 final String fileloc = newFileLoc.toString();
4138 final String sviewid = viewerData.getKey();
4139 final AlignFrame alf = af;
4140 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
4141 svattrib.getWidth(), svattrib.getHeight());
4144 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
4149 JalviewStructureDisplayI sview = null;
4152 sview = new StructureViewer(
4153 alf.alignPanel.getStructureSelectionManager())
4154 .createView(StructureViewer.ViewerType.JMOL,
4155 pdbf, id, sq, alf.alignPanel, svattrib,
4156 fileloc, rect, sviewid);
4157 addNewStructureViewer(sview);
4158 } catch (OutOfMemoryError ex)
4160 new OOMWarning("restoring structure view for PDB id " + id,
4161 (OutOfMemoryError) ex.getCause());
4162 if (sview != null && sview.isVisible())
4164 sview.closeViewer(false);
4165 sview.setVisible(false);
4171 } catch (InvocationTargetException ex)
4173 warn("Unexpected error when opening Jmol view.", ex);
4175 } catch (InterruptedException e)
4177 // e.printStackTrace();
4183 * Generates a name for the entry in the project jar file to hold state
4184 * information for a structure viewer
4189 protected String getViewerJarEntryName(String viewId)
4191 return VIEWER_PREFIX + viewId;
4195 * Returns any open frame that matches given structure viewer data. The match
4196 * is based on the unique viewId, or (for older project versions) the frame's
4202 protected StructureViewerBase findMatchingViewer(
4203 Entry<String, StructureViewerModel> viewerData)
4205 final String sviewid = viewerData.getKey();
4206 final StructureViewerModel svattrib = viewerData.getValue();
4207 StructureViewerBase comp = null;
4208 JInternalFrame[] frames = getAllFrames();
4209 for (JInternalFrame frame : frames)
4211 if (frame instanceof StructureViewerBase)
4214 * Post jalview 2.4 schema includes structure view id
4216 if (sviewid != null && ((StructureViewerBase) frame).getViewId()
4219 comp = (StructureViewerBase) frame;
4220 break; // break added in 2.9
4223 * Otherwise test for matching position and size of viewer frame
4225 else if (frame.getX() == svattrib.getX()
4226 && frame.getY() == svattrib.getY()
4227 && frame.getHeight() == svattrib.getHeight()
4228 && frame.getWidth() == svattrib.getWidth())
4230 comp = (StructureViewerBase) frame;
4231 // no break in faint hope of an exact match on viewId
4239 * Link an AlignmentPanel to an existing structure viewer.
4244 * @param useinViewerSuperpos
4245 * @param usetoColourbyseq
4246 * @param viewerColouring
4248 protected void linkStructureViewer(AlignmentPanel ap,
4249 StructureViewerBase viewer, StructureViewerModel stateData)
4251 // NOTE: if the jalview project is part of a shared session then
4252 // view synchronization should/could be done here.
4254 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4255 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4256 final boolean viewerColouring = stateData.isColourByViewer();
4257 Map<File, StructureData> oldFiles = stateData.getFileData();
4260 * Add mapping for sequences in this view to an already open viewer
4262 final AAStructureBindingModel binding = viewer.getBinding();
4263 for (File id : oldFiles.keySet())
4265 // add this and any other pdb files that should be present in the
4267 StructureData filedat = oldFiles.get(id);
4268 String pdbFile = filedat.getFilePath();
4269 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4270 binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE,
4272 binding.addSequenceForStructFile(pdbFile, seq);
4274 // and add the AlignmentPanel's reference to the view panel
4275 viewer.addAlignmentPanel(ap);
4276 if (useinViewerSuperpos)
4278 viewer.useAlignmentPanelForSuperposition(ap);
4282 viewer.excludeAlignmentPanelForSuperposition(ap);
4284 if (usetoColourbyseq)
4286 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4290 viewer.excludeAlignmentPanelForColourbyseq(ap);
4295 * Get all frames within the Desktop.
4299 protected JInternalFrame[] getAllFrames()
4301 JInternalFrame[] frames = null;
4302 // TODO is this necessary - is it safe - risk of hanging?
4307 frames = Desktop.desktop.getAllFrames();
4308 } catch (ArrayIndexOutOfBoundsException e)
4310 // occasional No such child exceptions are thrown here...
4314 } catch (InterruptedException f)
4318 } while (frames == null);
4323 * Answers true if 'version' is equal to or later than 'supported', where each
4324 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4325 * changes. Development and test values for 'version' are leniently treated
4329 * - minimum version we are comparing against
4331 * - version of data being processsed
4334 public static boolean isVersionStringLaterThan(String supported,
4337 if (supported == null || version == null
4338 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4339 || version.equalsIgnoreCase("Test")
4340 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4342 System.err.println("Assuming project file with "
4343 + (version == null ? "null" : version)
4344 + " is compatible with Jalview version " + supported);
4349 return StringUtils.compareVersions(version, supported, "b") >= 0;
4353 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4355 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4357 if (newStructureViewers != null)
4359 sview.getBinding().setFinishedLoadingFromArchive(false);
4360 newStructureViewers.add(sview);
4364 protected void setLoadingFinishedForNewStructureViewers()
4366 if (newStructureViewers != null)
4368 for (JalviewStructureDisplayI sview : newStructureViewers)
4370 sview.getBinding().setFinishedLoadingFromArchive(true);
4372 newStructureViewers.clear();
4373 newStructureViewers = null;
4377 AlignFrame loadViewport(String file, JSeq[] JSEQ,
4378 List<SequenceI> hiddenSeqs, AlignmentI al,
4379 JalviewModelSequence jms, Viewport view, String uniqueSeqSetId,
4380 String viewId, List<JvAnnotRow> autoAlan)
4382 AlignFrame af = null;
4383 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
4384 uniqueSeqSetId, viewId);
4386 af.setFileName(file, FileFormat.Jalview);
4388 for (int i = 0; i < JSEQ.length; i++)
4390 af.viewport.setSequenceColour(
4391 af.viewport.getAlignment().getSequenceAt(i),
4392 new java.awt.Color(JSEQ[i].getColour()));
4397 af.getViewport().setColourByReferenceSeq(true);
4398 af.getViewport().setDisplayReferenceSeq(true);
4401 af.viewport.setGatherViewsHere(view.getGatheredViews());
4403 if (view.getSequenceSetId() != null)
4405 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4407 af.viewport.setSequenceSetId(uniqueSeqSetId);
4410 // propagate shared settings to this new view
4411 af.viewport.setHistoryList(av.getHistoryList());
4412 af.viewport.setRedoList(av.getRedoList());
4416 viewportsAdded.put(uniqueSeqSetId, af.viewport);
4418 // TODO: check if this method can be called repeatedly without
4419 // side-effects if alignpanel already registered.
4420 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4422 // apply Hidden regions to view.
4423 if (hiddenSeqs != null)
4425 for (int s = 0; s < JSEQ.length; s++)
4427 SequenceGroup hidden = new SequenceGroup();
4428 boolean isRepresentative = false;
4429 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
4431 isRepresentative = true;
4432 SequenceI sequenceToHide = al
4433 .getSequenceAt(JSEQ[s].getHiddenSequences(r));
4434 hidden.addSequence(sequenceToHide, false);
4435 // remove from hiddenSeqs list so we don't try to hide it twice
4436 hiddenSeqs.remove(sequenceToHide);
4438 if (isRepresentative)
4440 SequenceI representativeSequence = al.getSequenceAt(s);
4441 hidden.addSequence(representativeSequence, false);
4442 af.viewport.hideRepSequences(representativeSequence, hidden);
4446 SequenceI[] hseqs = hiddenSeqs
4447 .toArray(new SequenceI[hiddenSeqs.size()]);
4448 af.viewport.hideSequence(hseqs);
4451 // recover view properties and display parameters
4453 af.viewport.setShowAnnotation(view.getShowAnnotation());
4454 af.viewport.setAbovePIDThreshold(view.getPidSelected());
4455 af.viewport.setThreshold(view.getPidThreshold());
4457 af.viewport.setColourText(view.getShowColourText());
4459 af.viewport.setConservationSelected(view.getConservationSelected());
4460 af.viewport.setIncrement(view.getConsThreshold());
4461 af.viewport.setShowJVSuffix(view.getShowFullId());
4462 af.viewport.setRightAlignIds(view.getRightAlignIds());
4463 af.viewport.setFont(new java.awt.Font(view.getFontName(),
4464 view.getFontStyle(), view.getFontSize()), true);
4465 ViewStyleI vs = af.viewport.getViewStyle();
4466 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
4467 af.viewport.setViewStyle(vs);
4468 // TODO: allow custom charWidth/Heights to be restored by updating them
4469 // after setting font - which means set above to false
4470 af.viewport.setRenderGaps(view.getRenderGaps());
4471 af.viewport.setWrapAlignment(view.getWrapAlignment());
4472 af.viewport.setShowAnnotation(view.getShowAnnotation());
4474 af.viewport.setShowBoxes(view.getShowBoxes());
4476 af.viewport.setShowText(view.getShowText());
4478 af.viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
4479 af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
4480 af.viewport.setThresholdTextColour(view.getTextColThreshold());
4481 af.viewport.setShowUnconserved(
4482 view.hasShowUnconserved() ? view.isShowUnconserved() : false);
4483 af.viewport.getRanges().setStartRes(view.getStartRes());
4485 if (view.getViewName() != null)
4487 af.viewport.viewName = view.getViewName();
4488 af.setInitialTabVisible();
4490 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
4492 // startSeq set in af.alignPanel.updateLayout below
4493 af.alignPanel.updateLayout();
4494 ColourSchemeI cs = null;
4495 // apply colourschemes
4496 if (view.getBgColour() != null)
4498 if (view.getBgColour().startsWith("ucs"))
4500 cs = getUserColourScheme(jms, view.getBgColour());
4502 else if (view.getBgColour().startsWith("Annotation"))
4504 AnnotationColours viewAnnColour = view.getAnnotationColours();
4505 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
4512 cs = ColourSchemeProperty.getColourScheme(al, view.getBgColour());
4516 af.viewport.setGlobalColourScheme(cs);
4517 af.viewport.getResidueShading().setThreshold(view.getPidThreshold(),
4518 view.getIgnoreGapsinConsensus());
4519 af.viewport.getResidueShading()
4520 .setConsensus(af.viewport.getSequenceConsensusHash());
4521 af.viewport.setColourAppliesToAllGroups(false);
4523 if (view.getConservationSelected() && cs != null)
4525 af.viewport.getResidueShading()
4526 .setConservationInc(view.getConsThreshold());
4529 af.changeColour(cs);
4531 af.viewport.setColourAppliesToAllGroups(true);
4533 af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures());
4535 if (view.hasCentreColumnLabels())
4537 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
4539 if (view.hasIgnoreGapsinConsensus())
4541 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
4544 if (view.hasFollowHighlight())
4546 af.viewport.setFollowHighlight(view.getFollowHighlight());
4548 if (view.hasFollowSelection())
4550 af.viewport.followSelection = view.getFollowSelection();
4552 if (view.hasShowConsensusHistogram())
4555 .setShowConsensusHistogram(view.getShowConsensusHistogram());
4559 af.viewport.setShowConsensusHistogram(true);
4561 if (view.hasShowSequenceLogo())
4563 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
4567 af.viewport.setShowSequenceLogo(false);
4569 if (view.hasNormaliseSequenceLogo())
4571 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
4573 if (view.hasShowDbRefTooltip())
4575 af.viewport.setShowDBRefs(view.getShowDbRefTooltip());
4577 if (view.hasShowNPfeatureTooltip())
4579 af.viewport.setShowNPFeats(view.hasShowNPfeatureTooltip());
4581 if (view.hasShowGroupConsensus())
4583 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
4587 af.viewport.setShowGroupConsensus(false);
4589 if (view.hasShowGroupConservation())
4591 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
4595 af.viewport.setShowGroupConservation(false);
4598 // recover featre settings
4599 if (jms.getFeatureSettings() != null)
4601 FeaturesDisplayed fdi;
4602 af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
4603 String[] renderOrder = new String[jms.getFeatureSettings()
4604 .getSettingCount()];
4605 Map<String, FeatureColourI> featureColours = new Hashtable<>();
4606 Map<String, Float> featureOrder = new Hashtable<>();
4608 for (int fs = 0; fs < jms.getFeatureSettings()
4609 .getSettingCount(); fs++)
4611 Setting setting = jms.getFeatureSettings().getSetting(fs);
4612 if (setting.hasMincolour())
4614 FeatureColourI gc = setting.hasMin()
4615 ? new FeatureColour(new Color(setting.getMincolour()),
4616 new Color(setting.getColour()), setting.getMin(),
4618 : new FeatureColour(new Color(setting.getMincolour()),
4619 new Color(setting.getColour()), 0, 1);
4620 if (setting.hasThreshold())
4622 gc.setThreshold(setting.getThreshold());
4623 int threshstate = setting.getThreshstate();
4624 // -1 = None, 0 = Below, 1 = Above threshold
4625 if (threshstate == 0)
4627 gc.setBelowThreshold(true);
4629 else if (threshstate == 1)
4631 gc.setAboveThreshold(true);
4634 gc.setAutoScaled(true); // default
4635 if (setting.hasAutoScale())
4637 gc.setAutoScaled(setting.getAutoScale());
4639 if (setting.hasColourByLabel())
4641 gc.setColourByLabel(setting.getColourByLabel());
4643 // and put in the feature colour table.
4644 featureColours.put(setting.getType(), gc);
4648 featureColours.put(setting.getType(),
4649 new FeatureColour(new Color(setting.getColour())));
4651 renderOrder[fs] = setting.getType();
4652 if (setting.hasOrder())
4654 featureOrder.put(setting.getType(), setting.getOrder());
4658 featureOrder.put(setting.getType(), new Float(
4659 fs / jms.getFeatureSettings().getSettingCount()));
4661 if (setting.getDisplay())
4663 fdi.setVisible(setting.getType());
4666 Map<String, Boolean> fgtable = new Hashtable<>();
4667 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
4669 Group grp = jms.getFeatureSettings().getGroup(gs);
4670 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
4672 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4673 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
4674 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
4675 FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4676 fgtable, featureColours, 1.0f, featureOrder);
4677 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
4678 .transferSettings(frs);
4682 if (view.getHiddenColumnsCount() > 0)
4684 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
4686 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(),
4687 view.getHiddenColumns(c).getEnd() // +1
4691 if (view.getCalcIdParam() != null)
4693 for (CalcIdParam calcIdParam : view.getCalcIdParam())
4695 if (calcIdParam != null)
4697 if (recoverCalcIdParam(calcIdParam, af.viewport))
4702 warn("Couldn't recover parameters for "
4703 + calcIdParam.getCalcId());
4708 af.setMenusFromViewport(af.viewport);
4709 af.setTitle(view.getTitle());
4710 // TODO: we don't need to do this if the viewport is aready visible.
4712 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
4713 * has a 'cdna/protein complement' view, in which case save it in order to
4714 * populate a SplitFrame once all views have been read in.
4716 String complementaryViewId = view.getComplementId();
4717 if (complementaryViewId == null)
4719 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
4721 // recompute any autoannotation
4722 af.alignPanel.updateAnnotation(false, true);
4723 reorderAutoannotation(af, al, autoAlan);
4724 af.alignPanel.alignmentChanged();
4728 splitFrameCandidates.put(view, af);
4734 * Reads saved data to restore Colour by Annotation settings
4736 * @param viewAnnColour
4740 * @param checkGroupAnnColour
4743 private ColourSchemeI constructAnnotationColour(
4744 AnnotationColours viewAnnColour, AlignFrame af, AlignmentI al,
4745 JalviewModelSequence jms, boolean checkGroupAnnColour)
4747 boolean propagateAnnColour = false;
4748 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
4749 if (checkGroupAnnColour && al.getGroups() != null
4750 && al.getGroups().size() > 0)
4752 // pre 2.8.1 behaviour
4753 // check to see if we should transfer annotation colours
4754 propagateAnnColour = true;
4755 for (SequenceGroup sg : al.getGroups())
4757 if (sg.getColourScheme() instanceof AnnotationColourGradient)
4759 propagateAnnColour = false;
4765 * 2.10.2- : saved annotationId is AlignmentAnnotation.annotationId
4767 String annotationId = viewAnnColour.getAnnotation();
4768 AlignmentAnnotation matchedAnnotation = annotationIds.get(annotationId);
4771 * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
4773 if (matchedAnnotation == null
4774 && annAlignment.getAlignmentAnnotation() != null)
4776 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
4779 .equals(annAlignment.getAlignmentAnnotation()[i].label))
4781 matchedAnnotation = annAlignment.getAlignmentAnnotation()[i];
4786 if (matchedAnnotation == null)
4788 System.err.println("Failed to match annotation colour scheme for "
4792 if (matchedAnnotation.getThreshold() == null)
4794 matchedAnnotation.setThreshold(new GraphLine(
4795 viewAnnColour.getThreshold(), "Threshold", Color.black));
4798 AnnotationColourGradient cs = null;
4799 if (viewAnnColour.getColourScheme().equals("None"))
4801 cs = new AnnotationColourGradient(matchedAnnotation,
4802 new Color(viewAnnColour.getMinColour()),
4803 new Color(viewAnnColour.getMaxColour()),
4804 viewAnnColour.getAboveThreshold());
4806 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
4808 cs = new AnnotationColourGradient(matchedAnnotation,
4809 getUserColourScheme(jms, viewAnnColour.getColourScheme()),
4810 viewAnnColour.getAboveThreshold());
4814 cs = new AnnotationColourGradient(matchedAnnotation,
4815 ColourSchemeProperty.getColourScheme(al,
4816 viewAnnColour.getColourScheme()),
4817 viewAnnColour.getAboveThreshold());
4820 boolean perSequenceOnly = viewAnnColour.isPerSequence();
4821 boolean useOriginalColours = viewAnnColour.isPredefinedColours();
4822 cs.setSeqAssociated(perSequenceOnly);
4823 cs.setPredefinedColours(useOriginalColours);
4825 if (propagateAnnColour && al.getGroups() != null)
4827 // Also use these settings for all the groups
4828 for (int g = 0; g < al.getGroups().size(); g++)
4830 SequenceGroup sg = al.getGroups().get(g);
4831 if (sg.getGroupColourScheme() == null)
4836 AnnotationColourGradient groupScheme = new AnnotationColourGradient(
4837 matchedAnnotation, sg.getColourScheme(),
4838 viewAnnColour.getAboveThreshold());
4839 sg.setColourScheme(groupScheme);
4840 groupScheme.setSeqAssociated(perSequenceOnly);
4841 groupScheme.setPredefinedColours(useOriginalColours);
4847 private void reorderAutoannotation(AlignFrame af, AlignmentI al,
4848 List<JvAnnotRow> autoAlan)
4850 // copy over visualization settings for autocalculated annotation in the
4852 if (al.getAlignmentAnnotation() != null)
4855 * Kludge for magic autoannotation names (see JAL-811)
4857 String[] magicNames = new String[] { "Consensus", "Quality",
4859 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
4860 Hashtable<String, JvAnnotRow> visan = new Hashtable<>();
4861 for (String nm : magicNames)
4863 visan.put(nm, nullAnnot);
4865 for (JvAnnotRow auan : autoAlan)
4867 visan.put(auan.template.label
4868 + (auan.template.getCalcId() == null ? ""
4869 : "\t" + auan.template.getCalcId()),
4872 int hSize = al.getAlignmentAnnotation().length;
4873 List<JvAnnotRow> reorder = new ArrayList<>();
4874 // work through any autoCalculated annotation already on the view
4875 // removing it if it should be placed in a different location on the
4876 // annotation panel.
4877 List<String> remains = new ArrayList<>(visan.keySet());
4878 for (int h = 0; h < hSize; h++)
4880 jalview.datamodel.AlignmentAnnotation jalan = al
4881 .getAlignmentAnnotation()[h];
4882 if (jalan.autoCalculated)
4885 JvAnnotRow valan = visan.get(k = jalan.label);
4886 if (jalan.getCalcId() != null)
4888 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
4893 // delete the auto calculated row from the alignment
4894 al.deleteAnnotation(jalan, false);
4898 if (valan != nullAnnot)
4900 if (jalan != valan.template)
4902 // newly created autoannotation row instance
4903 // so keep a reference to the visible annotation row
4904 // and copy over all relevant attributes
4905 if (valan.template.graphHeight >= 0)
4908 jalan.graphHeight = valan.template.graphHeight;
4910 jalan.visible = valan.template.visible;
4912 reorder.add(new JvAnnotRow(valan.order, jalan));
4917 // Add any (possibly stale) autocalculated rows that were not appended to
4918 // the view during construction
4919 for (String other : remains)
4921 JvAnnotRow othera = visan.get(other);
4922 if (othera != nullAnnot && othera.template.getCalcId() != null
4923 && othera.template.getCalcId().length() > 0)
4925 reorder.add(othera);
4928 // now put the automatic annotation in its correct place
4929 int s = 0, srt[] = new int[reorder.size()];
4930 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
4931 for (JvAnnotRow jvar : reorder)
4934 srt[s++] = jvar.order;
4937 jalview.util.QuickSort.sort(srt, rws);
4938 // and re-insert the annotation at its correct position
4939 for (JvAnnotRow jvar : rws)
4941 al.addAnnotation(jvar.template, jvar.order);
4943 af.alignPanel.adjustAnnotationHeight();
4947 Hashtable skipList = null;
4950 * TODO remove this method
4953 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
4954 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
4955 * throw new Error("Implementation Error. No skipList defined for this
4956 * Jalview2XML instance."); } return (AlignFrame)
4957 * skipList.get(view.getSequenceSetId()); }
4961 * Check if the Jalview view contained in object should be skipped or not.
4964 * @return true if view's sequenceSetId is a key in skipList
4966 private boolean skipViewport(JalviewModel object)
4968 if (skipList == null)
4973 if (skipList.containsKey(
4974 id = object.getJalviewModelSequence().getViewport()[0]
4975 .getSequenceSetId()))
4977 if (Cache.log != null && Cache.log.isDebugEnabled())
4979 Cache.log.debug("Skipping seuqence set id " + id);
4986 public void addToSkipList(AlignFrame af)
4988 if (skipList == null)
4990 skipList = new Hashtable();
4992 skipList.put(af.getViewport().getSequenceSetId(), af);
4995 public void clearSkipList()
4997 if (skipList != null)
5004 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
5005 boolean ignoreUnrefed)
5007 jalview.datamodel.AlignmentI ds = getDatasetFor(
5008 vamsasSet.getDatasetId());
5009 Vector dseqs = null;
5012 // create a list of new dataset sequences
5013 dseqs = new Vector();
5015 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
5017 Sequence vamsasSeq = vamsasSet.getSequence(i);
5018 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
5020 // create a new dataset
5023 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
5024 dseqs.copyInto(dsseqs);
5025 ds = new jalview.datamodel.Alignment(dsseqs);
5026 debug("Created new dataset " + vamsasSet.getDatasetId()
5027 + " for alignment " + System.identityHashCode(al));
5028 addDatasetRef(vamsasSet.getDatasetId(), ds);
5030 // set the dataset for the newly imported alignment.
5031 if (al.getDataset() == null && !ignoreUnrefed)
5040 * sequence definition to create/merge dataset sequence for
5044 * vector to add new dataset sequence to
5045 * @param ignoreUnrefed
5046 * - when true, don't create new sequences from vamsasSeq if it's id
5047 * doesn't already have an asssociated Jalview sequence.
5049 * - used to reorder the sequence in the alignment according to the
5050 * vamsasSeq array ordering, to preserve ordering of dataset
5052 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
5053 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed, int vseqpos)
5055 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
5057 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
5058 boolean reorder = false;
5059 SequenceI dsq = null;
5060 if (sq != null && sq.getDatasetSequence() != null)
5062 dsq = sq.getDatasetSequence();
5068 if (sq == null && ignoreUnrefed)
5072 String sqid = vamsasSeq.getDsseqid();
5075 // need to create or add a new dataset sequence reference to this sequence
5078 dsq = seqRefIds.get(sqid);
5083 // make a new dataset sequence
5084 dsq = sq.createDatasetSequence();
5087 // make up a new dataset reference for this sequence
5088 sqid = seqHash(dsq);
5090 dsq.setVamsasId(uniqueSetSuffix + sqid);
5091 seqRefIds.put(sqid, dsq);
5096 dseqs.addElement(dsq);
5101 ds.addSequence(dsq);
5107 { // make this dataset sequence sq's dataset sequence
5108 sq.setDatasetSequence(dsq);
5109 // and update the current dataset alignment
5114 if (!dseqs.contains(dsq))
5121 if (ds.findIndex(dsq) < 0)
5123 ds.addSequence(dsq);
5130 // TODO: refactor this as a merge dataset sequence function
5131 // now check that sq (the dataset sequence) sequence really is the union of
5132 // all references to it
5133 // boolean pre = sq.getStart() < dsq.getStart();
5134 // boolean post = sq.getEnd() > dsq.getEnd();
5138 // StringBuffer sb = new StringBuffer();
5139 String newres = jalview.analysis.AlignSeq.extractGaps(
5140 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
5141 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
5142 && newres.length() > dsq.getLength())
5144 // Update with the longer sequence.
5148 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
5149 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
5150 * sb.append(newres.substring(newres.length() - sq.getEnd() -
5151 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
5153 dsq.setSequence(newres);
5155 // TODO: merges will never happen if we 'know' we have the real dataset
5156 // sequence - this should be detected when id==dssid
5158 "DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
5159 // + (pre ? "prepended" : "") + " "
5160 // + (post ? "appended" : ""));
5165 // sequence refs are identical. We may need to update the existing dataset
5166 // alignment with this one, though.
5167 if (ds != null && dseqs == null)
5169 int opos = ds.findIndex(dsq);
5170 SequenceI tseq = null;
5171 if (opos != -1 && vseqpos != opos)
5173 // remove from old position
5174 ds.deleteSequence(dsq);
5176 if (vseqpos < ds.getHeight())
5178 if (vseqpos != opos)
5180 // save sequence at destination position
5181 tseq = ds.getSequenceAt(vseqpos);
5182 ds.replaceSequenceAt(vseqpos, dsq);
5183 ds.addSequence(tseq);
5188 ds.addSequence(dsq);
5195 * TODO use AlignmentI here and in related methods - needs
5196 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
5198 Hashtable<String, AlignmentI> datasetIds = null;
5200 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
5202 private AlignmentI getDatasetFor(String datasetId)
5204 if (datasetIds == null)
5206 datasetIds = new Hashtable<>();
5209 if (datasetIds.containsKey(datasetId))
5211 return datasetIds.get(datasetId);
5216 private void addDatasetRef(String datasetId, AlignmentI dataset)
5218 if (datasetIds == null)
5220 datasetIds = new Hashtable<>();
5222 datasetIds.put(datasetId, dataset);
5226 * make a new dataset ID for this jalview dataset alignment
5231 private String getDatasetIdRef(AlignmentI dataset)
5233 if (dataset.getDataset() != null)
5235 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
5237 String datasetId = makeHashCode(dataset, null);
5238 if (datasetId == null)
5240 // make a new datasetId and record it
5241 if (dataset2Ids == null)
5243 dataset2Ids = new IdentityHashMap<>();
5247 datasetId = dataset2Ids.get(dataset);
5249 if (datasetId == null)
5251 datasetId = "ds" + dataset2Ids.size() + 1;
5252 dataset2Ids.put(dataset, datasetId);
5258 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5260 for (int d = 0; d < sequence.getDBRefCount(); d++)
5262 DBRef dr = sequence.getDBRef(d);
5263 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
5264 sequence.getDBRef(d).getSource(),
5265 sequence.getDBRef(d).getVersion(),
5266 sequence.getDBRef(d).getAccessionId());
5267 if (dr.getMapping() != null)
5269 entry.setMap(addMapping(dr.getMapping()));
5271 datasetSequence.addDBRef(entry);
5275 private jalview.datamodel.Mapping addMapping(Mapping m)
5277 SequenceI dsto = null;
5278 // Mapping m = dr.getMapping();
5279 int fr[] = new int[m.getMapListFromCount() * 2];
5280 Enumeration f = m.enumerateMapListFrom();
5281 for (int _i = 0; f.hasMoreElements(); _i += 2)
5283 MapListFrom mf = (MapListFrom) f.nextElement();
5284 fr[_i] = mf.getStart();
5285 fr[_i + 1] = mf.getEnd();
5287 int fto[] = new int[m.getMapListToCount() * 2];
5288 f = m.enumerateMapListTo();
5289 for (int _i = 0; f.hasMoreElements(); _i += 2)
5291 MapListTo mf = (MapListTo) f.nextElement();
5292 fto[_i] = mf.getStart();
5293 fto[_i + 1] = mf.getEnd();
5295 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto, fr,
5296 fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
5297 if (m.getMappingChoice() != null)
5299 MappingChoice mc = m.getMappingChoice();
5300 if (mc.getDseqFor() != null)
5302 String dsfor = "" + mc.getDseqFor();
5303 if (seqRefIds.containsKey(dsfor))
5308 jmap.setTo(seqRefIds.get(dsfor));
5312 frefedSequence.add(newMappingRef(dsfor, jmap));
5318 * local sequence definition
5320 Sequence ms = mc.getSequence();
5321 SequenceI djs = null;
5322 String sqid = ms.getDsseqid();
5323 if (sqid != null && sqid.length() > 0)
5326 * recover dataset sequence
5328 djs = seqRefIds.get(sqid);
5333 "Warning - making up dataset sequence id for DbRef sequence map reference");
5334 sqid = ((Object) ms).toString(); // make up a new hascode for
5335 // undefined dataset sequence hash
5336 // (unlikely to happen)
5342 * make a new dataset sequence and add it to refIds hash
5344 djs = new jalview.datamodel.Sequence(ms.getName(),
5346 djs.setStart(jmap.getMap().getToLowest());
5347 djs.setEnd(jmap.getMap().getToHighest());
5348 djs.setVamsasId(uniqueSetSuffix + sqid);
5350 incompleteSeqs.put(sqid, djs);
5351 seqRefIds.put(sqid, djs);
5354 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5364 * Provides a 'copy' of an alignment view (on action New View) by 'saving' the
5365 * view as XML (but not to file), and then reloading it
5370 public AlignmentPanel copyAlignPanel(AlignmentPanel ap)
5373 JalviewModel jm = saveState(ap, null, null, null);
5375 uniqueSetSuffix = "";
5376 jm.getJalviewModelSequence().getViewport(0).setId(null);
5377 // we don't overwrite the view we just copied
5379 if (this.frefedSequence == null)
5381 frefedSequence = new Vector<>();
5384 viewportsAdded.clear();
5386 AlignFrame af = loadFromObject(jm, null, false, null);
5387 af.alignPanels.clear();
5388 af.closeMenuItem_actionPerformed(true);
5391 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5392 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5393 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5394 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5395 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5398 return af.alignPanel;
5401 private Hashtable jvids2vobj;
5403 private void warn(String msg)
5408 private void warn(String msg, Exception e)
5410 if (Cache.log != null)
5414 Cache.log.warn(msg, e);
5418 Cache.log.warn(msg);
5423 System.err.println("Warning: " + msg);
5426 e.printStackTrace();
5431 private void debug(String string)
5433 debug(string, null);
5436 private void debug(String msg, Exception e)
5438 if (Cache.log != null)
5442 Cache.log.debug(msg, e);
5446 Cache.log.debug(msg);
5451 System.err.println("Warning: " + msg);
5454 e.printStackTrace();
5460 * set the object to ID mapping tables used to write/recover objects and XML
5461 * ID strings for the jalview project. If external tables are provided then
5462 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
5463 * object goes out of scope. - also populates the datasetIds hashtable with
5464 * alignment objects containing dataset sequences
5467 * Map from ID strings to jalview datamodel
5469 * Map from jalview datamodel to ID strings
5473 public void setObjectMappingTables(Hashtable vobj2jv,
5474 IdentityHashMap jv2vobj)
5476 this.jv2vobj = jv2vobj;
5477 this.vobj2jv = vobj2jv;
5478 Iterator ds = jv2vobj.keySet().iterator();
5480 while (ds.hasNext())
5482 Object jvobj = ds.next();
5483 id = jv2vobj.get(jvobj).toString();
5484 if (jvobj instanceof jalview.datamodel.Alignment)
5486 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
5488 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
5491 else if (jvobj instanceof jalview.datamodel.Sequence)
5493 // register sequence object so the XML parser can recover it.
5494 if (seqRefIds == null)
5496 seqRefIds = new HashMap<>();
5498 if (seqsToIds == null)
5500 seqsToIds = new IdentityHashMap<>();
5502 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
5503 seqsToIds.put((SequenceI) jvobj, id);
5505 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
5508 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
5509 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
5510 if (jvann.annotationId == null)
5512 jvann.annotationId = anid;
5514 if (!jvann.annotationId.equals(anid))
5516 // TODO verify that this is the correct behaviour
5517 this.warn("Overriding Annotation ID for " + anid
5518 + " from different id : " + jvann.annotationId);
5519 jvann.annotationId = anid;
5522 else if (jvobj instanceof String)
5524 if (jvids2vobj == null)
5526 jvids2vobj = new Hashtable();
5527 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
5532 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
5538 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
5539 * objects created from the project archive. If string is null (default for
5540 * construction) then suffix will be set automatically.
5544 public void setUniqueSetSuffix(String string)
5546 uniqueSetSuffix = string;
5551 * uses skipList2 as the skipList for skipping views on sequence sets
5552 * associated with keys in the skipList
5556 public void setSkipList(Hashtable skipList2)
5558 skipList = skipList2;
5562 * Reads the jar entry of given name and returns its contents, or null if the
5563 * entry is not found.
5566 * @param jarEntryName
5569 protected String readJarEntry(jarInputStreamProvider jprovider,
5570 String jarEntryName)
5572 String result = null;
5573 BufferedReader in = null;
5578 * Reopen the jar input stream and traverse its entries to find a matching
5581 JarInputStream jin = jprovider.getJarInputStream();
5582 JarEntry entry = null;
5585 entry = jin.getNextJarEntry();
5586 } while (entry != null && !entry.getName().equals(jarEntryName));
5590 StringBuilder out = new StringBuilder(256);
5591 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
5594 while ((data = in.readLine()) != null)
5598 result = out.toString();
5602 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
5604 } catch (Exception ex)
5606 ex.printStackTrace();
5614 } catch (IOException e)
5625 * Returns an incrementing counter (0, 1, 2...)
5629 private synchronized int nextCounter()