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.SequenceGroup;
36 import jalview.datamodel.SequenceI;
37 import jalview.datamodel.StructureViewerModel;
38 import jalview.datamodel.StructureViewerModel.StructureData;
39 import jalview.ext.varna.RnaModel;
40 import jalview.gui.StructureViewer.ViewerType;
41 import jalview.io.DataSourceType;
42 import jalview.io.FileFormat;
43 import jalview.renderer.ResidueShaderI;
44 import jalview.schemabinding.version2.AlcodMap;
45 import jalview.schemabinding.version2.AlcodonFrame;
46 import jalview.schemabinding.version2.Annotation;
47 import jalview.schemabinding.version2.AnnotationColours;
48 import jalview.schemabinding.version2.AnnotationElement;
49 import jalview.schemabinding.version2.CalcIdParam;
50 import jalview.schemabinding.version2.DBRef;
51 import jalview.schemabinding.version2.Features;
52 import jalview.schemabinding.version2.Group;
53 import jalview.schemabinding.version2.HiddenColumns;
54 import jalview.schemabinding.version2.JGroup;
55 import jalview.schemabinding.version2.JSeq;
56 import jalview.schemabinding.version2.JalviewModel;
57 import jalview.schemabinding.version2.JalviewModelSequence;
58 import jalview.schemabinding.version2.MapListFrom;
59 import jalview.schemabinding.version2.MapListTo;
60 import jalview.schemabinding.version2.Mapping;
61 import jalview.schemabinding.version2.MappingChoice;
62 import jalview.schemabinding.version2.OtherData;
63 import jalview.schemabinding.version2.PdbentryItem;
64 import jalview.schemabinding.version2.Pdbids;
65 import jalview.schemabinding.version2.Property;
66 import jalview.schemabinding.version2.RnaViewer;
67 import jalview.schemabinding.version2.SecondaryStructure;
68 import jalview.schemabinding.version2.Sequence;
69 import jalview.schemabinding.version2.SequenceSet;
70 import jalview.schemabinding.version2.SequenceSetProperties;
71 import jalview.schemabinding.version2.Setting;
72 import jalview.schemabinding.version2.StructureState;
73 import jalview.schemabinding.version2.ThresholdLine;
74 import jalview.schemabinding.version2.Tree;
75 import jalview.schemabinding.version2.UserColours;
76 import jalview.schemabinding.version2.Viewport;
77 import jalview.schemes.AnnotationColourGradient;
78 import jalview.schemes.ColourSchemeI;
79 import jalview.schemes.ColourSchemeProperty;
80 import jalview.schemes.FeatureColour;
81 import jalview.schemes.ResidueProperties;
82 import jalview.schemes.UserColourScheme;
83 import jalview.structure.StructureSelectionManager;
84 import jalview.structures.models.AAStructureBindingModel;
85 import jalview.util.MessageManager;
86 import jalview.util.Platform;
87 import jalview.util.StringUtils;
88 import jalview.util.jarInputStreamProvider;
89 import jalview.viewmodel.AlignmentViewport;
90 import jalview.viewmodel.ViewportRanges;
91 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
92 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
93 import jalview.ws.jws2.Jws2Discoverer;
94 import jalview.ws.jws2.dm.AAConSettings;
95 import jalview.ws.jws2.jabaws2.Jws2Instance;
96 import jalview.ws.params.ArgumentI;
97 import jalview.ws.params.AutoCalcSetting;
98 import jalview.ws.params.WsParamSetI;
100 import java.awt.Color;
101 import java.awt.Rectangle;
102 import java.io.BufferedReader;
103 import java.io.DataInputStream;
104 import java.io.DataOutputStream;
106 import java.io.FileInputStream;
107 import java.io.FileOutputStream;
108 import java.io.IOException;
109 import java.io.InputStreamReader;
110 import java.io.OutputStreamWriter;
111 import java.io.PrintWriter;
112 import java.lang.reflect.InvocationTargetException;
113 import java.net.MalformedURLException;
115 import java.util.ArrayList;
116 import java.util.Arrays;
117 import java.util.Enumeration;
118 import java.util.HashMap;
119 import java.util.HashSet;
120 import java.util.Hashtable;
121 import java.util.IdentityHashMap;
122 import java.util.Iterator;
123 import java.util.LinkedHashMap;
124 import java.util.List;
125 import java.util.Map;
126 import java.util.Map.Entry;
127 import java.util.Set;
128 import java.util.Vector;
129 import java.util.jar.JarEntry;
130 import java.util.jar.JarInputStream;
131 import java.util.jar.JarOutputStream;
133 import javax.swing.JInternalFrame;
134 import javax.swing.SwingUtilities;
136 import org.exolab.castor.xml.Marshaller;
137 import org.exolab.castor.xml.Unmarshaller;
140 * Write out the current jalview desktop state as a Jalview XML stream.
142 * Note: the vamsas objects referred to here are primitive versions of the
143 * VAMSAS project schema elements - they are not the same and most likely never
147 * @version $Revision: 1.134 $
149 public class Jalview2XML
151 private static final String VIEWER_PREFIX = "viewer_";
153 private static final String RNA_PREFIX = "rna_";
155 private static final String UTF_8 = "UTF-8";
157 // use this with nextCounter() to make unique names for entities
158 private int counter = 0;
161 * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
162 * of sequence objects are created.
164 IdentityHashMap<SequenceI, String> seqsToIds = null;
167 * jalview XML Sequence ID to jalview sequence object reference (both dataset
168 * and alignment sequences. Populated as XML reps of sequence objects are
171 Map<String, SequenceI> seqRefIds = null;
173 Map<String, SequenceI> incompleteSeqs = null;
175 List<SeqFref> frefedSequence = null;
177 boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
180 * Map of reconstructed AlignFrame objects that appear to have come from
181 * SplitFrame objects (have a dna/protein complement view).
183 private Map<Viewport, AlignFrame> splitFrameCandidates = new HashMap<>();
186 * Map from displayed rna structure models to their saved session state jar
189 private Map<RnaModel, String> rnaSessions = new HashMap<>();
192 * create/return unique hash string for sq
195 * @return new or existing unique string for sq
197 String seqHash(SequenceI sq)
199 if (seqsToIds == null)
203 if (seqsToIds.containsKey(sq))
205 return seqsToIds.get(sq);
209 // create sequential key
210 String key = "sq" + (seqsToIds.size() + 1);
211 key = makeHashCode(sq, key); // check we don't have an external reference
213 seqsToIds.put(sq, key);
222 if (seqRefIds != null)
226 if (seqsToIds != null)
230 if (incompleteSeqs != null)
232 incompleteSeqs.clear();
240 warn("clearSeqRefs called when _cleartables was not set. Doing nothing.");
241 // seqRefIds = new Hashtable();
242 // seqsToIds = new IdentityHashMap();
248 if (seqsToIds == null)
250 seqsToIds = new IdentityHashMap<>();
252 if (seqRefIds == null)
254 seqRefIds = new HashMap<>();
256 if (incompleteSeqs == null)
258 incompleteSeqs = new HashMap<>();
260 if (frefedSequence == null)
262 frefedSequence = new ArrayList<>();
270 public Jalview2XML(boolean raiseGUI)
272 this.raiseGUI = raiseGUI;
276 * base class for resolving forward references to sequences by their ID
281 abstract class SeqFref
287 public SeqFref(String _sref, String type)
293 public String getSref()
298 public SequenceI getSrefSeq()
300 return seqRefIds.get(sref);
303 public boolean isResolvable()
305 return seqRefIds.get(sref) != null;
308 public SequenceI getSrefDatasetSeq()
310 SequenceI sq = seqRefIds.get(sref);
313 while (sq.getDatasetSequence() != null)
315 sq = sq.getDatasetSequence();
322 * @return true if the forward reference was fully resolved
324 abstract boolean resolve();
327 public String toString()
329 return type + " reference to " + sref;
334 * create forward reference for a mapping
340 public SeqFref newMappingRef(final String sref,
341 final jalview.datamodel.Mapping _jmap)
343 SeqFref fref = new SeqFref(sref, "Mapping")
345 public jalview.datamodel.Mapping jmap = _jmap;
350 SequenceI seq = getSrefDatasetSeq();
362 public SeqFref newAlcodMapRef(final String sref,
363 final AlignedCodonFrame _cf, final jalview.datamodel.Mapping _jmap)
366 SeqFref fref = new SeqFref(sref, "Codon Frame")
368 AlignedCodonFrame cf = _cf;
370 public jalview.datamodel.Mapping mp = _jmap;
373 public boolean isResolvable()
375 return super.isResolvable() && mp.getTo() != null;
381 SequenceI seq = getSrefDatasetSeq();
386 cf.addMap(seq, mp.getTo(), mp.getMap());
393 public void resolveFrefedSequences()
395 Iterator<SeqFref> nextFref = frefedSequence.iterator();
396 int toresolve = frefedSequence.size();
397 int unresolved = 0, failedtoresolve = 0;
398 while (nextFref.hasNext())
400 SeqFref ref = nextFref.next();
401 if (ref.isResolvable())
413 } catch (Exception x)
416 .println("IMPLEMENTATION ERROR: Failed to resolve forward reference for sequence "
429 System.err.println("Jalview Project Import: There were " + unresolved
430 + " forward references left unresolved on the stack.");
432 if (failedtoresolve > 0)
434 System.err.println("SERIOUS! " + failedtoresolve
435 + " resolvable forward references failed to resolve.");
437 if (incompleteSeqs != null && incompleteSeqs.size() > 0)
439 System.err.println("Jalview Project Import: There are "
440 + incompleteSeqs.size()
441 + " sequences which may have incomplete metadata.");
442 if (incompleteSeqs.size() < 10)
444 for (SequenceI s : incompleteSeqs.values())
446 System.err.println(s.toString());
452 .println("Too many to report. Skipping output of incomplete sequences.");
458 * This maintains a map of viewports, the key being the seqSetId. Important to
459 * set historyItem and redoList for multiple views
461 Map<String, AlignViewport> viewportsAdded = new HashMap<>();
463 Map<String, AlignmentAnnotation> annotationIds = new HashMap<>();
465 String uniqueSetSuffix = "";
468 * List of pdbfiles added to Jar
470 List<String> pdbfiles = null;
472 // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
473 public void saveState(File statefile)
475 FileOutputStream fos = null;
478 fos = new FileOutputStream(statefile);
479 JarOutputStream jout = new JarOutputStream(fos);
482 } catch (Exception e)
484 // TODO: inform user of the problem - they need to know if their data was
486 if (errorMessage == null)
488 errorMessage = "Couldn't write Jalview Archive to output file '"
489 + statefile + "' - See console error log for details";
493 errorMessage += "(output file was '" + statefile + "')";
503 } catch (IOException e)
513 * Writes a jalview project archive to the given Jar output stream.
517 public void saveState(JarOutputStream jout)
519 AlignFrame[] frames = Desktop.getAlignFrames();
525 saveAllFrames(Arrays.asList(frames), jout);
529 * core method for storing state for a set of AlignFrames.
532 * - frames involving all data to be exported (including containing
535 * - project output stream
537 private void saveAllFrames(List<AlignFrame> frames, JarOutputStream jout)
539 Hashtable<String, AlignFrame> dsses = new Hashtable<>();
542 * ensure cached data is clear before starting
544 // todo tidy up seqRefIds, seqsToIds initialisation / reset
546 splitFrameCandidates.clear();
551 // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
552 // //////////////////////////////////////////////////
554 List<String> shortNames = new ArrayList<>();
555 List<String> viewIds = new ArrayList<>();
558 for (int i = frames.size() - 1; i > -1; i--)
560 AlignFrame af = frames.get(i);
564 .containsKey(af.getViewport().getSequenceSetId()))
569 String shortName = makeFilename(af, shortNames);
571 int ap, apSize = af.alignPanels.size();
573 for (ap = 0; ap < apSize; ap++)
575 AlignmentPanel apanel = af.alignPanels.get(ap);
576 String fileName = apSize == 1 ? shortName : ap + shortName;
577 if (!fileName.endsWith(".xml"))
579 fileName = fileName + ".xml";
582 saveState(apanel, fileName, jout, viewIds);
584 String dssid = getDatasetIdRef(af.getViewport().getAlignment()
586 if (!dsses.containsKey(dssid))
588 dsses.put(dssid, af);
593 writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix,
599 } catch (Exception foo)
604 } catch (Exception ex)
606 // TODO: inform user of the problem - they need to know if their data was
608 if (errorMessage == null)
610 errorMessage = "Couldn't write Jalview Archive - see error output for details";
612 ex.printStackTrace();
617 * Generates a distinct file name, based on the title of the AlignFrame, by
618 * appending _n for increasing n until an unused name is generated. The new
619 * name (without its extension) is added to the list.
623 * @return the generated name, with .xml extension
625 protected String makeFilename(AlignFrame af, List<String> namesUsed)
627 String shortName = af.getTitle();
629 if (shortName.indexOf(File.separatorChar) > -1)
631 shortName = shortName.substring(shortName
632 .lastIndexOf(File.separatorChar) + 1);
637 while (namesUsed.contains(shortName))
639 if (shortName.endsWith("_" + (count - 1)))
641 shortName = shortName.substring(0, shortName.lastIndexOf("_"));
644 shortName = shortName.concat("_" + count);
648 namesUsed.add(shortName);
650 if (!shortName.endsWith(".xml"))
652 shortName = shortName + ".xml";
657 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
658 public boolean saveAlignment(AlignFrame af, String jarFile,
663 FileOutputStream fos = new FileOutputStream(jarFile);
664 JarOutputStream jout = new JarOutputStream(fos);
665 List<AlignFrame> frames = new ArrayList<>();
667 // resolve splitframes
668 if (af.getViewport().getCodingComplement() != null)
670 frames = ((SplitFrame) af.getSplitViewContainer()).getAlignFrames();
676 saveAllFrames(frames, jout);
680 } catch (Exception foo)
686 } catch (Exception ex)
688 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
689 ex.printStackTrace();
694 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
695 String fileName, JarOutputStream jout)
698 for (String dssids : dsses.keySet())
700 AlignFrame _af = dsses.get(dssids);
701 String jfileName = fileName + " Dataset for " + _af.getTitle();
702 if (!jfileName.endsWith(".xml"))
704 jfileName = jfileName + ".xml";
706 saveState(_af.alignPanel, jfileName, true, jout, null);
711 * create a JalviewModel from an alignment view and marshall it to a
715 * panel to create jalview model for
717 * name of alignment panel written to output stream
724 public JalviewModel saveState(AlignmentPanel ap, String fileName,
725 JarOutputStream jout, List<String> viewIds)
727 return saveState(ap, fileName, false, jout, viewIds);
731 * create a JalviewModel from an alignment view and marshall it to a
735 * panel to create jalview model for
737 * name of alignment panel written to output stream
739 * when true, only write the dataset for the alignment, not the data
740 * associated with the view.
746 public JalviewModel saveState(AlignmentPanel ap, String fileName,
747 boolean storeDS, JarOutputStream jout, List<String> viewIds)
751 viewIds = new ArrayList<>();
756 List<UserColourScheme> userColours = new ArrayList<>();
758 AlignViewport av = ap.av;
759 ViewportRanges vpRanges = av.getRanges();
761 JalviewModel object = new JalviewModel();
762 object.setVamsasModel(new jalview.schemabinding.version2.VamsasModel());
764 object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
765 object.setVersion(jalview.bin.Cache.getDefault("VERSION",
766 "Development Build"));
769 * rjal is full height alignment, jal is actual alignment with full metadata
770 * but excludes hidden sequences.
772 jalview.datamodel.AlignmentI rjal = av.getAlignment(), jal = rjal;
774 if (av.hasHiddenRows())
776 rjal = jal.getHiddenSequences().getFullAlignment();
779 SequenceSet vamsasSet = new SequenceSet();
781 JalviewModelSequence jms = new JalviewModelSequence();
783 vamsasSet.setGapChar(jal.getGapCharacter() + "");
785 if (jal.getDataset() != null)
787 // dataset id is the dataset's hashcode
788 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
791 // switch jal and the dataset
792 jal = jal.getDataset();
796 if (jal.getProperties() != null)
798 Enumeration en = jal.getProperties().keys();
799 while (en.hasMoreElements())
801 String key = en.nextElement().toString();
802 SequenceSetProperties ssp = new SequenceSetProperties();
804 ssp.setValue(jal.getProperties().get(key).toString());
805 vamsasSet.addSequenceSetProperties(ssp);
810 Set<String> calcIdSet = new HashSet<>();
811 // record the set of vamsas sequence XML POJO we create.
812 HashMap<String, Sequence> vamsasSetIds = new HashMap<>();
814 for (final SequenceI jds : rjal.getSequences())
816 final SequenceI jdatasq = jds.getDatasetSequence() == null ? jds
817 : jds.getDatasetSequence();
818 String id = seqHash(jds);
819 if (vamsasSetIds.get(id) == null)
821 if (seqRefIds.get(id) != null && !storeDS)
823 // This happens for two reasons: 1. multiple views are being
825 // 2. the hashCode has collided with another sequence's code. This
827 // HAPPEN! (PF00072.15.stk does this)
828 // JBPNote: Uncomment to debug writing out of files that do not read
829 // back in due to ArrayOutOfBoundExceptions.
830 // System.err.println("vamsasSeq backref: "+id+"");
831 // System.err.println(jds.getName()+"
832 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
833 // System.err.println("Hashcode: "+seqHash(jds));
834 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
835 // System.err.println(rsq.getName()+"
836 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
837 // System.err.println("Hashcode: "+seqHash(rsq));
841 vamsasSeq = createVamsasSequence(id, jds);
842 vamsasSet.addSequence(vamsasSeq);
843 vamsasSetIds.put(id, vamsasSeq);
844 seqRefIds.put(id, jds);
848 jseq.setStart(jds.getStart());
849 jseq.setEnd(jds.getEnd());
850 jseq.setColour(av.getSequenceColour(jds).getRGB());
852 jseq.setId(id); // jseq id should be a string not a number
855 // Store any sequences this sequence represents
856 if (av.hasHiddenRows())
858 // use rjal, contains the full height alignment
859 jseq.setHidden(av.getAlignment().getHiddenSequences()
862 if (av.isHiddenRepSequence(jds))
864 jalview.datamodel.SequenceI[] reps = av
865 .getRepresentedSequences(jds).getSequencesInOrder(rjal);
867 for (int h = 0; h < reps.length; h++)
871 jseq.addHiddenSequences(rjal.findIndex(reps[h]));
876 // mark sequence as reference - if it is the reference for this view
879 jseq.setViewreference(jds == jal.getSeqrep());
883 // TODO: omit sequence features from each alignment view's XML dump if we
884 // are storing dataset
885 if (jds.getSequenceFeatures() != null)
887 jalview.datamodel.SequenceFeature[] sf = jds.getSequenceFeatures();
889 while (index < sf.length)
891 Features features = new Features();
893 features.setBegin(sf[index].getBegin());
894 features.setEnd(sf[index].getEnd());
895 features.setDescription(sf[index].getDescription());
896 features.setType(sf[index].getType());
897 features.setFeatureGroup(sf[index].getFeatureGroup());
898 features.setScore(sf[index].getScore());
899 if (sf[index].links != null)
901 for (int l = 0; l < sf[index].links.size(); l++)
903 OtherData keyValue = new OtherData();
904 keyValue.setKey("LINK_" + l);
905 keyValue.setValue(sf[index].links.elementAt(l).toString());
906 features.addOtherData(keyValue);
909 if (sf[index].otherDetails != null)
912 Iterator<String> keys = sf[index].otherDetails.keySet()
914 while (keys.hasNext())
917 OtherData keyValue = new OtherData();
918 keyValue.setKey(key);
919 keyValue.setValue(sf[index].otherDetails.get(key).toString());
920 features.addOtherData(keyValue);
924 jseq.addFeatures(features);
929 if (jdatasq.getAllPDBEntries() != null)
931 Enumeration en = jdatasq.getAllPDBEntries().elements();
932 while (en.hasMoreElements())
934 Pdbids pdb = new Pdbids();
935 jalview.datamodel.PDBEntry entry = (jalview.datamodel.PDBEntry) en
938 String pdbId = entry.getId();
940 pdb.setType(entry.getType());
943 * Store any structure views associated with this sequence. This
944 * section copes with duplicate entries in the project, so a dataset
945 * only view *should* be coped with sensibly.
947 // This must have been loaded, is it still visible?
948 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
949 String matchedFile = null;
950 for (int f = frames.length - 1; f > -1; f--)
952 if (frames[f] instanceof StructureViewerBase)
954 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
955 matchedFile = saveStructureState(ap, jds, pdb, entry,
956 viewIds, matchedFile, viewFrame);
958 * Only store each structure viewer's state once in the project
959 * jar. First time through only (storeDS==false)
961 String viewId = viewFrame.getViewId();
962 if (!storeDS && !viewIds.contains(viewId))
967 String viewerState = viewFrame.getStateInfo();
968 writeJarEntry(jout, getViewerJarEntryName(viewId),
969 viewerState.getBytes());
970 } catch (IOException e)
972 System.err.println("Error saving viewer state: "
979 if (matchedFile != null || entry.getFile() != null)
981 if (entry.getFile() != null)
984 matchedFile = entry.getFile();
986 pdb.setFile(matchedFile); // entry.getFile());
987 if (pdbfiles == null)
989 pdbfiles = new ArrayList<>();
992 if (!pdbfiles.contains(pdbId))
995 copyFileToJar(jout, matchedFile, pdbId);
999 Enumeration<String> props = entry.getProperties();
1000 if (props.hasMoreElements())
1002 PdbentryItem item = new PdbentryItem();
1003 while (props.hasMoreElements())
1005 Property prop = new Property();
1006 String key = props.nextElement();
1008 prop.setValue(entry.getProperty(key).toString());
1009 item.addProperty(prop);
1011 pdb.addPdbentryItem(item);
1014 jseq.addPdbids(pdb);
1018 saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
1023 if (!storeDS && av.hasHiddenRows())
1025 jal = av.getAlignment();
1029 if (storeDS && jal.getCodonFrames() != null)
1031 List<AlignedCodonFrame> jac = jal.getCodonFrames();
1032 for (AlignedCodonFrame acf : jac)
1034 AlcodonFrame alc = new AlcodonFrame();
1035 if (acf.getProtMappings() != null
1036 && acf.getProtMappings().length > 0)
1038 boolean hasMap = false;
1039 SequenceI[] dnas = acf.getdnaSeqs();
1040 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1041 for (int m = 0; m < pmaps.length; m++)
1043 AlcodMap alcmap = new AlcodMap();
1044 alcmap.setDnasq(seqHash(dnas[m]));
1045 alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
1047 alc.addAlcodMap(alcmap);
1052 vamsasSet.addAlcodonFrame(alc);
1055 // TODO: delete this ? dead code from 2.8.3->2.9 ?
1057 // AlcodonFrame alc = new AlcodonFrame();
1058 // vamsasSet.addAlcodonFrame(alc);
1059 // for (int p = 0; p < acf.aaWidth; p++)
1061 // Alcodon cmap = new Alcodon();
1062 // if (acf.codons[p] != null)
1064 // // Null codons indicate a gapped column in the translated peptide
1066 // cmap.setPos1(acf.codons[p][0]);
1067 // cmap.setPos2(acf.codons[p][1]);
1068 // cmap.setPos3(acf.codons[p][2]);
1070 // alc.addAlcodon(cmap);
1072 // if (acf.getProtMappings() != null
1073 // && acf.getProtMappings().length > 0)
1075 // SequenceI[] dnas = acf.getdnaSeqs();
1076 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1077 // for (int m = 0; m < pmaps.length; m++)
1079 // AlcodMap alcmap = new AlcodMap();
1080 // alcmap.setDnasq(seqHash(dnas[m]));
1081 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
1083 // alc.addAlcodMap(alcmap);
1090 // /////////////////////////////////
1091 if (!storeDS && av.currentTree != null)
1093 // FIND ANY ASSOCIATED TREES
1094 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
1095 if (Desktop.desktop != null)
1097 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1099 for (int t = 0; t < frames.length; t++)
1101 if (frames[t] instanceof TreePanel)
1103 TreePanel tp = (TreePanel) frames[t];
1105 if (tp.treeCanvas.av.getAlignment() == jal)
1107 Tree tree = new Tree();
1108 tree.setTitle(tp.getTitle());
1109 tree.setCurrentTree((av.currentTree == tp.getTree()));
1110 tree.setNewick(tp.getTree().print());
1111 tree.setThreshold(tp.treeCanvas.threshold);
1113 tree.setFitToWindow(tp.fitToWindow.getState());
1114 tree.setFontName(tp.getTreeFont().getName());
1115 tree.setFontSize(tp.getTreeFont().getSize());
1116 tree.setFontStyle(tp.getTreeFont().getStyle());
1117 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
1119 tree.setShowBootstrap(tp.bootstrapMenu.getState());
1120 tree.setShowDistances(tp.distanceMenu.getState());
1122 tree.setHeight(tp.getHeight());
1123 tree.setWidth(tp.getWidth());
1124 tree.setXpos(tp.getX());
1125 tree.setYpos(tp.getY());
1126 tree.setId(makeHashCode(tp, null));
1136 * store forward refs from an annotationRow to any groups
1138 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<>();
1141 for (SequenceI sq : jal.getSequences())
1143 // Store annotation on dataset sequences only
1144 AlignmentAnnotation[] aa = sq.getAnnotation();
1145 if (aa != null && aa.length > 0)
1147 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1154 if (jal.getAlignmentAnnotation() != null)
1156 // Store the annotation shown on the alignment.
1157 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1158 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1163 if (jal.getGroups() != null)
1165 JGroup[] groups = new JGroup[jal.getGroups().size()];
1167 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1169 JGroup jGroup = new JGroup();
1170 groups[++i] = jGroup;
1172 jGroup.setStart(sg.getStartRes());
1173 jGroup.setEnd(sg.getEndRes());
1174 jGroup.setName(sg.getName());
1175 if (groupRefs.containsKey(sg))
1177 // group has references so set its ID field
1178 jGroup.setId(groupRefs.get(sg));
1180 ColourSchemeI colourScheme = sg.getColourScheme();
1181 if (colourScheme != null)
1183 ResidueShaderI groupColourScheme = sg
1184 .getGroupColourScheme();
1185 if (groupColourScheme.conservationApplied())
1187 jGroup.setConsThreshold(groupColourScheme.getConservationInc());
1189 if (colourScheme instanceof jalview.schemes.UserColourScheme)
1191 jGroup.setColour(setUserColourScheme(colourScheme,
1196 jGroup.setColour(colourScheme.getSchemeName());
1199 else if (colourScheme instanceof jalview.schemes.AnnotationColourGradient)
1201 jGroup.setColour("AnnotationColourGradient");
1202 jGroup.setAnnotationColours(constructAnnotationColours(
1203 (jalview.schemes.AnnotationColourGradient) colourScheme,
1206 else if (colourScheme instanceof jalview.schemes.UserColourScheme)
1208 jGroup.setColour(setUserColourScheme(colourScheme,
1213 jGroup.setColour(colourScheme.getSchemeName());
1216 jGroup.setPidThreshold(groupColourScheme.getThreshold());
1219 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1220 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1221 jGroup.setDisplayText(sg.getDisplayText());
1222 jGroup.setColourText(sg.getColourText());
1223 jGroup.setTextCol1(sg.textColour.getRGB());
1224 jGroup.setTextCol2(sg.textColour2.getRGB());
1225 jGroup.setTextColThreshold(sg.thresholdTextColour);
1226 jGroup.setShowUnconserved(sg.getShowNonconserved());
1227 jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1228 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1229 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1230 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1231 for (SequenceI seq : sg.getSequences())
1233 jGroup.addSeq(seqHash(seq));
1237 jms.setJGroup(groups);
1241 // /////////SAVE VIEWPORT
1242 Viewport view = new Viewport();
1243 view.setTitle(ap.alignFrame.getTitle());
1244 view.setSequenceSetId(makeHashCode(av.getSequenceSetId(),
1245 av.getSequenceSetId()));
1246 view.setId(av.getViewId());
1247 if (av.getCodingComplement() != null)
1249 view.setComplementId(av.getCodingComplement().getViewId());
1251 view.setViewName(av.viewName);
1252 view.setGatheredViews(av.isGatherViewsHere());
1254 Rectangle size = ap.av.getExplodedGeometry();
1255 Rectangle position = size;
1258 size = ap.alignFrame.getBounds();
1259 if (av.getCodingComplement() != null)
1261 position = ((SplitFrame) ap.alignFrame.getSplitViewContainer())
1269 view.setXpos(position.x);
1270 view.setYpos(position.y);
1272 view.setWidth(size.width);
1273 view.setHeight(size.height);
1275 view.setStartRes(vpRanges.getStartRes());
1276 view.setStartSeq(vpRanges.getStartSeq());
1278 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1280 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1283 else if (av.getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1285 AnnotationColours ac = constructAnnotationColours(
1286 (jalview.schemes.AnnotationColourGradient) av
1287 .getGlobalColourScheme(),
1290 view.setAnnotationColours(ac);
1291 view.setBgColour("AnnotationColourGradient");
1295 view.setBgColour(ColourSchemeProperty.getColourName(av
1296 .getGlobalColourScheme()));
1299 ResidueShaderI vcs = av.getResidueShading();
1300 ColourSchemeI cs = av.getGlobalColourScheme();
1304 if (vcs.conservationApplied())
1306 view.setConsThreshold(vcs.getConservationInc());
1307 if (cs instanceof jalview.schemes.UserColourScheme)
1309 view.setBgColour(setUserColourScheme(cs, userColours, jms));
1312 view.setPidThreshold(vcs.getThreshold());
1315 view.setConservationSelected(av.getConservationSelected());
1316 view.setPidSelected(av.getAbovePIDThreshold());
1317 view.setFontName(av.font.getName());
1318 view.setFontSize(av.font.getSize());
1319 view.setFontStyle(av.font.getStyle());
1320 view.setScaleProteinAsCdna(av.getViewStyle().isScaleProteinAsCdna());
1321 view.setRenderGaps(av.isRenderGaps());
1322 view.setShowAnnotation(av.isShowAnnotation());
1323 view.setShowBoxes(av.getShowBoxes());
1324 view.setShowColourText(av.getColourText());
1325 view.setShowFullId(av.getShowJVSuffix());
1326 view.setRightAlignIds(av.isRightAlignIds());
1327 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1328 view.setShowText(av.getShowText());
1329 view.setShowUnconserved(av.getShowUnconserved());
1330 view.setWrapAlignment(av.getWrapAlignment());
1331 view.setTextCol1(av.getTextColour().getRGB());
1332 view.setTextCol2(av.getTextColour2().getRGB());
1333 view.setTextColThreshold(av.getThresholdTextColour());
1334 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1335 view.setShowSequenceLogo(av.isShowSequenceLogo());
1336 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1337 view.setShowGroupConsensus(av.isShowGroupConsensus());
1338 view.setShowGroupConservation(av.isShowGroupConservation());
1339 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1340 view.setShowDbRefTooltip(av.isShowDBRefs());
1341 view.setFollowHighlight(av.isFollowHighlight());
1342 view.setFollowSelection(av.followSelection);
1343 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1344 if (av.getFeaturesDisplayed() != null)
1346 jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
1348 String[] renderOrder = ap.getSeqPanel().seqCanvas
1349 .getFeatureRenderer().getRenderOrder()
1350 .toArray(new String[0]);
1352 Vector<String> settingsAdded = new Vector<>();
1353 if (renderOrder != null)
1355 for (String featureType : renderOrder)
1357 FeatureColourI fcol = ap.getSeqPanel().seqCanvas
1358 .getFeatureRenderer().getFeatureStyle(featureType);
1359 Setting setting = new Setting();
1360 setting.setType(featureType);
1361 if (!fcol.isSimpleColour())
1363 setting.setColour(fcol.getMaxColour().getRGB());
1364 setting.setMincolour(fcol.getMinColour().getRGB());
1365 setting.setMin(fcol.getMin());
1366 setting.setMax(fcol.getMax());
1367 setting.setColourByLabel(fcol.isColourByLabel());
1368 setting.setAutoScale(fcol.isAutoScaled());
1369 setting.setThreshold(fcol.getThreshold());
1370 // -1 = No threshold, 0 = Below, 1 = Above
1371 setting.setThreshstate(fcol.isAboveThreshold() ? 1 : (fcol
1372 .isBelowThreshold() ? 0 : -1));
1376 setting.setColour(fcol.getColour().getRGB());
1379 setting.setDisplay(av.getFeaturesDisplayed().isVisible(
1381 float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1382 .getOrder(featureType);
1385 setting.setOrder(rorder);
1387 fs.addSetting(setting);
1388 settingsAdded.addElement(featureType);
1392 // is groups actually supposed to be a map here ?
1393 Iterator<String> en = ap.getSeqPanel().seqCanvas
1394 .getFeatureRenderer().getFeatureGroups().iterator();
1395 Vector<String> groupsAdded = new Vector<>();
1396 while (en.hasNext())
1398 String grp = en.next();
1399 if (groupsAdded.contains(grp))
1403 Group g = new Group();
1405 g.setDisplay(((Boolean) ap.getSeqPanel().seqCanvas
1406 .getFeatureRenderer().checkGroupVisibility(grp, false))
1409 groupsAdded.addElement(grp);
1411 jms.setFeatureSettings(fs);
1414 if (av.hasHiddenColumns())
1416 jalview.datamodel.HiddenColumns hidden = av.getAlignment()
1417 .getHiddenColumns();
1420 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1424 for (int[] region : hidden)
1426 HiddenColumns hc = new HiddenColumns();
1427 hc.setStart(region[0]);
1428 hc.setEnd(region[1]);
1429 view.addHiddenColumns(hc);
1433 if (calcIdSet.size() > 0)
1435 for (String calcId : calcIdSet)
1437 if (calcId.trim().length() > 0)
1439 CalcIdParam cidp = createCalcIdParam(calcId, av);
1440 // Some calcIds have no parameters.
1443 view.addCalcIdParam(cidp);
1449 jms.addViewport(view);
1451 object.setJalviewModelSequence(jms);
1452 object.getVamsasModel().addSequenceSet(vamsasSet);
1454 if (jout != null && fileName != null)
1456 // We may not want to write the object to disk,
1457 // eg we can copy the alignViewport to a new view object
1458 // using save and then load
1461 System.out.println("Writing jar entry " + fileName);
1462 JarEntry entry = new JarEntry(fileName);
1463 jout.putNextEntry(entry);
1464 PrintWriter pout = new PrintWriter(new OutputStreamWriter(jout,
1466 Marshaller marshaller = new Marshaller(pout);
1467 marshaller.marshal(object);
1470 } catch (Exception ex)
1472 // TODO: raise error in GUI if marshalling failed.
1473 ex.printStackTrace();
1480 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1481 * for each viewer, with
1483 * <li>viewer geometry (position, size, split pane divider location)</li>
1484 * <li>index of the selected structure in the viewer (currently shows gapped
1486 * <li>the id of the annotation holding RNA secondary structure</li>
1487 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1489 * Varna viewer state is also written out (in native Varna XML) to separate
1490 * project jar entries. A separate entry is written for each RNA structure
1491 * displayed, with the naming convention
1493 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
1501 * @param storeDataset
1503 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
1504 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
1505 boolean storeDataset)
1507 if (Desktop.desktop == null)
1511 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1512 for (int f = frames.length - 1; f > -1; f--)
1514 if (frames[f] instanceof AppVarna)
1516 AppVarna varna = (AppVarna) frames[f];
1518 * link the sequence to every viewer that is showing it and is linked to
1519 * its alignment panel
1521 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1523 String viewId = varna.getViewId();
1524 RnaViewer rna = new RnaViewer();
1525 rna.setViewId(viewId);
1526 rna.setTitle(varna.getTitle());
1527 rna.setXpos(varna.getX());
1528 rna.setYpos(varna.getY());
1529 rna.setWidth(varna.getWidth());
1530 rna.setHeight(varna.getHeight());
1531 rna.setDividerLocation(varna.getDividerLocation());
1532 rna.setSelectedRna(varna.getSelectedIndex());
1533 jseq.addRnaViewer(rna);
1536 * Store each Varna panel's state once in the project per sequence.
1537 * First time through only (storeDataset==false)
1539 // boolean storeSessions = false;
1540 // String sequenceViewId = viewId + seqsToIds.get(jds);
1541 // if (!storeDataset && !viewIds.contains(sequenceViewId))
1543 // viewIds.add(sequenceViewId);
1544 // storeSessions = true;
1546 for (RnaModel model : varna.getModels())
1548 if (model.seq == jds)
1551 * VARNA saves each view (sequence or alignment secondary
1552 * structure, gapped or trimmed) as a separate XML file
1554 String jarEntryName = rnaSessions.get(model);
1555 if (jarEntryName == null)
1558 String varnaStateFile = varna.getStateInfo(model.rna);
1559 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
1560 copyFileToJar(jout, varnaStateFile, jarEntryName);
1561 rnaSessions.put(model, jarEntryName);
1563 SecondaryStructure ss = new SecondaryStructure();
1564 String annotationId = varna.getAnnotation(jds).annotationId;
1565 ss.setAnnotationId(annotationId);
1566 ss.setViewerState(jarEntryName);
1567 ss.setGapped(model.gapped);
1568 ss.setTitle(model.title);
1569 rna.addSecondaryStructure(ss);
1578 * Copy the contents of a file to a new entry added to the output jar
1582 * @param jarEntryName
1584 protected void copyFileToJar(JarOutputStream jout, String infilePath,
1585 String jarEntryName)
1587 DataInputStream dis = null;
1590 File file = new File(infilePath);
1591 if (file.exists() && jout != null)
1593 dis = new DataInputStream(new FileInputStream(file));
1594 byte[] data = new byte[(int) file.length()];
1595 dis.readFully(data);
1596 writeJarEntry(jout, jarEntryName, data);
1598 } catch (Exception ex)
1600 ex.printStackTrace();
1608 } catch (IOException e)
1617 * Write the data to a new entry of given name in the output jar file
1620 * @param jarEntryName
1622 * @throws IOException
1624 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
1625 byte[] data) throws IOException
1629 System.out.println("Writing jar entry " + jarEntryName);
1630 jout.putNextEntry(new JarEntry(jarEntryName));
1631 DataOutputStream dout = new DataOutputStream(jout);
1632 dout.write(data, 0, data.length);
1639 * Save the state of a structure viewer
1644 * the archive XML element under which to save the state
1647 * @param matchedFile
1651 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
1652 Pdbids pdb, PDBEntry entry, List<String> viewIds,
1653 String matchedFile, StructureViewerBase viewFrame)
1655 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
1658 * Look for any bindings for this viewer to the PDB file of interest
1659 * (including part matches excluding chain id)
1661 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
1663 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
1664 final String pdbId = pdbentry.getId();
1665 if (!pdbId.equals(entry.getId())
1666 && !(entry.getId().length() > 4 && entry.getId()
1667 .toLowerCase().startsWith(pdbId.toLowerCase())))
1670 * not interested in a binding to a different PDB entry here
1674 if (matchedFile == null)
1676 matchedFile = pdbentry.getFile();
1678 else if (!matchedFile.equals(pdbentry.getFile()))
1681 .warn("Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
1682 + pdbentry.getFile());
1686 // can get at it if the ID
1687 // match is ambiguous (e.g.
1690 for (int smap = 0; smap < viewFrame.getBinding().getSequence()[peid].length; smap++)
1692 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
1693 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
1695 StructureState state = new StructureState();
1696 state.setVisible(true);
1697 state.setXpos(viewFrame.getX());
1698 state.setYpos(viewFrame.getY());
1699 state.setWidth(viewFrame.getWidth());
1700 state.setHeight(viewFrame.getHeight());
1701 final String viewId = viewFrame.getViewId();
1702 state.setViewId(viewId);
1703 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
1704 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
1705 state.setColourByJmol(viewFrame.isColouredByViewer());
1706 state.setType(viewFrame.getViewerType().toString());
1707 pdb.addStructureState(state);
1715 * Populates the AnnotationColours xml for save. This captures the settings of
1716 * the options in the 'Colour by Annotation' dialog.
1719 * @param userColours
1723 private AnnotationColours constructAnnotationColours(
1724 AnnotationColourGradient acg, List<UserColourScheme> userColours,
1725 JalviewModelSequence jms)
1727 AnnotationColours ac = new AnnotationColours();
1728 ac.setAboveThreshold(acg.getAboveThreshold());
1729 ac.setThreshold(acg.getAnnotationThreshold());
1730 // 2.10.2 save annotationId (unique) not annotation label
1731 ac.setAnnotation(acg.getAnnotation().annotationId);
1732 if (acg.getBaseColour() instanceof UserColourScheme)
1734 ac.setColourScheme(setUserColourScheme(acg.getBaseColour(),
1739 ac.setColourScheme(ColourSchemeProperty.getColourName(acg.getBaseColour()));
1742 ac.setMaxColour(acg.getMaxColour().getRGB());
1743 ac.setMinColour(acg.getMinColour().getRGB());
1744 ac.setPerSequence(acg.isSeqAssociated());
1745 ac.setPredefinedColours(acg.isPredefinedColours());
1749 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
1750 IdentityHashMap<SequenceGroup, String> groupRefs,
1751 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
1752 SequenceSet vamsasSet)
1755 for (int i = 0; i < aa.length; i++)
1757 Annotation an = new Annotation();
1759 AlignmentAnnotation annotation = aa[i];
1760 if (annotation.annotationId != null)
1762 annotationIds.put(annotation.annotationId, annotation);
1765 an.setId(annotation.annotationId);
1767 an.setVisible(annotation.visible);
1769 an.setDescription(annotation.description);
1771 if (annotation.sequenceRef != null)
1773 // 2.9 JAL-1781 xref on sequence id rather than name
1774 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
1776 if (annotation.groupRef != null)
1778 String groupIdr = groupRefs.get(annotation.groupRef);
1779 if (groupIdr == null)
1781 // make a locally unique String
1783 annotation.groupRef,
1784 groupIdr = ("" + System.currentTimeMillis()
1785 + annotation.groupRef.getName() + groupRefs
1788 an.setGroupRef(groupIdr.toString());
1791 // store all visualization attributes for annotation
1792 an.setGraphHeight(annotation.graphHeight);
1793 an.setCentreColLabels(annotation.centreColLabels);
1794 an.setScaleColLabels(annotation.scaleColLabel);
1795 an.setShowAllColLabels(annotation.showAllColLabels);
1796 an.setBelowAlignment(annotation.belowAlignment);
1798 if (annotation.graph > 0)
1801 an.setGraphType(annotation.graph);
1802 an.setGraphGroup(annotation.graphGroup);
1803 if (annotation.getThreshold() != null)
1805 ThresholdLine line = new ThresholdLine();
1806 line.setLabel(annotation.getThreshold().label);
1807 line.setValue(annotation.getThreshold().value);
1808 line.setColour(annotation.getThreshold().colour.getRGB());
1809 an.setThresholdLine(line);
1817 an.setLabel(annotation.label);
1819 if (annotation == av.getAlignmentQualityAnnot()
1820 || annotation == av.getAlignmentConservationAnnotation()
1821 || annotation == av.getAlignmentConsensusAnnotation()
1822 || annotation.autoCalculated)
1824 // new way of indicating autocalculated annotation -
1825 an.setAutoCalculated(annotation.autoCalculated);
1827 if (annotation.hasScore())
1829 an.setScore(annotation.getScore());
1832 if (annotation.getCalcId() != null)
1834 calcIdSet.add(annotation.getCalcId());
1835 an.setCalcId(annotation.getCalcId());
1837 if (annotation.hasProperties())
1839 for (String pr : annotation.getProperties())
1841 Property prop = new Property();
1843 prop.setValue(annotation.getProperty(pr));
1844 an.addProperty(prop);
1848 AnnotationElement ae;
1849 if (annotation.annotations != null)
1851 an.setScoreOnly(false);
1852 for (int a = 0; a < annotation.annotations.length; a++)
1854 if ((annotation == null) || (annotation.annotations[a] == null))
1859 ae = new AnnotationElement();
1860 if (annotation.annotations[a].description != null)
1862 ae.setDescription(annotation.annotations[a].description);
1864 if (annotation.annotations[a].displayCharacter != null)
1866 ae.setDisplayCharacter(annotation.annotations[a].displayCharacter);
1869 if (!Float.isNaN(annotation.annotations[a].value))
1871 ae.setValue(annotation.annotations[a].value);
1875 if (annotation.annotations[a].secondaryStructure > ' ')
1877 ae.setSecondaryStructure(annotation.annotations[a].secondaryStructure
1881 if (annotation.annotations[a].colour != null
1882 && annotation.annotations[a].colour != java.awt.Color.black)
1884 ae.setColour(annotation.annotations[a].colour.getRGB());
1887 an.addAnnotationElement(ae);
1888 if (annotation.autoCalculated)
1890 // only write one non-null entry into the annotation row -
1891 // sufficient to get the visualization attributes necessary to
1899 an.setScoreOnly(true);
1901 if (!storeDS || (storeDS && !annotation.autoCalculated))
1903 // skip autocalculated annotation - these are only provided for
1905 vamsasSet.addAnnotation(an);
1911 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
1913 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
1914 if (settings != null)
1916 CalcIdParam vCalcIdParam = new CalcIdParam();
1917 vCalcIdParam.setCalcId(calcId);
1918 vCalcIdParam.addServiceURL(settings.getServiceURI());
1919 // generic URI allowing a third party to resolve another instance of the
1920 // service used for this calculation
1921 for (String urls : settings.getServiceURLs())
1923 vCalcIdParam.addServiceURL(urls);
1925 vCalcIdParam.setVersion("1.0");
1926 if (settings.getPreset() != null)
1928 WsParamSetI setting = settings.getPreset();
1929 vCalcIdParam.setName(setting.getName());
1930 vCalcIdParam.setDescription(setting.getDescription());
1934 vCalcIdParam.setName("");
1935 vCalcIdParam.setDescription("Last used parameters");
1937 // need to be able to recover 1) settings 2) user-defined presets or
1938 // recreate settings from preset 3) predefined settings provided by
1939 // service - or settings that can be transferred (or discarded)
1940 vCalcIdParam.setParameters(settings.getWsParamFile().replace("\n",
1942 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
1943 // todo - decide if updateImmediately is needed for any projects.
1945 return vCalcIdParam;
1950 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
1953 if (calcIdParam.getVersion().equals("1.0"))
1955 Jws2Instance service = Jws2Discoverer.getDiscoverer()
1956 .getPreferredServiceFor(calcIdParam.getServiceURL());
1957 if (service != null)
1959 WsParamSetI parmSet = null;
1962 parmSet = service.getParamStore().parseServiceParameterFile(
1963 calcIdParam.getName(), calcIdParam.getDescription(),
1964 calcIdParam.getServiceURL(),
1965 calcIdParam.getParameters().replace("|\\n|", "\n"));
1966 } catch (IOException x)
1968 warn("Couldn't parse parameter data for "
1969 + calcIdParam.getCalcId(), x);
1972 List<ArgumentI> argList = null;
1973 if (calcIdParam.getName().length() > 0)
1975 parmSet = service.getParamStore()
1976 .getPreset(calcIdParam.getName());
1977 if (parmSet != null)
1979 // TODO : check we have a good match with settings in AACon -
1980 // otherwise we'll need to create a new preset
1985 argList = parmSet.getArguments();
1988 AAConSettings settings = new AAConSettings(
1989 calcIdParam.isAutoUpdate(), service, parmSet, argList);
1990 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
1991 calcIdParam.isNeedsUpdate());
1996 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
2000 throw new Error(MessageManager.formatMessage(
2001 "error.unsupported_version_calcIdparam",
2002 new Object[] { calcIdParam.toString() }));
2006 * External mapping between jalview objects and objects yielding a valid and
2007 * unique object ID string. This is null for normal Jalview project IO, but
2008 * non-null when a jalview project is being read or written as part of a
2011 IdentityHashMap jv2vobj = null;
2014 * Construct a unique ID for jvobj using either existing bindings or if none
2015 * exist, the result of the hashcode call for the object.
2018 * jalview data object
2019 * @return unique ID for referring to jvobj
2021 private String makeHashCode(Object jvobj, String altCode)
2023 if (jv2vobj != null)
2025 Object id = jv2vobj.get(jvobj);
2028 return id.toString();
2030 // check string ID mappings
2031 if (jvids2vobj != null && jvobj instanceof String)
2033 id = jvids2vobj.get(jvobj);
2037 return id.toString();
2039 // give up and warn that something has gone wrong
2040 warn("Cannot find ID for object in external mapping : " + jvobj);
2046 * return local jalview object mapped to ID, if it exists
2050 * @return null or object bound to idcode
2052 private Object retrieveExistingObj(String idcode)
2054 if (idcode != null && vobj2jv != null)
2056 return vobj2jv.get(idcode);
2062 * binding from ID strings from external mapping table to jalview data model
2065 private Hashtable vobj2jv;
2067 private Sequence createVamsasSequence(String id, SequenceI jds)
2069 return createVamsasSequence(true, id, jds, null);
2072 private Sequence createVamsasSequence(boolean recurse, String id,
2073 SequenceI jds, SequenceI parentseq)
2075 Sequence vamsasSeq = new Sequence();
2076 vamsasSeq.setId(id);
2077 vamsasSeq.setName(jds.getName());
2078 vamsasSeq.setSequence(jds.getSequenceAsString());
2079 vamsasSeq.setDescription(jds.getDescription());
2080 jalview.datamodel.DBRefEntry[] dbrefs = null;
2081 if (jds.getDatasetSequence() != null)
2083 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
2087 // seqId==dsseqid so we can tell which sequences really are
2088 // dataset sequences only
2089 vamsasSeq.setDsseqid(id);
2090 dbrefs = jds.getDBRefs();
2091 if (parentseq == null)
2098 for (int d = 0; d < dbrefs.length; d++)
2100 DBRef dbref = new DBRef();
2101 dbref.setSource(dbrefs[d].getSource());
2102 dbref.setVersion(dbrefs[d].getVersion());
2103 dbref.setAccessionId(dbrefs[d].getAccessionId());
2104 if (dbrefs[d].hasMap())
2106 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
2108 dbref.setMapping(mp);
2110 vamsasSeq.addDBRef(dbref);
2116 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
2117 SequenceI parentseq, SequenceI jds, boolean recurse)
2120 if (jmp.getMap() != null)
2124 jalview.util.MapList mlst = jmp.getMap();
2125 List<int[]> r = mlst.getFromRanges();
2126 for (int[] range : r)
2128 MapListFrom mfrom = new MapListFrom();
2129 mfrom.setStart(range[0]);
2130 mfrom.setEnd(range[1]);
2131 mp.addMapListFrom(mfrom);
2133 r = mlst.getToRanges();
2134 for (int[] range : r)
2136 MapListTo mto = new MapListTo();
2137 mto.setStart(range[0]);
2138 mto.setEnd(range[1]);
2139 mp.addMapListTo(mto);
2141 mp.setMapFromUnit(mlst.getFromRatio());
2142 mp.setMapToUnit(mlst.getToRatio());
2143 if (jmp.getTo() != null)
2145 MappingChoice mpc = new MappingChoice();
2147 // check/create ID for the sequence referenced by getTo()
2150 SequenceI ps = null;
2151 if (parentseq != jmp.getTo()
2152 && parentseq.getDatasetSequence() != jmp.getTo())
2154 // chaining dbref rather than a handshaking one
2155 jmpid = seqHash(ps = jmp.getTo());
2159 jmpid = seqHash(ps = parentseq);
2161 mpc.setDseqFor(jmpid);
2162 if (!seqRefIds.containsKey(mpc.getDseqFor()))
2164 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2165 seqRefIds.put(mpc.getDseqFor(), ps);
2169 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2172 mp.setMappingChoice(mpc);
2178 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2179 List<UserColourScheme> userColours, JalviewModelSequence jms)
2182 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2183 boolean newucs = false;
2184 if (!userColours.contains(ucs))
2186 userColours.add(ucs);
2189 id = "ucs" + userColours.indexOf(ucs);
2192 // actually create the scheme's entry in the XML model
2193 java.awt.Color[] colours = ucs.getColours();
2194 jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
2195 jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
2197 for (int i = 0; i < colours.length; i++)
2199 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2200 col.setName(ResidueProperties.aa[i]);
2201 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2202 jbucs.addColour(col);
2204 if (ucs.getLowerCaseColours() != null)
2206 colours = ucs.getLowerCaseColours();
2207 for (int i = 0; i < colours.length; i++)
2209 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2210 col.setName(ResidueProperties.aa[i].toLowerCase());
2211 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2212 jbucs.addColour(col);
2217 uc.setUserColourScheme(jbucs);
2218 jms.addUserColours(uc);
2224 jalview.schemes.UserColourScheme getUserColourScheme(
2225 JalviewModelSequence jms, String id)
2227 UserColours[] uc = jms.getUserColours();
2228 UserColours colours = null;
2230 for (int i = 0; i < uc.length; i++)
2232 if (uc[i].getId().equals(id))
2240 java.awt.Color[] newColours = new java.awt.Color[24];
2242 for (int i = 0; i < 24; i++)
2244 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2245 .getUserColourScheme().getColour(i).getRGB(), 16));
2248 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2251 if (colours.getUserColourScheme().getColourCount() > 24)
2253 newColours = new java.awt.Color[23];
2254 for (int i = 0; i < 23; i++)
2256 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2257 .getUserColourScheme().getColour(i + 24).getRGB(), 16));
2259 ucs.setLowerCaseColours(newColours);
2266 * contains last error message (if any) encountered by XML loader.
2268 String errorMessage = null;
2271 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2272 * exceptions are raised during project XML parsing
2274 public boolean attemptversion1parse = true;
2277 * Load a jalview project archive from a jar file
2280 * - HTTP URL or filename
2282 public AlignFrame loadJalviewAlign(final String file)
2285 jalview.gui.AlignFrame af = null;
2289 // create list to store references for any new Jmol viewers created
2290 newStructureViewers = new Vector<>();
2291 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2292 // Workaround is to make sure caller implements the JarInputStreamProvider
2294 // so we can re-open the jar input stream for each entry.
2296 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2297 af = loadJalviewAlign(jprovider);
2299 } catch (MalformedURLException e)
2301 errorMessage = "Invalid URL format for '" + file + "'";
2307 SwingUtilities.invokeAndWait(new Runnable()
2312 setLoadingFinishedForNewStructureViewers();
2315 } catch (Exception x)
2317 System.err.println("Error loading alignment: " + x.getMessage());
2323 private jarInputStreamProvider createjarInputStreamProvider(
2324 final String file) throws MalformedURLException
2327 errorMessage = null;
2328 uniqueSetSuffix = null;
2330 viewportsAdded.clear();
2331 frefedSequence = null;
2333 if (file.startsWith("http://"))
2335 url = new URL(file);
2337 final URL _url = url;
2338 return new jarInputStreamProvider()
2342 public JarInputStream getJarInputStream() throws IOException
2346 return new JarInputStream(_url.openStream());
2350 return new JarInputStream(new FileInputStream(file));
2355 public String getFilename()
2363 * Recover jalview session from a jalview project archive. Caller may
2364 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2365 * themselves. Any null fields will be initialised with default values,
2366 * non-null fields are left alone.
2371 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2373 errorMessage = null;
2374 if (uniqueSetSuffix == null)
2376 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2378 if (seqRefIds == null)
2382 AlignFrame af = null, _af = null;
2383 IdentityHashMap<AlignmentI, AlignmentI> importedDatasets = new IdentityHashMap<>();
2384 Map<String, AlignFrame> gatherToThisFrame = new HashMap<>();
2385 final String file = jprovider.getFilename();
2388 JarInputStream jin = null;
2389 JarEntry jarentry = null;
2394 jin = jprovider.getJarInputStream();
2395 for (int i = 0; i < entryCount; i++)
2397 jarentry = jin.getNextJarEntry();
2400 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2402 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2403 JalviewModel object = new JalviewModel();
2405 Unmarshaller unmar = new Unmarshaller(object);
2406 unmar.setValidation(false);
2407 object = (JalviewModel) unmar.unmarshal(in);
2408 if (true) // !skipViewport(object))
2410 _af = loadFromObject(object, file, true, jprovider);
2412 && object.getJalviewModelSequence().getViewportCount() > 0)
2416 // store a reference to the first view
2419 if (_af.viewport.isGatherViewsHere())
2421 // if this is a gathered view, keep its reference since
2422 // after gathering views, only this frame will remain
2424 gatherToThisFrame.put(_af.viewport.getSequenceSetId(), _af);
2426 // Save dataset to register mappings once all resolved
2427 importedDatasets.put(af.viewport.getAlignment().getDataset(),
2428 af.viewport.getAlignment().getDataset());
2433 else if (jarentry != null)
2435 // Some other file here.
2438 } while (jarentry != null);
2439 resolveFrefedSequences();
2440 } catch (IOException ex)
2442 ex.printStackTrace();
2443 errorMessage = "Couldn't locate Jalview XML file : " + file;
2444 System.err.println("Exception whilst loading jalview XML file : "
2446 } catch (Exception ex)
2448 System.err.println("Parsing as Jalview Version 2 file failed.");
2449 ex.printStackTrace(System.err);
2450 if (attemptversion1parse)
2452 // Is Version 1 Jar file?
2455 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
2456 } catch (Exception ex2)
2458 System.err.println("Exception whilst loading as jalviewXMLV1:");
2459 ex2.printStackTrace();
2463 if (Desktop.instance != null)
2465 Desktop.instance.stopLoading();
2469 System.out.println("Successfully loaded archive file");
2472 ex.printStackTrace();
2474 System.err.println("Exception whilst loading jalview XML file : "
2476 } catch (OutOfMemoryError e)
2478 // Don't use the OOM Window here
2479 errorMessage = "Out of memory loading jalview XML file";
2480 System.err.println("Out of memory whilst loading jalview XML file");
2481 e.printStackTrace();
2485 * Regather multiple views (with the same sequence set id) to the frame (if
2486 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2487 * views instead of separate frames. Note this doesn't restore a state where
2488 * some expanded views in turn have tabbed views - the last "first tab" read
2489 * in will play the role of gatherer for all.
2491 for (AlignFrame fr : gatherToThisFrame.values())
2493 Desktop.instance.gatherViews(fr);
2496 restoreSplitFrames();
2497 for (AlignmentI ds : importedDatasets.keySet())
2499 if (ds.getCodonFrames() != null)
2501 StructureSelectionManager.getStructureSelectionManager(
2502 Desktop.instance).registerMappings(ds.getCodonFrames());
2505 if (errorMessage != null)
2510 if (Desktop.instance != null)
2512 Desktop.instance.stopLoading();
2519 * Try to reconstruct and display SplitFrame windows, where each contains
2520 * complementary dna and protein alignments. Done by pairing up AlignFrame
2521 * objects (created earlier) which have complementary viewport ids associated.
2523 protected void restoreSplitFrames()
2525 List<SplitFrame> gatherTo = new ArrayList<>();
2526 List<AlignFrame> addedToSplitFrames = new ArrayList<>();
2527 Map<String, AlignFrame> dna = new HashMap<>();
2530 * Identify the DNA alignments
2532 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2535 AlignFrame af = candidate.getValue();
2536 if (af.getViewport().getAlignment().isNucleotide())
2538 dna.put(candidate.getKey().getId(), af);
2543 * Try to match up the protein complements
2545 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2548 AlignFrame af = candidate.getValue();
2549 if (!af.getViewport().getAlignment().isNucleotide())
2551 String complementId = candidate.getKey().getComplementId();
2552 // only non-null complements should be in the Map
2553 if (complementId != null && dna.containsKey(complementId))
2555 final AlignFrame dnaFrame = dna.get(complementId);
2556 SplitFrame sf = createSplitFrame(dnaFrame, af);
2557 addedToSplitFrames.add(dnaFrame);
2558 addedToSplitFrames.add(af);
2559 dnaFrame.setMenusForViewport();
2560 af.setMenusForViewport();
2561 if (af.viewport.isGatherViewsHere())
2570 * Open any that we failed to pair up (which shouldn't happen!) as
2571 * standalone AlignFrame's.
2573 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2576 AlignFrame af = candidate.getValue();
2577 if (!addedToSplitFrames.contains(af))
2579 Viewport view = candidate.getKey();
2580 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
2582 af.setMenusForViewport();
2583 System.err.println("Failed to restore view " + view.getTitle()
2584 + " to split frame");
2589 * Gather back into tabbed views as flagged.
2591 for (SplitFrame sf : gatherTo)
2593 Desktop.instance.gatherViews(sf);
2596 splitFrameCandidates.clear();
2600 * Construct and display one SplitFrame holding DNA and protein alignments.
2603 * @param proteinFrame
2606 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
2607 AlignFrame proteinFrame)
2609 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
2610 String title = MessageManager.getString("label.linked_view_title");
2611 int width = (int) dnaFrame.getBounds().getWidth();
2612 int height = (int) (dnaFrame.getBounds().getHeight()
2613 + proteinFrame.getBounds().getHeight() + 50);
2616 * SplitFrame location is saved to both enclosed frames
2618 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
2619 Desktop.addInternalFrame(splitFrame, title, width, height);
2622 * And compute cDNA consensus (couldn't do earlier with consensus as
2623 * mappings were not yet present)
2625 proteinFrame.viewport.alignmentChanged(proteinFrame.alignPanel);
2631 * check errorMessage for a valid error message and raise an error box in the
2632 * GUI or write the current errorMessage to stderr and then clear the error
2635 protected void reportErrors()
2637 reportErrors(false);
2640 protected void reportErrors(final boolean saving)
2642 if (errorMessage != null)
2644 final String finalErrorMessage = errorMessage;
2647 javax.swing.SwingUtilities.invokeLater(new Runnable()
2653 .showInternalMessageDialog(Desktop.desktop,
2654 finalErrorMessage, "Error "
2655 + (saving ? "saving" : "loading")
2657 JvOptionPane.WARNING_MESSAGE);
2663 System.err.println("Problem loading Jalview file: " + errorMessage);
2666 errorMessage = null;
2669 Map<String, String> alreadyLoadedPDB = new HashMap<>();
2672 * when set, local views will be updated from view stored in JalviewXML
2673 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2674 * sync if this is set to true.
2676 private final boolean updateLocalViews = false;
2679 * Returns the path to a temporary file holding the PDB file for the given PDB
2680 * id. The first time of asking, searches for a file of that name in the
2681 * Jalview project jar, and copies it to a new temporary file. Any repeat
2682 * requests just return the path to the file previously created.
2688 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId,
2691 if (alreadyLoadedPDB.containsKey(pdbId))
2693 return alreadyLoadedPDB.get(pdbId).toString();
2696 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb",
2698 if (tempFile != null)
2700 alreadyLoadedPDB.put(pdbId, tempFile);
2706 * Copies the jar entry of given name to a new temporary file and returns the
2707 * path to the file, or null if the entry is not found.
2710 * @param jarEntryName
2712 * a prefix for the temporary file name, must be at least three
2715 * null or original file - so new file can be given the same suffix
2719 protected String copyJarEntry(jarInputStreamProvider jprovider,
2720 String jarEntryName, String prefix, String origFile)
2722 BufferedReader in = null;
2723 PrintWriter out = null;
2724 String suffix = ".tmp";
2725 if (origFile == null)
2727 origFile = jarEntryName;
2729 int sfpos = origFile.lastIndexOf(".");
2730 if (sfpos > -1 && sfpos < (origFile.length() - 3))
2732 suffix = "." + origFile.substring(sfpos + 1);
2736 JarInputStream jin = jprovider.getJarInputStream();
2738 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2739 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2740 * FileInputStream(jprovider)); }
2743 JarEntry entry = null;
2746 entry = jin.getNextJarEntry();
2747 } while (entry != null && !entry.getName().equals(jarEntryName));
2750 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
2751 File outFile = File.createTempFile(prefix, suffix);
2752 outFile.deleteOnExit();
2753 out = new PrintWriter(new FileOutputStream(outFile));
2756 while ((data = in.readLine()) != null)
2761 String t = outFile.getAbsolutePath();
2766 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
2768 } catch (Exception ex)
2770 ex.printStackTrace();
2778 } catch (IOException e)
2792 private class JvAnnotRow
2794 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2801 * persisted version of annotation row from which to take vis properties
2803 public jalview.datamodel.AlignmentAnnotation template;
2806 * original position of the annotation row in the alignment
2812 * Load alignment frame from jalview XML DOM object
2817 * filename source string
2818 * @param loadTreesAndStructures
2819 * when false only create Viewport
2821 * data source provider
2822 * @return alignment frame created from view stored in DOM
2824 AlignFrame loadFromObject(JalviewModel object, String file,
2825 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
2827 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
2828 Sequence[] vamsasSeq = vamsasSet.getSequence();
2830 JalviewModelSequence jms = object.getJalviewModelSequence();
2832 Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
2835 // ////////////////////////////////
2838 List<SequenceI> hiddenSeqs = null;
2840 List<SequenceI> tmpseqs = new ArrayList<>();
2842 boolean multipleView = false;
2843 SequenceI referenceseqForView = null;
2844 JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
2845 int vi = 0; // counter in vamsasSeq array
2846 for (int i = 0; i < jseqs.length; i++)
2848 String seqId = jseqs[i].getId();
2850 SequenceI tmpSeq = seqRefIds.get(seqId);
2853 if (!incompleteSeqs.containsKey(seqId))
2855 // may not need this check, but keep it for at least 2.9,1 release
2856 if (tmpSeq.getStart() != jseqs[i].getStart()
2857 || tmpSeq.getEnd() != jseqs[i].getEnd())
2860 .println("Warning JAL-2154 regression: updating start/end for sequence "
2861 + tmpSeq.toString() + " to " + jseqs[i]);
2866 incompleteSeqs.remove(seqId);
2868 if (vamsasSeq.length > vi && vamsasSeq[vi].getId().equals(seqId))
2870 // most likely we are reading a dataset XML document so
2871 // update from vamsasSeq section of XML for this sequence
2872 tmpSeq.setName(vamsasSeq[vi].getName());
2873 tmpSeq.setDescription(vamsasSeq[vi].getDescription());
2874 tmpSeq.setSequence(vamsasSeq[vi].getSequence());
2879 // reading multiple views, so vamsasSeq set is a subset of JSeq
2880 multipleView = true;
2882 tmpSeq.setStart(jseqs[i].getStart());
2883 tmpSeq.setEnd(jseqs[i].getEnd());
2884 tmpseqs.add(tmpSeq);
2888 tmpSeq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
2889 vamsasSeq[vi].getSequence());
2890 tmpSeq.setDescription(vamsasSeq[vi].getDescription());
2891 tmpSeq.setStart(jseqs[i].getStart());
2892 tmpSeq.setEnd(jseqs[i].getEnd());
2893 tmpSeq.setVamsasId(uniqueSetSuffix + seqId);
2894 seqRefIds.put(vamsasSeq[vi].getId(), tmpSeq);
2895 tmpseqs.add(tmpSeq);
2899 if (jseqs[i].hasViewreference() && jseqs[i].getViewreference())
2901 referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
2904 if (jseqs[i].getHidden())
2906 if (hiddenSeqs == null)
2908 hiddenSeqs = new ArrayList<>();
2911 hiddenSeqs.add(tmpSeq);
2916 // Create the alignment object from the sequence set
2917 // ///////////////////////////////
2918 SequenceI[] orderedSeqs = tmpseqs
2919 .toArray(new SequenceI[tmpseqs.size()]);
2921 AlignmentI al = null;
2922 // so we must create or recover the dataset alignment before going further
2923 // ///////////////////////////////
2924 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
2926 // older jalview projects do not have a dataset - so creat alignment and
2928 al = new Alignment(orderedSeqs);
2929 al.setDataset(null);
2933 boolean isdsal = object.getJalviewModelSequence().getViewportCount() == 0;
2936 // we are importing a dataset record, so
2937 // recover reference to an alignment already materialsed as dataset
2938 al = getDatasetFor(vamsasSet.getDatasetId());
2942 // materialse the alignment
2943 al = new Alignment(orderedSeqs);
2947 addDatasetRef(vamsasSet.getDatasetId(), al);
2950 // finally, verify all data in vamsasSet is actually present in al
2951 // passing on flag indicating if it is actually a stored dataset
2952 recoverDatasetFor(vamsasSet, al, isdsal);
2955 if (referenceseqForView != null)
2957 al.setSeqrep(referenceseqForView);
2959 // / Add the alignment properties
2960 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
2962 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
2963 al.setProperty(ssp.getKey(), ssp.getValue());
2966 // ///////////////////////////////
2968 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
2971 // load sequence features, database references and any associated PDB
2972 // structures for the alignment
2974 // prior to 2.10, this part would only be executed the first time a
2975 // sequence was encountered, but not afterwards.
2976 // now, for 2.10 projects, this is also done if the xml doc includes
2977 // dataset sequences not actually present in any particular view.
2979 for (int i = 0; i < vamsasSeq.length; i++)
2981 if (jseqs[i].getFeaturesCount() > 0)
2983 Features[] features = jseqs[i].getFeatures();
2984 for (int f = 0; f < features.length; f++)
2986 jalview.datamodel.SequenceFeature sf = new jalview.datamodel.SequenceFeature(
2987 features[f].getType(), features[f].getDescription(),
2988 features[f].getStatus(), features[f].getBegin(),
2989 features[f].getEnd(), features[f].getFeatureGroup());
2991 sf.setScore(features[f].getScore());
2992 for (int od = 0; od < features[f].getOtherDataCount(); od++)
2994 OtherData keyValue = features[f].getOtherData(od);
2995 if (keyValue.getKey().startsWith("LINK"))
2997 sf.addLink(keyValue.getValue());
3001 sf.setValue(keyValue.getKey(), keyValue.getValue());
3005 // adds feature to datasequence's feature set (since Jalview 2.10)
3006 al.getSequenceAt(i).addSequenceFeature(sf);
3009 if (vamsasSeq[i].getDBRefCount() > 0)
3011 // adds dbrefs to datasequence's set (since Jalview 2.10)
3013 al.getSequenceAt(i).getDatasetSequence() == null ? al.getSequenceAt(i)
3014 : al.getSequenceAt(i).getDatasetSequence(),
3017 if (jseqs[i].getPdbidsCount() > 0)
3019 Pdbids[] ids = jseqs[i].getPdbids();
3020 for (int p = 0; p < ids.length; p++)
3022 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
3023 entry.setId(ids[p].getId());
3024 if (ids[p].getType() != null)
3026 if (PDBEntry.Type.getType(ids[p].getType()) != null)
3028 entry.setType(PDBEntry.Type.getType(ids[p].getType()));
3032 entry.setType(PDBEntry.Type.FILE);
3035 // jprovider is null when executing 'New View'
3036 if (ids[p].getFile() != null && jprovider != null)
3038 if (!pdbloaded.containsKey(ids[p].getFile()))
3040 entry.setFile(loadPDBFile(jprovider, ids[p].getId(),
3045 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
3048 if (ids[p].getPdbentryItem() != null)
3050 for (PdbentryItem item : ids[p].getPdbentryItem())
3052 for (Property pr : item.getProperty())
3054 entry.setProperty(pr.getName(), pr.getValue());
3058 StructureSelectionManager.getStructureSelectionManager(
3059 Desktop.instance).registerPDBEntry(entry);
3060 // adds PDBEntry to datasequence's set (since Jalview 2.10)
3061 if (al.getSequenceAt(i).getDatasetSequence() != null)
3063 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
3067 al.getSequenceAt(i).addPDBId(entry);
3072 } // end !multipleview
3074 // ///////////////////////////////
3075 // LOAD SEQUENCE MAPPINGS
3077 if (vamsasSet.getAlcodonFrameCount() > 0)
3079 // TODO Potentially this should only be done once for all views of an
3081 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
3082 for (int i = 0; i < alc.length; i++)
3084 AlignedCodonFrame cf = new AlignedCodonFrame();
3085 if (alc[i].getAlcodMapCount() > 0)
3087 AlcodMap[] maps = alc[i].getAlcodMap();
3088 for (int m = 0; m < maps.length; m++)
3090 SequenceI dnaseq = seqRefIds.get(maps[m].getDnasq());
3092 jalview.datamodel.Mapping mapping = null;
3093 // attach to dna sequence reference.
3094 if (maps[m].getMapping() != null)
3096 mapping = addMapping(maps[m].getMapping());
3097 if (dnaseq != null && mapping.getTo() != null)
3099 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
3104 frefedSequence.add(newAlcodMapRef(maps[m].getDnasq(), cf,
3109 al.addCodonFrame(cf);
3114 // ////////////////////////////////
3116 List<JvAnnotRow> autoAlan = new ArrayList<>();
3119 * store any annotations which forward reference a group's ID
3121 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<>();
3123 if (vamsasSet.getAnnotationCount() > 0)
3125 Annotation[] an = vamsasSet.getAnnotation();
3127 for (int i = 0; i < an.length; i++)
3129 Annotation annotation = an[i];
3132 * test if annotation is automatically calculated for this view only
3134 boolean autoForView = false;
3135 if (annotation.getLabel().equals("Quality")
3136 || annotation.getLabel().equals("Conservation")
3137 || annotation.getLabel().equals("Consensus"))
3139 // Kludge for pre 2.5 projects which lacked the autocalculated flag
3141 if (!annotation.hasAutoCalculated())
3143 annotation.setAutoCalculated(true);
3147 || (annotation.hasAutoCalculated() && annotation
3148 .isAutoCalculated()))
3150 // remove ID - we don't recover annotation from other views for
3151 // view-specific annotation
3152 annotation.setId(null);
3155 // set visiblity for other annotation in this view
3156 String annotationId = annotation.getId();
3157 if (annotationId != null && annotationIds.containsKey(annotationId))
3159 AlignmentAnnotation jda = annotationIds.get(annotationId);
3160 // in principle Visible should always be true for annotation displayed
3161 // in multiple views
3162 if (annotation.hasVisible())
3164 jda.visible = annotation.getVisible();
3167 al.addAnnotation(jda);
3171 // Construct new annotation from model.
3172 AnnotationElement[] ae = annotation.getAnnotationElement();
3173 jalview.datamodel.Annotation[] anot = null;
3174 java.awt.Color firstColour = null;
3176 if (!annotation.getScoreOnly())
3178 anot = new jalview.datamodel.Annotation[al.getWidth()];
3179 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
3181 anpos = ae[aa].getPosition();
3183 if (anpos >= anot.length)
3188 anot[anpos] = new jalview.datamodel.Annotation(
3190 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
3191 (ae[aa].getSecondaryStructure() == null || ae[aa]
3192 .getSecondaryStructure().length() == 0) ? ' '
3193 : ae[aa].getSecondaryStructure().charAt(0),
3197 // JBPNote: Consider verifying dataflow for IO of secondary
3198 // structure annotation read from Stockholm files
3199 // this was added to try to ensure that
3200 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
3202 // anot[ae[aa].getPosition()].displayCharacter = "";
3204 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
3205 if (firstColour == null)
3207 firstColour = anot[anpos].colour;
3211 jalview.datamodel.AlignmentAnnotation jaa = null;
3213 if (annotation.getGraph())
3215 float llim = 0, hlim = 0;
3216 // if (autoForView || an[i].isAutoCalculated()) {
3219 jaa = new jalview.datamodel.AlignmentAnnotation(
3220 annotation.getLabel(), annotation.getDescription(), anot,
3221 llim, hlim, annotation.getGraphType());
3223 jaa.graphGroup = annotation.getGraphGroup();
3224 jaa._linecolour = firstColour;
3225 if (annotation.getThresholdLine() != null)
3227 jaa.setThreshold(new jalview.datamodel.GraphLine(annotation
3228 .getThresholdLine().getValue(), annotation
3229 .getThresholdLine().getLabel(), new java.awt.Color(
3230 annotation.getThresholdLine().getColour())));
3233 if (autoForView || annotation.isAutoCalculated())
3235 // Hardwire the symbol display line to ensure that labels for
3236 // histograms are displayed
3242 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
3243 an[i].getDescription(), anot);
3244 jaa._linecolour = firstColour;
3246 // register new annotation
3247 if (an[i].getId() != null)
3249 annotationIds.put(an[i].getId(), jaa);
3250 jaa.annotationId = an[i].getId();
3252 // recover sequence association
3253 String sequenceRef = an[i].getSequenceRef();
3254 if (sequenceRef != null)
3256 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3257 SequenceI sequence = seqRefIds.get(sequenceRef);
3258 if (sequence == null)
3260 // in pre-2.9 projects sequence ref is to sequence name
3261 sequence = al.findName(sequenceRef);
3263 if (sequence != null)
3265 jaa.createSequenceMapping(sequence, 1, true);
3266 sequence.addAlignmentAnnotation(jaa);
3269 // and make a note of any group association
3270 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
3272 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3273 .get(an[i].getGroupRef());
3276 aal = new ArrayList<>();
3277 groupAnnotRefs.put(an[i].getGroupRef(), aal);
3282 if (an[i].hasScore())
3284 jaa.setScore(an[i].getScore());
3286 if (an[i].hasVisible())
3288 jaa.visible = an[i].getVisible();
3291 if (an[i].hasCentreColLabels())
3293 jaa.centreColLabels = an[i].getCentreColLabels();
3296 if (an[i].hasScaleColLabels())
3298 jaa.scaleColLabel = an[i].getScaleColLabels();
3300 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
3302 // newer files have an 'autoCalculated' flag and store calculation
3303 // state in viewport properties
3304 jaa.autoCalculated = true; // means annotation will be marked for
3305 // update at end of load.
3307 if (an[i].hasGraphHeight())
3309 jaa.graphHeight = an[i].getGraphHeight();
3311 if (an[i].hasBelowAlignment())
3313 jaa.belowAlignment = an[i].isBelowAlignment();
3315 jaa.setCalcId(an[i].getCalcId());
3316 if (an[i].getPropertyCount() > 0)
3318 for (jalview.schemabinding.version2.Property prop : an[i]
3321 jaa.setProperty(prop.getName(), prop.getValue());
3324 if (jaa.autoCalculated)
3326 autoAlan.add(new JvAnnotRow(i, jaa));
3329 // if (!autoForView)
3331 // add autocalculated group annotation and any user created annotation
3333 al.addAnnotation(jaa);
3337 // ///////////////////////
3339 // Create alignment markup and styles for this view
3340 if (jms.getJGroupCount() > 0)
3342 JGroup[] groups = jms.getJGroup();
3343 boolean addAnnotSchemeGroup = false;
3344 for (int i = 0; i < groups.length; i++)
3346 JGroup jGroup = groups[i];
3347 ColourSchemeI cs = null;
3348 if (jGroup.getColour() != null)
3350 if (jGroup.getColour().startsWith("ucs"))
3352 cs = getUserColourScheme(jms, jGroup.getColour());
3354 else if (jGroup.getColour().equals("AnnotationColourGradient")
3355 && jGroup.getAnnotationColours() != null)
3357 addAnnotSchemeGroup = true;
3361 cs = ColourSchemeProperty.getColourScheme(al, jGroup.getColour());
3364 int pidThreshold = jGroup.getPidThreshold();
3366 Vector<SequenceI> seqs = new Vector<>();
3368 for (int s = 0; s < jGroup.getSeqCount(); s++)
3370 String seqId = jGroup.getSeq(s) + "";
3371 SequenceI ts = seqRefIds.get(seqId);
3375 seqs.addElement(ts);
3379 if (seqs.size() < 1)
3384 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3385 jGroup.getDisplayBoxes(), jGroup.getDisplayText(),
3386 jGroup.getColourText(), jGroup.getStart(), jGroup.getEnd());
3387 sg.getGroupColourScheme().setThreshold(pidThreshold, true);
3388 sg.getGroupColourScheme().setConservationInc(jGroup.getConsThreshold());
3389 sg.setOutlineColour(new java.awt.Color(jGroup.getOutlineColour()));
3391 sg.textColour = new java.awt.Color(jGroup.getTextCol1());
3392 sg.textColour2 = new java.awt.Color(jGroup.getTextCol2());
3393 sg.setShowNonconserved(jGroup.hasShowUnconserved() ? jGroup
3394 .isShowUnconserved() : false);
3395 sg.thresholdTextColour = jGroup.getTextColThreshold();
3396 if (jGroup.hasShowConsensusHistogram())
3398 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3401 if (jGroup.hasShowSequenceLogo())
3403 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3405 if (jGroup.hasNormaliseSequenceLogo())
3407 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3409 if (jGroup.hasIgnoreGapsinConsensus())
3411 sg.setIgnoreGapsConsensus(jGroup.getIgnoreGapsinConsensus());
3413 if (jGroup.getConsThreshold() != 0)
3415 Conservation c = new Conservation("All", sg.getSequences(null),
3416 0, sg.getWidth() - 1);
3418 c.verdict(false, 25);
3419 sg.cs.setConservation(c);
3422 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3424 // re-instate unique group/annotation row reference
3425 List<AlignmentAnnotation> jaal = groupAnnotRefs.get(jGroup
3429 for (AlignmentAnnotation jaa : jaal)
3432 if (jaa.autoCalculated)
3434 // match up and try to set group autocalc alignment row for this
3436 if (jaa.label.startsWith("Consensus for "))
3438 sg.setConsensus(jaa);
3440 // match up and try to set group autocalc alignment row for this
3442 if (jaa.label.startsWith("Conservation for "))
3444 sg.setConservationRow(jaa);
3451 if (addAnnotSchemeGroup)
3453 // reconstruct the annotation colourscheme
3454 sg.setColourScheme(constructAnnotationColour(
3455 jGroup.getAnnotationColours(), null, al, jms, false));
3461 // only dataset in this model, so just return.
3464 // ///////////////////////////////
3467 // If we just load in the same jar file again, the sequenceSetId
3468 // will be the same, and we end up with multiple references
3469 // to the same sequenceSet. We must modify this id on load
3470 // so that each load of the file gives a unique id
3471 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3472 String viewId = (view.getId() == null ? null : view.getId()
3474 AlignFrame af = null;
3475 AlignViewport av = null;
3476 // now check to see if we really need to create a new viewport.
3477 if (multipleView && viewportsAdded.size() == 0)
3479 // We recovered an alignment for which a viewport already exists.
3480 // TODO: fix up any settings necessary for overlaying stored state onto
3481 // state recovered from another document. (may not be necessary).
3482 // we may need a binding from a viewport in memory to one recovered from
3484 // and then recover its containing af to allow the settings to be applied.
3485 // TODO: fix for vamsas demo
3487 .println("About to recover a viewport for existing alignment: Sequence set ID is "
3489 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3490 if (seqsetobj != null)
3492 if (seqsetobj instanceof String)
3494 uniqueSeqSetId = (String) seqsetobj;
3496 .println("Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
3502 .println("Warning : Collision between sequence set ID string and existing jalview object mapping.");
3508 * indicate that annotation colours are applied across all groups (pre
3509 * Jalview 2.8.1 behaviour)
3511 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan(
3512 "2.8.1", object.getVersion());
3514 AlignmentPanel ap = null;
3515 boolean isnewview = true;
3518 // Check to see if this alignment already has a view id == viewId
3519 jalview.gui.AlignmentPanel views[] = Desktop
3520 .getAlignmentPanels(uniqueSeqSetId);
3521 if (views != null && views.length > 0)
3523 for (int v = 0; v < views.length; v++)
3525 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
3527 // recover the existing alignpanel, alignframe, viewport
3528 af = views[v].alignFrame;
3531 // TODO: could even skip resetting view settings if we don't want to
3532 // change the local settings from other jalview processes
3541 af = loadViewport(file, jseqs, hiddenSeqs, al, jms, view,
3542 uniqueSeqSetId, viewId, autoAlan);
3548 * Load any trees, PDB structures and viewers
3550 * Not done if flag is false (when this method is used for New View)
3552 if (loadTreesAndStructures)
3554 loadTrees(jms, view, af, av, ap);
3555 loadPDBStructures(jprovider, jseqs, af, ap);
3556 loadRnaViewers(jprovider, jseqs, ap);
3558 // and finally return.
3563 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
3564 * panel is restored from separate jar entries, two (gapped and trimmed) per
3565 * sequence and secondary structure.
3567 * Currently each viewer shows just one sequence and structure (gapped and
3568 * trimmed), however this method is designed to support multiple sequences or
3569 * structures in viewers if wanted in future.
3575 private void loadRnaViewers(jarInputStreamProvider jprovider,
3576 JSeq[] jseqs, AlignmentPanel ap)
3579 * scan the sequences for references to viewers; create each one the first
3580 * time it is referenced, add Rna models to existing viewers
3582 for (JSeq jseq : jseqs)
3584 for (int i = 0; i < jseq.getRnaViewerCount(); i++)
3586 RnaViewer viewer = jseq.getRnaViewer(i);
3587 AppVarna appVarna = findOrCreateVarnaViewer(viewer,
3588 uniqueSetSuffix, ap);
3590 for (int j = 0; j < viewer.getSecondaryStructureCount(); j++)
3592 SecondaryStructure ss = viewer.getSecondaryStructure(j);
3593 SequenceI seq = seqRefIds.get(jseq.getId());
3594 AlignmentAnnotation ann = this.annotationIds.get(ss
3595 .getAnnotationId());
3598 * add the structure to the Varna display (with session state copied
3599 * from the jar to a temporary file)
3601 boolean gapped = ss.isGapped();
3602 String rnaTitle = ss.getTitle();
3603 String sessionState = ss.getViewerState();
3604 String tempStateFile = copyJarEntry(jprovider, sessionState,
3606 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
3607 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
3609 appVarna.setInitialSelection(viewer.getSelectedRna());
3615 * Locate and return an already instantiated matching AppVarna, or create one
3619 * @param viewIdSuffix
3623 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
3624 String viewIdSuffix, AlignmentPanel ap)
3627 * on each load a suffix is appended to the saved viewId, to avoid conflicts
3628 * if load is repeated
3630 String postLoadId = viewer.getViewId() + viewIdSuffix;
3631 for (JInternalFrame frame : getAllFrames())
3633 if (frame instanceof AppVarna)
3635 AppVarna varna = (AppVarna) frame;
3636 if (postLoadId.equals(varna.getViewId()))
3638 // this viewer is already instantiated
3639 // could in future here add ap as another 'parent' of the
3640 // AppVarna window; currently just 1-to-many
3647 * viewer not found - make it
3649 RnaViewerModel model = new RnaViewerModel(postLoadId,
3650 viewer.getTitle(), viewer.getXpos(), viewer.getYpos(),
3651 viewer.getWidth(), viewer.getHeight(),
3652 viewer.getDividerLocation());
3653 AppVarna varna = new AppVarna(model, ap);
3659 * Load any saved trees
3667 protected void loadTrees(JalviewModelSequence jms, Viewport view,
3668 AlignFrame af, AlignViewport av, AlignmentPanel ap)
3670 // TODO result of automated refactoring - are all these parameters needed?
3673 for (int t = 0; t < jms.getTreeCount(); t++)
3676 Tree tree = jms.getTree(t);
3678 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
3681 tp = af.showNewickTree(
3682 new jalview.io.NewickFile(tree.getNewick()),
3683 tree.getTitle(), tree.getWidth(), tree.getHeight(),
3684 tree.getXpos(), tree.getYpos());
3685 if (tree.getId() != null)
3687 // perhaps bind the tree id to something ?
3692 // update local tree attributes ?
3693 // TODO: should check if tp has been manipulated by user - if so its
3694 // settings shouldn't be modified
3695 tp.setTitle(tree.getTitle());
3696 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(), tree
3697 .getWidth(), tree.getHeight()));
3698 tp.av = av; // af.viewport; // TODO: verify 'associate with all
3701 tp.treeCanvas.av = av; // af.viewport;
3702 tp.treeCanvas.ap = ap; // af.alignPanel;
3707 warn("There was a problem recovering stored Newick tree: \n"
3708 + tree.getNewick());
3712 tp.fitToWindow.setState(tree.getFitToWindow());
3713 tp.fitToWindow_actionPerformed(null);
3715 if (tree.getFontName() != null)
3717 tp.setTreeFont(new java.awt.Font(tree.getFontName(), tree
3718 .getFontStyle(), tree.getFontSize()));
3722 tp.setTreeFont(new java.awt.Font(view.getFontName(), view
3723 .getFontStyle(), tree.getFontSize()));
3726 tp.showPlaceholders(tree.getMarkUnlinked());
3727 tp.showBootstrap(tree.getShowBootstrap());
3728 tp.showDistances(tree.getShowDistances());
3730 tp.treeCanvas.threshold = tree.getThreshold();
3732 if (tree.getCurrentTree())
3734 af.viewport.setCurrentTree(tp.getTree());
3738 } catch (Exception ex)
3740 ex.printStackTrace();
3745 * Load and link any saved structure viewers.
3752 protected void loadPDBStructures(jarInputStreamProvider jprovider,
3753 JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
3756 * Run through all PDB ids on the alignment, and collect mappings between
3757 * distinct view ids and all sequences referring to that view.
3759 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<>();
3761 for (int i = 0; i < jseqs.length; i++)
3763 if (jseqs[i].getPdbidsCount() > 0)
3765 Pdbids[] ids = jseqs[i].getPdbids();
3766 for (int p = 0; p < ids.length; p++)
3768 final int structureStateCount = ids[p].getStructureStateCount();
3769 for (int s = 0; s < structureStateCount; s++)
3771 // check to see if we haven't already created this structure view
3772 final StructureState structureState = ids[p]
3773 .getStructureState(s);
3774 String sviewid = (structureState.getViewId() == null) ? null
3775 : structureState.getViewId() + uniqueSetSuffix;
3776 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
3777 // Originally : ids[p].getFile()
3778 // : TODO: verify external PDB file recovery still works in normal
3779 // jalview project load
3780 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId(),
3782 jpdb.setId(ids[p].getId());
3784 int x = structureState.getXpos();
3785 int y = structureState.getYpos();
3786 int width = structureState.getWidth();
3787 int height = structureState.getHeight();
3789 // Probably don't need to do this anymore...
3790 // Desktop.desktop.getComponentAt(x, y);
3791 // TODO: NOW: check that this recovers the PDB file correctly.
3792 String pdbFile = loadPDBFile(jprovider, ids[p].getId(),
3794 jalview.datamodel.SequenceI seq = seqRefIds.get(jseqs[i]
3796 if (sviewid == null)
3798 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width
3801 if (!structureViewers.containsKey(sviewid))
3803 structureViewers.put(sviewid,
3804 new StructureViewerModel(x, y, width, height, false,
3805 false, true, structureState.getViewId(),
3806 structureState.getType()));
3807 // Legacy pre-2.7 conversion JAL-823 :
3808 // do not assume any view has to be linked for colour by
3812 // assemble String[] { pdb files }, String[] { id for each
3813 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3814 // seqs_file 2}, boolean[] {
3815 // linkAlignPanel,superposeWithAlignpanel}} from hash
3816 StructureViewerModel jmoldat = structureViewers.get(sviewid);
3817 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
3818 | (structureState.hasAlignwithAlignPanel() ? structureState
3819 .getAlignwithAlignPanel() : false));
3822 * Default colour by linked panel to false if not specified (e.g.
3823 * for pre-2.7 projects)
3825 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
3826 colourWithAlignPanel |= (structureState
3827 .hasColourwithAlignPanel() ? structureState
3828 .getColourwithAlignPanel() : false);
3829 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
3832 * Default colour by viewer to true if not specified (e.g. for
3835 boolean colourByViewer = jmoldat.isColourByViewer();
3836 colourByViewer &= structureState.hasColourByJmol() ? structureState
3837 .getColourByJmol() : true;
3838 jmoldat.setColourByViewer(colourByViewer);
3840 if (jmoldat.getStateData().length() < structureState
3841 .getContent().length())
3844 jmoldat.setStateData(structureState.getContent());
3847 if (ids[p].getFile() != null)
3849 File mapkey = new File(ids[p].getFile());
3850 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
3851 if (seqstrmaps == null)
3853 jmoldat.getFileData().put(
3855 seqstrmaps = jmoldat.new StructureData(pdbFile,
3858 if (!seqstrmaps.getSeqList().contains(seq))
3860 seqstrmaps.getSeqList().add(seq);
3866 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");
3873 // Instantiate the associated structure views
3874 for (Entry<String, StructureViewerModel> entry : structureViewers
3879 createOrLinkStructureViewer(entry, af, ap, jprovider);
3880 } catch (Exception e)
3882 System.err.println("Error loading structure viewer: "
3884 // failed - try the next one
3896 protected void createOrLinkStructureViewer(
3897 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3898 AlignmentPanel ap, jarInputStreamProvider jprovider)
3900 final StructureViewerModel stateData = viewerData.getValue();
3903 * Search for any viewer windows already open from other alignment views
3904 * that exactly match the stored structure state
3906 StructureViewerBase comp = findMatchingViewer(viewerData);
3910 linkStructureViewer(ap, comp, stateData);
3915 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
3916 * "viewer_"+stateData.viewId
3918 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
3920 createChimeraViewer(viewerData, af, jprovider);
3925 * else Jmol (if pre-2.9, stateData contains JMOL state string)
3927 createJmolViewer(viewerData, af, jprovider);
3932 * Create a new Chimera viewer.
3938 protected void createChimeraViewer(
3939 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3940 jarInputStreamProvider jprovider)
3942 StructureViewerModel data = viewerData.getValue();
3943 String chimeraSessionFile = data.getStateData();
3946 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
3948 * NB this is the 'saved' viewId as in the project file XML, _not_ the
3949 * 'uniquified' sviewid used to reconstruct the viewer here
3951 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
3952 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
3955 Set<Entry<File, StructureData>> fileData = data.getFileData()
3957 List<PDBEntry> pdbs = new ArrayList<>();
3958 List<SequenceI[]> allseqs = new ArrayList<>();
3959 for (Entry<File, StructureData> pdb : fileData)
3961 String filePath = pdb.getValue().getFilePath();
3962 String pdbId = pdb.getValue().getPdbId();
3963 // pdbs.add(new PDBEntry(filePath, pdbId));
3964 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
3965 final List<SequenceI> seqList = pdb.getValue().getSeqList();
3966 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
3970 boolean colourByChimera = data.isColourByViewer();
3971 boolean colourBySequence = data.isColourWithAlignPanel();
3973 // TODO use StructureViewer as a factory here, see JAL-1761
3974 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
3975 final SequenceI[][] seqsArray = allseqs.toArray(new SequenceI[allseqs
3977 String newViewId = viewerData.getKey();
3979 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
3980 af.alignPanel, pdbArray, seqsArray, colourByChimera,
3981 colourBySequence, newViewId);
3982 cvf.setSize(data.getWidth(), data.getHeight());
3983 cvf.setLocation(data.getX(), data.getY());
3987 * Create a new Jmol window. First parse the Jmol state to translate filenames
3988 * loaded into the view, and record the order in which files are shown in the
3989 * Jmol view, so we can add the sequence mappings in same order.
3995 protected void createJmolViewer(
3996 final Entry<String, StructureViewerModel> viewerData,
3997 AlignFrame af, jarInputStreamProvider jprovider)
3999 final StructureViewerModel svattrib = viewerData.getValue();
4000 String state = svattrib.getStateData();
4003 * Pre-2.9: state element value is the Jmol state string
4005 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
4008 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
4010 state = readJarEntry(jprovider,
4011 getViewerJarEntryName(svattrib.getViewId()));
4014 List<String> pdbfilenames = new ArrayList<>();
4015 List<SequenceI[]> seqmaps = new ArrayList<>();
4016 List<String> pdbids = new ArrayList<>();
4017 StringBuilder newFileLoc = new StringBuilder(64);
4018 int cp = 0, ncp, ecp;
4019 Map<File, StructureData> oldFiles = svattrib.getFileData();
4020 while ((ncp = state.indexOf("load ", cp)) > -1)
4024 // look for next filename in load statement
4025 newFileLoc.append(state.substring(cp,
4026 ncp = (state.indexOf("\"", ncp + 1) + 1)));
4027 String oldfilenam = state.substring(ncp,
4028 ecp = state.indexOf("\"", ncp));
4029 // recover the new mapping data for this old filename
4030 // have to normalize filename - since Jmol and jalview do
4032 // translation differently.
4033 StructureData filedat = oldFiles.get(new File(oldfilenam));
4034 if (filedat == null)
4036 String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\");
4037 filedat = oldFiles.get(new File(reformatedOldFilename));
4039 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
4040 pdbfilenames.add(filedat.getFilePath());
4041 pdbids.add(filedat.getPdbId());
4042 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4043 newFileLoc.append("\"");
4044 cp = ecp + 1; // advance beyond last \" and set cursor so we can
4045 // look for next file statement.
4046 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
4050 // just append rest of state
4051 newFileLoc.append(state.substring(cp));
4055 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
4056 newFileLoc = new StringBuilder(state);
4057 newFileLoc.append("; load append ");
4058 for (File id : oldFiles.keySet())
4060 // add this and any other pdb files that should be present in
4062 StructureData filedat = oldFiles.get(id);
4063 newFileLoc.append(filedat.getFilePath());
4064 pdbfilenames.add(filedat.getFilePath());
4065 pdbids.add(filedat.getPdbId());
4066 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4067 newFileLoc.append(" \"");
4068 newFileLoc.append(filedat.getFilePath());
4069 newFileLoc.append("\"");
4072 newFileLoc.append(";");
4075 if (newFileLoc.length() == 0)
4079 int histbug = newFileLoc.indexOf("history = ");
4083 * change "history = [true|false];" to "history = [1|0];"
4086 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
4087 String val = (diff == -1) ? null : newFileLoc
4088 .substring(histbug, diff);
4089 if (val != null && val.length() >= 4)
4091 if (val.contains("e")) // eh? what can it be?
4093 if (val.trim().equals("true"))
4101 newFileLoc.replace(histbug, diff, val);
4106 final String[] pdbf = pdbfilenames.toArray(new String[pdbfilenames
4108 final String[] id = pdbids.toArray(new String[pdbids.size()]);
4109 final SequenceI[][] sq = seqmaps
4110 .toArray(new SequenceI[seqmaps.size()][]);
4111 final String fileloc = newFileLoc.toString();
4112 final String sviewid = viewerData.getKey();
4113 final AlignFrame alf = af;
4114 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
4115 svattrib.getWidth(), svattrib.getHeight());
4118 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
4123 JalviewStructureDisplayI sview = null;
4126 sview = new StructureViewer(alf.alignPanel
4127 .getStructureSelectionManager()).createView(
4128 StructureViewer.ViewerType.JMOL, pdbf, id, sq,
4129 alf.alignPanel, svattrib, fileloc, rect, sviewid);
4130 addNewStructureViewer(sview);
4131 } catch (OutOfMemoryError ex)
4133 new OOMWarning("restoring structure view for PDB id " + id,
4134 (OutOfMemoryError) ex.getCause());
4135 if (sview != null && sview.isVisible())
4137 sview.closeViewer(false);
4138 sview.setVisible(false);
4144 } catch (InvocationTargetException ex)
4146 warn("Unexpected error when opening Jmol view.", ex);
4148 } catch (InterruptedException e)
4150 // e.printStackTrace();
4156 * Generates a name for the entry in the project jar file to hold state
4157 * information for a structure viewer
4162 protected String getViewerJarEntryName(String viewId)
4164 return VIEWER_PREFIX + viewId;
4168 * Returns any open frame that matches given structure viewer data. The match
4169 * is based on the unique viewId, or (for older project versions) the frame's
4175 protected StructureViewerBase findMatchingViewer(
4176 Entry<String, StructureViewerModel> viewerData)
4178 final String sviewid = viewerData.getKey();
4179 final StructureViewerModel svattrib = viewerData.getValue();
4180 StructureViewerBase comp = null;
4181 JInternalFrame[] frames = getAllFrames();
4182 for (JInternalFrame frame : frames)
4184 if (frame instanceof StructureViewerBase)
4187 * Post jalview 2.4 schema includes structure view id
4190 && ((StructureViewerBase) frame).getViewId()
4193 comp = (StructureViewerBase) frame;
4194 break; // break added in 2.9
4197 * Otherwise test for matching position and size of viewer frame
4199 else if (frame.getX() == svattrib.getX()
4200 && frame.getY() == svattrib.getY()
4201 && frame.getHeight() == svattrib.getHeight()
4202 && frame.getWidth() == svattrib.getWidth())
4204 comp = (StructureViewerBase) frame;
4205 // no break in faint hope of an exact match on viewId
4213 * Link an AlignmentPanel to an existing structure viewer.
4218 * @param useinViewerSuperpos
4219 * @param usetoColourbyseq
4220 * @param viewerColouring
4222 protected void linkStructureViewer(AlignmentPanel ap,
4223 StructureViewerBase viewer, StructureViewerModel stateData)
4225 // NOTE: if the jalview project is part of a shared session then
4226 // view synchronization should/could be done here.
4228 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4229 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4230 final boolean viewerColouring = stateData.isColourByViewer();
4231 Map<File, StructureData> oldFiles = stateData.getFileData();
4234 * Add mapping for sequences in this view to an already open viewer
4236 final AAStructureBindingModel binding = viewer.getBinding();
4237 for (File id : oldFiles.keySet())
4239 // add this and any other pdb files that should be present in the
4241 StructureData filedat = oldFiles.get(id);
4242 String pdbFile = filedat.getFilePath();
4243 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4244 binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE);
4245 binding.addSequenceForStructFile(pdbFile, seq);
4247 // and add the AlignmentPanel's reference to the view panel
4248 viewer.addAlignmentPanel(ap);
4249 if (useinViewerSuperpos)
4251 viewer.useAlignmentPanelForSuperposition(ap);
4255 viewer.excludeAlignmentPanelForSuperposition(ap);
4257 if (usetoColourbyseq)
4259 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4263 viewer.excludeAlignmentPanelForColourbyseq(ap);
4268 * Get all frames within the Desktop.
4272 protected JInternalFrame[] getAllFrames()
4274 JInternalFrame[] frames = null;
4275 // TODO is this necessary - is it safe - risk of hanging?
4280 frames = Desktop.desktop.getAllFrames();
4281 } catch (ArrayIndexOutOfBoundsException e)
4283 // occasional No such child exceptions are thrown here...
4287 } catch (InterruptedException f)
4291 } while (frames == null);
4296 * Answers true if 'version' is equal to or later than 'supported', where each
4297 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4298 * changes. Development and test values for 'version' are leniently treated
4302 * - minimum version we are comparing against
4304 * - version of data being processsed
4307 public static boolean isVersionStringLaterThan(String supported,
4310 if (supported == null || version == null
4311 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4312 || version.equalsIgnoreCase("Test")
4313 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4315 System.err.println("Assuming project file with "
4316 + (version == null ? "null" : version)
4317 + " is compatible with Jalview version " + supported);
4322 return StringUtils.compareVersions(version, supported, "b") >= 0;
4326 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4328 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4330 if (newStructureViewers != null)
4332 sview.getBinding().setFinishedLoadingFromArchive(false);
4333 newStructureViewers.add(sview);
4337 protected void setLoadingFinishedForNewStructureViewers()
4339 if (newStructureViewers != null)
4341 for (JalviewStructureDisplayI sview : newStructureViewers)
4343 sview.getBinding().setFinishedLoadingFromArchive(true);
4345 newStructureViewers.clear();
4346 newStructureViewers = null;
4350 AlignFrame loadViewport(String file, JSeq[] JSEQ,
4351 List<SequenceI> hiddenSeqs, AlignmentI al,
4352 JalviewModelSequence jms, Viewport view, String uniqueSeqSetId,
4353 String viewId, List<JvAnnotRow> autoAlan)
4355 AlignFrame af = null;
4356 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
4357 uniqueSeqSetId, viewId);
4359 af.setFileName(file, FileFormat.Jalview);
4361 for (int i = 0; i < JSEQ.length; i++)
4363 af.viewport.setSequenceColour(af.viewport.getAlignment()
4364 .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour()));
4369 af.getViewport().setColourByReferenceSeq(true);
4370 af.getViewport().setDisplayReferenceSeq(true);
4373 af.viewport.setGatherViewsHere(view.getGatheredViews());
4375 if (view.getSequenceSetId() != null)
4377 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4379 af.viewport.setSequenceSetId(uniqueSeqSetId);
4382 // propagate shared settings to this new view
4383 af.viewport.setHistoryList(av.getHistoryList());
4384 af.viewport.setRedoList(av.getRedoList());
4388 viewportsAdded.put(uniqueSeqSetId, af.viewport);
4390 // TODO: check if this method can be called repeatedly without
4391 // side-effects if alignpanel already registered.
4392 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4394 // apply Hidden regions to view.
4395 if (hiddenSeqs != null)
4397 for (int s = 0; s < JSEQ.length; s++)
4399 SequenceGroup hidden = new SequenceGroup();
4400 boolean isRepresentative = false;
4401 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
4403 isRepresentative = true;
4404 SequenceI sequenceToHide = al.getSequenceAt(JSEQ[s]
4405 .getHiddenSequences(r));
4406 hidden.addSequence(sequenceToHide, false);
4407 // remove from hiddenSeqs list so we don't try to hide it twice
4408 hiddenSeqs.remove(sequenceToHide);
4410 if (isRepresentative)
4412 SequenceI representativeSequence = al.getSequenceAt(s);
4413 hidden.addSequence(representativeSequence, false);
4414 af.viewport.hideRepSequences(representativeSequence, hidden);
4418 SequenceI[] hseqs = hiddenSeqs.toArray(new SequenceI[hiddenSeqs
4420 af.viewport.hideSequence(hseqs);
4423 // recover view properties and display parameters
4424 if (view.getViewName() != null)
4426 af.viewport.viewName = view.getViewName();
4427 af.setInitialTabVisible();
4429 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
4432 af.viewport.setShowAnnotation(view.getShowAnnotation());
4433 af.viewport.setAbovePIDThreshold(view.getPidSelected());
4434 af.viewport.setThreshold(view.getPidThreshold());
4436 af.viewport.setColourText(view.getShowColourText());
4438 af.viewport.setConservationSelected(view.getConservationSelected());
4439 af.viewport.setIncrement(view.getConsThreshold());
4440 af.viewport.setShowJVSuffix(view.getShowFullId());
4441 af.viewport.setRightAlignIds(view.getRightAlignIds());
4442 af.viewport.setFont(
4443 new java.awt.Font(view.getFontName(), view.getFontStyle(), view
4444 .getFontSize()), true);
4445 ViewStyleI vs = af.viewport.getViewStyle();
4446 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
4447 af.viewport.setViewStyle(vs);
4448 // TODO: allow custom charWidth/Heights to be restored by updating them
4449 // after setting font - which means set above to false
4450 af.viewport.setRenderGaps(view.getRenderGaps());
4451 af.viewport.setWrapAlignment(view.getWrapAlignment());
4452 af.viewport.setShowAnnotation(view.getShowAnnotation());
4454 af.viewport.setShowBoxes(view.getShowBoxes());
4456 af.viewport.setShowText(view.getShowText());
4458 af.viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
4459 af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
4460 af.viewport.setThresholdTextColour(view.getTextColThreshold());
4461 af.viewport.setShowUnconserved(view.hasShowUnconserved() ? view
4462 .isShowUnconserved() : false);
4463 af.viewport.getRanges().setStartRes(view.getStartRes());
4464 // startSeq set in af.alignPanel.updateLayout below
4465 af.alignPanel.updateLayout();
4466 ColourSchemeI cs = null;
4467 // apply colourschemes
4468 if (view.getBgColour() != null)
4470 if (view.getBgColour().startsWith("ucs"))
4472 cs = getUserColourScheme(jms, view.getBgColour());
4474 else if (view.getBgColour().startsWith("Annotation"))
4476 AnnotationColours viewAnnColour = view.getAnnotationColours();
4477 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
4484 cs = ColourSchemeProperty.getColourScheme(al, view.getBgColour());
4488 af.viewport.setGlobalColourScheme(cs);
4489 af.viewport.getResidueShading().setThreshold(
4490 view.getPidThreshold(), true);
4491 af.viewport.getResidueShading().setConsensus(
4492 af.viewport.getSequenceConsensusHash());
4493 af.viewport.setColourAppliesToAllGroups(false);
4495 if (view.getConservationSelected() && cs != null)
4497 af.viewport.getResidueShading().setConservationInc(
4498 view.getConsThreshold());
4501 af.changeColour(cs);
4503 af.viewport.setColourAppliesToAllGroups(true);
4505 af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures());
4507 if (view.hasCentreColumnLabels())
4509 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
4511 if (view.hasIgnoreGapsinConsensus())
4513 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
4516 if (view.hasFollowHighlight())
4518 af.viewport.setFollowHighlight(view.getFollowHighlight());
4520 if (view.hasFollowSelection())
4522 af.viewport.followSelection = view.getFollowSelection();
4524 if (view.hasShowConsensusHistogram())
4526 af.viewport.setShowConsensusHistogram(view
4527 .getShowConsensusHistogram());
4531 af.viewport.setShowConsensusHistogram(true);
4533 if (view.hasShowSequenceLogo())
4535 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
4539 af.viewport.setShowSequenceLogo(false);
4541 if (view.hasNormaliseSequenceLogo())
4543 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
4545 if (view.hasShowDbRefTooltip())
4547 af.viewport.setShowDBRefs(view.getShowDbRefTooltip());
4549 if (view.hasShowNPfeatureTooltip())
4551 af.viewport.setShowNPFeats(view.hasShowNPfeatureTooltip());
4553 if (view.hasShowGroupConsensus())
4555 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
4559 af.viewport.setShowGroupConsensus(false);
4561 if (view.hasShowGroupConservation())
4563 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
4567 af.viewport.setShowGroupConservation(false);
4570 // recover featre settings
4571 if (jms.getFeatureSettings() != null)
4573 FeaturesDisplayed fdi;
4574 af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
4575 String[] renderOrder = new String[jms.getFeatureSettings()
4576 .getSettingCount()];
4577 Map<String, FeatureColourI> featureColours = new Hashtable<>();
4578 Map<String, Float> featureOrder = new Hashtable<>();
4580 for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
4582 Setting setting = jms.getFeatureSettings().getSetting(fs);
4583 if (setting.hasMincolour())
4585 FeatureColourI gc = setting.hasMin() ? new FeatureColour(
4586 new Color(setting.getMincolour()), new Color(
4587 setting.getColour()), setting.getMin(),
4588 setting.getMax()) : new FeatureColour(new Color(
4589 setting.getMincolour()), new Color(setting.getColour()),
4591 if (setting.hasThreshold())
4593 gc.setThreshold(setting.getThreshold());
4594 int threshstate = setting.getThreshstate();
4595 // -1 = None, 0 = Below, 1 = Above threshold
4596 if (threshstate == 0)
4598 gc.setBelowThreshold(true);
4600 else if (threshstate == 1)
4602 gc.setAboveThreshold(true);
4605 gc.setAutoScaled(true); // default
4606 if (setting.hasAutoScale())
4608 gc.setAutoScaled(setting.getAutoScale());
4610 if (setting.hasColourByLabel())
4612 gc.setColourByLabel(setting.getColourByLabel());
4614 // and put in the feature colour table.
4615 featureColours.put(setting.getType(), gc);
4619 featureColours.put(setting.getType(), new FeatureColour(
4620 new Color(setting.getColour())));
4622 renderOrder[fs] = setting.getType();
4623 if (setting.hasOrder())
4625 featureOrder.put(setting.getType(), setting.getOrder());
4629 featureOrder.put(setting.getType(), new Float(fs
4630 / jms.getFeatureSettings().getSettingCount()));
4632 if (setting.getDisplay())
4634 fdi.setVisible(setting.getType());
4637 Map<String, Boolean> fgtable = new Hashtable<>();
4638 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
4640 Group grp = jms.getFeatureSettings().getGroup(gs);
4641 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
4643 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4644 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
4645 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
4646 FeatureRendererSettings frs = new FeatureRendererSettings(
4647 renderOrder, fgtable, featureColours, 1.0f, featureOrder);
4648 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
4649 .transferSettings(frs);
4653 if (view.getHiddenColumnsCount() > 0)
4655 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
4657 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(), view
4658 .getHiddenColumns(c).getEnd() // +1
4662 if (view.getCalcIdParam() != null)
4664 for (CalcIdParam calcIdParam : view.getCalcIdParam())
4666 if (calcIdParam != null)
4668 if (recoverCalcIdParam(calcIdParam, af.viewport))
4673 warn("Couldn't recover parameters for "
4674 + calcIdParam.getCalcId());
4679 af.setMenusFromViewport(af.viewport);
4680 af.setTitle(view.getTitle());
4681 // TODO: we don't need to do this if the viewport is aready visible.
4683 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
4684 * has a 'cdna/protein complement' view, in which case save it in order to
4685 * populate a SplitFrame once all views have been read in.
4687 String complementaryViewId = view.getComplementId();
4688 if (complementaryViewId == null)
4690 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
4692 // recompute any autoannotation
4693 af.alignPanel.updateAnnotation(false, true);
4694 reorderAutoannotation(af, al, autoAlan);
4695 af.alignPanel.alignmentChanged();
4699 splitFrameCandidates.put(view, af);
4705 * Reads saved data to restore Colour by Annotation settings
4707 * @param viewAnnColour
4711 * @param checkGroupAnnColour
4714 private ColourSchemeI constructAnnotationColour(
4715 AnnotationColours viewAnnColour, AlignFrame af, AlignmentI al,
4716 JalviewModelSequence jms, boolean checkGroupAnnColour)
4718 boolean propagateAnnColour = false;
4719 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
4720 if (checkGroupAnnColour && al.getGroups() != null
4721 && al.getGroups().size() > 0)
4723 // pre 2.8.1 behaviour
4724 // check to see if we should transfer annotation colours
4725 propagateAnnColour = true;
4726 for (SequenceGroup sg : al.getGroups())
4728 if (sg.getColourScheme() instanceof AnnotationColourGradient)
4730 propagateAnnColour = false;
4736 * 2.10.2- : saved annotationId is AlignmentAnnotation.annotationId
4738 String annotationId = viewAnnColour.getAnnotation();
4739 AlignmentAnnotation matchedAnnotation = annotationIds.get(annotationId);
4742 * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
4744 if (matchedAnnotation == null && annAlignment.getAlignmentAnnotation() != null)
4746 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
4749 .equals(annAlignment.getAlignmentAnnotation()[i].label))
4751 matchedAnnotation = annAlignment.getAlignmentAnnotation()[i];
4756 if (matchedAnnotation == null)
4758 System.err.println("Failed to match annotation colour scheme for "
4762 if (matchedAnnotation.getThreshold() == null)
4764 matchedAnnotation.setThreshold(new GraphLine(viewAnnColour.getThreshold(),
4765 "Threshold", Color.black));
4768 AnnotationColourGradient cs = null;
4769 if (viewAnnColour.getColourScheme().equals("None"))
4771 cs = new AnnotationColourGradient(matchedAnnotation, new Color(
4772 viewAnnColour.getMinColour()), new Color(
4773 viewAnnColour.getMaxColour()),
4774 viewAnnColour.getAboveThreshold());
4776 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
4778 cs = new AnnotationColourGradient(matchedAnnotation, getUserColourScheme(
4779 jms, viewAnnColour.getColourScheme()),
4780 viewAnnColour.getAboveThreshold());
4784 cs = new AnnotationColourGradient(matchedAnnotation,
4785 ColourSchemeProperty.getColourScheme(al,
4786 viewAnnColour.getColourScheme()),
4787 viewAnnColour.getAboveThreshold());
4790 boolean perSequenceOnly = viewAnnColour.isPerSequence();
4791 boolean useOriginalColours = viewAnnColour.isPredefinedColours();
4792 cs.setSeqAssociated(perSequenceOnly);
4793 cs.setPredefinedColours(useOriginalColours);
4795 if (propagateAnnColour && al.getGroups() != null)
4797 // Also use these settings for all the groups
4798 for (int g = 0; g < al.getGroups().size(); g++)
4800 SequenceGroup sg = al.getGroups().get(g);
4801 if (sg.getGroupColourScheme() == null)
4806 AnnotationColourGradient groupScheme = new AnnotationColourGradient(
4807 matchedAnnotation, sg.getColourScheme(),
4808 viewAnnColour.getAboveThreshold());
4809 sg.setColourScheme(groupScheme);
4810 groupScheme.setSeqAssociated(perSequenceOnly);
4811 groupScheme.setPredefinedColours(useOriginalColours);
4817 private void reorderAutoannotation(AlignFrame af, AlignmentI al,
4818 List<JvAnnotRow> autoAlan)
4820 // copy over visualization settings for autocalculated annotation in the
4822 if (al.getAlignmentAnnotation() != null)
4825 * Kludge for magic autoannotation names (see JAL-811)
4827 String[] magicNames = new String[] { "Consensus", "Quality",
4829 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
4830 Hashtable<String, JvAnnotRow> visan = new Hashtable<>();
4831 for (String nm : magicNames)
4833 visan.put(nm, nullAnnot);
4835 for (JvAnnotRow auan : autoAlan)
4837 visan.put(auan.template.label
4838 + (auan.template.getCalcId() == null ? "" : "\t"
4839 + auan.template.getCalcId()), auan);
4841 int hSize = al.getAlignmentAnnotation().length;
4842 List<JvAnnotRow> reorder = new ArrayList<>();
4843 // work through any autoCalculated annotation already on the view
4844 // removing it if it should be placed in a different location on the
4845 // annotation panel.
4846 List<String> remains = new ArrayList<>(visan.keySet());
4847 for (int h = 0; h < hSize; h++)
4849 jalview.datamodel.AlignmentAnnotation jalan = al
4850 .getAlignmentAnnotation()[h];
4851 if (jalan.autoCalculated)
4854 JvAnnotRow valan = visan.get(k = jalan.label);
4855 if (jalan.getCalcId() != null)
4857 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
4862 // delete the auto calculated row from the alignment
4863 al.deleteAnnotation(jalan, false);
4867 if (valan != nullAnnot)
4869 if (jalan != valan.template)
4871 // newly created autoannotation row instance
4872 // so keep a reference to the visible annotation row
4873 // and copy over all relevant attributes
4874 if (valan.template.graphHeight >= 0)
4877 jalan.graphHeight = valan.template.graphHeight;
4879 jalan.visible = valan.template.visible;
4881 reorder.add(new JvAnnotRow(valan.order, jalan));
4886 // Add any (possibly stale) autocalculated rows that were not appended to
4887 // the view during construction
4888 for (String other : remains)
4890 JvAnnotRow othera = visan.get(other);
4891 if (othera != nullAnnot && othera.template.getCalcId() != null
4892 && othera.template.getCalcId().length() > 0)
4894 reorder.add(othera);
4897 // now put the automatic annotation in its correct place
4898 int s = 0, srt[] = new int[reorder.size()];
4899 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
4900 for (JvAnnotRow jvar : reorder)
4903 srt[s++] = jvar.order;
4906 jalview.util.QuickSort.sort(srt, rws);
4907 // and re-insert the annotation at its correct position
4908 for (JvAnnotRow jvar : rws)
4910 al.addAnnotation(jvar.template, jvar.order);
4912 af.alignPanel.adjustAnnotationHeight();
4916 Hashtable skipList = null;
4919 * TODO remove this method
4922 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
4923 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
4924 * throw new Error("Implementation Error. No skipList defined for this
4925 * Jalview2XML instance."); } return (AlignFrame)
4926 * skipList.get(view.getSequenceSetId()); }
4930 * Check if the Jalview view contained in object should be skipped or not.
4933 * @return true if view's sequenceSetId is a key in skipList
4935 private boolean skipViewport(JalviewModel object)
4937 if (skipList == null)
4942 if (skipList.containsKey(id = object.getJalviewModelSequence()
4943 .getViewport()[0].getSequenceSetId()))
4945 if (Cache.log != null && Cache.log.isDebugEnabled())
4947 Cache.log.debug("Skipping seuqence set id " + id);
4954 public void addToSkipList(AlignFrame af)
4956 if (skipList == null)
4958 skipList = new Hashtable();
4960 skipList.put(af.getViewport().getSequenceSetId(), af);
4963 public void clearSkipList()
4965 if (skipList != null)
4972 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
4973 boolean ignoreUnrefed)
4975 jalview.datamodel.AlignmentI ds = getDatasetFor(vamsasSet
4977 Vector dseqs = null;
4980 // create a list of new dataset sequences
4981 dseqs = new Vector();
4983 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
4985 Sequence vamsasSeq = vamsasSet.getSequence(i);
4986 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
4988 // create a new dataset
4991 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
4992 dseqs.copyInto(dsseqs);
4993 ds = new jalview.datamodel.Alignment(dsseqs);
4994 debug("Created new dataset " + vamsasSet.getDatasetId()
4995 + " for alignment " + System.identityHashCode(al));
4996 addDatasetRef(vamsasSet.getDatasetId(), ds);
4998 // set the dataset for the newly imported alignment.
4999 if (al.getDataset() == null && !ignoreUnrefed)
5008 * sequence definition to create/merge dataset sequence for
5012 * vector to add new dataset sequence to
5013 * @param ignoreUnrefed
5014 * - when true, don't create new sequences from vamsasSeq if it's id
5015 * doesn't already have an asssociated Jalview sequence.
5017 * - used to reorder the sequence in the alignment according to the
5018 * vamsasSeq array ordering, to preserve ordering of dataset
5020 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
5021 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed, int vseqpos)
5023 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
5025 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
5026 boolean reorder = false;
5027 SequenceI dsq = null;
5028 if (sq != null && sq.getDatasetSequence() != null)
5030 dsq = sq.getDatasetSequence();
5036 if (sq == null && ignoreUnrefed)
5040 String sqid = vamsasSeq.getDsseqid();
5043 // need to create or add a new dataset sequence reference to this sequence
5046 dsq = seqRefIds.get(sqid);
5051 // make a new dataset sequence
5052 dsq = sq.createDatasetSequence();
5055 // make up a new dataset reference for this sequence
5056 sqid = seqHash(dsq);
5058 dsq.setVamsasId(uniqueSetSuffix + sqid);
5059 seqRefIds.put(sqid, dsq);
5064 dseqs.addElement(dsq);
5069 ds.addSequence(dsq);
5075 { // make this dataset sequence sq's dataset sequence
5076 sq.setDatasetSequence(dsq);
5077 // and update the current dataset alignment
5082 if (!dseqs.contains(dsq))
5089 if (ds.findIndex(dsq) < 0)
5091 ds.addSequence(dsq);
5098 // TODO: refactor this as a merge dataset sequence function
5099 // now check that sq (the dataset sequence) sequence really is the union of
5100 // all references to it
5101 // boolean pre = sq.getStart() < dsq.getStart();
5102 // boolean post = sq.getEnd() > dsq.getEnd();
5106 // StringBuffer sb = new StringBuffer();
5107 String newres = jalview.analysis.AlignSeq.extractGaps(
5108 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
5109 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
5110 && newres.length() > dsq.getLength())
5112 // Update with the longer sequence.
5116 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
5117 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
5118 * sb.append(newres.substring(newres.length() - sq.getEnd() -
5119 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
5121 dsq.setSequence(newres);
5123 // TODO: merges will never happen if we 'know' we have the real dataset
5124 // sequence - this should be detected when id==dssid
5126 .println("DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
5127 // + (pre ? "prepended" : "") + " "
5128 // + (post ? "appended" : ""));
5133 // sequence refs are identical. We may need to update the existing dataset
5134 // alignment with this one, though.
5135 if (ds != null && dseqs == null)
5137 int opos = ds.findIndex(dsq);
5138 SequenceI tseq = null;
5139 if (opos != -1 && vseqpos != opos)
5141 // remove from old position
5142 ds.deleteSequence(dsq);
5144 if (vseqpos < ds.getHeight())
5146 if (vseqpos != opos)
5148 // save sequence at destination position
5149 tseq = ds.getSequenceAt(vseqpos);
5150 ds.replaceSequenceAt(vseqpos, dsq);
5151 ds.addSequence(tseq);
5156 ds.addSequence(dsq);
5163 * TODO use AlignmentI here and in related methods - needs
5164 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
5166 Hashtable<String, AlignmentI> datasetIds = null;
5168 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
5170 private AlignmentI getDatasetFor(String datasetId)
5172 if (datasetIds == null)
5174 datasetIds = new Hashtable<>();
5177 if (datasetIds.containsKey(datasetId))
5179 return datasetIds.get(datasetId);
5184 private void addDatasetRef(String datasetId, AlignmentI dataset)
5186 if (datasetIds == null)
5188 datasetIds = new Hashtable<>();
5190 datasetIds.put(datasetId, dataset);
5194 * make a new dataset ID for this jalview dataset alignment
5199 private String getDatasetIdRef(AlignmentI dataset)
5201 if (dataset.getDataset() != null)
5203 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
5205 String datasetId = makeHashCode(dataset, null);
5206 if (datasetId == null)
5208 // make a new datasetId and record it
5209 if (dataset2Ids == null)
5211 dataset2Ids = new IdentityHashMap<>();
5215 datasetId = dataset2Ids.get(dataset);
5217 if (datasetId == null)
5219 datasetId = "ds" + dataset2Ids.size() + 1;
5220 dataset2Ids.put(dataset, datasetId);
5226 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5228 for (int d = 0; d < sequence.getDBRefCount(); d++)
5230 DBRef dr = sequence.getDBRef(d);
5231 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
5232 sequence.getDBRef(d).getSource(), sequence.getDBRef(d)
5233 .getVersion(), sequence.getDBRef(d).getAccessionId());
5234 if (dr.getMapping() != null)
5236 entry.setMap(addMapping(dr.getMapping()));
5238 datasetSequence.addDBRef(entry);
5242 private jalview.datamodel.Mapping addMapping(Mapping m)
5244 SequenceI dsto = null;
5245 // Mapping m = dr.getMapping();
5246 int fr[] = new int[m.getMapListFromCount() * 2];
5247 Enumeration f = m.enumerateMapListFrom();
5248 for (int _i = 0; f.hasMoreElements(); _i += 2)
5250 MapListFrom mf = (MapListFrom) f.nextElement();
5251 fr[_i] = mf.getStart();
5252 fr[_i + 1] = mf.getEnd();
5254 int fto[] = new int[m.getMapListToCount() * 2];
5255 f = m.enumerateMapListTo();
5256 for (int _i = 0; f.hasMoreElements(); _i += 2)
5258 MapListTo mf = (MapListTo) f.nextElement();
5259 fto[_i] = mf.getStart();
5260 fto[_i + 1] = mf.getEnd();
5262 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto,
5263 fr, fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
5264 if (m.getMappingChoice() != null)
5266 MappingChoice mc = m.getMappingChoice();
5267 if (mc.getDseqFor() != null)
5269 String dsfor = "" + mc.getDseqFor();
5270 if (seqRefIds.containsKey(dsfor))
5275 jmap.setTo(seqRefIds.get(dsfor));
5279 frefedSequence.add(newMappingRef(dsfor, jmap));
5285 * local sequence definition
5287 Sequence ms = mc.getSequence();
5288 SequenceI djs = null;
5289 String sqid = ms.getDsseqid();
5290 if (sqid != null && sqid.length() > 0)
5293 * recover dataset sequence
5295 djs = seqRefIds.get(sqid);
5300 .println("Warning - making up dataset sequence id for DbRef sequence map reference");
5301 sqid = ((Object) ms).toString(); // make up a new hascode for
5302 // undefined dataset sequence hash
5303 // (unlikely to happen)
5309 * make a new dataset sequence and add it to refIds hash
5311 djs = new jalview.datamodel.Sequence(ms.getName(),
5313 djs.setStart(jmap.getMap().getToLowest());
5314 djs.setEnd(jmap.getMap().getToHighest());
5315 djs.setVamsasId(uniqueSetSuffix + sqid);
5317 incompleteSeqs.put(sqid, djs);
5318 seqRefIds.put(sqid, djs);
5321 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5330 public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
5331 boolean keepSeqRefs)
5334 JalviewModel jm = saveState(ap, null, null, null);
5339 jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
5343 uniqueSetSuffix = "";
5344 jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
5349 if (this.frefedSequence == null)
5351 frefedSequence = new Vector();
5354 viewportsAdded.clear();
5356 AlignFrame af = loadFromObject(jm, null, false, null);
5357 af.alignPanels.clear();
5358 af.closeMenuItem_actionPerformed(true);
5361 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5362 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5363 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5364 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5365 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5368 return af.alignPanel;
5372 * flag indicating if hashtables should be cleared on finalization TODO this
5373 * flag may not be necessary
5375 private final boolean _cleartables = true;
5377 private Hashtable jvids2vobj;
5382 * @see java.lang.Object#finalize()
5385 protected void finalize() throws Throwable
5387 // really make sure we have no buried refs left.
5392 this.seqRefIds = null;
5393 this.seqsToIds = null;
5397 private void warn(String msg)
5402 private void warn(String msg, Exception e)
5404 if (Cache.log != null)
5408 Cache.log.warn(msg, e);
5412 Cache.log.warn(msg);
5417 System.err.println("Warning: " + msg);
5420 e.printStackTrace();
5425 private void debug(String string)
5427 debug(string, null);
5430 private void debug(String msg, Exception e)
5432 if (Cache.log != null)
5436 Cache.log.debug(msg, e);
5440 Cache.log.debug(msg);
5445 System.err.println("Warning: " + msg);
5448 e.printStackTrace();
5454 * set the object to ID mapping tables used to write/recover objects and XML
5455 * ID strings for the jalview project. If external tables are provided then
5456 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
5457 * object goes out of scope. - also populates the datasetIds hashtable with
5458 * alignment objects containing dataset sequences
5461 * Map from ID strings to jalview datamodel
5463 * Map from jalview datamodel to ID strings
5467 public void setObjectMappingTables(Hashtable vobj2jv,
5468 IdentityHashMap jv2vobj)
5470 this.jv2vobj = jv2vobj;
5471 this.vobj2jv = vobj2jv;
5472 Iterator ds = jv2vobj.keySet().iterator();
5474 while (ds.hasNext())
5476 Object jvobj = ds.next();
5477 id = jv2vobj.get(jvobj).toString();
5478 if (jvobj instanceof jalview.datamodel.Alignment)
5480 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
5482 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
5485 else if (jvobj instanceof jalview.datamodel.Sequence)
5487 // register sequence object so the XML parser can recover it.
5488 if (seqRefIds == null)
5490 seqRefIds = new HashMap<>();
5492 if (seqsToIds == null)
5494 seqsToIds = new IdentityHashMap<>();
5496 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
5497 seqsToIds.put((SequenceI) jvobj, id);
5499 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
5502 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
5503 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
5504 if (jvann.annotationId == null)
5506 jvann.annotationId = anid;
5508 if (!jvann.annotationId.equals(anid))
5510 // TODO verify that this is the correct behaviour
5511 this.warn("Overriding Annotation ID for " + anid
5512 + " from different id : " + jvann.annotationId);
5513 jvann.annotationId = anid;
5516 else if (jvobj instanceof String)
5518 if (jvids2vobj == null)
5520 jvids2vobj = new Hashtable();
5521 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
5526 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
5532 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
5533 * objects created from the project archive. If string is null (default for
5534 * construction) then suffix will be set automatically.
5538 public void setUniqueSetSuffix(String string)
5540 uniqueSetSuffix = string;
5545 * uses skipList2 as the skipList for skipping views on sequence sets
5546 * associated with keys in the skipList
5550 public void setSkipList(Hashtable skipList2)
5552 skipList = skipList2;
5556 * Reads the jar entry of given name and returns its contents, or null if the
5557 * entry is not found.
5560 * @param jarEntryName
5563 protected String readJarEntry(jarInputStreamProvider jprovider,
5564 String jarEntryName)
5566 String result = null;
5567 BufferedReader in = null;
5572 * Reopen the jar input stream and traverse its entries to find a matching
5575 JarInputStream jin = jprovider.getJarInputStream();
5576 JarEntry entry = null;
5579 entry = jin.getNextJarEntry();
5580 } while (entry != null && !entry.getName().equals(jarEntryName));
5584 StringBuilder out = new StringBuilder(256);
5585 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
5588 while ((data = in.readLine()) != null)
5592 result = out.toString();
5596 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
5598 } catch (Exception ex)
5600 ex.printStackTrace();
5608 } catch (IOException e)
5619 * Returns an incrementing counter (0, 1, 2...)
5623 private synchronized int nextCounter()