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 Iterator<String> keys = sf.otherDetails.keySet().iterator();
884 while (keys.hasNext())
887 OtherData keyValue = new OtherData();
888 keyValue.setKey(key);
889 keyValue.setValue(sf.otherDetails.get(key).toString());
890 features.addOtherData(keyValue);
894 jseq.addFeatures(features);
897 if (jdatasq.getAllPDBEntries() != null)
899 Enumeration en = jdatasq.getAllPDBEntries().elements();
900 while (en.hasMoreElements())
902 Pdbids pdb = new Pdbids();
903 jalview.datamodel.PDBEntry entry = (jalview.datamodel.PDBEntry) en
906 String pdbId = entry.getId();
908 pdb.setType(entry.getType());
911 * Store any structure views associated with this sequence. This
912 * section copes with duplicate entries in the project, so a dataset
913 * only view *should* be coped with sensibly.
915 // This must have been loaded, is it still visible?
916 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
917 String matchedFile = null;
918 for (int f = frames.length - 1; f > -1; f--)
920 if (frames[f] instanceof StructureViewerBase)
922 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
923 matchedFile = saveStructureState(ap, jds, pdb, entry, viewIds,
924 matchedFile, viewFrame);
926 * Only store each structure viewer's state once in the project
927 * jar. First time through only (storeDS==false)
929 String viewId = viewFrame.getViewId();
930 if (!storeDS && !viewIds.contains(viewId))
935 String viewerState = viewFrame.getStateInfo();
936 writeJarEntry(jout, getViewerJarEntryName(viewId),
937 viewerState.getBytes());
938 } catch (IOException e)
941 "Error saving viewer state: " + e.getMessage());
947 if (matchedFile != null || entry.getFile() != null)
949 if (entry.getFile() != null)
952 matchedFile = entry.getFile();
954 pdb.setFile(matchedFile); // entry.getFile());
955 if (pdbfiles == null)
957 pdbfiles = new ArrayList<>();
960 if (!pdbfiles.contains(pdbId))
963 copyFileToJar(jout, matchedFile, pdbId);
967 Enumeration<String> props = entry.getProperties();
968 if (props.hasMoreElements())
970 PdbentryItem item = new PdbentryItem();
971 while (props.hasMoreElements())
973 Property prop = new Property();
974 String key = props.nextElement();
976 prop.setValue(entry.getProperty(key).toString());
977 item.addProperty(prop);
979 pdb.addPdbentryItem(item);
986 saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
991 if (!storeDS && av.hasHiddenRows())
993 jal = av.getAlignment();
997 if (storeDS && jal.getCodonFrames() != null)
999 List<AlignedCodonFrame> jac = jal.getCodonFrames();
1000 for (AlignedCodonFrame acf : jac)
1002 AlcodonFrame alc = new AlcodonFrame();
1003 if (acf.getProtMappings() != null
1004 && acf.getProtMappings().length > 0)
1006 boolean hasMap = false;
1007 SequenceI[] dnas = acf.getdnaSeqs();
1008 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1009 for (int m = 0; m < pmaps.length; m++)
1011 AlcodMap alcmap = new AlcodMap();
1012 alcmap.setDnasq(seqHash(dnas[m]));
1014 createVamsasMapping(pmaps[m], dnas[m], null, false));
1015 alc.addAlcodMap(alcmap);
1020 vamsasSet.addAlcodonFrame(alc);
1023 // TODO: delete this ? dead code from 2.8.3->2.9 ?
1025 // AlcodonFrame alc = new AlcodonFrame();
1026 // vamsasSet.addAlcodonFrame(alc);
1027 // for (int p = 0; p < acf.aaWidth; p++)
1029 // Alcodon cmap = new Alcodon();
1030 // if (acf.codons[p] != null)
1032 // // Null codons indicate a gapped column in the translated peptide
1034 // cmap.setPos1(acf.codons[p][0]);
1035 // cmap.setPos2(acf.codons[p][1]);
1036 // cmap.setPos3(acf.codons[p][2]);
1038 // alc.addAlcodon(cmap);
1040 // if (acf.getProtMappings() != null
1041 // && acf.getProtMappings().length > 0)
1043 // SequenceI[] dnas = acf.getdnaSeqs();
1044 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1045 // for (int m = 0; m < pmaps.length; m++)
1047 // AlcodMap alcmap = new AlcodMap();
1048 // alcmap.setDnasq(seqHash(dnas[m]));
1049 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
1051 // alc.addAlcodMap(alcmap);
1058 // /////////////////////////////////
1059 if (!storeDS && av.currentTree != null)
1061 // FIND ANY ASSOCIATED TREES
1062 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
1063 if (Desktop.desktop != null)
1065 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1067 for (int t = 0; t < frames.length; t++)
1069 if (frames[t] instanceof TreePanel)
1071 TreePanel tp = (TreePanel) frames[t];
1073 if (tp.treeCanvas.av.getAlignment() == jal)
1075 Tree tree = new Tree();
1076 tree.setTitle(tp.getTitle());
1077 tree.setCurrentTree((av.currentTree == tp.getTree()));
1078 tree.setNewick(tp.getTree().print());
1079 tree.setThreshold(tp.treeCanvas.threshold);
1081 tree.setFitToWindow(tp.fitToWindow.getState());
1082 tree.setFontName(tp.getTreeFont().getName());
1083 tree.setFontSize(tp.getTreeFont().getSize());
1084 tree.setFontStyle(tp.getTreeFont().getStyle());
1085 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
1087 tree.setShowBootstrap(tp.bootstrapMenu.getState());
1088 tree.setShowDistances(tp.distanceMenu.getState());
1090 tree.setHeight(tp.getHeight());
1091 tree.setWidth(tp.getWidth());
1092 tree.setXpos(tp.getX());
1093 tree.setYpos(tp.getY());
1094 tree.setId(makeHashCode(tp, null));
1104 * store forward refs from an annotationRow to any groups
1106 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<>();
1109 for (SequenceI sq : jal.getSequences())
1111 // Store annotation on dataset sequences only
1112 AlignmentAnnotation[] aa = sq.getAnnotation();
1113 if (aa != null && aa.length > 0)
1115 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1122 if (jal.getAlignmentAnnotation() != null)
1124 // Store the annotation shown on the alignment.
1125 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1126 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1131 if (jal.getGroups() != null)
1133 JGroup[] groups = new JGroup[jal.getGroups().size()];
1135 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1137 JGroup jGroup = new JGroup();
1138 groups[++i] = jGroup;
1140 jGroup.setStart(sg.getStartRes());
1141 jGroup.setEnd(sg.getEndRes());
1142 jGroup.setName(sg.getName());
1143 if (groupRefs.containsKey(sg))
1145 // group has references so set its ID field
1146 jGroup.setId(groupRefs.get(sg));
1148 ColourSchemeI colourScheme = sg.getColourScheme();
1149 if (colourScheme != null)
1151 ResidueShaderI groupColourScheme = sg.getGroupColourScheme();
1152 if (groupColourScheme.conservationApplied())
1154 jGroup.setConsThreshold(groupColourScheme.getConservationInc());
1156 if (colourScheme instanceof jalview.schemes.UserColourScheme)
1159 setUserColourScheme(colourScheme, userColours, jms));
1163 jGroup.setColour(colourScheme.getSchemeName());
1166 else if (colourScheme instanceof jalview.schemes.AnnotationColourGradient)
1168 jGroup.setColour("AnnotationColourGradient");
1169 jGroup.setAnnotationColours(constructAnnotationColours(
1170 (jalview.schemes.AnnotationColourGradient) colourScheme,
1173 else if (colourScheme instanceof jalview.schemes.UserColourScheme)
1176 setUserColourScheme(colourScheme, userColours, jms));
1180 jGroup.setColour(colourScheme.getSchemeName());
1183 jGroup.setPidThreshold(groupColourScheme.getThreshold());
1186 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1187 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1188 jGroup.setDisplayText(sg.getDisplayText());
1189 jGroup.setColourText(sg.getColourText());
1190 jGroup.setTextCol1(sg.textColour.getRGB());
1191 jGroup.setTextCol2(sg.textColour2.getRGB());
1192 jGroup.setTextColThreshold(sg.thresholdTextColour);
1193 jGroup.setShowUnconserved(sg.getShowNonconserved());
1194 jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1195 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1196 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1197 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1198 for (SequenceI seq : sg.getSequences())
1200 jGroup.addSeq(seqHash(seq));
1204 jms.setJGroup(groups);
1208 // /////////SAVE VIEWPORT
1209 Viewport view = new Viewport();
1210 view.setTitle(ap.alignFrame.getTitle());
1211 view.setSequenceSetId(
1212 makeHashCode(av.getSequenceSetId(), av.getSequenceSetId()));
1213 view.setId(av.getViewId());
1214 if (av.getCodingComplement() != null)
1216 view.setComplementId(av.getCodingComplement().getViewId());
1218 view.setViewName(av.viewName);
1219 view.setGatheredViews(av.isGatherViewsHere());
1221 Rectangle size = ap.av.getExplodedGeometry();
1222 Rectangle position = size;
1225 size = ap.alignFrame.getBounds();
1226 if (av.getCodingComplement() != null)
1228 position = ((SplitFrame) ap.alignFrame.getSplitViewContainer())
1236 view.setXpos(position.x);
1237 view.setYpos(position.y);
1239 view.setWidth(size.width);
1240 view.setHeight(size.height);
1242 view.setStartRes(vpRanges.getStartRes());
1243 view.setStartSeq(vpRanges.getStartSeq());
1245 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1247 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1251 .getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1253 AnnotationColours ac = constructAnnotationColours(
1254 (jalview.schemes.AnnotationColourGradient) av
1255 .getGlobalColourScheme(),
1258 view.setAnnotationColours(ac);
1259 view.setBgColour("AnnotationColourGradient");
1263 view.setBgColour(ColourSchemeProperty
1264 .getColourName(av.getGlobalColourScheme()));
1267 ResidueShaderI vcs = av.getResidueShading();
1268 ColourSchemeI cs = av.getGlobalColourScheme();
1272 if (vcs.conservationApplied())
1274 view.setConsThreshold(vcs.getConservationInc());
1275 if (cs instanceof jalview.schemes.UserColourScheme)
1277 view.setBgColour(setUserColourScheme(cs, userColours, jms));
1280 view.setPidThreshold(vcs.getThreshold());
1283 view.setConservationSelected(av.getConservationSelected());
1284 view.setPidSelected(av.getAbovePIDThreshold());
1285 view.setFontName(av.font.getName());
1286 view.setFontSize(av.font.getSize());
1287 view.setFontStyle(av.font.getStyle());
1288 view.setScaleProteinAsCdna(av.getViewStyle().isScaleProteinAsCdna());
1289 view.setRenderGaps(av.isRenderGaps());
1290 view.setShowAnnotation(av.isShowAnnotation());
1291 view.setShowBoxes(av.getShowBoxes());
1292 view.setShowColourText(av.getColourText());
1293 view.setShowFullId(av.getShowJVSuffix());
1294 view.setRightAlignIds(av.isRightAlignIds());
1295 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1296 view.setShowText(av.getShowText());
1297 view.setShowUnconserved(av.getShowUnconserved());
1298 view.setWrapAlignment(av.getWrapAlignment());
1299 view.setTextCol1(av.getTextColour().getRGB());
1300 view.setTextCol2(av.getTextColour2().getRGB());
1301 view.setTextColThreshold(av.getThresholdTextColour());
1302 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1303 view.setShowSequenceLogo(av.isShowSequenceLogo());
1304 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1305 view.setShowGroupConsensus(av.isShowGroupConsensus());
1306 view.setShowGroupConservation(av.isShowGroupConservation());
1307 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1308 view.setShowDbRefTooltip(av.isShowDBRefs());
1309 view.setFollowHighlight(av.isFollowHighlight());
1310 view.setFollowSelection(av.followSelection);
1311 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1312 if (av.getFeaturesDisplayed() != null)
1314 jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
1316 String[] renderOrder = ap.getSeqPanel().seqCanvas
1317 .getFeatureRenderer().getRenderOrder()
1318 .toArray(new String[0]);
1320 Vector<String> settingsAdded = new Vector<>();
1321 if (renderOrder != null)
1323 for (String featureType : renderOrder)
1325 FeatureColourI fcol = ap.getSeqPanel().seqCanvas
1326 .getFeatureRenderer().getFeatureStyle(featureType);
1327 Setting setting = new Setting();
1328 setting.setType(featureType);
1329 if (!fcol.isSimpleColour())
1331 setting.setColour(fcol.getMaxColour().getRGB());
1332 setting.setMincolour(fcol.getMinColour().getRGB());
1333 setting.setMin(fcol.getMin());
1334 setting.setMax(fcol.getMax());
1335 setting.setColourByLabel(fcol.isColourByLabel());
1336 setting.setAutoScale(fcol.isAutoScaled());
1337 setting.setThreshold(fcol.getThreshold());
1338 // -1 = No threshold, 0 = Below, 1 = Above
1339 setting.setThreshstate(fcol.isAboveThreshold() ? 1
1340 : (fcol.isBelowThreshold() ? 0 : -1));
1344 setting.setColour(fcol.getColour().getRGB());
1348 av.getFeaturesDisplayed().isVisible(featureType));
1349 float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1350 .getOrder(featureType);
1353 setting.setOrder(rorder);
1355 fs.addSetting(setting);
1356 settingsAdded.addElement(featureType);
1360 // is groups actually supposed to be a map here ?
1361 Iterator<String> en = ap.getSeqPanel().seqCanvas
1362 .getFeatureRenderer().getFeatureGroups().iterator();
1363 Vector<String> groupsAdded = new Vector<>();
1364 while (en.hasNext())
1366 String grp = en.next();
1367 if (groupsAdded.contains(grp))
1371 Group g = new Group();
1373 g.setDisplay(((Boolean) ap.getSeqPanel().seqCanvas
1374 .getFeatureRenderer().checkGroupVisibility(grp, false))
1377 groupsAdded.addElement(grp);
1379 jms.setFeatureSettings(fs);
1382 if (av.hasHiddenColumns())
1384 jalview.datamodel.HiddenColumns hidden = av.getAlignment()
1385 .getHiddenColumns();
1388 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1392 ArrayList<int[]> hiddenRegions = hidden.getHiddenColumnsCopy();
1393 for (int[] region : hiddenRegions)
1395 HiddenColumns hc = new HiddenColumns();
1396 hc.setStart(region[0]);
1397 hc.setEnd(region[1]);
1398 view.addHiddenColumns(hc);
1402 if (calcIdSet.size() > 0)
1404 for (String calcId : calcIdSet)
1406 if (calcId.trim().length() > 0)
1408 CalcIdParam cidp = createCalcIdParam(calcId, av);
1409 // Some calcIds have no parameters.
1412 view.addCalcIdParam(cidp);
1418 jms.addViewport(view);
1420 object.setJalviewModelSequence(jms);
1421 object.getVamsasModel().addSequenceSet(vamsasSet);
1423 if (jout != null && fileName != null)
1425 // We may not want to write the object to disk,
1426 // eg we can copy the alignViewport to a new view object
1427 // using save and then load
1430 System.out.println("Writing jar entry " + fileName);
1431 JarEntry entry = new JarEntry(fileName);
1432 jout.putNextEntry(entry);
1433 PrintWriter pout = new PrintWriter(
1434 new OutputStreamWriter(jout, UTF_8));
1435 Marshaller marshaller = new Marshaller(pout);
1436 marshaller.marshal(object);
1439 } catch (Exception ex)
1441 // TODO: raise error in GUI if marshalling failed.
1442 ex.printStackTrace();
1449 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1450 * for each viewer, with
1452 * <li>viewer geometry (position, size, split pane divider location)</li>
1453 * <li>index of the selected structure in the viewer (currently shows gapped
1455 * <li>the id of the annotation holding RNA secondary structure</li>
1456 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1458 * Varna viewer state is also written out (in native Varna XML) to separate
1459 * project jar entries. A separate entry is written for each RNA structure
1460 * displayed, with the naming convention
1462 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
1470 * @param storeDataset
1472 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
1473 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
1474 boolean storeDataset)
1476 if (Desktop.desktop == null)
1480 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1481 for (int f = frames.length - 1; f > -1; f--)
1483 if (frames[f] instanceof AppVarna)
1485 AppVarna varna = (AppVarna) frames[f];
1487 * link the sequence to every viewer that is showing it and is linked to
1488 * its alignment panel
1490 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1492 String viewId = varna.getViewId();
1493 RnaViewer rna = new RnaViewer();
1494 rna.setViewId(viewId);
1495 rna.setTitle(varna.getTitle());
1496 rna.setXpos(varna.getX());
1497 rna.setYpos(varna.getY());
1498 rna.setWidth(varna.getWidth());
1499 rna.setHeight(varna.getHeight());
1500 rna.setDividerLocation(varna.getDividerLocation());
1501 rna.setSelectedRna(varna.getSelectedIndex());
1502 jseq.addRnaViewer(rna);
1505 * Store each Varna panel's state once in the project per sequence.
1506 * First time through only (storeDataset==false)
1508 // boolean storeSessions = false;
1509 // String sequenceViewId = viewId + seqsToIds.get(jds);
1510 // if (!storeDataset && !viewIds.contains(sequenceViewId))
1512 // viewIds.add(sequenceViewId);
1513 // storeSessions = true;
1515 for (RnaModel model : varna.getModels())
1517 if (model.seq == jds)
1520 * VARNA saves each view (sequence or alignment secondary
1521 * structure, gapped or trimmed) as a separate XML file
1523 String jarEntryName = rnaSessions.get(model);
1524 if (jarEntryName == null)
1527 String varnaStateFile = varna.getStateInfo(model.rna);
1528 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
1529 copyFileToJar(jout, varnaStateFile, jarEntryName);
1530 rnaSessions.put(model, jarEntryName);
1532 SecondaryStructure ss = new SecondaryStructure();
1533 String annotationId = varna.getAnnotation(jds).annotationId;
1534 ss.setAnnotationId(annotationId);
1535 ss.setViewerState(jarEntryName);
1536 ss.setGapped(model.gapped);
1537 ss.setTitle(model.title);
1538 rna.addSecondaryStructure(ss);
1547 * Copy the contents of a file to a new entry added to the output jar
1551 * @param jarEntryName
1553 protected void copyFileToJar(JarOutputStream jout, String infilePath,
1554 String jarEntryName)
1556 DataInputStream dis = null;
1559 File file = new File(infilePath);
1560 if (file.exists() && jout != null)
1562 dis = new DataInputStream(new FileInputStream(file));
1563 byte[] data = new byte[(int) file.length()];
1564 dis.readFully(data);
1565 writeJarEntry(jout, jarEntryName, data);
1567 } catch (Exception ex)
1569 ex.printStackTrace();
1577 } catch (IOException e)
1586 * Write the data to a new entry of given name in the output jar file
1589 * @param jarEntryName
1591 * @throws IOException
1593 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
1594 byte[] data) throws IOException
1598 System.out.println("Writing jar entry " + jarEntryName);
1599 jout.putNextEntry(new JarEntry(jarEntryName));
1600 DataOutputStream dout = new DataOutputStream(jout);
1601 dout.write(data, 0, data.length);
1608 * Save the state of a structure viewer
1613 * the archive XML element under which to save the state
1616 * @param matchedFile
1620 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
1621 Pdbids pdb, PDBEntry entry, List<String> viewIds,
1622 String matchedFile, StructureViewerBase viewFrame)
1624 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
1627 * Look for any bindings for this viewer to the PDB file of interest
1628 * (including part matches excluding chain id)
1630 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
1632 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
1633 final String pdbId = pdbentry.getId();
1634 if (!pdbId.equals(entry.getId())
1635 && !(entry.getId().length() > 4 && entry.getId().toLowerCase()
1636 .startsWith(pdbId.toLowerCase())))
1639 * not interested in a binding to a different PDB entry here
1643 if (matchedFile == null)
1645 matchedFile = pdbentry.getFile();
1647 else if (!matchedFile.equals(pdbentry.getFile()))
1650 "Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
1651 + pdbentry.getFile());
1655 // can get at it if the ID
1656 // match is ambiguous (e.g.
1659 for (int smap = 0; smap < viewFrame.getBinding()
1660 .getSequence()[peid].length; smap++)
1662 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
1663 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
1665 StructureState state = new StructureState();
1666 state.setVisible(true);
1667 state.setXpos(viewFrame.getX());
1668 state.setYpos(viewFrame.getY());
1669 state.setWidth(viewFrame.getWidth());
1670 state.setHeight(viewFrame.getHeight());
1671 final String viewId = viewFrame.getViewId();
1672 state.setViewId(viewId);
1673 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
1674 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
1675 state.setColourByJmol(viewFrame.isColouredByViewer());
1676 state.setType(viewFrame.getViewerType().toString());
1677 pdb.addStructureState(state);
1685 * Populates the AnnotationColours xml for save. This captures the settings of
1686 * the options in the 'Colour by Annotation' dialog.
1689 * @param userColours
1693 private AnnotationColours constructAnnotationColours(
1694 AnnotationColourGradient acg, List<UserColourScheme> userColours,
1695 JalviewModelSequence jms)
1697 AnnotationColours ac = new AnnotationColours();
1698 ac.setAboveThreshold(acg.getAboveThreshold());
1699 ac.setThreshold(acg.getAnnotationThreshold());
1700 // 2.10.2 save annotationId (unique) not annotation label
1701 ac.setAnnotation(acg.getAnnotation().annotationId);
1702 if (acg.getBaseColour() instanceof UserColourScheme)
1705 setUserColourScheme(acg.getBaseColour(), userColours, jms));
1710 ColourSchemeProperty.getColourName(acg.getBaseColour()));
1713 ac.setMaxColour(acg.getMaxColour().getRGB());
1714 ac.setMinColour(acg.getMinColour().getRGB());
1715 ac.setPerSequence(acg.isSeqAssociated());
1716 ac.setPredefinedColours(acg.isPredefinedColours());
1720 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
1721 IdentityHashMap<SequenceGroup, String> groupRefs,
1722 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
1723 SequenceSet vamsasSet)
1726 for (int i = 0; i < aa.length; i++)
1728 Annotation an = new Annotation();
1730 AlignmentAnnotation annotation = aa[i];
1731 if (annotation.annotationId != null)
1733 annotationIds.put(annotation.annotationId, annotation);
1736 an.setId(annotation.annotationId);
1738 an.setVisible(annotation.visible);
1740 an.setDescription(annotation.description);
1742 if (annotation.sequenceRef != null)
1744 // 2.9 JAL-1781 xref on sequence id rather than name
1745 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
1747 if (annotation.groupRef != null)
1749 String groupIdr = groupRefs.get(annotation.groupRef);
1750 if (groupIdr == null)
1752 // make a locally unique String
1753 groupRefs.put(annotation.groupRef,
1754 groupIdr = ("" + System.currentTimeMillis()
1755 + annotation.groupRef.getName()
1756 + groupRefs.size()));
1758 an.setGroupRef(groupIdr.toString());
1761 // store all visualization attributes for annotation
1762 an.setGraphHeight(annotation.graphHeight);
1763 an.setCentreColLabels(annotation.centreColLabels);
1764 an.setScaleColLabels(annotation.scaleColLabel);
1765 an.setShowAllColLabels(annotation.showAllColLabels);
1766 an.setBelowAlignment(annotation.belowAlignment);
1768 if (annotation.graph > 0)
1771 an.setGraphType(annotation.graph);
1772 an.setGraphGroup(annotation.graphGroup);
1773 if (annotation.getThreshold() != null)
1775 ThresholdLine line = new ThresholdLine();
1776 line.setLabel(annotation.getThreshold().label);
1777 line.setValue(annotation.getThreshold().value);
1778 line.setColour(annotation.getThreshold().colour.getRGB());
1779 an.setThresholdLine(line);
1787 an.setLabel(annotation.label);
1789 if (annotation == av.getAlignmentQualityAnnot()
1790 || annotation == av.getAlignmentConservationAnnotation()
1791 || annotation == av.getAlignmentConsensusAnnotation()
1792 || annotation.autoCalculated)
1794 // new way of indicating autocalculated annotation -
1795 an.setAutoCalculated(annotation.autoCalculated);
1797 if (annotation.hasScore())
1799 an.setScore(annotation.getScore());
1802 if (annotation.getCalcId() != null)
1804 calcIdSet.add(annotation.getCalcId());
1805 an.setCalcId(annotation.getCalcId());
1807 if (annotation.hasProperties())
1809 for (String pr : annotation.getProperties())
1811 Property prop = new Property();
1813 prop.setValue(annotation.getProperty(pr));
1814 an.addProperty(prop);
1818 AnnotationElement ae;
1819 if (annotation.annotations != null)
1821 an.setScoreOnly(false);
1822 for (int a = 0; a < annotation.annotations.length; a++)
1824 if ((annotation == null) || (annotation.annotations[a] == null))
1829 ae = new AnnotationElement();
1830 if (annotation.annotations[a].description != null)
1832 ae.setDescription(annotation.annotations[a].description);
1834 if (annotation.annotations[a].displayCharacter != null)
1836 ae.setDisplayCharacter(
1837 annotation.annotations[a].displayCharacter);
1840 if (!Float.isNaN(annotation.annotations[a].value))
1842 ae.setValue(annotation.annotations[a].value);
1846 if (annotation.annotations[a].secondaryStructure > ' ')
1848 ae.setSecondaryStructure(
1849 annotation.annotations[a].secondaryStructure + "");
1852 if (annotation.annotations[a].colour != null
1853 && annotation.annotations[a].colour != java.awt.Color.black)
1855 ae.setColour(annotation.annotations[a].colour.getRGB());
1858 an.addAnnotationElement(ae);
1859 if (annotation.autoCalculated)
1861 // only write one non-null entry into the annotation row -
1862 // sufficient to get the visualization attributes necessary to
1870 an.setScoreOnly(true);
1872 if (!storeDS || (storeDS && !annotation.autoCalculated))
1874 // skip autocalculated annotation - these are only provided for
1876 vamsasSet.addAnnotation(an);
1882 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
1884 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
1885 if (settings != null)
1887 CalcIdParam vCalcIdParam = new CalcIdParam();
1888 vCalcIdParam.setCalcId(calcId);
1889 vCalcIdParam.addServiceURL(settings.getServiceURI());
1890 // generic URI allowing a third party to resolve another instance of the
1891 // service used for this calculation
1892 for (String urls : settings.getServiceURLs())
1894 vCalcIdParam.addServiceURL(urls);
1896 vCalcIdParam.setVersion("1.0");
1897 if (settings.getPreset() != null)
1899 WsParamSetI setting = settings.getPreset();
1900 vCalcIdParam.setName(setting.getName());
1901 vCalcIdParam.setDescription(setting.getDescription());
1905 vCalcIdParam.setName("");
1906 vCalcIdParam.setDescription("Last used parameters");
1908 // need to be able to recover 1) settings 2) user-defined presets or
1909 // recreate settings from preset 3) predefined settings provided by
1910 // service - or settings that can be transferred (or discarded)
1911 vCalcIdParam.setParameters(
1912 settings.getWsParamFile().replace("\n", "|\\n|"));
1913 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
1914 // todo - decide if updateImmediately is needed for any projects.
1916 return vCalcIdParam;
1921 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
1924 if (calcIdParam.getVersion().equals("1.0"))
1926 Jws2Instance service = Jws2Discoverer.getDiscoverer()
1927 .getPreferredServiceFor(calcIdParam.getServiceURL());
1928 if (service != null)
1930 WsParamSetI parmSet = null;
1933 parmSet = service.getParamStore().parseServiceParameterFile(
1934 calcIdParam.getName(), calcIdParam.getDescription(),
1935 calcIdParam.getServiceURL(),
1936 calcIdParam.getParameters().replace("|\\n|", "\n"));
1937 } catch (IOException x)
1939 warn("Couldn't parse parameter data for "
1940 + calcIdParam.getCalcId(), x);
1943 List<ArgumentI> argList = null;
1944 if (calcIdParam.getName().length() > 0)
1946 parmSet = service.getParamStore()
1947 .getPreset(calcIdParam.getName());
1948 if (parmSet != null)
1950 // TODO : check we have a good match with settings in AACon -
1951 // otherwise we'll need to create a new preset
1956 argList = parmSet.getArguments();
1959 AAConSettings settings = new AAConSettings(
1960 calcIdParam.isAutoUpdate(), service, parmSet, argList);
1961 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
1962 calcIdParam.isNeedsUpdate());
1967 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
1971 throw new Error(MessageManager.formatMessage(
1972 "error.unsupported_version_calcIdparam", new Object[]
1973 { calcIdParam.toString() }));
1977 * External mapping between jalview objects and objects yielding a valid and
1978 * unique object ID string. This is null for normal Jalview project IO, but
1979 * non-null when a jalview project is being read or written as part of a
1982 IdentityHashMap jv2vobj = null;
1985 * Construct a unique ID for jvobj using either existing bindings or if none
1986 * exist, the result of the hashcode call for the object.
1989 * jalview data object
1990 * @return unique ID for referring to jvobj
1992 private String makeHashCode(Object jvobj, String altCode)
1994 if (jv2vobj != null)
1996 Object id = jv2vobj.get(jvobj);
1999 return id.toString();
2001 // check string ID mappings
2002 if (jvids2vobj != null && jvobj instanceof String)
2004 id = jvids2vobj.get(jvobj);
2008 return id.toString();
2010 // give up and warn that something has gone wrong
2011 warn("Cannot find ID for object in external mapping : " + jvobj);
2017 * return local jalview object mapped to ID, if it exists
2021 * @return null or object bound to idcode
2023 private Object retrieveExistingObj(String idcode)
2025 if (idcode != null && vobj2jv != null)
2027 return vobj2jv.get(idcode);
2033 * binding from ID strings from external mapping table to jalview data model
2036 private Hashtable vobj2jv;
2038 private Sequence createVamsasSequence(String id, SequenceI jds)
2040 return createVamsasSequence(true, id, jds, null);
2043 private Sequence createVamsasSequence(boolean recurse, String id,
2044 SequenceI jds, SequenceI parentseq)
2046 Sequence vamsasSeq = new Sequence();
2047 vamsasSeq.setId(id);
2048 vamsasSeq.setName(jds.getName());
2049 vamsasSeq.setSequence(jds.getSequenceAsString());
2050 vamsasSeq.setDescription(jds.getDescription());
2051 jalview.datamodel.DBRefEntry[] dbrefs = null;
2052 if (jds.getDatasetSequence() != null)
2054 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
2058 // seqId==dsseqid so we can tell which sequences really are
2059 // dataset sequences only
2060 vamsasSeq.setDsseqid(id);
2061 dbrefs = jds.getDBRefs();
2062 if (parentseq == null)
2069 for (int d = 0; d < dbrefs.length; d++)
2071 DBRef dbref = new DBRef();
2072 dbref.setSource(dbrefs[d].getSource());
2073 dbref.setVersion(dbrefs[d].getVersion());
2074 dbref.setAccessionId(dbrefs[d].getAccessionId());
2075 if (dbrefs[d].hasMap())
2077 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
2079 dbref.setMapping(mp);
2081 vamsasSeq.addDBRef(dbref);
2087 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
2088 SequenceI parentseq, SequenceI jds, boolean recurse)
2091 if (jmp.getMap() != null)
2095 jalview.util.MapList mlst = jmp.getMap();
2096 List<int[]> r = mlst.getFromRanges();
2097 for (int[] range : r)
2099 MapListFrom mfrom = new MapListFrom();
2100 mfrom.setStart(range[0]);
2101 mfrom.setEnd(range[1]);
2102 mp.addMapListFrom(mfrom);
2104 r = mlst.getToRanges();
2105 for (int[] range : r)
2107 MapListTo mto = new MapListTo();
2108 mto.setStart(range[0]);
2109 mto.setEnd(range[1]);
2110 mp.addMapListTo(mto);
2112 mp.setMapFromUnit(mlst.getFromRatio());
2113 mp.setMapToUnit(mlst.getToRatio());
2114 if (jmp.getTo() != null)
2116 MappingChoice mpc = new MappingChoice();
2118 // check/create ID for the sequence referenced by getTo()
2121 SequenceI ps = null;
2122 if (parentseq != jmp.getTo()
2123 && parentseq.getDatasetSequence() != jmp.getTo())
2125 // chaining dbref rather than a handshaking one
2126 jmpid = seqHash(ps = jmp.getTo());
2130 jmpid = seqHash(ps = parentseq);
2132 mpc.setDseqFor(jmpid);
2133 if (!seqRefIds.containsKey(mpc.getDseqFor()))
2135 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2136 seqRefIds.put(mpc.getDseqFor(), ps);
2140 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2143 mp.setMappingChoice(mpc);
2149 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2150 List<UserColourScheme> userColours, JalviewModelSequence jms)
2153 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2154 boolean newucs = false;
2155 if (!userColours.contains(ucs))
2157 userColours.add(ucs);
2160 id = "ucs" + userColours.indexOf(ucs);
2163 // actually create the scheme's entry in the XML model
2164 java.awt.Color[] colours = ucs.getColours();
2165 jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
2166 jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
2168 for (int i = 0; i < colours.length; i++)
2170 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2171 col.setName(ResidueProperties.aa[i]);
2172 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2173 jbucs.addColour(col);
2175 if (ucs.getLowerCaseColours() != null)
2177 colours = ucs.getLowerCaseColours();
2178 for (int i = 0; i < colours.length; i++)
2180 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2181 col.setName(ResidueProperties.aa[i].toLowerCase());
2182 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2183 jbucs.addColour(col);
2188 uc.setUserColourScheme(jbucs);
2189 jms.addUserColours(uc);
2195 jalview.schemes.UserColourScheme getUserColourScheme(
2196 JalviewModelSequence jms, String id)
2198 UserColours[] uc = jms.getUserColours();
2199 UserColours colours = null;
2201 for (int i = 0; i < uc.length; i++)
2203 if (uc[i].getId().equals(id))
2211 java.awt.Color[] newColours = new java.awt.Color[24];
2213 for (int i = 0; i < 24; i++)
2215 newColours[i] = new java.awt.Color(Integer.parseInt(
2216 colours.getUserColourScheme().getColour(i).getRGB(), 16));
2219 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2222 if (colours.getUserColourScheme().getColourCount() > 24)
2224 newColours = new java.awt.Color[23];
2225 for (int i = 0; i < 23; i++)
2227 newColours[i] = new java.awt.Color(Integer.parseInt(
2228 colours.getUserColourScheme().getColour(i + 24).getRGB(),
2231 ucs.setLowerCaseColours(newColours);
2238 * contains last error message (if any) encountered by XML loader.
2240 String errorMessage = null;
2243 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2244 * exceptions are raised during project XML parsing
2246 public boolean attemptversion1parse = true;
2249 * Load a jalview project archive from a jar file
2252 * - HTTP URL or filename
2254 public AlignFrame loadJalviewAlign(final String file)
2257 jalview.gui.AlignFrame af = null;
2261 // create list to store references for any new Jmol viewers created
2262 newStructureViewers = new Vector<>();
2263 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2264 // Workaround is to make sure caller implements the JarInputStreamProvider
2266 // so we can re-open the jar input stream for each entry.
2268 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2269 af = loadJalviewAlign(jprovider);
2271 } catch (MalformedURLException e)
2273 errorMessage = "Invalid URL format for '" + file + "'";
2279 SwingUtilities.invokeAndWait(new Runnable()
2284 setLoadingFinishedForNewStructureViewers();
2287 } catch (Exception x)
2289 System.err.println("Error loading alignment: " + x.getMessage());
2295 private jarInputStreamProvider createjarInputStreamProvider(
2296 final String file) throws MalformedURLException
2299 errorMessage = null;
2300 uniqueSetSuffix = null;
2302 viewportsAdded.clear();
2303 frefedSequence = null;
2305 if (file.startsWith("http://"))
2307 url = new URL(file);
2309 final URL _url = url;
2310 return new jarInputStreamProvider()
2314 public JarInputStream getJarInputStream() throws IOException
2318 return new JarInputStream(_url.openStream());
2322 return new JarInputStream(new FileInputStream(file));
2327 public String getFilename()
2335 * Recover jalview session from a jalview project archive. Caller may
2336 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2337 * themselves. Any null fields will be initialised with default values,
2338 * non-null fields are left alone.
2343 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2345 errorMessage = null;
2346 if (uniqueSetSuffix == null)
2348 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2350 if (seqRefIds == null)
2354 AlignFrame af = null, _af = null;
2355 IdentityHashMap<AlignmentI, AlignmentI> importedDatasets = new IdentityHashMap<>();
2356 Map<String, AlignFrame> gatherToThisFrame = new HashMap<>();
2357 final String file = jprovider.getFilename();
2360 JarInputStream jin = null;
2361 JarEntry jarentry = null;
2366 jin = jprovider.getJarInputStream();
2367 for (int i = 0; i < entryCount; i++)
2369 jarentry = jin.getNextJarEntry();
2372 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2374 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2375 JalviewModel object = new JalviewModel();
2377 Unmarshaller unmar = new Unmarshaller(object);
2378 unmar.setValidation(false);
2379 object = (JalviewModel) unmar.unmarshal(in);
2380 if (true) // !skipViewport(object))
2382 _af = loadFromObject(object, file, true, jprovider);
2383 if (_af != null && object.getJalviewModelSequence()
2384 .getViewportCount() > 0)
2388 // store a reference to the first view
2391 if (_af.viewport.isGatherViewsHere())
2393 // if this is a gathered view, keep its reference since
2394 // after gathering views, only this frame will remain
2396 gatherToThisFrame.put(_af.viewport.getSequenceSetId(), _af);
2398 // Save dataset to register mappings once all resolved
2399 importedDatasets.put(af.viewport.getAlignment().getDataset(),
2400 af.viewport.getAlignment().getDataset());
2405 else if (jarentry != null)
2407 // Some other file here.
2410 } while (jarentry != null);
2411 resolveFrefedSequences();
2412 } catch (IOException ex)
2414 ex.printStackTrace();
2415 errorMessage = "Couldn't locate Jalview XML file : " + file;
2417 "Exception whilst loading jalview XML file : " + ex + "\n");
2418 } catch (Exception ex)
2420 System.err.println("Parsing as Jalview Version 2 file failed.");
2421 ex.printStackTrace(System.err);
2422 if (attemptversion1parse)
2424 // Is Version 1 Jar file?
2427 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
2428 } catch (Exception ex2)
2430 System.err.println("Exception whilst loading as jalviewXMLV1:");
2431 ex2.printStackTrace();
2435 if (Desktop.instance != null)
2437 Desktop.instance.stopLoading();
2441 System.out.println("Successfully loaded archive file");
2444 ex.printStackTrace();
2447 "Exception whilst loading jalview XML file : " + ex + "\n");
2448 } catch (OutOfMemoryError e)
2450 // Don't use the OOM Window here
2451 errorMessage = "Out of memory loading jalview XML file";
2452 System.err.println("Out of memory whilst loading jalview XML file");
2453 e.printStackTrace();
2457 * Regather multiple views (with the same sequence set id) to the frame (if
2458 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2459 * views instead of separate frames. Note this doesn't restore a state where
2460 * some expanded views in turn have tabbed views - the last "first tab" read
2461 * in will play the role of gatherer for all.
2463 for (AlignFrame fr : gatherToThisFrame.values())
2465 Desktop.instance.gatherViews(fr);
2468 restoreSplitFrames();
2469 for (AlignmentI ds : importedDatasets.keySet())
2471 if (ds.getCodonFrames() != null)
2473 StructureSelectionManager
2474 .getStructureSelectionManager(Desktop.instance)
2475 .registerMappings(ds.getCodonFrames());
2478 if (errorMessage != null)
2483 if (Desktop.instance != null)
2485 Desktop.instance.stopLoading();
2492 * Try to reconstruct and display SplitFrame windows, where each contains
2493 * complementary dna and protein alignments. Done by pairing up AlignFrame
2494 * objects (created earlier) which have complementary viewport ids associated.
2496 protected void restoreSplitFrames()
2498 List<SplitFrame> gatherTo = new ArrayList<>();
2499 List<AlignFrame> addedToSplitFrames = new ArrayList<>();
2500 Map<String, AlignFrame> dna = new HashMap<>();
2503 * Identify the DNA alignments
2505 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2508 AlignFrame af = candidate.getValue();
2509 if (af.getViewport().getAlignment().isNucleotide())
2511 dna.put(candidate.getKey().getId(), af);
2516 * Try to match up the protein complements
2518 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2521 AlignFrame af = candidate.getValue();
2522 if (!af.getViewport().getAlignment().isNucleotide())
2524 String complementId = candidate.getKey().getComplementId();
2525 // only non-null complements should be in the Map
2526 if (complementId != null && dna.containsKey(complementId))
2528 final AlignFrame dnaFrame = dna.get(complementId);
2529 SplitFrame sf = createSplitFrame(dnaFrame, af);
2530 addedToSplitFrames.add(dnaFrame);
2531 addedToSplitFrames.add(af);
2532 dnaFrame.setMenusForViewport();
2533 af.setMenusForViewport();
2534 if (af.viewport.isGatherViewsHere())
2543 * Open any that we failed to pair up (which shouldn't happen!) as
2544 * standalone AlignFrame's.
2546 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2549 AlignFrame af = candidate.getValue();
2550 if (!addedToSplitFrames.contains(af))
2552 Viewport view = candidate.getKey();
2553 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
2555 af.setMenusForViewport();
2556 System.err.println("Failed to restore view " + view.getTitle()
2557 + " to split frame");
2562 * Gather back into tabbed views as flagged.
2564 for (SplitFrame sf : gatherTo)
2566 Desktop.instance.gatherViews(sf);
2569 splitFrameCandidates.clear();
2573 * Construct and display one SplitFrame holding DNA and protein alignments.
2576 * @param proteinFrame
2579 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
2580 AlignFrame proteinFrame)
2582 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
2583 String title = MessageManager.getString("label.linked_view_title");
2584 int width = (int) dnaFrame.getBounds().getWidth();
2585 int height = (int) (dnaFrame.getBounds().getHeight()
2586 + proteinFrame.getBounds().getHeight() + 50);
2589 * SplitFrame location is saved to both enclosed frames
2591 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
2592 Desktop.addInternalFrame(splitFrame, title, width, height);
2595 * And compute cDNA consensus (couldn't do earlier with consensus as
2596 * mappings were not yet present)
2598 proteinFrame.viewport.alignmentChanged(proteinFrame.alignPanel);
2604 * check errorMessage for a valid error message and raise an error box in the
2605 * GUI or write the current errorMessage to stderr and then clear the error
2608 protected void reportErrors()
2610 reportErrors(false);
2613 protected void reportErrors(final boolean saving)
2615 if (errorMessage != null)
2617 final String finalErrorMessage = errorMessage;
2620 javax.swing.SwingUtilities.invokeLater(new Runnable()
2625 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2627 "Error " + (saving ? "saving" : "loading")
2629 JvOptionPane.WARNING_MESSAGE);
2635 System.err.println("Problem loading Jalview file: " + errorMessage);
2638 errorMessage = null;
2641 Map<String, String> alreadyLoadedPDB = new HashMap<>();
2644 * when set, local views will be updated from view stored in JalviewXML
2645 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2646 * sync if this is set to true.
2648 private final boolean updateLocalViews = false;
2651 * Returns the path to a temporary file holding the PDB file for the given PDB
2652 * id. The first time of asking, searches for a file of that name in the
2653 * Jalview project jar, and copies it to a new temporary file. Any repeat
2654 * requests just return the path to the file previously created.
2660 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId,
2663 if (alreadyLoadedPDB.containsKey(pdbId))
2665 return alreadyLoadedPDB.get(pdbId).toString();
2668 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb",
2670 if (tempFile != null)
2672 alreadyLoadedPDB.put(pdbId, tempFile);
2678 * Copies the jar entry of given name to a new temporary file and returns the
2679 * path to the file, or null if the entry is not found.
2682 * @param jarEntryName
2684 * a prefix for the temporary file name, must be at least three
2687 * null or original file - so new file can be given the same suffix
2691 protected String copyJarEntry(jarInputStreamProvider jprovider,
2692 String jarEntryName, String prefix, String origFile)
2694 BufferedReader in = null;
2695 PrintWriter out = null;
2696 String suffix = ".tmp";
2697 if (origFile == null)
2699 origFile = jarEntryName;
2701 int sfpos = origFile.lastIndexOf(".");
2702 if (sfpos > -1 && sfpos < (origFile.length() - 3))
2704 suffix = "." + origFile.substring(sfpos + 1);
2708 JarInputStream jin = jprovider.getJarInputStream();
2710 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2711 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2712 * FileInputStream(jprovider)); }
2715 JarEntry entry = null;
2718 entry = jin.getNextJarEntry();
2719 } while (entry != null && !entry.getName().equals(jarEntryName));
2722 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
2723 File outFile = File.createTempFile(prefix, suffix);
2724 outFile.deleteOnExit();
2725 out = new PrintWriter(new FileOutputStream(outFile));
2728 while ((data = in.readLine()) != null)
2733 String t = outFile.getAbsolutePath();
2738 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
2740 } catch (Exception ex)
2742 ex.printStackTrace();
2750 } catch (IOException e)
2764 private class JvAnnotRow
2766 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2773 * persisted version of annotation row from which to take vis properties
2775 public jalview.datamodel.AlignmentAnnotation template;
2778 * original position of the annotation row in the alignment
2784 * Load alignment frame from jalview XML DOM object
2789 * filename source string
2790 * @param loadTreesAndStructures
2791 * when false only create Viewport
2793 * data source provider
2794 * @return alignment frame created from view stored in DOM
2796 AlignFrame loadFromObject(JalviewModel object, String file,
2797 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
2799 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
2800 Sequence[] vamsasSeq = vamsasSet.getSequence();
2802 JalviewModelSequence jms = object.getJalviewModelSequence();
2804 Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
2807 // ////////////////////////////////
2810 List<SequenceI> hiddenSeqs = null;
2812 List<SequenceI> tmpseqs = new ArrayList<>();
2814 boolean multipleView = false;
2815 SequenceI referenceseqForView = null;
2816 JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
2817 int vi = 0; // counter in vamsasSeq array
2818 for (int i = 0; i < jseqs.length; i++)
2820 String seqId = jseqs[i].getId();
2822 SequenceI tmpSeq = seqRefIds.get(seqId);
2825 if (!incompleteSeqs.containsKey(seqId))
2827 // may not need this check, but keep it for at least 2.9,1 release
2828 if (tmpSeq.getStart() != jseqs[i].getStart()
2829 || tmpSeq.getEnd() != jseqs[i].getEnd())
2832 "Warning JAL-2154 regression: updating start/end for sequence "
2833 + tmpSeq.toString() + " to " + jseqs[i]);
2838 incompleteSeqs.remove(seqId);
2840 if (vamsasSeq.length > vi && vamsasSeq[vi].getId().equals(seqId))
2842 // most likely we are reading a dataset XML document so
2843 // update from vamsasSeq section of XML for this sequence
2844 tmpSeq.setName(vamsasSeq[vi].getName());
2845 tmpSeq.setDescription(vamsasSeq[vi].getDescription());
2846 tmpSeq.setSequence(vamsasSeq[vi].getSequence());
2851 // reading multiple views, so vamsasSeq set is a subset of JSeq
2852 multipleView = true;
2854 tmpSeq.setStart(jseqs[i].getStart());
2855 tmpSeq.setEnd(jseqs[i].getEnd());
2856 tmpseqs.add(tmpSeq);
2860 tmpSeq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
2861 vamsasSeq[vi].getSequence());
2862 tmpSeq.setDescription(vamsasSeq[vi].getDescription());
2863 tmpSeq.setStart(jseqs[i].getStart());
2864 tmpSeq.setEnd(jseqs[i].getEnd());
2865 tmpSeq.setVamsasId(uniqueSetSuffix + seqId);
2866 seqRefIds.put(vamsasSeq[vi].getId(), tmpSeq);
2867 tmpseqs.add(tmpSeq);
2871 if (jseqs[i].hasViewreference() && jseqs[i].getViewreference())
2873 referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
2876 if (jseqs[i].getHidden())
2878 if (hiddenSeqs == null)
2880 hiddenSeqs = new ArrayList<>();
2883 hiddenSeqs.add(tmpSeq);
2888 // Create the alignment object from the sequence set
2889 // ///////////////////////////////
2890 SequenceI[] orderedSeqs = tmpseqs
2891 .toArray(new SequenceI[tmpseqs.size()]);
2893 AlignmentI al = null;
2894 // so we must create or recover the dataset alignment before going further
2895 // ///////////////////////////////
2896 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
2898 // older jalview projects do not have a dataset - so creat alignment and
2900 al = new Alignment(orderedSeqs);
2901 al.setDataset(null);
2905 boolean isdsal = object.getJalviewModelSequence()
2906 .getViewportCount() == 0;
2909 // we are importing a dataset record, so
2910 // recover reference to an alignment already materialsed as dataset
2911 al = getDatasetFor(vamsasSet.getDatasetId());
2915 // materialse the alignment
2916 al = new Alignment(orderedSeqs);
2920 addDatasetRef(vamsasSet.getDatasetId(), al);
2923 // finally, verify all data in vamsasSet is actually present in al
2924 // passing on flag indicating if it is actually a stored dataset
2925 recoverDatasetFor(vamsasSet, al, isdsal);
2928 if (referenceseqForView != null)
2930 al.setSeqrep(referenceseqForView);
2932 // / Add the alignment properties
2933 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
2935 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
2936 al.setProperty(ssp.getKey(), ssp.getValue());
2939 // ///////////////////////////////
2941 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
2944 // load sequence features, database references and any associated PDB
2945 // structures for the alignment
2947 // prior to 2.10, this part would only be executed the first time a
2948 // sequence was encountered, but not afterwards.
2949 // now, for 2.10 projects, this is also done if the xml doc includes
2950 // dataset sequences not actually present in any particular view.
2952 for (int i = 0; i < vamsasSeq.length; i++)
2954 if (jseqs[i].getFeaturesCount() > 0)
2956 Features[] features = jseqs[i].getFeatures();
2957 for (int f = 0; f < features.length; f++)
2959 SequenceFeature sf = new SequenceFeature(features[f].getType(),
2960 features[f].getDescription(), features[f].getBegin(),
2961 features[f].getEnd(), features[f].getScore(),
2962 features[f].getFeatureGroup());
2963 sf.setStatus(features[f].getStatus());
2964 for (int od = 0; od < features[f].getOtherDataCount(); od++)
2966 OtherData keyValue = features[f].getOtherData(od);
2967 if (keyValue.getKey().startsWith("LINK"))
2969 sf.addLink(keyValue.getValue());
2973 sf.setValue(keyValue.getKey(), keyValue.getValue());
2977 // adds feature to datasequence's feature set (since Jalview 2.10)
2978 al.getSequenceAt(i).addSequenceFeature(sf);
2981 if (vamsasSeq[i].getDBRefCount() > 0)
2983 // adds dbrefs to datasequence's set (since Jalview 2.10)
2985 al.getSequenceAt(i).getDatasetSequence() == null
2986 ? al.getSequenceAt(i)
2987 : al.getSequenceAt(i).getDatasetSequence(),
2990 if (jseqs[i].getPdbidsCount() > 0)
2992 Pdbids[] ids = jseqs[i].getPdbids();
2993 for (int p = 0; p < ids.length; p++)
2995 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
2996 entry.setId(ids[p].getId());
2997 if (ids[p].getType() != null)
2999 if (PDBEntry.Type.getType(ids[p].getType()) != null)
3001 entry.setType(PDBEntry.Type.getType(ids[p].getType()));
3005 entry.setType(PDBEntry.Type.FILE);
3008 // jprovider is null when executing 'New View'
3009 if (ids[p].getFile() != null && jprovider != null)
3011 if (!pdbloaded.containsKey(ids[p].getFile()))
3013 entry.setFile(loadPDBFile(jprovider, ids[p].getId(),
3018 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
3021 if (ids[p].getPdbentryItem() != null)
3023 for (PdbentryItem item : ids[p].getPdbentryItem())
3025 for (Property pr : item.getProperty())
3027 entry.setProperty(pr.getName(), pr.getValue());
3031 StructureSelectionManager
3032 .getStructureSelectionManager(Desktop.instance)
3033 .registerPDBEntry(entry);
3034 // adds PDBEntry to datasequence's set (since Jalview 2.10)
3035 if (al.getSequenceAt(i).getDatasetSequence() != null)
3037 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
3041 al.getSequenceAt(i).addPDBId(entry);
3046 } // end !multipleview
3048 // ///////////////////////////////
3049 // LOAD SEQUENCE MAPPINGS
3051 if (vamsasSet.getAlcodonFrameCount() > 0)
3053 // TODO Potentially this should only be done once for all views of an
3055 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
3056 for (int i = 0; i < alc.length; i++)
3058 AlignedCodonFrame cf = new AlignedCodonFrame();
3059 if (alc[i].getAlcodMapCount() > 0)
3061 AlcodMap[] maps = alc[i].getAlcodMap();
3062 for (int m = 0; m < maps.length; m++)
3064 SequenceI dnaseq = seqRefIds.get(maps[m].getDnasq());
3066 jalview.datamodel.Mapping mapping = null;
3067 // attach to dna sequence reference.
3068 if (maps[m].getMapping() != null)
3070 mapping = addMapping(maps[m].getMapping());
3071 if (dnaseq != null && mapping.getTo() != null)
3073 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
3079 newAlcodMapRef(maps[m].getDnasq(), cf, mapping));
3083 al.addCodonFrame(cf);
3088 // ////////////////////////////////
3090 List<JvAnnotRow> autoAlan = new ArrayList<>();
3093 * store any annotations which forward reference a group's ID
3095 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<>();
3097 if (vamsasSet.getAnnotationCount() > 0)
3099 Annotation[] an = vamsasSet.getAnnotation();
3101 for (int i = 0; i < an.length; i++)
3103 Annotation annotation = an[i];
3106 * test if annotation is automatically calculated for this view only
3108 boolean autoForView = false;
3109 if (annotation.getLabel().equals("Quality")
3110 || annotation.getLabel().equals("Conservation")
3111 || annotation.getLabel().equals("Consensus"))
3113 // Kludge for pre 2.5 projects which lacked the autocalculated flag
3115 if (!annotation.hasAutoCalculated())
3117 annotation.setAutoCalculated(true);
3120 if (autoForView || (annotation.hasAutoCalculated()
3121 && annotation.isAutoCalculated()))
3123 // remove ID - we don't recover annotation from other views for
3124 // view-specific annotation
3125 annotation.setId(null);
3128 // set visiblity for other annotation in this view
3129 String annotationId = annotation.getId();
3130 if (annotationId != null && annotationIds.containsKey(annotationId))
3132 AlignmentAnnotation jda = annotationIds.get(annotationId);
3133 // in principle Visible should always be true for annotation displayed
3134 // in multiple views
3135 if (annotation.hasVisible())
3137 jda.visible = annotation.getVisible();
3140 al.addAnnotation(jda);
3144 // Construct new annotation from model.
3145 AnnotationElement[] ae = annotation.getAnnotationElement();
3146 jalview.datamodel.Annotation[] anot = null;
3147 java.awt.Color firstColour = null;
3149 if (!annotation.getScoreOnly())
3151 anot = new jalview.datamodel.Annotation[al.getWidth()];
3152 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
3154 anpos = ae[aa].getPosition();
3156 if (anpos >= anot.length)
3161 anot[anpos] = new jalview.datamodel.Annotation(
3163 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
3164 (ae[aa].getSecondaryStructure() == null
3165 || ae[aa].getSecondaryStructure().length() == 0)
3167 : ae[aa].getSecondaryStructure()
3172 // JBPNote: Consider verifying dataflow for IO of secondary
3173 // structure annotation read from Stockholm files
3174 // this was added to try to ensure that
3175 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
3177 // anot[ae[aa].getPosition()].displayCharacter = "";
3179 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
3180 if (firstColour == null)
3182 firstColour = anot[anpos].colour;
3186 jalview.datamodel.AlignmentAnnotation jaa = null;
3188 if (annotation.getGraph())
3190 float llim = 0, hlim = 0;
3191 // if (autoForView || an[i].isAutoCalculated()) {
3194 jaa = new jalview.datamodel.AlignmentAnnotation(
3195 annotation.getLabel(), annotation.getDescription(), anot,
3196 llim, hlim, annotation.getGraphType());
3198 jaa.graphGroup = annotation.getGraphGroup();
3199 jaa._linecolour = firstColour;
3200 if (annotation.getThresholdLine() != null)
3202 jaa.setThreshold(new jalview.datamodel.GraphLine(
3203 annotation.getThresholdLine().getValue(),
3204 annotation.getThresholdLine().getLabel(),
3206 annotation.getThresholdLine().getColour())));
3209 if (autoForView || annotation.isAutoCalculated())
3211 // Hardwire the symbol display line to ensure that labels for
3212 // histograms are displayed
3218 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
3219 an[i].getDescription(), anot);
3220 jaa._linecolour = firstColour;
3222 // register new annotation
3223 if (an[i].getId() != null)
3225 annotationIds.put(an[i].getId(), jaa);
3226 jaa.annotationId = an[i].getId();
3228 // recover sequence association
3229 String sequenceRef = an[i].getSequenceRef();
3230 if (sequenceRef != null)
3232 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3233 SequenceI sequence = seqRefIds.get(sequenceRef);
3234 if (sequence == null)
3236 // in pre-2.9 projects sequence ref is to sequence name
3237 sequence = al.findName(sequenceRef);
3239 if (sequence != null)
3241 jaa.createSequenceMapping(sequence, 1, true);
3242 sequence.addAlignmentAnnotation(jaa);
3245 // and make a note of any group association
3246 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
3248 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3249 .get(an[i].getGroupRef());
3252 aal = new ArrayList<>();
3253 groupAnnotRefs.put(an[i].getGroupRef(), aal);
3258 if (an[i].hasScore())
3260 jaa.setScore(an[i].getScore());
3262 if (an[i].hasVisible())
3264 jaa.visible = an[i].getVisible();
3267 if (an[i].hasCentreColLabels())
3269 jaa.centreColLabels = an[i].getCentreColLabels();
3272 if (an[i].hasScaleColLabels())
3274 jaa.scaleColLabel = an[i].getScaleColLabels();
3276 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
3278 // newer files have an 'autoCalculated' flag and store calculation
3279 // state in viewport properties
3280 jaa.autoCalculated = true; // means annotation will be marked for
3281 // update at end of load.
3283 if (an[i].hasGraphHeight())
3285 jaa.graphHeight = an[i].getGraphHeight();
3287 if (an[i].hasBelowAlignment())
3289 jaa.belowAlignment = an[i].isBelowAlignment();
3291 jaa.setCalcId(an[i].getCalcId());
3292 if (an[i].getPropertyCount() > 0)
3294 for (jalview.schemabinding.version2.Property prop : an[i]
3297 jaa.setProperty(prop.getName(), prop.getValue());
3300 if (jaa.autoCalculated)
3302 autoAlan.add(new JvAnnotRow(i, jaa));
3305 // if (!autoForView)
3307 // add autocalculated group annotation and any user created annotation
3309 al.addAnnotation(jaa);
3313 // ///////////////////////
3315 // Create alignment markup and styles for this view
3316 if (jms.getJGroupCount() > 0)
3318 JGroup[] groups = jms.getJGroup();
3319 boolean addAnnotSchemeGroup = false;
3320 for (int i = 0; i < groups.length; i++)
3322 JGroup jGroup = groups[i];
3323 ColourSchemeI cs = null;
3324 if (jGroup.getColour() != null)
3326 if (jGroup.getColour().startsWith("ucs"))
3328 cs = getUserColourScheme(jms, jGroup.getColour());
3330 else if (jGroup.getColour().equals("AnnotationColourGradient")
3331 && jGroup.getAnnotationColours() != null)
3333 addAnnotSchemeGroup = true;
3337 cs = ColourSchemeProperty.getColourScheme(al,
3338 jGroup.getColour());
3341 int pidThreshold = jGroup.getPidThreshold();
3343 Vector<SequenceI> seqs = new Vector<>();
3345 for (int s = 0; s < jGroup.getSeqCount(); s++)
3347 String seqId = jGroup.getSeq(s) + "";
3348 SequenceI ts = seqRefIds.get(seqId);
3352 seqs.addElement(ts);
3356 if (seqs.size() < 1)
3361 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3362 jGroup.getDisplayBoxes(), jGroup.getDisplayText(),
3363 jGroup.getColourText(), jGroup.getStart(), jGroup.getEnd());
3364 sg.getGroupColourScheme().setThreshold(pidThreshold, true);
3365 sg.getGroupColourScheme()
3366 .setConservationInc(jGroup.getConsThreshold());
3367 sg.setOutlineColour(new java.awt.Color(jGroup.getOutlineColour()));
3369 sg.textColour = new java.awt.Color(jGroup.getTextCol1());
3370 sg.textColour2 = new java.awt.Color(jGroup.getTextCol2());
3371 sg.setShowNonconserved(
3372 jGroup.hasShowUnconserved() ? jGroup.isShowUnconserved()
3374 sg.thresholdTextColour = jGroup.getTextColThreshold();
3375 if (jGroup.hasShowConsensusHistogram())
3377 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3380 if (jGroup.hasShowSequenceLogo())
3382 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3384 if (jGroup.hasNormaliseSequenceLogo())
3386 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3388 if (jGroup.hasIgnoreGapsinConsensus())
3390 sg.setIgnoreGapsConsensus(jGroup.getIgnoreGapsinConsensus());
3392 if (jGroup.getConsThreshold() != 0)
3394 Conservation c = new Conservation("All", sg.getSequences(null), 0,
3397 c.verdict(false, 25);
3398 sg.cs.setConservation(c);
3401 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3403 // re-instate unique group/annotation row reference
3404 List<AlignmentAnnotation> jaal = groupAnnotRefs
3405 .get(jGroup.getId());
3408 for (AlignmentAnnotation jaa : jaal)
3411 if (jaa.autoCalculated)
3413 // match up and try to set group autocalc alignment row for this
3415 if (jaa.label.startsWith("Consensus for "))
3417 sg.setConsensus(jaa);
3419 // match up and try to set group autocalc alignment row for this
3421 if (jaa.label.startsWith("Conservation for "))
3423 sg.setConservationRow(jaa);
3430 if (addAnnotSchemeGroup)
3432 // reconstruct the annotation colourscheme
3433 sg.setColourScheme(constructAnnotationColour(
3434 jGroup.getAnnotationColours(), null, al, jms, false));
3440 // only dataset in this model, so just return.
3443 // ///////////////////////////////
3446 // If we just load in the same jar file again, the sequenceSetId
3447 // will be the same, and we end up with multiple references
3448 // to the same sequenceSet. We must modify this id on load
3449 // so that each load of the file gives a unique id
3450 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3451 String viewId = (view.getId() == null ? null
3452 : view.getId() + uniqueSetSuffix);
3453 AlignFrame af = null;
3454 AlignViewport av = null;
3455 // now check to see if we really need to create a new viewport.
3456 if (multipleView && viewportsAdded.size() == 0)
3458 // We recovered an alignment for which a viewport already exists.
3459 // TODO: fix up any settings necessary for overlaying stored state onto
3460 // state recovered from another document. (may not be necessary).
3461 // we may need a binding from a viewport in memory to one recovered from
3463 // and then recover its containing af to allow the settings to be applied.
3464 // TODO: fix for vamsas demo
3466 "About to recover a viewport for existing alignment: Sequence set ID is "
3468 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3469 if (seqsetobj != null)
3471 if (seqsetobj instanceof String)
3473 uniqueSeqSetId = (String) seqsetobj;
3475 "Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
3481 "Warning : Collision between sequence set ID string and existing jalview object mapping.");
3487 * indicate that annotation colours are applied across all groups (pre
3488 * Jalview 2.8.1 behaviour)
3490 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan("2.8.1",
3491 object.getVersion());
3493 AlignmentPanel ap = null;
3494 boolean isnewview = true;
3497 // Check to see if this alignment already has a view id == viewId
3498 jalview.gui.AlignmentPanel views[] = Desktop
3499 .getAlignmentPanels(uniqueSeqSetId);
3500 if (views != null && views.length > 0)
3502 for (int v = 0; v < views.length; v++)
3504 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
3506 // recover the existing alignpanel, alignframe, viewport
3507 af = views[v].alignFrame;
3510 // TODO: could even skip resetting view settings if we don't want to
3511 // change the local settings from other jalview processes
3520 af = loadViewport(file, jseqs, hiddenSeqs, al, jms, view,
3521 uniqueSeqSetId, viewId, autoAlan);
3527 * Load any trees, PDB structures and viewers
3529 * Not done if flag is false (when this method is used for New View)
3531 if (loadTreesAndStructures)
3533 loadTrees(jms, view, af, av, ap);
3534 loadPDBStructures(jprovider, jseqs, af, ap);
3535 loadRnaViewers(jprovider, jseqs, ap);
3537 // and finally return.
3542 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
3543 * panel is restored from separate jar entries, two (gapped and trimmed) per
3544 * sequence and secondary structure.
3546 * Currently each viewer shows just one sequence and structure (gapped and
3547 * trimmed), however this method is designed to support multiple sequences or
3548 * structures in viewers if wanted in future.
3554 private void loadRnaViewers(jarInputStreamProvider jprovider,
3555 JSeq[] jseqs, AlignmentPanel ap)
3558 * scan the sequences for references to viewers; create each one the first
3559 * time it is referenced, add Rna models to existing viewers
3561 for (JSeq jseq : jseqs)
3563 for (int i = 0; i < jseq.getRnaViewerCount(); i++)
3565 RnaViewer viewer = jseq.getRnaViewer(i);
3566 AppVarna appVarna = findOrCreateVarnaViewer(viewer, uniqueSetSuffix,
3569 for (int j = 0; j < viewer.getSecondaryStructureCount(); j++)
3571 SecondaryStructure ss = viewer.getSecondaryStructure(j);
3572 SequenceI seq = seqRefIds.get(jseq.getId());
3573 AlignmentAnnotation ann = this.annotationIds
3574 .get(ss.getAnnotationId());
3577 * add the structure to the Varna display (with session state copied
3578 * from the jar to a temporary file)
3580 boolean gapped = ss.isGapped();
3581 String rnaTitle = ss.getTitle();
3582 String sessionState = ss.getViewerState();
3583 String tempStateFile = copyJarEntry(jprovider, sessionState,
3585 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
3586 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
3588 appVarna.setInitialSelection(viewer.getSelectedRna());
3594 * Locate and return an already instantiated matching AppVarna, or create one
3598 * @param viewIdSuffix
3602 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
3603 String viewIdSuffix, AlignmentPanel ap)
3606 * on each load a suffix is appended to the saved viewId, to avoid conflicts
3607 * if load is repeated
3609 String postLoadId = viewer.getViewId() + viewIdSuffix;
3610 for (JInternalFrame frame : getAllFrames())
3612 if (frame instanceof AppVarna)
3614 AppVarna varna = (AppVarna) frame;
3615 if (postLoadId.equals(varna.getViewId()))
3617 // this viewer is already instantiated
3618 // could in future here add ap as another 'parent' of the
3619 // AppVarna window; currently just 1-to-many
3626 * viewer not found - make it
3628 RnaViewerModel model = new RnaViewerModel(postLoadId, viewer.getTitle(),
3629 viewer.getXpos(), viewer.getYpos(), viewer.getWidth(),
3630 viewer.getHeight(), viewer.getDividerLocation());
3631 AppVarna varna = new AppVarna(model, ap);
3637 * Load any saved trees
3645 protected void loadTrees(JalviewModelSequence jms, Viewport view,
3646 AlignFrame af, AlignViewport av, AlignmentPanel ap)
3648 // TODO result of automated refactoring - are all these parameters needed?
3651 for (int t = 0; t < jms.getTreeCount(); t++)
3654 Tree tree = jms.getTree(t);
3656 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
3659 tp = af.showNewickTree(
3660 new jalview.io.NewickFile(tree.getNewick()),
3661 tree.getTitle(), tree.getWidth(), tree.getHeight(),
3662 tree.getXpos(), tree.getYpos());
3663 if (tree.getId() != null)
3665 // perhaps bind the tree id to something ?
3670 // update local tree attributes ?
3671 // TODO: should check if tp has been manipulated by user - if so its
3672 // settings shouldn't be modified
3673 tp.setTitle(tree.getTitle());
3674 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(),
3675 tree.getWidth(), tree.getHeight()));
3676 tp.av = av; // af.viewport; // TODO: verify 'associate with all
3679 tp.treeCanvas.av = av; // af.viewport;
3680 tp.treeCanvas.ap = ap; // af.alignPanel;
3685 warn("There was a problem recovering stored Newick tree: \n"
3686 + tree.getNewick());
3690 tp.fitToWindow.setState(tree.getFitToWindow());
3691 tp.fitToWindow_actionPerformed(null);
3693 if (tree.getFontName() != null)
3695 tp.setTreeFont(new java.awt.Font(tree.getFontName(),
3696 tree.getFontStyle(), tree.getFontSize()));
3700 tp.setTreeFont(new java.awt.Font(view.getFontName(),
3701 view.getFontStyle(), tree.getFontSize()));
3704 tp.showPlaceholders(tree.getMarkUnlinked());
3705 tp.showBootstrap(tree.getShowBootstrap());
3706 tp.showDistances(tree.getShowDistances());
3708 tp.treeCanvas.threshold = tree.getThreshold();
3710 if (tree.getCurrentTree())
3712 af.viewport.setCurrentTree(tp.getTree());
3716 } catch (Exception ex)
3718 ex.printStackTrace();
3723 * Load and link any saved structure viewers.
3730 protected void loadPDBStructures(jarInputStreamProvider jprovider,
3731 JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
3734 * Run through all PDB ids on the alignment, and collect mappings between
3735 * distinct view ids and all sequences referring to that view.
3737 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<>();
3739 for (int i = 0; i < jseqs.length; i++)
3741 if (jseqs[i].getPdbidsCount() > 0)
3743 Pdbids[] ids = jseqs[i].getPdbids();
3744 for (int p = 0; p < ids.length; p++)
3746 final int structureStateCount = ids[p].getStructureStateCount();
3747 for (int s = 0; s < structureStateCount; s++)
3749 // check to see if we haven't already created this structure view
3750 final StructureState structureState = ids[p]
3751 .getStructureState(s);
3752 String sviewid = (structureState.getViewId() == null) ? null
3753 : structureState.getViewId() + uniqueSetSuffix;
3754 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
3755 // Originally : ids[p].getFile()
3756 // : TODO: verify external PDB file recovery still works in normal
3757 // jalview project load
3758 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId(),
3760 jpdb.setId(ids[p].getId());
3762 int x = structureState.getXpos();
3763 int y = structureState.getYpos();
3764 int width = structureState.getWidth();
3765 int height = structureState.getHeight();
3767 // Probably don't need to do this anymore...
3768 // Desktop.desktop.getComponentAt(x, y);
3769 // TODO: NOW: check that this recovers the PDB file correctly.
3770 String pdbFile = loadPDBFile(jprovider, ids[p].getId(),
3772 jalview.datamodel.SequenceI seq = seqRefIds
3773 .get(jseqs[i].getId() + "");
3774 if (sviewid == null)
3776 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width + ","
3779 if (!structureViewers.containsKey(sviewid))
3781 structureViewers.put(sviewid,
3782 new StructureViewerModel(x, y, width, height, false,
3783 false, true, structureState.getViewId(),
3784 structureState.getType()));
3785 // Legacy pre-2.7 conversion JAL-823 :
3786 // do not assume any view has to be linked for colour by
3790 // assemble String[] { pdb files }, String[] { id for each
3791 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3792 // seqs_file 2}, boolean[] {
3793 // linkAlignPanel,superposeWithAlignpanel}} from hash
3794 StructureViewerModel jmoldat = structureViewers.get(sviewid);
3795 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
3796 | (structureState.hasAlignwithAlignPanel()
3797 ? structureState.getAlignwithAlignPanel()
3801 * Default colour by linked panel to false if not specified (e.g.
3802 * for pre-2.7 projects)
3804 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
3805 colourWithAlignPanel |= (structureState
3806 .hasColourwithAlignPanel()
3807 ? structureState.getColourwithAlignPanel()
3809 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
3812 * Default colour by viewer to true if not specified (e.g. for
3815 boolean colourByViewer = jmoldat.isColourByViewer();
3816 colourByViewer &= structureState.hasColourByJmol()
3817 ? structureState.getColourByJmol()
3819 jmoldat.setColourByViewer(colourByViewer);
3821 if (jmoldat.getStateData().length() < structureState
3822 .getContent().length())
3825 jmoldat.setStateData(structureState.getContent());
3828 if (ids[p].getFile() != null)
3830 File mapkey = new File(ids[p].getFile());
3831 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
3832 if (seqstrmaps == null)
3834 jmoldat.getFileData().put(mapkey,
3835 seqstrmaps = jmoldat.new StructureData(pdbFile,
3838 if (!seqstrmaps.getSeqList().contains(seq))
3840 seqstrmaps.getSeqList().add(seq);
3846 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");
3853 // Instantiate the associated structure views
3854 for (Entry<String, StructureViewerModel> entry : structureViewers
3859 createOrLinkStructureViewer(entry, af, ap, jprovider);
3860 } catch (Exception e)
3863 "Error loading structure viewer: " + e.getMessage());
3864 // failed - try the next one
3876 protected void createOrLinkStructureViewer(
3877 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3878 AlignmentPanel ap, jarInputStreamProvider jprovider)
3880 final StructureViewerModel stateData = viewerData.getValue();
3883 * Search for any viewer windows already open from other alignment views
3884 * that exactly match the stored structure state
3886 StructureViewerBase comp = findMatchingViewer(viewerData);
3890 linkStructureViewer(ap, comp, stateData);
3895 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
3896 * "viewer_"+stateData.viewId
3898 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
3900 createChimeraViewer(viewerData, af, jprovider);
3905 * else Jmol (if pre-2.9, stateData contains JMOL state string)
3907 createJmolViewer(viewerData, af, jprovider);
3912 * Create a new Chimera viewer.
3918 protected void createChimeraViewer(
3919 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3920 jarInputStreamProvider jprovider)
3922 StructureViewerModel data = viewerData.getValue();
3923 String chimeraSessionFile = data.getStateData();
3926 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
3928 * NB this is the 'saved' viewId as in the project file XML, _not_ the
3929 * 'uniquified' sviewid used to reconstruct the viewer here
3931 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
3932 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
3935 Set<Entry<File, StructureData>> fileData = data.getFileData()
3937 List<PDBEntry> pdbs = new ArrayList<>();
3938 List<SequenceI[]> allseqs = new ArrayList<>();
3939 for (Entry<File, StructureData> pdb : fileData)
3941 String filePath = pdb.getValue().getFilePath();
3942 String pdbId = pdb.getValue().getPdbId();
3943 // pdbs.add(new PDBEntry(filePath, pdbId));
3944 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
3945 final List<SequenceI> seqList = pdb.getValue().getSeqList();
3946 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
3950 boolean colourByChimera = data.isColourByViewer();
3951 boolean colourBySequence = data.isColourWithAlignPanel();
3953 // TODO use StructureViewer as a factory here, see JAL-1761
3954 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
3955 final SequenceI[][] seqsArray = allseqs
3956 .toArray(new SequenceI[allseqs.size()][]);
3957 String newViewId = viewerData.getKey();
3959 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
3960 af.alignPanel, pdbArray, seqsArray, colourByChimera,
3961 colourBySequence, newViewId);
3962 cvf.setSize(data.getWidth(), data.getHeight());
3963 cvf.setLocation(data.getX(), data.getY());
3967 * Create a new Jmol window. First parse the Jmol state to translate filenames
3968 * loaded into the view, and record the order in which files are shown in the
3969 * Jmol view, so we can add the sequence mappings in same order.
3975 protected void createJmolViewer(
3976 final Entry<String, StructureViewerModel> viewerData,
3977 AlignFrame af, jarInputStreamProvider jprovider)
3979 final StructureViewerModel svattrib = viewerData.getValue();
3980 String state = svattrib.getStateData();
3983 * Pre-2.9: state element value is the Jmol state string
3985 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
3988 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
3990 state = readJarEntry(jprovider,
3991 getViewerJarEntryName(svattrib.getViewId()));
3994 List<String> pdbfilenames = new ArrayList<>();
3995 List<SequenceI[]> seqmaps = new ArrayList<>();
3996 List<String> pdbids = new ArrayList<>();
3997 StringBuilder newFileLoc = new StringBuilder(64);
3998 int cp = 0, ncp, ecp;
3999 Map<File, StructureData> oldFiles = svattrib.getFileData();
4000 while ((ncp = state.indexOf("load ", cp)) > -1)
4004 // look for next filename in load statement
4005 newFileLoc.append(state.substring(cp,
4006 ncp = (state.indexOf("\"", ncp + 1) + 1)));
4007 String oldfilenam = state.substring(ncp,
4008 ecp = state.indexOf("\"", ncp));
4009 // recover the new mapping data for this old filename
4010 // have to normalize filename - since Jmol and jalview do
4012 // translation differently.
4013 StructureData filedat = oldFiles.get(new File(oldfilenam));
4014 if (filedat == null)
4016 String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\");
4017 filedat = oldFiles.get(new File(reformatedOldFilename));
4019 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
4020 pdbfilenames.add(filedat.getFilePath());
4021 pdbids.add(filedat.getPdbId());
4022 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4023 newFileLoc.append("\"");
4024 cp = ecp + 1; // advance beyond last \" and set cursor so we can
4025 // look for next file statement.
4026 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
4030 // just append rest of state
4031 newFileLoc.append(state.substring(cp));
4035 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
4036 newFileLoc = new StringBuilder(state);
4037 newFileLoc.append("; load append ");
4038 for (File id : oldFiles.keySet())
4040 // add this and any other pdb files that should be present in
4042 StructureData filedat = oldFiles.get(id);
4043 newFileLoc.append(filedat.getFilePath());
4044 pdbfilenames.add(filedat.getFilePath());
4045 pdbids.add(filedat.getPdbId());
4046 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4047 newFileLoc.append(" \"");
4048 newFileLoc.append(filedat.getFilePath());
4049 newFileLoc.append("\"");
4052 newFileLoc.append(";");
4055 if (newFileLoc.length() == 0)
4059 int histbug = newFileLoc.indexOf("history = ");
4063 * change "history = [true|false];" to "history = [1|0];"
4066 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
4067 String val = (diff == -1) ? null
4068 : newFileLoc.substring(histbug, diff);
4069 if (val != null && val.length() >= 4)
4071 if (val.contains("e")) // eh? what can it be?
4073 if (val.trim().equals("true"))
4081 newFileLoc.replace(histbug, diff, val);
4086 final String[] pdbf = pdbfilenames
4087 .toArray(new String[pdbfilenames.size()]);
4088 final String[] id = pdbids.toArray(new String[pdbids.size()]);
4089 final SequenceI[][] sq = seqmaps
4090 .toArray(new SequenceI[seqmaps.size()][]);
4091 final String fileloc = newFileLoc.toString();
4092 final String sviewid = viewerData.getKey();
4093 final AlignFrame alf = af;
4094 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
4095 svattrib.getWidth(), svattrib.getHeight());
4098 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
4103 JalviewStructureDisplayI sview = null;
4106 sview = new StructureViewer(
4107 alf.alignPanel.getStructureSelectionManager())
4108 .createView(StructureViewer.ViewerType.JMOL,
4109 pdbf, id, sq, alf.alignPanel, svattrib,
4110 fileloc, rect, sviewid);
4111 addNewStructureViewer(sview);
4112 } catch (OutOfMemoryError ex)
4114 new OOMWarning("restoring structure view for PDB id " + id,
4115 (OutOfMemoryError) ex.getCause());
4116 if (sview != null && sview.isVisible())
4118 sview.closeViewer(false);
4119 sview.setVisible(false);
4125 } catch (InvocationTargetException ex)
4127 warn("Unexpected error when opening Jmol view.", ex);
4129 } catch (InterruptedException e)
4131 // e.printStackTrace();
4137 * Generates a name for the entry in the project jar file to hold state
4138 * information for a structure viewer
4143 protected String getViewerJarEntryName(String viewId)
4145 return VIEWER_PREFIX + viewId;
4149 * Returns any open frame that matches given structure viewer data. The match
4150 * is based on the unique viewId, or (for older project versions) the frame's
4156 protected StructureViewerBase findMatchingViewer(
4157 Entry<String, StructureViewerModel> viewerData)
4159 final String sviewid = viewerData.getKey();
4160 final StructureViewerModel svattrib = viewerData.getValue();
4161 StructureViewerBase comp = null;
4162 JInternalFrame[] frames = getAllFrames();
4163 for (JInternalFrame frame : frames)
4165 if (frame instanceof StructureViewerBase)
4168 * Post jalview 2.4 schema includes structure view id
4170 if (sviewid != null && ((StructureViewerBase) frame).getViewId()
4173 comp = (StructureViewerBase) frame;
4174 break; // break added in 2.9
4177 * Otherwise test for matching position and size of viewer frame
4179 else if (frame.getX() == svattrib.getX()
4180 && frame.getY() == svattrib.getY()
4181 && frame.getHeight() == svattrib.getHeight()
4182 && frame.getWidth() == svattrib.getWidth())
4184 comp = (StructureViewerBase) frame;
4185 // no break in faint hope of an exact match on viewId
4193 * Link an AlignmentPanel to an existing structure viewer.
4198 * @param useinViewerSuperpos
4199 * @param usetoColourbyseq
4200 * @param viewerColouring
4202 protected void linkStructureViewer(AlignmentPanel ap,
4203 StructureViewerBase viewer, StructureViewerModel stateData)
4205 // NOTE: if the jalview project is part of a shared session then
4206 // view synchronization should/could be done here.
4208 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4209 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4210 final boolean viewerColouring = stateData.isColourByViewer();
4211 Map<File, StructureData> oldFiles = stateData.getFileData();
4214 * Add mapping for sequences in this view to an already open viewer
4216 final AAStructureBindingModel binding = viewer.getBinding();
4217 for (File id : oldFiles.keySet())
4219 // add this and any other pdb files that should be present in the
4221 StructureData filedat = oldFiles.get(id);
4222 String pdbFile = filedat.getFilePath();
4223 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4224 binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE);
4225 binding.addSequenceForStructFile(pdbFile, seq);
4227 // and add the AlignmentPanel's reference to the view panel
4228 viewer.addAlignmentPanel(ap);
4229 if (useinViewerSuperpos)
4231 viewer.useAlignmentPanelForSuperposition(ap);
4235 viewer.excludeAlignmentPanelForSuperposition(ap);
4237 if (usetoColourbyseq)
4239 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4243 viewer.excludeAlignmentPanelForColourbyseq(ap);
4248 * Get all frames within the Desktop.
4252 protected JInternalFrame[] getAllFrames()
4254 JInternalFrame[] frames = null;
4255 // TODO is this necessary - is it safe - risk of hanging?
4260 frames = Desktop.desktop.getAllFrames();
4261 } catch (ArrayIndexOutOfBoundsException e)
4263 // occasional No such child exceptions are thrown here...
4267 } catch (InterruptedException f)
4271 } while (frames == null);
4276 * Answers true if 'version' is equal to or later than 'supported', where each
4277 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4278 * changes. Development and test values for 'version' are leniently treated
4282 * - minimum version we are comparing against
4284 * - version of data being processsed
4287 public static boolean isVersionStringLaterThan(String supported,
4290 if (supported == null || version == null
4291 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4292 || version.equalsIgnoreCase("Test")
4293 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4295 System.err.println("Assuming project file with "
4296 + (version == null ? "null" : version)
4297 + " is compatible with Jalview version " + supported);
4302 return StringUtils.compareVersions(version, supported, "b") >= 0;
4306 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4308 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4310 if (newStructureViewers != null)
4312 sview.getBinding().setFinishedLoadingFromArchive(false);
4313 newStructureViewers.add(sview);
4317 protected void setLoadingFinishedForNewStructureViewers()
4319 if (newStructureViewers != null)
4321 for (JalviewStructureDisplayI sview : newStructureViewers)
4323 sview.getBinding().setFinishedLoadingFromArchive(true);
4325 newStructureViewers.clear();
4326 newStructureViewers = null;
4330 AlignFrame loadViewport(String file, JSeq[] JSEQ,
4331 List<SequenceI> hiddenSeqs, AlignmentI al,
4332 JalviewModelSequence jms, Viewport view, String uniqueSeqSetId,
4333 String viewId, List<JvAnnotRow> autoAlan)
4335 AlignFrame af = null;
4336 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
4337 uniqueSeqSetId, viewId);
4339 af.setFileName(file, FileFormat.Jalview);
4341 for (int i = 0; i < JSEQ.length; i++)
4343 af.viewport.setSequenceColour(
4344 af.viewport.getAlignment().getSequenceAt(i),
4345 new java.awt.Color(JSEQ[i].getColour()));
4350 af.getViewport().setColourByReferenceSeq(true);
4351 af.getViewport().setDisplayReferenceSeq(true);
4354 af.viewport.setGatherViewsHere(view.getGatheredViews());
4356 if (view.getSequenceSetId() != null)
4358 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4360 af.viewport.setSequenceSetId(uniqueSeqSetId);
4363 // propagate shared settings to this new view
4364 af.viewport.setHistoryList(av.getHistoryList());
4365 af.viewport.setRedoList(av.getRedoList());
4369 viewportsAdded.put(uniqueSeqSetId, af.viewport);
4371 // TODO: check if this method can be called repeatedly without
4372 // side-effects if alignpanel already registered.
4373 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4375 // apply Hidden regions to view.
4376 if (hiddenSeqs != null)
4378 for (int s = 0; s < JSEQ.length; s++)
4380 SequenceGroup hidden = new SequenceGroup();
4381 boolean isRepresentative = false;
4382 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
4384 isRepresentative = true;
4385 SequenceI sequenceToHide = al
4386 .getSequenceAt(JSEQ[s].getHiddenSequences(r));
4387 hidden.addSequence(sequenceToHide, false);
4388 // remove from hiddenSeqs list so we don't try to hide it twice
4389 hiddenSeqs.remove(sequenceToHide);
4391 if (isRepresentative)
4393 SequenceI representativeSequence = al.getSequenceAt(s);
4394 hidden.addSequence(representativeSequence, false);
4395 af.viewport.hideRepSequences(representativeSequence, hidden);
4399 SequenceI[] hseqs = hiddenSeqs
4400 .toArray(new SequenceI[hiddenSeqs.size()]);
4401 af.viewport.hideSequence(hseqs);
4404 // recover view properties and display parameters
4406 af.viewport.setShowAnnotation(view.getShowAnnotation());
4407 af.viewport.setAbovePIDThreshold(view.getPidSelected());
4408 af.viewport.setThreshold(view.getPidThreshold());
4410 af.viewport.setColourText(view.getShowColourText());
4412 af.viewport.setConservationSelected(view.getConservationSelected());
4413 af.viewport.setIncrement(view.getConsThreshold());
4414 af.viewport.setShowJVSuffix(view.getShowFullId());
4415 af.viewport.setRightAlignIds(view.getRightAlignIds());
4416 af.viewport.setFont(new java.awt.Font(view.getFontName(),
4417 view.getFontStyle(), view.getFontSize()), true);
4418 ViewStyleI vs = af.viewport.getViewStyle();
4419 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
4420 af.viewport.setViewStyle(vs);
4421 // TODO: allow custom charWidth/Heights to be restored by updating them
4422 // after setting font - which means set above to false
4423 af.viewport.setRenderGaps(view.getRenderGaps());
4424 af.viewport.setWrapAlignment(view.getWrapAlignment());
4425 af.viewport.setShowAnnotation(view.getShowAnnotation());
4427 af.viewport.setShowBoxes(view.getShowBoxes());
4429 af.viewport.setShowText(view.getShowText());
4431 af.viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
4432 af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
4433 af.viewport.setThresholdTextColour(view.getTextColThreshold());
4434 af.viewport.setShowUnconserved(
4435 view.hasShowUnconserved() ? view.isShowUnconserved() : false);
4436 af.viewport.getRanges().setStartRes(view.getStartRes());
4438 if (view.getViewName() != null)
4440 af.viewport.viewName = view.getViewName();
4441 af.setInitialTabVisible();
4443 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
4445 // startSeq set in af.alignPanel.updateLayout below
4446 af.alignPanel.updateLayout();
4447 ColourSchemeI cs = null;
4448 // apply colourschemes
4449 if (view.getBgColour() != null)
4451 if (view.getBgColour().startsWith("ucs"))
4453 cs = getUserColourScheme(jms, view.getBgColour());
4455 else if (view.getBgColour().startsWith("Annotation"))
4457 AnnotationColours viewAnnColour = view.getAnnotationColours();
4458 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
4465 cs = ColourSchemeProperty.getColourScheme(al, view.getBgColour());
4469 af.viewport.setGlobalColourScheme(cs);
4470 af.viewport.getResidueShading().setThreshold(view.getPidThreshold(),
4471 view.getIgnoreGapsinConsensus());
4472 af.viewport.getResidueShading()
4473 .setConsensus(af.viewport.getSequenceConsensusHash());
4474 af.viewport.setColourAppliesToAllGroups(false);
4476 if (view.getConservationSelected() && cs != null)
4478 af.viewport.getResidueShading()
4479 .setConservationInc(view.getConsThreshold());
4482 af.changeColour(cs);
4484 af.viewport.setColourAppliesToAllGroups(true);
4486 af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures());
4488 if (view.hasCentreColumnLabels())
4490 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
4492 if (view.hasIgnoreGapsinConsensus())
4494 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
4497 if (view.hasFollowHighlight())
4499 af.viewport.setFollowHighlight(view.getFollowHighlight());
4501 if (view.hasFollowSelection())
4503 af.viewport.followSelection = view.getFollowSelection();
4505 if (view.hasShowConsensusHistogram())
4508 .setShowConsensusHistogram(view.getShowConsensusHistogram());
4512 af.viewport.setShowConsensusHistogram(true);
4514 if (view.hasShowSequenceLogo())
4516 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
4520 af.viewport.setShowSequenceLogo(false);
4522 if (view.hasNormaliseSequenceLogo())
4524 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
4526 if (view.hasShowDbRefTooltip())
4528 af.viewport.setShowDBRefs(view.getShowDbRefTooltip());
4530 if (view.hasShowNPfeatureTooltip())
4532 af.viewport.setShowNPFeats(view.hasShowNPfeatureTooltip());
4534 if (view.hasShowGroupConsensus())
4536 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
4540 af.viewport.setShowGroupConsensus(false);
4542 if (view.hasShowGroupConservation())
4544 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
4548 af.viewport.setShowGroupConservation(false);
4551 // recover featre settings
4552 if (jms.getFeatureSettings() != null)
4554 FeaturesDisplayed fdi;
4555 af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
4556 String[] renderOrder = new String[jms.getFeatureSettings()
4557 .getSettingCount()];
4558 Map<String, FeatureColourI> featureColours = new Hashtable<>();
4559 Map<String, Float> featureOrder = new Hashtable<>();
4561 for (int fs = 0; fs < jms.getFeatureSettings()
4562 .getSettingCount(); fs++)
4564 Setting setting = jms.getFeatureSettings().getSetting(fs);
4565 if (setting.hasMincolour())
4567 FeatureColourI gc = setting.hasMin()
4568 ? new FeatureColour(new Color(setting.getMincolour()),
4569 new Color(setting.getColour()), setting.getMin(),
4571 : new FeatureColour(new Color(setting.getMincolour()),
4572 new Color(setting.getColour()), 0, 1);
4573 if (setting.hasThreshold())
4575 gc.setThreshold(setting.getThreshold());
4576 int threshstate = setting.getThreshstate();
4577 // -1 = None, 0 = Below, 1 = Above threshold
4578 if (threshstate == 0)
4580 gc.setBelowThreshold(true);
4582 else if (threshstate == 1)
4584 gc.setAboveThreshold(true);
4587 gc.setAutoScaled(true); // default
4588 if (setting.hasAutoScale())
4590 gc.setAutoScaled(setting.getAutoScale());
4592 if (setting.hasColourByLabel())
4594 gc.setColourByLabel(setting.getColourByLabel());
4596 // and put in the feature colour table.
4597 featureColours.put(setting.getType(), gc);
4601 featureColours.put(setting.getType(),
4602 new FeatureColour(new Color(setting.getColour())));
4604 renderOrder[fs] = setting.getType();
4605 if (setting.hasOrder())
4607 featureOrder.put(setting.getType(), setting.getOrder());
4611 featureOrder.put(setting.getType(), new Float(
4612 fs / jms.getFeatureSettings().getSettingCount()));
4614 if (setting.getDisplay())
4616 fdi.setVisible(setting.getType());
4619 Map<String, Boolean> fgtable = new Hashtable<>();
4620 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
4622 Group grp = jms.getFeatureSettings().getGroup(gs);
4623 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
4625 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4626 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
4627 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
4628 FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4629 fgtable, featureColours, 1.0f, featureOrder);
4630 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
4631 .transferSettings(frs);
4635 if (view.getHiddenColumnsCount() > 0)
4637 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
4639 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(),
4640 view.getHiddenColumns(c).getEnd() // +1
4644 if (view.getCalcIdParam() != null)
4646 for (CalcIdParam calcIdParam : view.getCalcIdParam())
4648 if (calcIdParam != null)
4650 if (recoverCalcIdParam(calcIdParam, af.viewport))
4655 warn("Couldn't recover parameters for "
4656 + calcIdParam.getCalcId());
4661 af.setMenusFromViewport(af.viewport);
4662 af.setTitle(view.getTitle());
4663 // TODO: we don't need to do this if the viewport is aready visible.
4665 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
4666 * has a 'cdna/protein complement' view, in which case save it in order to
4667 * populate a SplitFrame once all views have been read in.
4669 String complementaryViewId = view.getComplementId();
4670 if (complementaryViewId == null)
4672 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
4674 // recompute any autoannotation
4675 af.alignPanel.updateAnnotation(false, true);
4676 reorderAutoannotation(af, al, autoAlan);
4677 af.alignPanel.alignmentChanged();
4681 splitFrameCandidates.put(view, af);
4687 * Reads saved data to restore Colour by Annotation settings
4689 * @param viewAnnColour
4693 * @param checkGroupAnnColour
4696 private ColourSchemeI constructAnnotationColour(
4697 AnnotationColours viewAnnColour, AlignFrame af, AlignmentI al,
4698 JalviewModelSequence jms, boolean checkGroupAnnColour)
4700 boolean propagateAnnColour = false;
4701 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
4702 if (checkGroupAnnColour && al.getGroups() != null
4703 && al.getGroups().size() > 0)
4705 // pre 2.8.1 behaviour
4706 // check to see if we should transfer annotation colours
4707 propagateAnnColour = true;
4708 for (SequenceGroup sg : al.getGroups())
4710 if (sg.getColourScheme() instanceof AnnotationColourGradient)
4712 propagateAnnColour = false;
4718 * 2.10.2- : saved annotationId is AlignmentAnnotation.annotationId
4720 String annotationId = viewAnnColour.getAnnotation();
4721 AlignmentAnnotation matchedAnnotation = annotationIds.get(annotationId);
4724 * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
4726 if (matchedAnnotation == null
4727 && annAlignment.getAlignmentAnnotation() != null)
4729 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
4732 .equals(annAlignment.getAlignmentAnnotation()[i].label))
4734 matchedAnnotation = annAlignment.getAlignmentAnnotation()[i];
4739 if (matchedAnnotation == null)
4741 System.err.println("Failed to match annotation colour scheme for "
4745 if (matchedAnnotation.getThreshold() == null)
4747 matchedAnnotation.setThreshold(new GraphLine(
4748 viewAnnColour.getThreshold(), "Threshold", Color.black));
4751 AnnotationColourGradient cs = null;
4752 if (viewAnnColour.getColourScheme().equals("None"))
4754 cs = new AnnotationColourGradient(matchedAnnotation,
4755 new Color(viewAnnColour.getMinColour()),
4756 new Color(viewAnnColour.getMaxColour()),
4757 viewAnnColour.getAboveThreshold());
4759 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
4761 cs = new AnnotationColourGradient(matchedAnnotation,
4762 getUserColourScheme(jms, viewAnnColour.getColourScheme()),
4763 viewAnnColour.getAboveThreshold());
4767 cs = new AnnotationColourGradient(matchedAnnotation,
4768 ColourSchemeProperty.getColourScheme(al,
4769 viewAnnColour.getColourScheme()),
4770 viewAnnColour.getAboveThreshold());
4773 boolean perSequenceOnly = viewAnnColour.isPerSequence();
4774 boolean useOriginalColours = viewAnnColour.isPredefinedColours();
4775 cs.setSeqAssociated(perSequenceOnly);
4776 cs.setPredefinedColours(useOriginalColours);
4778 if (propagateAnnColour && al.getGroups() != null)
4780 // Also use these settings for all the groups
4781 for (int g = 0; g < al.getGroups().size(); g++)
4783 SequenceGroup sg = al.getGroups().get(g);
4784 if (sg.getGroupColourScheme() == null)
4789 AnnotationColourGradient groupScheme = new AnnotationColourGradient(
4790 matchedAnnotation, sg.getColourScheme(),
4791 viewAnnColour.getAboveThreshold());
4792 sg.setColourScheme(groupScheme);
4793 groupScheme.setSeqAssociated(perSequenceOnly);
4794 groupScheme.setPredefinedColours(useOriginalColours);
4800 private void reorderAutoannotation(AlignFrame af, AlignmentI al,
4801 List<JvAnnotRow> autoAlan)
4803 // copy over visualization settings for autocalculated annotation in the
4805 if (al.getAlignmentAnnotation() != null)
4808 * Kludge for magic autoannotation names (see JAL-811)
4810 String[] magicNames = new String[] { "Consensus", "Quality",
4812 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
4813 Hashtable<String, JvAnnotRow> visan = new Hashtable<>();
4814 for (String nm : magicNames)
4816 visan.put(nm, nullAnnot);
4818 for (JvAnnotRow auan : autoAlan)
4820 visan.put(auan.template.label
4821 + (auan.template.getCalcId() == null ? ""
4822 : "\t" + auan.template.getCalcId()),
4825 int hSize = al.getAlignmentAnnotation().length;
4826 List<JvAnnotRow> reorder = new ArrayList<>();
4827 // work through any autoCalculated annotation already on the view
4828 // removing it if it should be placed in a different location on the
4829 // annotation panel.
4830 List<String> remains = new ArrayList<>(visan.keySet());
4831 for (int h = 0; h < hSize; h++)
4833 jalview.datamodel.AlignmentAnnotation jalan = al
4834 .getAlignmentAnnotation()[h];
4835 if (jalan.autoCalculated)
4838 JvAnnotRow valan = visan.get(k = jalan.label);
4839 if (jalan.getCalcId() != null)
4841 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
4846 // delete the auto calculated row from the alignment
4847 al.deleteAnnotation(jalan, false);
4851 if (valan != nullAnnot)
4853 if (jalan != valan.template)
4855 // newly created autoannotation row instance
4856 // so keep a reference to the visible annotation row
4857 // and copy over all relevant attributes
4858 if (valan.template.graphHeight >= 0)
4861 jalan.graphHeight = valan.template.graphHeight;
4863 jalan.visible = valan.template.visible;
4865 reorder.add(new JvAnnotRow(valan.order, jalan));
4870 // Add any (possibly stale) autocalculated rows that were not appended to
4871 // the view during construction
4872 for (String other : remains)
4874 JvAnnotRow othera = visan.get(other);
4875 if (othera != nullAnnot && othera.template.getCalcId() != null
4876 && othera.template.getCalcId().length() > 0)
4878 reorder.add(othera);
4881 // now put the automatic annotation in its correct place
4882 int s = 0, srt[] = new int[reorder.size()];
4883 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
4884 for (JvAnnotRow jvar : reorder)
4887 srt[s++] = jvar.order;
4890 jalview.util.QuickSort.sort(srt, rws);
4891 // and re-insert the annotation at its correct position
4892 for (JvAnnotRow jvar : rws)
4894 al.addAnnotation(jvar.template, jvar.order);
4896 af.alignPanel.adjustAnnotationHeight();
4900 Hashtable skipList = null;
4903 * TODO remove this method
4906 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
4907 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
4908 * throw new Error("Implementation Error. No skipList defined for this
4909 * Jalview2XML instance."); } return (AlignFrame)
4910 * skipList.get(view.getSequenceSetId()); }
4914 * Check if the Jalview view contained in object should be skipped or not.
4917 * @return true if view's sequenceSetId is a key in skipList
4919 private boolean skipViewport(JalviewModel object)
4921 if (skipList == null)
4926 if (skipList.containsKey(
4927 id = object.getJalviewModelSequence().getViewport()[0]
4928 .getSequenceSetId()))
4930 if (Cache.log != null && Cache.log.isDebugEnabled())
4932 Cache.log.debug("Skipping seuqence set id " + id);
4939 public void addToSkipList(AlignFrame af)
4941 if (skipList == null)
4943 skipList = new Hashtable();
4945 skipList.put(af.getViewport().getSequenceSetId(), af);
4948 public void clearSkipList()
4950 if (skipList != null)
4957 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
4958 boolean ignoreUnrefed)
4960 jalview.datamodel.AlignmentI ds = getDatasetFor(
4961 vamsasSet.getDatasetId());
4962 Vector dseqs = null;
4965 // create a list of new dataset sequences
4966 dseqs = new Vector();
4968 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
4970 Sequence vamsasSeq = vamsasSet.getSequence(i);
4971 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
4973 // create a new dataset
4976 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
4977 dseqs.copyInto(dsseqs);
4978 ds = new jalview.datamodel.Alignment(dsseqs);
4979 debug("Created new dataset " + vamsasSet.getDatasetId()
4980 + " for alignment " + System.identityHashCode(al));
4981 addDatasetRef(vamsasSet.getDatasetId(), ds);
4983 // set the dataset for the newly imported alignment.
4984 if (al.getDataset() == null && !ignoreUnrefed)
4993 * sequence definition to create/merge dataset sequence for
4997 * vector to add new dataset sequence to
4998 * @param ignoreUnrefed
4999 * - when true, don't create new sequences from vamsasSeq if it's id
5000 * doesn't already have an asssociated Jalview sequence.
5002 * - used to reorder the sequence in the alignment according to the
5003 * vamsasSeq array ordering, to preserve ordering of dataset
5005 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
5006 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed, int vseqpos)
5008 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
5010 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
5011 boolean reorder = false;
5012 SequenceI dsq = null;
5013 if (sq != null && sq.getDatasetSequence() != null)
5015 dsq = sq.getDatasetSequence();
5021 if (sq == null && ignoreUnrefed)
5025 String sqid = vamsasSeq.getDsseqid();
5028 // need to create or add a new dataset sequence reference to this sequence
5031 dsq = seqRefIds.get(sqid);
5036 // make a new dataset sequence
5037 dsq = sq.createDatasetSequence();
5040 // make up a new dataset reference for this sequence
5041 sqid = seqHash(dsq);
5043 dsq.setVamsasId(uniqueSetSuffix + sqid);
5044 seqRefIds.put(sqid, dsq);
5049 dseqs.addElement(dsq);
5054 ds.addSequence(dsq);
5060 { // make this dataset sequence sq's dataset sequence
5061 sq.setDatasetSequence(dsq);
5062 // and update the current dataset alignment
5067 if (!dseqs.contains(dsq))
5074 if (ds.findIndex(dsq) < 0)
5076 ds.addSequence(dsq);
5083 // TODO: refactor this as a merge dataset sequence function
5084 // now check that sq (the dataset sequence) sequence really is the union of
5085 // all references to it
5086 // boolean pre = sq.getStart() < dsq.getStart();
5087 // boolean post = sq.getEnd() > dsq.getEnd();
5091 // StringBuffer sb = new StringBuffer();
5092 String newres = jalview.analysis.AlignSeq.extractGaps(
5093 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
5094 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
5095 && newres.length() > dsq.getLength())
5097 // Update with the longer sequence.
5101 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
5102 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
5103 * sb.append(newres.substring(newres.length() - sq.getEnd() -
5104 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
5106 dsq.setSequence(newres);
5108 // TODO: merges will never happen if we 'know' we have the real dataset
5109 // sequence - this should be detected when id==dssid
5111 "DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
5112 // + (pre ? "prepended" : "") + " "
5113 // + (post ? "appended" : ""));
5118 // sequence refs are identical. We may need to update the existing dataset
5119 // alignment with this one, though.
5120 if (ds != null && dseqs == null)
5122 int opos = ds.findIndex(dsq);
5123 SequenceI tseq = null;
5124 if (opos != -1 && vseqpos != opos)
5126 // remove from old position
5127 ds.deleteSequence(dsq);
5129 if (vseqpos < ds.getHeight())
5131 if (vseqpos != opos)
5133 // save sequence at destination position
5134 tseq = ds.getSequenceAt(vseqpos);
5135 ds.replaceSequenceAt(vseqpos, dsq);
5136 ds.addSequence(tseq);
5141 ds.addSequence(dsq);
5148 * TODO use AlignmentI here and in related methods - needs
5149 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
5151 Hashtable<String, AlignmentI> datasetIds = null;
5153 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
5155 private AlignmentI getDatasetFor(String datasetId)
5157 if (datasetIds == null)
5159 datasetIds = new Hashtable<>();
5162 if (datasetIds.containsKey(datasetId))
5164 return datasetIds.get(datasetId);
5169 private void addDatasetRef(String datasetId, AlignmentI dataset)
5171 if (datasetIds == null)
5173 datasetIds = new Hashtable<>();
5175 datasetIds.put(datasetId, dataset);
5179 * make a new dataset ID for this jalview dataset alignment
5184 private String getDatasetIdRef(AlignmentI dataset)
5186 if (dataset.getDataset() != null)
5188 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
5190 String datasetId = makeHashCode(dataset, null);
5191 if (datasetId == null)
5193 // make a new datasetId and record it
5194 if (dataset2Ids == null)
5196 dataset2Ids = new IdentityHashMap<>();
5200 datasetId = dataset2Ids.get(dataset);
5202 if (datasetId == null)
5204 datasetId = "ds" + dataset2Ids.size() + 1;
5205 dataset2Ids.put(dataset, datasetId);
5211 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5213 for (int d = 0; d < sequence.getDBRefCount(); d++)
5215 DBRef dr = sequence.getDBRef(d);
5216 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
5217 sequence.getDBRef(d).getSource(),
5218 sequence.getDBRef(d).getVersion(),
5219 sequence.getDBRef(d).getAccessionId());
5220 if (dr.getMapping() != null)
5222 entry.setMap(addMapping(dr.getMapping()));
5224 datasetSequence.addDBRef(entry);
5228 private jalview.datamodel.Mapping addMapping(Mapping m)
5230 SequenceI dsto = null;
5231 // Mapping m = dr.getMapping();
5232 int fr[] = new int[m.getMapListFromCount() * 2];
5233 Enumeration f = m.enumerateMapListFrom();
5234 for (int _i = 0; f.hasMoreElements(); _i += 2)
5236 MapListFrom mf = (MapListFrom) f.nextElement();
5237 fr[_i] = mf.getStart();
5238 fr[_i + 1] = mf.getEnd();
5240 int fto[] = new int[m.getMapListToCount() * 2];
5241 f = m.enumerateMapListTo();
5242 for (int _i = 0; f.hasMoreElements(); _i += 2)
5244 MapListTo mf = (MapListTo) f.nextElement();
5245 fto[_i] = mf.getStart();
5246 fto[_i + 1] = mf.getEnd();
5248 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto, fr,
5249 fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
5250 if (m.getMappingChoice() != null)
5252 MappingChoice mc = m.getMappingChoice();
5253 if (mc.getDseqFor() != null)
5255 String dsfor = "" + mc.getDseqFor();
5256 if (seqRefIds.containsKey(dsfor))
5261 jmap.setTo(seqRefIds.get(dsfor));
5265 frefedSequence.add(newMappingRef(dsfor, jmap));
5271 * local sequence definition
5273 Sequence ms = mc.getSequence();
5274 SequenceI djs = null;
5275 String sqid = ms.getDsseqid();
5276 if (sqid != null && sqid.length() > 0)
5279 * recover dataset sequence
5281 djs = seqRefIds.get(sqid);
5286 "Warning - making up dataset sequence id for DbRef sequence map reference");
5287 sqid = ((Object) ms).toString(); // make up a new hascode for
5288 // undefined dataset sequence hash
5289 // (unlikely to happen)
5295 * make a new dataset sequence and add it to refIds hash
5297 djs = new jalview.datamodel.Sequence(ms.getName(),
5299 djs.setStart(jmap.getMap().getToLowest());
5300 djs.setEnd(jmap.getMap().getToHighest());
5301 djs.setVamsasId(uniqueSetSuffix + sqid);
5303 incompleteSeqs.put(sqid, djs);
5304 seqRefIds.put(sqid, djs);
5307 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5317 * Provides a 'copy' of an alignment view (on action New View) by 'saving' the
5318 * view as XML (but not to file), and then reloading it
5323 public AlignmentPanel copyAlignPanel(AlignmentPanel ap)
5326 JalviewModel jm = saveState(ap, null, null, null);
5328 uniqueSetSuffix = "";
5329 jm.getJalviewModelSequence().getViewport(0).setId(null);
5330 // we don't overwrite the view we just copied
5332 if (this.frefedSequence == null)
5334 frefedSequence = new Vector<SeqFref>();
5337 viewportsAdded.clear();
5339 AlignFrame af = loadFromObject(jm, null, false, null);
5340 af.alignPanels.clear();
5341 af.closeMenuItem_actionPerformed(true);
5344 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5345 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5346 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5347 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5348 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5351 return af.alignPanel;
5354 private Hashtable jvids2vobj;
5356 private void warn(String msg)
5361 private void warn(String msg, Exception e)
5363 if (Cache.log != null)
5367 Cache.log.warn(msg, e);
5371 Cache.log.warn(msg);
5376 System.err.println("Warning: " + msg);
5379 e.printStackTrace();
5384 private void debug(String string)
5386 debug(string, null);
5389 private void debug(String msg, Exception e)
5391 if (Cache.log != null)
5395 Cache.log.debug(msg, e);
5399 Cache.log.debug(msg);
5404 System.err.println("Warning: " + msg);
5407 e.printStackTrace();
5413 * set the object to ID mapping tables used to write/recover objects and XML
5414 * ID strings for the jalview project. If external tables are provided then
5415 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
5416 * object goes out of scope. - also populates the datasetIds hashtable with
5417 * alignment objects containing dataset sequences
5420 * Map from ID strings to jalview datamodel
5422 * Map from jalview datamodel to ID strings
5426 public void setObjectMappingTables(Hashtable vobj2jv,
5427 IdentityHashMap jv2vobj)
5429 this.jv2vobj = jv2vobj;
5430 this.vobj2jv = vobj2jv;
5431 Iterator ds = jv2vobj.keySet().iterator();
5433 while (ds.hasNext())
5435 Object jvobj = ds.next();
5436 id = jv2vobj.get(jvobj).toString();
5437 if (jvobj instanceof jalview.datamodel.Alignment)
5439 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
5441 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
5444 else if (jvobj instanceof jalview.datamodel.Sequence)
5446 // register sequence object so the XML parser can recover it.
5447 if (seqRefIds == null)
5449 seqRefIds = new HashMap<>();
5451 if (seqsToIds == null)
5453 seqsToIds = new IdentityHashMap<>();
5455 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
5456 seqsToIds.put((SequenceI) jvobj, id);
5458 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
5461 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
5462 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
5463 if (jvann.annotationId == null)
5465 jvann.annotationId = anid;
5467 if (!jvann.annotationId.equals(anid))
5469 // TODO verify that this is the correct behaviour
5470 this.warn("Overriding Annotation ID for " + anid
5471 + " from different id : " + jvann.annotationId);
5472 jvann.annotationId = anid;
5475 else if (jvobj instanceof String)
5477 if (jvids2vobj == null)
5479 jvids2vobj = new Hashtable();
5480 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
5485 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
5491 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
5492 * objects created from the project archive. If string is null (default for
5493 * construction) then suffix will be set automatically.
5497 public void setUniqueSetSuffix(String string)
5499 uniqueSetSuffix = string;
5504 * uses skipList2 as the skipList for skipping views on sequence sets
5505 * associated with keys in the skipList
5509 public void setSkipList(Hashtable skipList2)
5511 skipList = skipList2;
5515 * Reads the jar entry of given name and returns its contents, or null if the
5516 * entry is not found.
5519 * @param jarEntryName
5522 protected String readJarEntry(jarInputStreamProvider jprovider,
5523 String jarEntryName)
5525 String result = null;
5526 BufferedReader in = null;
5531 * Reopen the jar input stream and traverse its entries to find a matching
5534 JarInputStream jin = jprovider.getJarInputStream();
5535 JarEntry entry = null;
5538 entry = jin.getNextJarEntry();
5539 } while (entry != null && !entry.getName().equals(jarEntryName));
5543 StringBuilder out = new StringBuilder(256);
5544 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
5547 while ((data = in.readLine()) != null)
5551 result = out.toString();
5555 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
5557 } catch (Exception ex)
5559 ex.printStackTrace();
5567 } catch (IOException e)
5578 * Returns an incrementing counter (0, 1, 2...)
5582 private synchronized int nextCounter()