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.PDBEntry;
33 import jalview.datamodel.RnaViewerModel;
34 import jalview.datamodel.SequenceGroup;
35 import jalview.datamodel.SequenceI;
36 import jalview.datamodel.StructureViewerModel;
37 import jalview.datamodel.StructureViewerModel.StructureData;
38 import jalview.ext.varna.RnaModel;
39 import jalview.gui.StructureViewer.ViewerType;
40 import jalview.io.DataSourceType;
41 import jalview.io.FileFormat;
42 import jalview.schemabinding.version2.AlcodMap;
43 import jalview.schemabinding.version2.AlcodonFrame;
44 import jalview.schemabinding.version2.Annotation;
45 import jalview.schemabinding.version2.AnnotationColours;
46 import jalview.schemabinding.version2.AnnotationElement;
47 import jalview.schemabinding.version2.CalcIdParam;
48 import jalview.schemabinding.version2.DBRef;
49 import jalview.schemabinding.version2.Features;
50 import jalview.schemabinding.version2.Group;
51 import jalview.schemabinding.version2.HiddenColumns;
52 import jalview.schemabinding.version2.JGroup;
53 import jalview.schemabinding.version2.JSeq;
54 import jalview.schemabinding.version2.JalviewModel;
55 import jalview.schemabinding.version2.JalviewModelSequence;
56 import jalview.schemabinding.version2.MapListFrom;
57 import jalview.schemabinding.version2.MapListTo;
58 import jalview.schemabinding.version2.Mapping;
59 import jalview.schemabinding.version2.MappingChoice;
60 import jalview.schemabinding.version2.OtherData;
61 import jalview.schemabinding.version2.PdbentryItem;
62 import jalview.schemabinding.version2.Pdbids;
63 import jalview.schemabinding.version2.Property;
64 import jalview.schemabinding.version2.RnaViewer;
65 import jalview.schemabinding.version2.SecondaryStructure;
66 import jalview.schemabinding.version2.Sequence;
67 import jalview.schemabinding.version2.SequenceSet;
68 import jalview.schemabinding.version2.SequenceSetProperties;
69 import jalview.schemabinding.version2.Setting;
70 import jalview.schemabinding.version2.StructureState;
71 import jalview.schemabinding.version2.ThresholdLine;
72 import jalview.schemabinding.version2.Tree;
73 import jalview.schemabinding.version2.UserColours;
74 import jalview.schemabinding.version2.Viewport;
75 import jalview.schemes.AnnotationColourGradient;
76 import jalview.schemes.ColourSchemeI;
77 import jalview.schemes.ColourSchemeProperty;
78 import jalview.schemes.FeatureColour;
79 import jalview.schemes.ResidueColourScheme;
80 import jalview.schemes.ResidueProperties;
81 import jalview.schemes.UserColourScheme;
82 import jalview.structure.StructureSelectionManager;
83 import jalview.structures.models.AAStructureBindingModel;
84 import jalview.util.MessageManager;
85 import jalview.util.Platform;
86 import jalview.util.StringUtils;
87 import jalview.util.jarInputStreamProvider;
88 import jalview.viewmodel.AlignmentViewport;
89 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
90 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
91 import jalview.ws.jws2.Jws2Discoverer;
92 import jalview.ws.jws2.dm.AAConSettings;
93 import jalview.ws.jws2.jabaws2.Jws2Instance;
94 import jalview.ws.params.ArgumentI;
95 import jalview.ws.params.AutoCalcSetting;
96 import jalview.ws.params.WsParamSetI;
98 import java.awt.Color;
99 import java.awt.Rectangle;
100 import java.io.BufferedReader;
101 import java.io.DataInputStream;
102 import java.io.DataOutputStream;
104 import java.io.FileInputStream;
105 import java.io.FileOutputStream;
106 import java.io.IOException;
107 import java.io.InputStreamReader;
108 import java.io.OutputStreamWriter;
109 import java.io.PrintWriter;
110 import java.lang.reflect.InvocationTargetException;
111 import java.net.MalformedURLException;
113 import java.util.ArrayList;
114 import java.util.Arrays;
115 import java.util.Enumeration;
116 import java.util.HashMap;
117 import java.util.HashSet;
118 import java.util.Hashtable;
119 import java.util.IdentityHashMap;
120 import java.util.Iterator;
121 import java.util.LinkedHashMap;
122 import java.util.List;
123 import java.util.Map;
124 import java.util.Map.Entry;
125 import java.util.Set;
126 import java.util.Vector;
127 import java.util.jar.JarEntry;
128 import java.util.jar.JarInputStream;
129 import java.util.jar.JarOutputStream;
131 import javax.swing.JInternalFrame;
132 import javax.swing.JOptionPane;
133 import javax.swing.SwingUtilities;
135 import org.exolab.castor.xml.Marshaller;
136 import org.exolab.castor.xml.Unmarshaller;
139 * Write out the current jalview desktop state as a Jalview XML stream.
141 * Note: the vamsas objects referred to here are primitive versions of the
142 * VAMSAS project schema elements - they are not the same and most likely never
146 * @version $Revision: 1.134 $
148 public class Jalview2XML
150 private static final String VIEWER_PREFIX = "viewer_";
152 private static final String RNA_PREFIX = "rna_";
154 private static final String UTF_8 = "UTF-8";
156 // use this with nextCounter() to make unique names for entities
157 private int counter = 0;
160 * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
161 * of sequence objects are created.
163 IdentityHashMap<SequenceI, String> seqsToIds = null;
166 * jalview XML Sequence ID to jalview sequence object reference (both dataset
167 * and alignment sequences. Populated as XML reps of sequence objects are
170 Map<String, SequenceI> seqRefIds = null;
172 Map<String, SequenceI> incompleteSeqs = null;
174 List<SeqFref> frefedSequence = null;
176 boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
179 * Map of reconstructed AlignFrame objects that appear to have come from
180 * SplitFrame objects (have a dna/protein complement view).
182 private Map<Viewport, AlignFrame> splitFrameCandidates = new HashMap<Viewport, AlignFrame>();
185 * Map from displayed rna structure models to their saved session state jar
188 private Map<RnaModel, String> rnaSessions = new HashMap<RnaModel, String>();
191 * create/return unique hash string for sq
194 * @return new or existing unique string for sq
196 String seqHash(SequenceI sq)
198 if (seqsToIds == null)
202 if (seqsToIds.containsKey(sq))
204 return seqsToIds.get(sq);
208 // create sequential key
209 String key = "sq" + (seqsToIds.size() + 1);
210 key = makeHashCode(sq, key); // check we don't have an external reference
212 seqsToIds.put(sq, key);
221 if (seqRefIds != null)
225 if (seqsToIds != null)
229 if (incompleteSeqs != null)
231 incompleteSeqs.clear();
239 warn("clearSeqRefs called when _cleartables was not set. Doing nothing.");
240 // seqRefIds = new Hashtable();
241 // seqsToIds = new IdentityHashMap();
247 if (seqsToIds == null)
249 seqsToIds = new IdentityHashMap<SequenceI, String>();
251 if (seqRefIds == null)
253 seqRefIds = new HashMap<String, SequenceI>();
255 if (incompleteSeqs == null)
257 incompleteSeqs = new HashMap<String, SequenceI>();
259 if (frefedSequence == null)
261 frefedSequence = new ArrayList<SeqFref>();
269 public Jalview2XML(boolean raiseGUI)
271 this.raiseGUI = raiseGUI;
275 * base class for resolving forward references to sequences by their ID
280 abstract class SeqFref
286 public SeqFref(String _sref, String type)
292 public String getSref()
297 public SequenceI getSrefSeq()
299 return seqRefIds.get(sref);
302 public boolean isResolvable()
304 return seqRefIds.get(sref) != null;
307 public SequenceI getSrefDatasetSeq()
309 SequenceI sq = seqRefIds.get(sref);
312 while (sq.getDatasetSequence() != null)
314 sq = sq.getDatasetSequence();
321 * @return true if the forward reference was fully resolved
323 abstract boolean resolve();
326 public String toString()
328 return type + " reference to " + sref;
333 * create forward reference for a mapping
339 public SeqFref newMappingRef(final String sref,
340 final jalview.datamodel.Mapping _jmap)
342 SeqFref fref = new SeqFref(sref, "Mapping")
344 public jalview.datamodel.Mapping jmap = _jmap;
349 SequenceI seq = getSrefDatasetSeq();
361 public SeqFref newAlcodMapRef(final String sref,
362 final AlignedCodonFrame _cf, final jalview.datamodel.Mapping _jmap)
365 SeqFref fref = new SeqFref(sref, "Codon Frame")
367 AlignedCodonFrame cf = _cf;
369 public jalview.datamodel.Mapping mp = _jmap;
372 public boolean isResolvable()
374 return super.isResolvable() && mp.getTo() != null;
380 SequenceI seq = getSrefDatasetSeq();
385 cf.addMap(seq, mp.getTo(), mp.getMap());
392 public void resolveFrefedSequences()
394 Iterator<SeqFref> nextFref = frefedSequence.iterator();
395 int toresolve = frefedSequence.size();
396 int unresolved = 0, failedtoresolve = 0;
397 while (nextFref.hasNext())
399 SeqFref ref = nextFref.next();
400 if (ref.isResolvable())
412 } catch (Exception x)
415 .println("IMPLEMENTATION ERROR: Failed to resolve forward reference for sequence "
428 System.err.println("Jalview Project Import: There were " + unresolved
429 + " forward references left unresolved on the stack.");
431 if (failedtoresolve > 0)
433 System.err.println("SERIOUS! " + failedtoresolve
434 + " resolvable forward references failed to resolve.");
436 if (incompleteSeqs != null && incompleteSeqs.size() > 0)
438 System.err.println("Jalview Project Import: There are "
439 + incompleteSeqs.size()
440 + " sequences which may have incomplete metadata.");
441 if (incompleteSeqs.size() < 10)
443 for (SequenceI s : incompleteSeqs.values())
445 System.err.println(s.toString());
451 .println("Too many to report. Skipping output of incomplete sequences.");
457 * This maintains a map of viewports, the key being the seqSetId. Important to
458 * set historyItem and redoList for multiple views
460 Map<String, AlignViewport> viewportsAdded = new HashMap<String, AlignViewport>();
462 Map<String, AlignmentAnnotation> annotationIds = new HashMap<String, AlignmentAnnotation>();
464 String uniqueSetSuffix = "";
467 * List of pdbfiles added to Jar
469 List<String> pdbfiles = null;
471 // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
472 public void saveState(File statefile)
474 FileOutputStream fos = null;
477 fos = new FileOutputStream(statefile);
478 JarOutputStream jout = new JarOutputStream(fos);
481 } catch (Exception e)
483 // TODO: inform user of the problem - they need to know if their data was
485 if (errorMessage == null)
487 errorMessage = "Couldn't write Jalview Archive to output file '"
488 + statefile + "' - See console error log for details";
492 errorMessage += "(output file was '" + statefile + "')";
502 } catch (IOException e)
512 * Writes a jalview project archive to the given Jar output stream.
516 public void saveState(JarOutputStream jout)
518 AlignFrame[] frames = Desktop.getAlignFrames();
524 saveAllFrames(Arrays.asList(frames), jout);
528 * core method for storing state for a set of AlignFrames.
531 * - frames involving all data to be exported (including containing
534 * - project output stream
536 private void saveAllFrames(List<AlignFrame> frames, JarOutputStream jout)
538 Hashtable<String, AlignFrame> dsses = new Hashtable<String, AlignFrame>();
541 * ensure cached data is clear before starting
543 // todo tidy up seqRefIds, seqsToIds initialisation / reset
545 splitFrameCandidates.clear();
550 // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
551 // //////////////////////////////////////////////////
553 List<String> shortNames = new ArrayList<String>();
554 List<String> viewIds = new ArrayList<String>();
557 for (int i = frames.size() - 1; i > -1; i--)
559 AlignFrame af = frames.get(i);
563 .containsKey(af.getViewport().getSequenceSetId()))
568 String shortName = makeFilename(af, shortNames);
570 int ap, apSize = af.alignPanels.size();
572 for (ap = 0; ap < apSize; ap++)
574 AlignmentPanel apanel = af.alignPanels.get(ap);
575 String fileName = apSize == 1 ? shortName : ap + shortName;
576 if (!fileName.endsWith(".xml"))
578 fileName = fileName + ".xml";
581 saveState(apanel, fileName, jout, viewIds);
583 String dssid = getDatasetIdRef(af.getViewport().getAlignment()
585 if (!dsses.containsKey(dssid))
587 dsses.put(dssid, af);
592 writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix,
598 } catch (Exception foo)
603 } catch (Exception ex)
605 // TODO: inform user of the problem - they need to know if their data was
607 if (errorMessage == null)
609 errorMessage = "Couldn't write Jalview Archive - see error output for details";
611 ex.printStackTrace();
616 * Generates a distinct file name, based on the title of the AlignFrame, by
617 * appending _n for increasing n until an unused name is generated. The new
618 * name (without its extension) is added to the list.
622 * @return the generated name, with .xml extension
624 protected String makeFilename(AlignFrame af, List<String> namesUsed)
626 String shortName = af.getTitle();
628 if (shortName.indexOf(File.separatorChar) > -1)
630 shortName = shortName.substring(shortName
631 .lastIndexOf(File.separatorChar) + 1);
636 while (namesUsed.contains(shortName))
638 if (shortName.endsWith("_" + (count - 1)))
640 shortName = shortName.substring(0, shortName.lastIndexOf("_"));
643 shortName = shortName.concat("_" + count);
647 namesUsed.add(shortName);
649 if (!shortName.endsWith(".xml"))
651 shortName = shortName + ".xml";
656 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
657 public boolean saveAlignment(AlignFrame af, String jarFile,
662 FileOutputStream fos = new FileOutputStream(jarFile);
663 JarOutputStream jout = new JarOutputStream(fos);
664 List<AlignFrame> frames = new ArrayList<AlignFrame>();
666 // resolve splitframes
667 if (af.getViewport().getCodingComplement() != null)
669 frames = ((SplitFrame) af.getSplitViewContainer()).getAlignFrames();
675 saveAllFrames(frames, jout);
679 } catch (Exception foo)
685 } catch (Exception ex)
687 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
688 ex.printStackTrace();
693 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
694 String fileName, JarOutputStream jout)
697 for (String dssids : dsses.keySet())
699 AlignFrame _af = dsses.get(dssids);
700 String jfileName = fileName + " Dataset for " + _af.getTitle();
701 if (!jfileName.endsWith(".xml"))
703 jfileName = jfileName + ".xml";
705 saveState(_af.alignPanel, jfileName, true, jout, null);
710 * create a JalviewModel from an alignment view and marshall it to a
714 * panel to create jalview model for
716 * name of alignment panel written to output stream
723 public JalviewModel saveState(AlignmentPanel ap, String fileName,
724 JarOutputStream jout, List<String> viewIds)
726 return saveState(ap, fileName, false, jout, viewIds);
730 * create a JalviewModel from an alignment view and marshall it to a
734 * panel to create jalview model for
736 * name of alignment panel written to output stream
738 * when true, only write the dataset for the alignment, not the data
739 * associated with the view.
745 public JalviewModel saveState(AlignmentPanel ap, String fileName,
746 boolean storeDS, JarOutputStream jout, List<String> viewIds)
750 viewIds = new ArrayList<String>();
755 List<UserColourScheme> userColours = new ArrayList<UserColourScheme>();
757 AlignViewport av = ap.av;
759 JalviewModel object = new JalviewModel();
760 object.setVamsasModel(new jalview.schemabinding.version2.VamsasModel());
762 object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
763 object.setVersion(jalview.bin.Cache.getDefault("VERSION",
764 "Development Build"));
767 * rjal is full height alignment, jal is actual alignment with full metadata
768 * but excludes hidden sequences.
770 jalview.datamodel.AlignmentI rjal = av.getAlignment(), jal = rjal;
772 if (av.hasHiddenRows())
774 rjal = jal.getHiddenSequences().getFullAlignment();
777 SequenceSet vamsasSet = new SequenceSet();
779 JalviewModelSequence jms = new JalviewModelSequence();
781 vamsasSet.setGapChar(jal.getGapCharacter() + "");
783 if (jal.getDataset() != null)
785 // dataset id is the dataset's hashcode
786 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
789 // switch jal and the dataset
790 jal = jal.getDataset();
794 if (jal.getProperties() != null)
796 Enumeration en = jal.getProperties().keys();
797 while (en.hasMoreElements())
799 String key = en.nextElement().toString();
800 SequenceSetProperties ssp = new SequenceSetProperties();
802 ssp.setValue(jal.getProperties().get(key).toString());
803 vamsasSet.addSequenceSetProperties(ssp);
808 Set<String> calcIdSet = new HashSet<String>();
809 // record the set of vamsas sequence XML POJO we create.
810 HashMap<String, Sequence> vamsasSetIds = new HashMap<String, Sequence>();
812 for (final SequenceI jds : rjal.getSequences())
814 final SequenceI jdatasq = jds.getDatasetSequence() == null ? jds
815 : jds.getDatasetSequence();
816 String id = seqHash(jds);
817 if (vamsasSetIds.get(id) == null)
819 if (seqRefIds.get(id) != null && !storeDS)
821 // This happens for two reasons: 1. multiple views are being
823 // 2. the hashCode has collided with another sequence's code. This
825 // HAPPEN! (PF00072.15.stk does this)
826 // JBPNote: Uncomment to debug writing out of files that do not read
827 // back in due to ArrayOutOfBoundExceptions.
828 // System.err.println("vamsasSeq backref: "+id+"");
829 // System.err.println(jds.getName()+"
830 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
831 // System.err.println("Hashcode: "+seqHash(jds));
832 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
833 // System.err.println(rsq.getName()+"
834 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
835 // System.err.println("Hashcode: "+seqHash(rsq));
839 vamsasSeq = createVamsasSequence(id, jds);
840 vamsasSet.addSequence(vamsasSeq);
841 vamsasSetIds.put(id, vamsasSeq);
842 seqRefIds.put(id, jds);
846 jseq.setStart(jds.getStart());
847 jseq.setEnd(jds.getEnd());
848 jseq.setColour(av.getSequenceColour(jds).getRGB());
850 jseq.setId(id); // jseq id should be a string not a number
853 // Store any sequences this sequence represents
854 if (av.hasHiddenRows())
856 // use rjal, contains the full height alignment
857 jseq.setHidden(av.getAlignment().getHiddenSequences()
860 if (av.isHiddenRepSequence(jds))
862 jalview.datamodel.SequenceI[] reps = av
863 .getRepresentedSequences(jds).getSequencesInOrder(rjal);
865 for (int h = 0; h < reps.length; h++)
869 jseq.addHiddenSequences(rjal.findIndex(reps[h]));
874 // mark sequence as reference - if it is the reference for this view
877 jseq.setViewreference(jds == jal.getSeqrep());
881 // TODO: omit sequence features from each alignment view's XML dump if we
882 // are storing dataset
883 if (jds.getSequenceFeatures() != null)
885 jalview.datamodel.SequenceFeature[] sf = jds.getSequenceFeatures();
887 while (index < sf.length)
889 Features features = new Features();
891 features.setBegin(sf[index].getBegin());
892 features.setEnd(sf[index].getEnd());
893 features.setDescription(sf[index].getDescription());
894 features.setType(sf[index].getType());
895 features.setFeatureGroup(sf[index].getFeatureGroup());
896 features.setScore(sf[index].getScore());
897 if (sf[index].links != null)
899 for (int l = 0; l < sf[index].links.size(); l++)
901 OtherData keyValue = new OtherData();
902 keyValue.setKey("LINK_" + l);
903 keyValue.setValue(sf[index].links.elementAt(l).toString());
904 features.addOtherData(keyValue);
907 if (sf[index].otherDetails != null)
910 Iterator<String> keys = sf[index].otherDetails.keySet()
912 while (keys.hasNext())
915 OtherData keyValue = new OtherData();
916 keyValue.setKey(key);
917 keyValue.setValue(sf[index].otherDetails.get(key).toString());
918 features.addOtherData(keyValue);
922 jseq.addFeatures(features);
927 if (jdatasq.getAllPDBEntries() != null)
929 Enumeration en = jdatasq.getAllPDBEntries().elements();
930 while (en.hasMoreElements())
932 Pdbids pdb = new Pdbids();
933 jalview.datamodel.PDBEntry entry = (jalview.datamodel.PDBEntry) en
936 String pdbId = entry.getId();
938 pdb.setType(entry.getType());
941 * Store any structure views associated with this sequence. This
942 * section copes with duplicate entries in the project, so a dataset
943 * only view *should* be coped with sensibly.
945 // This must have been loaded, is it still visible?
946 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
947 String matchedFile = null;
948 for (int f = frames.length - 1; f > -1; f--)
950 if (frames[f] instanceof StructureViewerBase)
952 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
953 matchedFile = saveStructureState(ap, jds, pdb, entry,
954 viewIds, matchedFile, viewFrame);
956 * Only store each structure viewer's state once in the project
957 * jar. First time through only (storeDS==false)
959 String viewId = viewFrame.getViewId();
960 if (!storeDS && !viewIds.contains(viewId))
965 String viewerState = viewFrame.getStateInfo();
966 writeJarEntry(jout, getViewerJarEntryName(viewId),
967 viewerState.getBytes());
968 } catch (IOException e)
970 System.err.println("Error saving viewer state: "
977 if (matchedFile != null || entry.getFile() != null)
979 if (entry.getFile() != null)
982 matchedFile = entry.getFile();
984 pdb.setFile(matchedFile); // entry.getFile());
985 if (pdbfiles == null)
987 pdbfiles = new ArrayList<String>();
990 if (!pdbfiles.contains(pdbId))
993 copyFileToJar(jout, matchedFile, pdbId);
997 Enumeration<String> props = entry.getProperties();
998 if (props.hasMoreElements())
1000 PdbentryItem item = new PdbentryItem();
1001 while (props.hasMoreElements())
1003 Property prop = new Property();
1004 String key = props.nextElement();
1006 prop.setValue(entry.getProperty(key).toString());
1007 item.addProperty(prop);
1009 pdb.addPdbentryItem(item);
1012 jseq.addPdbids(pdb);
1016 saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
1021 if (!storeDS && av.hasHiddenRows())
1023 jal = av.getAlignment();
1027 if (storeDS && jal.getCodonFrames() != null)
1029 List<AlignedCodonFrame> jac = jal.getCodonFrames();
1030 for (AlignedCodonFrame acf : jac)
1032 AlcodonFrame alc = new AlcodonFrame();
1033 if (acf.getProtMappings() != null
1034 && acf.getProtMappings().length > 0)
1036 boolean hasMap = false;
1037 SequenceI[] dnas = acf.getdnaSeqs();
1038 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1039 for (int m = 0; m < pmaps.length; m++)
1041 AlcodMap alcmap = new AlcodMap();
1042 alcmap.setDnasq(seqHash(dnas[m]));
1043 alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
1045 alc.addAlcodMap(alcmap);
1050 vamsasSet.addAlcodonFrame(alc);
1053 // TODO: delete this ? dead code from 2.8.3->2.9 ?
1055 // AlcodonFrame alc = new AlcodonFrame();
1056 // vamsasSet.addAlcodonFrame(alc);
1057 // for (int p = 0; p < acf.aaWidth; p++)
1059 // Alcodon cmap = new Alcodon();
1060 // if (acf.codons[p] != null)
1062 // // Null codons indicate a gapped column in the translated peptide
1064 // cmap.setPos1(acf.codons[p][0]);
1065 // cmap.setPos2(acf.codons[p][1]);
1066 // cmap.setPos3(acf.codons[p][2]);
1068 // alc.addAlcodon(cmap);
1070 // if (acf.getProtMappings() != null
1071 // && acf.getProtMappings().length > 0)
1073 // SequenceI[] dnas = acf.getdnaSeqs();
1074 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1075 // for (int m = 0; m < pmaps.length; m++)
1077 // AlcodMap alcmap = new AlcodMap();
1078 // alcmap.setDnasq(seqHash(dnas[m]));
1079 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
1081 // alc.addAlcodMap(alcmap);
1088 // /////////////////////////////////
1089 if (!storeDS && av.currentTree != null)
1091 // FIND ANY ASSOCIATED TREES
1092 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
1093 if (Desktop.desktop != null)
1095 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1097 for (int t = 0; t < frames.length; t++)
1099 if (frames[t] instanceof TreePanel)
1101 TreePanel tp = (TreePanel) frames[t];
1103 if (tp.treeCanvas.av.getAlignment() == jal)
1105 Tree tree = new Tree();
1106 tree.setTitle(tp.getTitle());
1107 tree.setCurrentTree((av.currentTree == tp.getTree()));
1108 tree.setNewick(tp.getTree().toString());
1109 tree.setThreshold(tp.treeCanvas.threshold);
1111 tree.setFitToWindow(tp.fitToWindow.getState());
1112 tree.setFontName(tp.getTreeFont().getName());
1113 tree.setFontSize(tp.getTreeFont().getSize());
1114 tree.setFontStyle(tp.getTreeFont().getStyle());
1115 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
1117 tree.setShowBootstrap(tp.bootstrapMenu.getState());
1118 tree.setShowDistances(tp.distanceMenu.getState());
1120 tree.setHeight(tp.getHeight());
1121 tree.setWidth(tp.getWidth());
1122 tree.setXpos(tp.getX());
1123 tree.setYpos(tp.getY());
1124 tree.setId(makeHashCode(tp, null));
1134 * store forward refs from an annotationRow to any groups
1136 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<SequenceGroup, String>();
1139 for (SequenceI sq : jal.getSequences())
1141 // Store annotation on dataset sequences only
1142 AlignmentAnnotation[] aa = sq.getAnnotation();
1143 if (aa != null && aa.length > 0)
1145 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1152 if (jal.getAlignmentAnnotation() != null)
1154 // Store the annotation shown on the alignment.
1155 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1156 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1161 if (jal.getGroups() != null)
1163 JGroup[] groups = new JGroup[jal.getGroups().size()];
1165 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1167 JGroup jGroup = new JGroup();
1168 groups[++i] = jGroup;
1170 jGroup.setStart(sg.getStartRes());
1171 jGroup.setEnd(sg.getEndRes());
1172 jGroup.setName(sg.getName());
1173 if (groupRefs.containsKey(sg))
1175 // group has references so set its ID field
1176 jGroup.setId(groupRefs.get(sg));
1180 if (sg.cs.conservationApplied())
1182 jGroup.setConsThreshold(sg.cs.getConservationInc());
1184 if (sg.cs instanceof jalview.schemes.UserColourScheme)
1186 jGroup.setColour(setUserColourScheme(sg.cs, userColours, jms));
1190 jGroup.setColour(ColourSchemeProperty.getColourName(sg.cs));
1193 else if (sg.cs instanceof jalview.schemes.AnnotationColourGradient)
1195 jGroup.setColour("AnnotationColourGradient");
1196 jGroup.setAnnotationColours(constructAnnotationColours(
1197 (jalview.schemes.AnnotationColourGradient) sg.cs,
1200 else if (sg.cs instanceof jalview.schemes.UserColourScheme)
1202 jGroup.setColour(setUserColourScheme(sg.cs, userColours, jms));
1206 jGroup.setColour(ColourSchemeProperty.getColourName(sg.cs));
1209 jGroup.setPidThreshold(sg.cs.getThreshold());
1212 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1213 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1214 jGroup.setDisplayText(sg.getDisplayText());
1215 jGroup.setColourText(sg.getColourText());
1216 jGroup.setTextCol1(sg.textColour.getRGB());
1217 jGroup.setTextCol2(sg.textColour2.getRGB());
1218 jGroup.setTextColThreshold(sg.thresholdTextColour);
1219 jGroup.setShowUnconserved(sg.getShowNonconserved());
1220 jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1221 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1222 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1223 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1224 for (SequenceI seq : sg.getSequences())
1226 jGroup.addSeq(seqHash(seq));
1230 jms.setJGroup(groups);
1234 // /////////SAVE VIEWPORT
1235 Viewport view = new Viewport();
1236 view.setTitle(ap.alignFrame.getTitle());
1237 view.setSequenceSetId(makeHashCode(av.getSequenceSetId(),
1238 av.getSequenceSetId()));
1239 view.setId(av.getViewId());
1240 if (av.getCodingComplement() != null)
1242 view.setComplementId(av.getCodingComplement().getViewId());
1244 view.setViewName(av.viewName);
1245 view.setGatheredViews(av.isGatherViewsHere());
1247 Rectangle size = ap.av.getExplodedGeometry();
1248 Rectangle position = size;
1251 size = ap.alignFrame.getBounds();
1252 if (av.getCodingComplement() != null)
1254 position = ((SplitFrame) ap.alignFrame.getSplitViewContainer())
1262 view.setXpos(position.x);
1263 view.setYpos(position.y);
1265 view.setWidth(size.width);
1266 view.setHeight(size.height);
1268 view.setStartRes(av.startRes);
1269 view.setStartSeq(av.startSeq);
1271 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1273 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1276 else if (av.getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1278 AnnotationColours ac = constructAnnotationColours(
1279 (jalview.schemes.AnnotationColourGradient) av
1280 .getGlobalColourScheme(),
1283 view.setAnnotationColours(ac);
1284 view.setBgColour("AnnotationColourGradient");
1288 view.setBgColour(ColourSchemeProperty.getColourName(av
1289 .getGlobalColourScheme()));
1292 ColourSchemeI cs = av.getGlobalColourScheme();
1296 if (cs.conservationApplied())
1298 view.setConsThreshold(cs.getConservationInc());
1299 if (cs instanceof jalview.schemes.UserColourScheme)
1301 view.setBgColour(setUserColourScheme(cs, userColours, jms));
1305 if (cs instanceof ResidueColourScheme)
1307 view.setPidThreshold(cs.getThreshold());
1311 view.setConservationSelected(av.getConservationSelected());
1312 view.setPidSelected(av.getAbovePIDThreshold());
1313 view.setFontName(av.font.getName());
1314 view.setFontSize(av.font.getSize());
1315 view.setFontStyle(av.font.getStyle());
1316 view.setScaleProteinAsCdna(av.getViewStyle().isScaleProteinAsCdna());
1317 view.setRenderGaps(av.isRenderGaps());
1318 view.setShowAnnotation(av.isShowAnnotation());
1319 view.setShowBoxes(av.getShowBoxes());
1320 view.setShowColourText(av.getColourText());
1321 view.setShowFullId(av.getShowJVSuffix());
1322 view.setRightAlignIds(av.isRightAlignIds());
1323 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1324 view.setShowText(av.getShowText());
1325 view.setShowUnconserved(av.getShowUnconserved());
1326 view.setWrapAlignment(av.getWrapAlignment());
1327 view.setTextCol1(av.getTextColour().getRGB());
1328 view.setTextCol2(av.getTextColour2().getRGB());
1329 view.setTextColThreshold(av.getThresholdTextColour());
1330 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1331 view.setShowSequenceLogo(av.isShowSequenceLogo());
1332 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1333 view.setShowGroupConsensus(av.isShowGroupConsensus());
1334 view.setShowGroupConservation(av.isShowGroupConservation());
1335 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1336 view.setShowDbRefTooltip(av.isShowDBRefs());
1337 view.setFollowHighlight(av.isFollowHighlight());
1338 view.setFollowSelection(av.followSelection);
1339 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1340 if (av.getFeaturesDisplayed() != null)
1342 jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
1344 String[] renderOrder = ap.getSeqPanel().seqCanvas
1345 .getFeatureRenderer().getRenderOrder()
1346 .toArray(new String[0]);
1348 Vector<String> settingsAdded = new Vector<String>();
1349 if (renderOrder != null)
1351 for (String featureType : renderOrder)
1353 FeatureColourI fcol = ap.getSeqPanel().seqCanvas
1354 .getFeatureRenderer().getFeatureStyle(featureType);
1355 Setting setting = new Setting();
1356 setting.setType(featureType);
1357 if (!fcol.isSimpleColour())
1359 setting.setColour(fcol.getMaxColour().getRGB());
1360 setting.setMincolour(fcol.getMinColour().getRGB());
1361 setting.setMin(fcol.getMin());
1362 setting.setMax(fcol.getMax());
1363 setting.setColourByLabel(fcol.isColourByLabel());
1364 setting.setAutoScale(fcol.isAutoScaled());
1365 setting.setThreshold(fcol.getThreshold());
1366 // -1 = No threshold, 0 = Below, 1 = Above
1367 setting.setThreshstate(fcol.isAboveThreshold() ? 1 : (fcol
1368 .isBelowThreshold() ? 0 : -1));
1372 setting.setColour(fcol.getColour().getRGB());
1375 setting.setDisplay(av.getFeaturesDisplayed().isVisible(
1377 float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1378 .getOrder(featureType);
1381 setting.setOrder(rorder);
1383 fs.addSetting(setting);
1384 settingsAdded.addElement(featureType);
1388 // is groups actually supposed to be a map here ?
1389 Iterator<String> en = ap.getSeqPanel().seqCanvas
1390 .getFeatureRenderer().getFeatureGroups().iterator();
1391 Vector<String> groupsAdded = new Vector<String>();
1392 while (en.hasNext())
1394 String grp = en.next();
1395 if (groupsAdded.contains(grp))
1399 Group g = new Group();
1401 g.setDisplay(((Boolean) ap.getSeqPanel().seqCanvas
1402 .getFeatureRenderer().checkGroupVisibility(grp, false))
1405 groupsAdded.addElement(grp);
1407 jms.setFeatureSettings(fs);
1410 if (av.hasHiddenColumns())
1412 if (av.getColumnSelection() == null
1413 || av.getColumnSelection().getHiddenColumns() == null)
1415 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1419 for (int c = 0; c < av.getColumnSelection().getHiddenColumns()
1422 int[] region = av.getColumnSelection().getHiddenColumns()
1424 HiddenColumns hc = new HiddenColumns();
1425 hc.setStart(region[0]);
1426 hc.setEnd(region[1]);
1427 view.addHiddenColumns(hc);
1431 if (calcIdSet.size() > 0)
1433 for (String calcId : calcIdSet)
1435 if (calcId.trim().length() > 0)
1437 CalcIdParam cidp = createCalcIdParam(calcId, av);
1438 // Some calcIds have no parameters.
1441 view.addCalcIdParam(cidp);
1447 jms.addViewport(view);
1449 object.setJalviewModelSequence(jms);
1450 object.getVamsasModel().addSequenceSet(vamsasSet);
1452 if (jout != null && fileName != null)
1454 // We may not want to write the object to disk,
1455 // eg we can copy the alignViewport to a new view object
1456 // using save and then load
1459 System.out.println("Writing jar entry " + fileName);
1460 JarEntry entry = new JarEntry(fileName);
1461 jout.putNextEntry(entry);
1462 PrintWriter pout = new PrintWriter(new OutputStreamWriter(jout,
1464 Marshaller marshaller = new Marshaller(pout);
1465 marshaller.marshal(object);
1468 } catch (Exception ex)
1470 // TODO: raise error in GUI if marshalling failed.
1471 ex.printStackTrace();
1478 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1479 * for each viewer, with
1481 * <li>viewer geometry (position, size, split pane divider location)</li>
1482 * <li>index of the selected structure in the viewer (currently shows gapped
1484 * <li>the id of the annotation holding RNA secondary structure</li>
1485 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1487 * Varna viewer state is also written out (in native Varna XML) to separate
1488 * project jar entries. A separate entry is written for each RNA structure
1489 * displayed, with the naming convention
1491 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
1499 * @param storeDataset
1501 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
1502 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
1503 boolean storeDataset)
1505 if (Desktop.desktop == null)
1509 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1510 for (int f = frames.length - 1; f > -1; f--)
1512 if (frames[f] instanceof AppVarna)
1514 AppVarna varna = (AppVarna) frames[f];
1516 * link the sequence to every viewer that is showing it and is linked to
1517 * its alignment panel
1519 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1521 String viewId = varna.getViewId();
1522 RnaViewer rna = new RnaViewer();
1523 rna.setViewId(viewId);
1524 rna.setTitle(varna.getTitle());
1525 rna.setXpos(varna.getX());
1526 rna.setYpos(varna.getY());
1527 rna.setWidth(varna.getWidth());
1528 rna.setHeight(varna.getHeight());
1529 rna.setDividerLocation(varna.getDividerLocation());
1530 rna.setSelectedRna(varna.getSelectedIndex());
1531 jseq.addRnaViewer(rna);
1534 * Store each Varna panel's state once in the project per sequence.
1535 * First time through only (storeDataset==false)
1537 // boolean storeSessions = false;
1538 // String sequenceViewId = viewId + seqsToIds.get(jds);
1539 // if (!storeDataset && !viewIds.contains(sequenceViewId))
1541 // viewIds.add(sequenceViewId);
1542 // storeSessions = true;
1544 for (RnaModel model : varna.getModels())
1546 if (model.seq == jds)
1549 * VARNA saves each view (sequence or alignment secondary
1550 * structure, gapped or trimmed) as a separate XML file
1552 String jarEntryName = rnaSessions.get(model);
1553 if (jarEntryName == null)
1556 String varnaStateFile = varna.getStateInfo(model.rna);
1557 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
1558 copyFileToJar(jout, varnaStateFile, jarEntryName);
1559 rnaSessions.put(model, jarEntryName);
1561 SecondaryStructure ss = new SecondaryStructure();
1562 String annotationId = varna.getAnnotation(jds).annotationId;
1563 ss.setAnnotationId(annotationId);
1564 ss.setViewerState(jarEntryName);
1565 ss.setGapped(model.gapped);
1566 ss.setTitle(model.title);
1567 rna.addSecondaryStructure(ss);
1576 * Copy the contents of a file to a new entry added to the output jar
1580 * @param jarEntryName
1582 protected void copyFileToJar(JarOutputStream jout, String infilePath,
1583 String jarEntryName)
1585 DataInputStream dis = null;
1588 File file = new File(infilePath);
1589 if (file.exists() && jout != null)
1591 dis = new DataInputStream(new FileInputStream(file));
1592 byte[] data = new byte[(int) file.length()];
1593 dis.readFully(data);
1594 writeJarEntry(jout, jarEntryName, data);
1596 } catch (Exception ex)
1598 ex.printStackTrace();
1606 } catch (IOException e)
1615 * Write the data to a new entry of given name in the output jar file
1618 * @param jarEntryName
1620 * @throws IOException
1622 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
1623 byte[] data) throws IOException
1627 System.out.println("Writing jar entry " + jarEntryName);
1628 jout.putNextEntry(new JarEntry(jarEntryName));
1629 DataOutputStream dout = new DataOutputStream(jout);
1630 dout.write(data, 0, data.length);
1637 * Save the state of a structure viewer
1642 * the archive XML element under which to save the state
1645 * @param matchedFile
1649 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
1650 Pdbids pdb, PDBEntry entry, List<String> viewIds,
1651 String matchedFile, StructureViewerBase viewFrame)
1653 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
1656 * Look for any bindings for this viewer to the PDB file of interest
1657 * (including part matches excluding chain id)
1659 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
1661 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
1662 final String pdbId = pdbentry.getId();
1663 if (!pdbId.equals(entry.getId())
1664 && !(entry.getId().length() > 4 && entry.getId()
1665 .toLowerCase().startsWith(pdbId.toLowerCase())))
1668 * not interested in a binding to a different PDB entry here
1672 if (matchedFile == null)
1674 matchedFile = pdbentry.getFile();
1676 else if (!matchedFile.equals(pdbentry.getFile()))
1679 .warn("Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
1680 + pdbentry.getFile());
1684 // can get at it if the ID
1685 // match is ambiguous (e.g.
1688 for (int smap = 0; smap < viewFrame.getBinding().getSequence()[peid].length; smap++)
1690 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
1691 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
1693 StructureState state = new StructureState();
1694 state.setVisible(true);
1695 state.setXpos(viewFrame.getX());
1696 state.setYpos(viewFrame.getY());
1697 state.setWidth(viewFrame.getWidth());
1698 state.setHeight(viewFrame.getHeight());
1699 final String viewId = viewFrame.getViewId();
1700 state.setViewId(viewId);
1701 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
1702 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
1703 state.setColourByJmol(viewFrame.isColouredByViewer());
1704 state.setType(viewFrame.getViewerType().toString());
1705 pdb.addStructureState(state);
1712 private AnnotationColours constructAnnotationColours(
1713 AnnotationColourGradient acg, List<UserColourScheme> userColours,
1714 JalviewModelSequence jms)
1716 AnnotationColours ac = new AnnotationColours();
1717 ac.setAboveThreshold(acg.getAboveThreshold());
1718 ac.setThreshold(acg.getAnnotationThreshold());
1719 ac.setAnnotation(acg.getAnnotation());
1720 if (acg.getBaseColour() instanceof jalview.schemes.UserColourScheme)
1722 ac.setColourScheme(setUserColourScheme(acg.getBaseColour(),
1727 ac.setColourScheme(ColourSchemeProperty.getColourName(acg
1731 ac.setMaxColour(acg.getMaxColour().getRGB());
1732 ac.setMinColour(acg.getMinColour().getRGB());
1733 ac.setPerSequence(acg.isSeqAssociated());
1734 ac.setPredefinedColours(acg.isPredefinedColours());
1738 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
1739 IdentityHashMap<SequenceGroup, String> groupRefs,
1740 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
1741 SequenceSet vamsasSet)
1744 for (int i = 0; i < aa.length; i++)
1746 Annotation an = new Annotation();
1748 AlignmentAnnotation annotation = aa[i];
1749 if (annotation.annotationId != null)
1751 annotationIds.put(annotation.annotationId, annotation);
1754 an.setId(annotation.annotationId);
1756 an.setVisible(annotation.visible);
1758 an.setDescription(annotation.description);
1760 if (annotation.sequenceRef != null)
1762 // 2.9 JAL-1781 xref on sequence id rather than name
1763 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
1765 if (annotation.groupRef != null)
1767 String groupIdr = groupRefs.get(annotation.groupRef);
1768 if (groupIdr == null)
1770 // make a locally unique String
1772 annotation.groupRef,
1773 groupIdr = ("" + System.currentTimeMillis()
1774 + annotation.groupRef.getName() + groupRefs
1777 an.setGroupRef(groupIdr.toString());
1780 // store all visualization attributes for annotation
1781 an.setGraphHeight(annotation.graphHeight);
1782 an.setCentreColLabels(annotation.centreColLabels);
1783 an.setScaleColLabels(annotation.scaleColLabel);
1784 an.setShowAllColLabels(annotation.showAllColLabels);
1785 an.setBelowAlignment(annotation.belowAlignment);
1787 if (annotation.graph > 0)
1790 an.setGraphType(annotation.graph);
1791 an.setGraphGroup(annotation.graphGroup);
1792 if (annotation.getThreshold() != null)
1794 ThresholdLine line = new ThresholdLine();
1795 line.setLabel(annotation.getThreshold().label);
1796 line.setValue(annotation.getThreshold().value);
1797 line.setColour(annotation.getThreshold().colour.getRGB());
1798 an.setThresholdLine(line);
1806 an.setLabel(annotation.label);
1808 if (annotation == av.getAlignmentQualityAnnot()
1809 || annotation == av.getAlignmentConservationAnnotation()
1810 || annotation == av.getAlignmentConsensusAnnotation()
1811 || annotation.autoCalculated)
1813 // new way of indicating autocalculated annotation -
1814 an.setAutoCalculated(annotation.autoCalculated);
1816 if (annotation.hasScore())
1818 an.setScore(annotation.getScore());
1821 if (annotation.getCalcId() != null)
1823 calcIdSet.add(annotation.getCalcId());
1824 an.setCalcId(annotation.getCalcId());
1826 if (annotation.hasProperties())
1828 for (String pr : annotation.getProperties())
1830 Property prop = new Property();
1832 prop.setValue(annotation.getProperty(pr));
1833 an.addProperty(prop);
1837 AnnotationElement ae;
1838 if (annotation.annotations != null)
1840 an.setScoreOnly(false);
1841 for (int a = 0; a < annotation.annotations.length; a++)
1843 if ((annotation == null) || (annotation.annotations[a] == null))
1848 ae = new AnnotationElement();
1849 if (annotation.annotations[a].description != null)
1851 ae.setDescription(annotation.annotations[a].description);
1853 if (annotation.annotations[a].displayCharacter != null)
1855 ae.setDisplayCharacter(annotation.annotations[a].displayCharacter);
1858 if (!Float.isNaN(annotation.annotations[a].value))
1860 ae.setValue(annotation.annotations[a].value);
1864 if (annotation.annotations[a].secondaryStructure > ' ')
1866 ae.setSecondaryStructure(annotation.annotations[a].secondaryStructure
1870 if (annotation.annotations[a].colour != null
1871 && annotation.annotations[a].colour != java.awt.Color.black)
1873 ae.setColour(annotation.annotations[a].colour.getRGB());
1876 an.addAnnotationElement(ae);
1877 if (annotation.autoCalculated)
1879 // only write one non-null entry into the annotation row -
1880 // sufficient to get the visualization attributes necessary to
1888 an.setScoreOnly(true);
1890 if (!storeDS || (storeDS && !annotation.autoCalculated))
1892 // skip autocalculated annotation - these are only provided for
1894 vamsasSet.addAnnotation(an);
1900 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
1902 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
1903 if (settings != null)
1905 CalcIdParam vCalcIdParam = new CalcIdParam();
1906 vCalcIdParam.setCalcId(calcId);
1907 vCalcIdParam.addServiceURL(settings.getServiceURI());
1908 // generic URI allowing a third party to resolve another instance of the
1909 // service used for this calculation
1910 for (String urls : settings.getServiceURLs())
1912 vCalcIdParam.addServiceURL(urls);
1914 vCalcIdParam.setVersion("1.0");
1915 if (settings.getPreset() != null)
1917 WsParamSetI setting = settings.getPreset();
1918 vCalcIdParam.setName(setting.getName());
1919 vCalcIdParam.setDescription(setting.getDescription());
1923 vCalcIdParam.setName("");
1924 vCalcIdParam.setDescription("Last used parameters");
1926 // need to be able to recover 1) settings 2) user-defined presets or
1927 // recreate settings from preset 3) predefined settings provided by
1928 // service - or settings that can be transferred (or discarded)
1929 vCalcIdParam.setParameters(settings.getWsParamFile().replace("\n",
1931 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
1932 // todo - decide if updateImmediately is needed for any projects.
1934 return vCalcIdParam;
1939 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
1942 if (calcIdParam.getVersion().equals("1.0"))
1944 Jws2Instance service = Jws2Discoverer.getDiscoverer()
1945 .getPreferredServiceFor(calcIdParam.getServiceURL());
1946 if (service != null)
1948 WsParamSetI parmSet = null;
1951 parmSet = service.getParamStore().parseServiceParameterFile(
1952 calcIdParam.getName(), calcIdParam.getDescription(),
1953 calcIdParam.getServiceURL(),
1954 calcIdParam.getParameters().replace("|\\n|", "\n"));
1955 } catch (IOException x)
1957 warn("Couldn't parse parameter data for "
1958 + calcIdParam.getCalcId(), x);
1961 List<ArgumentI> argList = null;
1962 if (calcIdParam.getName().length() > 0)
1964 parmSet = service.getParamStore()
1965 .getPreset(calcIdParam.getName());
1966 if (parmSet != null)
1968 // TODO : check we have a good match with settings in AACon -
1969 // otherwise we'll need to create a new preset
1974 argList = parmSet.getArguments();
1977 AAConSettings settings = new AAConSettings(
1978 calcIdParam.isAutoUpdate(), service, parmSet, argList);
1979 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
1980 calcIdParam.isNeedsUpdate());
1985 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
1989 throw new Error(MessageManager.formatMessage(
1990 "error.unsupported_version_calcIdparam",
1991 new Object[] { calcIdParam.toString() }));
1995 * External mapping between jalview objects and objects yielding a valid and
1996 * unique object ID string. This is null for normal Jalview project IO, but
1997 * non-null when a jalview project is being read or written as part of a
2000 IdentityHashMap jv2vobj = null;
2003 * Construct a unique ID for jvobj using either existing bindings or if none
2004 * exist, the result of the hashcode call for the object.
2007 * jalview data object
2008 * @return unique ID for referring to jvobj
2010 private String makeHashCode(Object jvobj, String altCode)
2012 if (jv2vobj != null)
2014 Object id = jv2vobj.get(jvobj);
2017 return id.toString();
2019 // check string ID mappings
2020 if (jvids2vobj != null && jvobj instanceof String)
2022 id = jvids2vobj.get(jvobj);
2026 return id.toString();
2028 // give up and warn that something has gone wrong
2029 warn("Cannot find ID for object in external mapping : " + jvobj);
2035 * return local jalview object mapped to ID, if it exists
2039 * @return null or object bound to idcode
2041 private Object retrieveExistingObj(String idcode)
2043 if (idcode != null && vobj2jv != null)
2045 return vobj2jv.get(idcode);
2051 * binding from ID strings from external mapping table to jalview data model
2054 private Hashtable vobj2jv;
2056 private Sequence createVamsasSequence(String id, SequenceI jds)
2058 return createVamsasSequence(true, id, jds, null);
2061 private Sequence createVamsasSequence(boolean recurse, String id,
2062 SequenceI jds, SequenceI parentseq)
2064 Sequence vamsasSeq = new Sequence();
2065 vamsasSeq.setId(id);
2066 vamsasSeq.setName(jds.getName());
2067 vamsasSeq.setSequence(jds.getSequenceAsString());
2068 vamsasSeq.setDescription(jds.getDescription());
2069 jalview.datamodel.DBRefEntry[] dbrefs = null;
2070 if (jds.getDatasetSequence() != null)
2072 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
2076 // seqId==dsseqid so we can tell which sequences really are
2077 // dataset sequences only
2078 vamsasSeq.setDsseqid(id);
2079 dbrefs = jds.getDBRefs();
2080 if (parentseq == null)
2087 for (int d = 0; d < dbrefs.length; d++)
2089 DBRef dbref = new DBRef();
2090 dbref.setSource(dbrefs[d].getSource());
2091 dbref.setVersion(dbrefs[d].getVersion());
2092 dbref.setAccessionId(dbrefs[d].getAccessionId());
2093 if (dbrefs[d].hasMap())
2095 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
2097 dbref.setMapping(mp);
2099 vamsasSeq.addDBRef(dbref);
2105 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
2106 SequenceI parentseq, SequenceI jds, boolean recurse)
2109 if (jmp.getMap() != null)
2113 jalview.util.MapList mlst = jmp.getMap();
2114 List<int[]> r = mlst.getFromRanges();
2115 for (int[] range : r)
2117 MapListFrom mfrom = new MapListFrom();
2118 mfrom.setStart(range[0]);
2119 mfrom.setEnd(range[1]);
2120 mp.addMapListFrom(mfrom);
2122 r = mlst.getToRanges();
2123 for (int[] range : r)
2125 MapListTo mto = new MapListTo();
2126 mto.setStart(range[0]);
2127 mto.setEnd(range[1]);
2128 mp.addMapListTo(mto);
2130 mp.setMapFromUnit(mlst.getFromRatio());
2131 mp.setMapToUnit(mlst.getToRatio());
2132 if (jmp.getTo() != null)
2134 MappingChoice mpc = new MappingChoice();
2136 // check/create ID for the sequence referenced by getTo()
2139 SequenceI ps = null;
2140 if (parentseq != jmp.getTo()
2141 && parentseq.getDatasetSequence() != jmp.getTo())
2143 // chaining dbref rather than a handshaking one
2144 jmpid = seqHash(ps = jmp.getTo());
2148 jmpid = seqHash(ps = parentseq);
2150 mpc.setDseqFor(jmpid);
2151 if (!seqRefIds.containsKey(mpc.getDseqFor()))
2153 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2154 seqRefIds.put(mpc.getDseqFor(), ps);
2158 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2161 mp.setMappingChoice(mpc);
2167 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2168 List<UserColourScheme> userColours, JalviewModelSequence jms)
2171 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2172 boolean newucs = false;
2173 if (!userColours.contains(ucs))
2175 userColours.add(ucs);
2178 id = "ucs" + userColours.indexOf(ucs);
2181 // actually create the scheme's entry in the XML model
2182 java.awt.Color[] colours = ucs.getColours();
2183 jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
2184 jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
2186 for (int i = 0; i < colours.length; i++)
2188 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2189 col.setName(ResidueProperties.aa[i]);
2190 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2191 jbucs.addColour(col);
2193 if (ucs.getLowerCaseColours() != null)
2195 colours = ucs.getLowerCaseColours();
2196 for (int i = 0; i < colours.length; i++)
2198 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2199 col.setName(ResidueProperties.aa[i].toLowerCase());
2200 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2201 jbucs.addColour(col);
2206 uc.setUserColourScheme(jbucs);
2207 jms.addUserColours(uc);
2213 jalview.schemes.UserColourScheme getUserColourScheme(
2214 JalviewModelSequence jms, String id)
2216 UserColours[] uc = jms.getUserColours();
2217 UserColours colours = null;
2219 for (int i = 0; i < uc.length; i++)
2221 if (uc[i].getId().equals(id))
2229 java.awt.Color[] newColours = new java.awt.Color[24];
2231 for (int i = 0; i < 24; i++)
2233 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2234 .getUserColourScheme().getColour(i).getRGB(), 16));
2237 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2240 if (colours.getUserColourScheme().getColourCount() > 24)
2242 newColours = new java.awt.Color[23];
2243 for (int i = 0; i < 23; i++)
2245 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2246 .getUserColourScheme().getColour(i + 24).getRGB(), 16));
2248 ucs.setLowerCaseColours(newColours);
2255 * contains last error message (if any) encountered by XML loader.
2257 String errorMessage = null;
2260 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2261 * exceptions are raised during project XML parsing
2263 public boolean attemptversion1parse = true;
2266 * Load a jalview project archive from a jar file
2269 * - HTTP URL or filename
2271 public AlignFrame loadJalviewAlign(final String file)
2274 jalview.gui.AlignFrame af = null;
2278 // create list to store references for any new Jmol viewers created
2279 newStructureViewers = new Vector<JalviewStructureDisplayI>();
2280 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2281 // Workaround is to make sure caller implements the JarInputStreamProvider
2283 // so we can re-open the jar input stream for each entry.
2285 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2286 af = loadJalviewAlign(jprovider);
2288 } catch (MalformedURLException e)
2290 errorMessage = "Invalid URL format for '" + file + "'";
2296 SwingUtilities.invokeAndWait(new Runnable()
2301 setLoadingFinishedForNewStructureViewers();
2304 } catch (Exception x)
2306 System.err.println("Error loading alignment: " + x.getMessage());
2312 private jarInputStreamProvider createjarInputStreamProvider(
2313 final String file) throws MalformedURLException
2316 errorMessage = null;
2317 uniqueSetSuffix = null;
2319 viewportsAdded.clear();
2320 frefedSequence = null;
2322 if (file.startsWith("http://"))
2324 url = new URL(file);
2326 final URL _url = url;
2327 return new jarInputStreamProvider()
2331 public JarInputStream getJarInputStream() throws IOException
2335 return new JarInputStream(_url.openStream());
2339 return new JarInputStream(new FileInputStream(file));
2344 public String getFilename()
2352 * Recover jalview session from a jalview project archive. Caller may
2353 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2354 * themselves. Any null fields will be initialised with default values,
2355 * non-null fields are left alone.
2360 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2362 errorMessage = null;
2363 if (uniqueSetSuffix == null)
2365 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2367 if (seqRefIds == null)
2371 AlignFrame af = null, _af = null;
2372 IdentityHashMap<AlignmentI, AlignmentI> importedDatasets = new IdentityHashMap<AlignmentI, AlignmentI>();
2373 Map<String, AlignFrame> gatherToThisFrame = new HashMap<String, AlignFrame>();
2374 final String file = jprovider.getFilename();
2377 JarInputStream jin = null;
2378 JarEntry jarentry = null;
2383 jin = jprovider.getJarInputStream();
2384 for (int i = 0; i < entryCount; i++)
2386 jarentry = jin.getNextJarEntry();
2389 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2391 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2392 JalviewModel object = new JalviewModel();
2394 Unmarshaller unmar = new Unmarshaller(object);
2395 unmar.setValidation(false);
2396 object = (JalviewModel) unmar.unmarshal(in);
2397 if (true) // !skipViewport(object))
2399 _af = loadFromObject(object, file, true, jprovider);
2401 && object.getJalviewModelSequence().getViewportCount() > 0)
2405 // store a reference to the first view
2408 if (_af.viewport.isGatherViewsHere())
2410 // if this is a gathered view, keep its reference since
2411 // after gathering views, only this frame will remain
2413 gatherToThisFrame.put(_af.viewport.getSequenceSetId(), _af);
2415 // Save dataset to register mappings once all resolved
2416 importedDatasets.put(af.viewport.getAlignment().getDataset(),
2417 af.viewport.getAlignment().getDataset());
2422 else if (jarentry != null)
2424 // Some other file here.
2427 } while (jarentry != null);
2428 resolveFrefedSequences();
2429 } catch (IOException ex)
2431 ex.printStackTrace();
2432 errorMessage = "Couldn't locate Jalview XML file : " + file;
2433 System.err.println("Exception whilst loading jalview XML file : "
2435 } catch (Exception ex)
2437 System.err.println("Parsing as Jalview Version 2 file failed.");
2438 ex.printStackTrace(System.err);
2439 if (attemptversion1parse)
2441 // Is Version 1 Jar file?
2444 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
2445 } catch (Exception ex2)
2447 System.err.println("Exception whilst loading as jalviewXMLV1:");
2448 ex2.printStackTrace();
2452 if (Desktop.instance != null)
2454 Desktop.instance.stopLoading();
2458 System.out.println("Successfully loaded archive file");
2461 ex.printStackTrace();
2463 System.err.println("Exception whilst loading jalview XML file : "
2465 } catch (OutOfMemoryError e)
2467 // Don't use the OOM Window here
2468 errorMessage = "Out of memory loading jalview XML file";
2469 System.err.println("Out of memory whilst loading jalview XML file");
2470 e.printStackTrace();
2474 * Regather multiple views (with the same sequence set id) to the frame (if
2475 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2476 * views instead of separate frames. Note this doesn't restore a state where
2477 * some expanded views in turn have tabbed views - the last "first tab" read
2478 * in will play the role of gatherer for all.
2480 for (AlignFrame fr : gatherToThisFrame.values())
2482 Desktop.instance.gatherViews(fr);
2485 restoreSplitFrames();
2486 for (AlignmentI ds : importedDatasets.keySet())
2488 if (ds.getCodonFrames() != null)
2490 StructureSelectionManager.getStructureSelectionManager(
2491 Desktop.instance).registerMappings(ds.getCodonFrames());
2494 if (errorMessage != null)
2499 if (Desktop.instance != null)
2501 Desktop.instance.stopLoading();
2508 * Try to reconstruct and display SplitFrame windows, where each contains
2509 * complementary dna and protein alignments. Done by pairing up AlignFrame
2510 * objects (created earlier) which have complementary viewport ids associated.
2512 protected void restoreSplitFrames()
2514 List<SplitFrame> gatherTo = new ArrayList<SplitFrame>();
2515 List<AlignFrame> addedToSplitFrames = new ArrayList<AlignFrame>();
2516 Map<String, AlignFrame> dna = new HashMap<String, AlignFrame>();
2519 * Identify the DNA alignments
2521 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2524 AlignFrame af = candidate.getValue();
2525 if (af.getViewport().getAlignment().isNucleotide())
2527 dna.put(candidate.getKey().getId(), af);
2532 * Try to match up the protein complements
2534 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2537 AlignFrame af = candidate.getValue();
2538 if (!af.getViewport().getAlignment().isNucleotide())
2540 String complementId = candidate.getKey().getComplementId();
2541 // only non-null complements should be in the Map
2542 if (complementId != null && dna.containsKey(complementId))
2544 final AlignFrame dnaFrame = dna.get(complementId);
2545 SplitFrame sf = createSplitFrame(dnaFrame, af);
2546 addedToSplitFrames.add(dnaFrame);
2547 addedToSplitFrames.add(af);
2548 dnaFrame.setMenusForViewport();
2549 af.setMenusForViewport();
2550 if (af.viewport.isGatherViewsHere())
2559 * Open any that we failed to pair up (which shouldn't happen!) as
2560 * standalone AlignFrame's.
2562 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2565 AlignFrame af = candidate.getValue();
2566 if (!addedToSplitFrames.contains(af))
2568 Viewport view = candidate.getKey();
2569 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
2571 af.setMenusForViewport();
2572 System.err.println("Failed to restore view " + view.getTitle()
2573 + " to split frame");
2578 * Gather back into tabbed views as flagged.
2580 for (SplitFrame sf : gatherTo)
2582 Desktop.instance.gatherViews(sf);
2585 splitFrameCandidates.clear();
2589 * Construct and display one SplitFrame holding DNA and protein alignments.
2592 * @param proteinFrame
2595 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
2596 AlignFrame proteinFrame)
2598 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
2599 String title = MessageManager.getString("label.linked_view_title");
2600 int width = (int) dnaFrame.getBounds().getWidth();
2601 int height = (int) (dnaFrame.getBounds().getHeight()
2602 + proteinFrame.getBounds().getHeight() + 50);
2605 * SplitFrame location is saved to both enclosed frames
2607 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
2608 Desktop.addInternalFrame(splitFrame, title, width, height);
2611 * And compute cDNA consensus (couldn't do earlier with consensus as
2612 * mappings were not yet present)
2614 proteinFrame.viewport.alignmentChanged(proteinFrame.alignPanel);
2620 * check errorMessage for a valid error message and raise an error box in the
2621 * GUI or write the current errorMessage to stderr and then clear the error
2624 protected void reportErrors()
2626 reportErrors(false);
2629 protected void reportErrors(final boolean saving)
2631 if (errorMessage != null)
2633 final String finalErrorMessage = errorMessage;
2636 javax.swing.SwingUtilities.invokeLater(new Runnable()
2641 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2642 finalErrorMessage, "Error "
2643 + (saving ? "saving" : "loading")
2644 + " Jalview file", JvOptionPane.WARNING_MESSAGE);
2650 System.err.println("Problem loading Jalview file: " + errorMessage);
2653 errorMessage = null;
2656 Map<String, String> alreadyLoadedPDB = new HashMap<String, String>();
2659 * when set, local views will be updated from view stored in JalviewXML
2660 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2661 * sync if this is set to true.
2663 private final boolean updateLocalViews = false;
2666 * Returns the path to a temporary file holding the PDB file for the given PDB
2667 * id. The first time of asking, searches for a file of that name in the
2668 * Jalview project jar, and copies it to a new temporary file. Any repeat
2669 * requests just return the path to the file previously created.
2675 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId,
2678 if (alreadyLoadedPDB.containsKey(pdbId))
2680 return alreadyLoadedPDB.get(pdbId).toString();
2683 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb",
2685 if (tempFile != null)
2687 alreadyLoadedPDB.put(pdbId, tempFile);
2693 * Copies the jar entry of given name to a new temporary file and returns the
2694 * path to the file, or null if the entry is not found.
2697 * @param jarEntryName
2699 * a prefix for the temporary file name, must be at least three
2702 * null or original file - so new file can be given the same suffix
2706 protected String copyJarEntry(jarInputStreamProvider jprovider,
2707 String jarEntryName, String prefix, String origFile)
2709 BufferedReader in = null;
2710 PrintWriter out = null;
2711 String suffix = ".tmp";
2712 if (origFile == null)
2714 origFile = jarEntryName;
2716 int sfpos = origFile.lastIndexOf(".");
2717 if (sfpos > -1 && sfpos < (origFile.length() - 3))
2719 suffix = "." + origFile.substring(sfpos + 1);
2723 JarInputStream jin = jprovider.getJarInputStream();
2725 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2726 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2727 * FileInputStream(jprovider)); }
2730 JarEntry entry = null;
2733 entry = jin.getNextJarEntry();
2734 } while (entry != null && !entry.getName().equals(jarEntryName));
2737 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
2738 File outFile = File.createTempFile(prefix, suffix);
2739 outFile.deleteOnExit();
2740 out = new PrintWriter(new FileOutputStream(outFile));
2743 while ((data = in.readLine()) != null)
2748 String t = outFile.getAbsolutePath();
2753 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
2755 } catch (Exception ex)
2757 ex.printStackTrace();
2765 } catch (IOException e)
2779 private class JvAnnotRow
2781 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2788 * persisted version of annotation row from which to take vis properties
2790 public jalview.datamodel.AlignmentAnnotation template;
2793 * original position of the annotation row in the alignment
2799 * Load alignment frame from jalview XML DOM object
2804 * filename source string
2805 * @param loadTreesAndStructures
2806 * when false only create Viewport
2808 * data source provider
2809 * @return alignment frame created from view stored in DOM
2811 AlignFrame loadFromObject(JalviewModel object, String file,
2812 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
2814 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
2815 Sequence[] vamsasSeq = vamsasSet.getSequence();
2817 JalviewModelSequence jms = object.getJalviewModelSequence();
2819 Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
2822 // ////////////////////////////////
2825 List<SequenceI> hiddenSeqs = null;
2827 List<SequenceI> tmpseqs = new ArrayList<SequenceI>();
2829 boolean multipleView = false;
2830 SequenceI referenceseqForView = null;
2831 JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
2832 int vi = 0; // counter in vamsasSeq array
2833 for (int i = 0; i < jseqs.length; i++)
2835 String seqId = jseqs[i].getId();
2837 SequenceI tmpSeq = seqRefIds.get(seqId);
2840 if (!incompleteSeqs.containsKey(seqId))
2842 // may not need this check, but keep it for at least 2.9,1 release
2843 if (tmpSeq.getStart() != jseqs[i].getStart()
2844 || tmpSeq.getEnd() != jseqs[i].getEnd())
2847 .println("Warning JAL-2154 regression: updating start/end for sequence "
2848 + tmpSeq.toString() + " to " + jseqs[i]);
2853 incompleteSeqs.remove(seqId);
2855 if (vamsasSeq.length > vi && vamsasSeq[vi].getId().equals(seqId))
2857 // most likely we are reading a dataset XML document so
2858 // update from vamsasSeq section of XML for this sequence
2859 tmpSeq.setName(vamsasSeq[vi].getName());
2860 tmpSeq.setDescription(vamsasSeq[vi].getDescription());
2861 tmpSeq.setSequence(vamsasSeq[vi].getSequence());
2866 // reading multiple views, so vamsasSeq set is a subset of JSeq
2867 multipleView = true;
2869 tmpSeq.setStart(jseqs[i].getStart());
2870 tmpSeq.setEnd(jseqs[i].getEnd());
2871 tmpseqs.add(tmpSeq);
2875 tmpSeq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
2876 vamsasSeq[vi].getSequence());
2877 tmpSeq.setDescription(vamsasSeq[vi].getDescription());
2878 tmpSeq.setStart(jseqs[i].getStart());
2879 tmpSeq.setEnd(jseqs[i].getEnd());
2880 tmpSeq.setVamsasId(uniqueSetSuffix + seqId);
2881 seqRefIds.put(vamsasSeq[vi].getId(), tmpSeq);
2882 tmpseqs.add(tmpSeq);
2886 if (jseqs[i].hasViewreference() && jseqs[i].getViewreference())
2888 referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
2891 if (jseqs[i].getHidden())
2893 if (hiddenSeqs == null)
2895 hiddenSeqs = new ArrayList<SequenceI>();
2898 hiddenSeqs.add(tmpSeq);
2903 // Create the alignment object from the sequence set
2904 // ///////////////////////////////
2905 SequenceI[] orderedSeqs = tmpseqs
2906 .toArray(new SequenceI[tmpseqs.size()]);
2908 AlignmentI al = null;
2909 // so we must create or recover the dataset alignment before going further
2910 // ///////////////////////////////
2911 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
2913 // older jalview projects do not have a dataset - so creat alignment and
2915 al = new Alignment(orderedSeqs);
2916 al.setDataset(null);
2920 boolean isdsal = object.getJalviewModelSequence().getViewportCount() == 0;
2923 // we are importing a dataset record, so
2924 // recover reference to an alignment already materialsed as dataset
2925 al = getDatasetFor(vamsasSet.getDatasetId());
2929 // materialse the alignment
2930 al = new Alignment(orderedSeqs);
2934 addDatasetRef(vamsasSet.getDatasetId(), al);
2937 // finally, verify all data in vamsasSet is actually present in al
2938 // passing on flag indicating if it is actually a stored dataset
2939 recoverDatasetFor(vamsasSet, al, isdsal);
2942 if (referenceseqForView != null)
2944 al.setSeqrep(referenceseqForView);
2946 // / Add the alignment properties
2947 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
2949 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
2950 al.setProperty(ssp.getKey(), ssp.getValue());
2953 // ///////////////////////////////
2955 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
2958 // load sequence features, database references and any associated PDB
2959 // structures for the alignment
2961 // prior to 2.10, this part would only be executed the first time a
2962 // sequence was encountered, but not afterwards.
2963 // now, for 2.10 projects, this is also done if the xml doc includes
2964 // dataset sequences not actually present in any particular view.
2966 for (int i = 0; i < vamsasSeq.length; i++)
2968 if (jseqs[i].getFeaturesCount() > 0)
2970 Features[] features = jseqs[i].getFeatures();
2971 for (int f = 0; f < features.length; f++)
2973 jalview.datamodel.SequenceFeature sf = new jalview.datamodel.SequenceFeature(
2974 features[f].getType(), features[f].getDescription(),
2975 features[f].getStatus(), features[f].getBegin(),
2976 features[f].getEnd(), features[f].getFeatureGroup());
2978 sf.setScore(features[f].getScore());
2979 for (int od = 0; od < features[f].getOtherDataCount(); od++)
2981 OtherData keyValue = features[f].getOtherData(od);
2982 if (keyValue.getKey().startsWith("LINK"))
2984 sf.addLink(keyValue.getValue());
2988 sf.setValue(keyValue.getKey(), keyValue.getValue());
2992 // adds feature to datasequence's feature set (since Jalview 2.10)
2993 al.getSequenceAt(i).addSequenceFeature(sf);
2996 if (vamsasSeq[i].getDBRefCount() > 0)
2998 // adds dbrefs to datasequence's set (since Jalview 2.10)
3000 al.getSequenceAt(i).getDatasetSequence() == null ? al.getSequenceAt(i)
3001 : al.getSequenceAt(i).getDatasetSequence(),
3004 if (jseqs[i].getPdbidsCount() > 0)
3006 Pdbids[] ids = jseqs[i].getPdbids();
3007 for (int p = 0; p < ids.length; p++)
3009 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
3010 entry.setId(ids[p].getId());
3011 if (ids[p].getType() != null)
3013 if (PDBEntry.Type.getType(ids[p].getType()) != null)
3015 entry.setType(PDBEntry.Type.getType(ids[p].getType()));
3019 entry.setType(PDBEntry.Type.FILE);
3022 // jprovider is null when executing 'New View'
3023 if (ids[p].getFile() != null && jprovider != null)
3025 if (!pdbloaded.containsKey(ids[p].getFile()))
3027 entry.setFile(loadPDBFile(jprovider, ids[p].getId(),
3032 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
3035 if (ids[p].getPdbentryItem() != null)
3037 for (PdbentryItem item : ids[p].getPdbentryItem())
3039 for (Property pr : item.getProperty())
3041 entry.setProperty(pr.getName(), pr.getValue());
3045 StructureSelectionManager.getStructureSelectionManager(
3046 Desktop.instance).registerPDBEntry(entry);
3047 // adds PDBEntry to datasequence's set (since Jalview 2.10)
3048 if (al.getSequenceAt(i).getDatasetSequence() != null)
3050 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
3054 al.getSequenceAt(i).addPDBId(entry);
3059 } // end !multipleview
3061 // ///////////////////////////////
3062 // LOAD SEQUENCE MAPPINGS
3064 if (vamsasSet.getAlcodonFrameCount() > 0)
3066 // TODO Potentially this should only be done once for all views of an
3068 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
3069 for (int i = 0; i < alc.length; i++)
3071 AlignedCodonFrame cf = new AlignedCodonFrame();
3072 if (alc[i].getAlcodMapCount() > 0)
3074 AlcodMap[] maps = alc[i].getAlcodMap();
3075 for (int m = 0; m < maps.length; m++)
3077 SequenceI dnaseq = seqRefIds.get(maps[m].getDnasq());
3079 jalview.datamodel.Mapping mapping = null;
3080 // attach to dna sequence reference.
3081 if (maps[m].getMapping() != null)
3083 mapping = addMapping(maps[m].getMapping());
3084 if (dnaseq != null && mapping.getTo() != null)
3086 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
3091 frefedSequence.add(newAlcodMapRef(maps[m].getDnasq(), cf,
3096 al.addCodonFrame(cf);
3101 // ////////////////////////////////
3103 List<JvAnnotRow> autoAlan = new ArrayList<JvAnnotRow>();
3106 * store any annotations which forward reference a group's ID
3108 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<String, List<AlignmentAnnotation>>();
3110 if (vamsasSet.getAnnotationCount() > 0)
3112 Annotation[] an = vamsasSet.getAnnotation();
3114 for (int i = 0; i < an.length; i++)
3116 Annotation annotation = an[i];
3119 * test if annotation is automatically calculated for this view only
3121 boolean autoForView = false;
3122 if (annotation.getLabel().equals("Quality")
3123 || annotation.getLabel().equals("Conservation")
3124 || annotation.getLabel().equals("Consensus"))
3126 // Kludge for pre 2.5 projects which lacked the autocalculated flag
3128 if (!annotation.hasAutoCalculated())
3130 annotation.setAutoCalculated(true);
3134 || (annotation.hasAutoCalculated() && annotation
3135 .isAutoCalculated()))
3137 // remove ID - we don't recover annotation from other views for
3138 // view-specific annotation
3139 annotation.setId(null);
3142 // set visiblity for other annotation in this view
3143 String annotationId = annotation.getId();
3144 if (annotationId != null && annotationIds.containsKey(annotationId))
3146 AlignmentAnnotation jda = annotationIds.get(annotationId);
3147 // in principle Visible should always be true for annotation displayed
3148 // in multiple views
3149 if (annotation.hasVisible())
3151 jda.visible = annotation.getVisible();
3154 al.addAnnotation(jda);
3158 // Construct new annotation from model.
3159 AnnotationElement[] ae = annotation.getAnnotationElement();
3160 jalview.datamodel.Annotation[] anot = null;
3161 java.awt.Color firstColour = null;
3163 if (!annotation.getScoreOnly())
3165 anot = new jalview.datamodel.Annotation[al.getWidth()];
3166 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
3168 anpos = ae[aa].getPosition();
3170 if (anpos >= anot.length)
3175 anot[anpos] = new jalview.datamodel.Annotation(
3177 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
3178 (ae[aa].getSecondaryStructure() == null || ae[aa]
3179 .getSecondaryStructure().length() == 0) ? ' '
3180 : ae[aa].getSecondaryStructure().charAt(0),
3184 // JBPNote: Consider verifying dataflow for IO of secondary
3185 // structure annotation read from Stockholm files
3186 // this was added to try to ensure that
3187 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
3189 // anot[ae[aa].getPosition()].displayCharacter = "";
3191 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
3192 if (firstColour == null)
3194 firstColour = anot[anpos].colour;
3198 jalview.datamodel.AlignmentAnnotation jaa = null;
3200 if (annotation.getGraph())
3202 float llim = 0, hlim = 0;
3203 // if (autoForView || an[i].isAutoCalculated()) {
3206 jaa = new jalview.datamodel.AlignmentAnnotation(
3207 annotation.getLabel(), annotation.getDescription(), anot,
3208 llim, hlim, annotation.getGraphType());
3210 jaa.graphGroup = annotation.getGraphGroup();
3211 jaa._linecolour = firstColour;
3212 if (annotation.getThresholdLine() != null)
3214 jaa.setThreshold(new jalview.datamodel.GraphLine(annotation
3215 .getThresholdLine().getValue(), annotation
3216 .getThresholdLine().getLabel(), new java.awt.Color(
3217 annotation.getThresholdLine().getColour())));
3220 if (autoForView || annotation.isAutoCalculated())
3222 // Hardwire the symbol display line to ensure that labels for
3223 // histograms are displayed
3229 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
3230 an[i].getDescription(), anot);
3231 jaa._linecolour = firstColour;
3233 // register new annotation
3234 if (an[i].getId() != null)
3236 annotationIds.put(an[i].getId(), jaa);
3237 jaa.annotationId = an[i].getId();
3239 // recover sequence association
3240 String sequenceRef = an[i].getSequenceRef();
3241 if (sequenceRef != null)
3243 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3244 SequenceI sequence = seqRefIds.get(sequenceRef);
3245 if (sequence == null)
3247 // in pre-2.9 projects sequence ref is to sequence name
3248 sequence = al.findName(sequenceRef);
3250 if (sequence != null)
3252 jaa.createSequenceMapping(sequence, 1, true);
3253 sequence.addAlignmentAnnotation(jaa);
3256 // and make a note of any group association
3257 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
3259 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3260 .get(an[i].getGroupRef());
3263 aal = new ArrayList<jalview.datamodel.AlignmentAnnotation>();
3264 groupAnnotRefs.put(an[i].getGroupRef(), aal);
3269 if (an[i].hasScore())
3271 jaa.setScore(an[i].getScore());
3273 if (an[i].hasVisible())
3275 jaa.visible = an[i].getVisible();
3278 if (an[i].hasCentreColLabels())
3280 jaa.centreColLabels = an[i].getCentreColLabels();
3283 if (an[i].hasScaleColLabels())
3285 jaa.scaleColLabel = an[i].getScaleColLabels();
3287 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
3289 // newer files have an 'autoCalculated' flag and store calculation
3290 // state in viewport properties
3291 jaa.autoCalculated = true; // means annotation will be marked for
3292 // update at end of load.
3294 if (an[i].hasGraphHeight())
3296 jaa.graphHeight = an[i].getGraphHeight();
3298 if (an[i].hasBelowAlignment())
3300 jaa.belowAlignment = an[i].isBelowAlignment();
3302 jaa.setCalcId(an[i].getCalcId());
3303 if (an[i].getPropertyCount() > 0)
3305 for (jalview.schemabinding.version2.Property prop : an[i]
3308 jaa.setProperty(prop.getName(), prop.getValue());
3311 if (jaa.autoCalculated)
3313 autoAlan.add(new JvAnnotRow(i, jaa));
3316 // if (!autoForView)
3318 // add autocalculated group annotation and any user created annotation
3320 al.addAnnotation(jaa);
3324 // ///////////////////////
3326 // Create alignment markup and styles for this view
3327 if (jms.getJGroupCount() > 0)
3329 JGroup[] groups = jms.getJGroup();
3330 boolean addAnnotSchemeGroup = false;
3331 for (int i = 0; i < groups.length; i++)
3333 JGroup jGroup = groups[i];
3334 ColourSchemeI cs = null;
3335 if (jGroup.getColour() != null)
3337 if (jGroup.getColour().startsWith("ucs"))
3339 cs = getUserColourScheme(jms, jGroup.getColour());
3341 else if (jGroup.getColour().equals("AnnotationColourGradient")
3342 && jGroup.getAnnotationColours() != null)
3344 addAnnotSchemeGroup = true;
3349 cs = ColourSchemeProperty.getColour(al, jGroup.getColour());
3354 cs.setThreshold(jGroup.getPidThreshold(), true);
3358 Vector<SequenceI> seqs = new Vector<SequenceI>();
3360 for (int s = 0; s < jGroup.getSeqCount(); s++)
3362 String seqId = jGroup.getSeq(s) + "";
3363 SequenceI ts = seqRefIds.get(seqId);
3367 seqs.addElement(ts);
3371 if (seqs.size() < 1)
3376 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3377 jGroup.getDisplayBoxes(), jGroup.getDisplayText(),
3378 jGroup.getColourText(), jGroup.getStart(), jGroup.getEnd());
3380 sg.setOutlineColour(new java.awt.Color(jGroup.getOutlineColour()));
3382 sg.textColour = new java.awt.Color(jGroup.getTextCol1());
3383 sg.textColour2 = new java.awt.Color(jGroup.getTextCol2());
3384 sg.setShowNonconserved(jGroup.hasShowUnconserved() ? jGroup
3385 .isShowUnconserved() : false);
3386 sg.thresholdTextColour = jGroup.getTextColThreshold();
3387 if (jGroup.hasShowConsensusHistogram())
3389 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3392 if (jGroup.hasShowSequenceLogo())
3394 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3396 if (jGroup.hasNormaliseSequenceLogo())
3398 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3400 if (jGroup.hasIgnoreGapsinConsensus())
3402 sg.setIgnoreGapsConsensus(jGroup.getIgnoreGapsinConsensus());
3404 if (jGroup.getConsThreshold() != 0)
3406 Conservation c = new Conservation("All", sg.getSequences(null),
3407 0, sg.getWidth() - 1);
3409 c.verdict(false, 25);
3410 sg.cs.setConservation(c);
3413 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3415 // re-instate unique group/annotation row reference
3416 List<AlignmentAnnotation> jaal = groupAnnotRefs.get(jGroup
3420 for (AlignmentAnnotation jaa : jaal)
3423 if (jaa.autoCalculated)
3425 // match up and try to set group autocalc alignment row for this
3427 if (jaa.label.startsWith("Consensus for "))
3429 sg.setConsensus(jaa);
3431 // match up and try to set group autocalc alignment row for this
3433 if (jaa.label.startsWith("Conservation for "))
3435 sg.setConservationRow(jaa);
3442 if (addAnnotSchemeGroup)
3444 // reconstruct the annotation colourscheme
3445 sg.cs = constructAnnotationColour(jGroup.getAnnotationColours(),
3446 null, al, jms, false);
3452 // only dataset in this model, so just return.
3455 // ///////////////////////////////
3458 // If we just load in the same jar file again, the sequenceSetId
3459 // will be the same, and we end up with multiple references
3460 // to the same sequenceSet. We must modify this id on load
3461 // so that each load of the file gives a unique id
3462 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3463 String viewId = (view.getId() == null ? null : view.getId()
3465 AlignFrame af = null;
3466 AlignViewport av = null;
3467 // now check to see if we really need to create a new viewport.
3468 if (multipleView && viewportsAdded.size() == 0)
3470 // We recovered an alignment for which a viewport already exists.
3471 // TODO: fix up any settings necessary for overlaying stored state onto
3472 // state recovered from another document. (may not be necessary).
3473 // we may need a binding from a viewport in memory to one recovered from
3475 // and then recover its containing af to allow the settings to be applied.
3476 // TODO: fix for vamsas demo
3478 .println("About to recover a viewport for existing alignment: Sequence set ID is "
3480 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3481 if (seqsetobj != null)
3483 if (seqsetobj instanceof String)
3485 uniqueSeqSetId = (String) seqsetobj;
3487 .println("Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
3493 .println("Warning : Collision between sequence set ID string and existing jalview object mapping.");
3499 * indicate that annotation colours are applied across all groups (pre
3500 * Jalview 2.8.1 behaviour)
3502 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan(
3503 "2.8.1", object.getVersion());
3505 AlignmentPanel ap = null;
3506 boolean isnewview = true;
3509 // Check to see if this alignment already has a view id == viewId
3510 jalview.gui.AlignmentPanel views[] = Desktop
3511 .getAlignmentPanels(uniqueSeqSetId);
3512 if (views != null && views.length > 0)
3514 for (int v = 0; v < views.length; v++)
3516 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
3518 // recover the existing alignpanel, alignframe, viewport
3519 af = views[v].alignFrame;
3522 // TODO: could even skip resetting view settings if we don't want to
3523 // change the local settings from other jalview processes
3532 af = loadViewport(file, jseqs, hiddenSeqs, al, jms, view,
3533 uniqueSeqSetId, viewId, autoAlan);
3539 * Load any trees, PDB structures and viewers
3541 * Not done if flag is false (when this method is used for New View)
3543 if (loadTreesAndStructures)
3545 loadTrees(jms, view, af, av, ap);
3546 loadPDBStructures(jprovider, jseqs, af, ap);
3547 loadRnaViewers(jprovider, jseqs, ap);
3549 // and finally return.
3554 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
3555 * panel is restored from separate jar entries, two (gapped and trimmed) per
3556 * sequence and secondary structure.
3558 * Currently each viewer shows just one sequence and structure (gapped and
3559 * trimmed), however this method is designed to support multiple sequences or
3560 * structures in viewers if wanted in future.
3566 private void loadRnaViewers(jarInputStreamProvider jprovider,
3567 JSeq[] jseqs, AlignmentPanel ap)
3570 * scan the sequences for references to viewers; create each one the first
3571 * time it is referenced, add Rna models to existing viewers
3573 for (JSeq jseq : jseqs)
3575 for (int i = 0; i < jseq.getRnaViewerCount(); i++)
3577 RnaViewer viewer = jseq.getRnaViewer(i);
3578 AppVarna appVarna = findOrCreateVarnaViewer(viewer,
3579 uniqueSetSuffix, ap);
3581 for (int j = 0; j < viewer.getSecondaryStructureCount(); j++)
3583 SecondaryStructure ss = viewer.getSecondaryStructure(j);
3584 SequenceI seq = seqRefIds.get(jseq.getId());
3585 AlignmentAnnotation ann = this.annotationIds.get(ss
3586 .getAnnotationId());
3589 * add the structure to the Varna display (with session state copied
3590 * from the jar to a temporary file)
3592 boolean gapped = ss.isGapped();
3593 String rnaTitle = ss.getTitle();
3594 String sessionState = ss.getViewerState();
3595 String tempStateFile = copyJarEntry(jprovider, sessionState,
3597 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
3598 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
3600 appVarna.setInitialSelection(viewer.getSelectedRna());
3606 * Locate and return an already instantiated matching AppVarna, or create one
3610 * @param viewIdSuffix
3614 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
3615 String viewIdSuffix, AlignmentPanel ap)
3618 * on each load a suffix is appended to the saved viewId, to avoid conflicts
3619 * if load is repeated
3621 String postLoadId = viewer.getViewId() + viewIdSuffix;
3622 for (JInternalFrame frame : getAllFrames())
3624 if (frame instanceof AppVarna)
3626 AppVarna varna = (AppVarna) frame;
3627 if (postLoadId.equals(varna.getViewId()))
3629 // this viewer is already instantiated
3630 // could in future here add ap as another 'parent' of the
3631 // AppVarna window; currently just 1-to-many
3638 * viewer not found - make it
3640 RnaViewerModel model = new RnaViewerModel(postLoadId,
3641 viewer.getTitle(), viewer.getXpos(), viewer.getYpos(),
3642 viewer.getWidth(), viewer.getHeight(),
3643 viewer.getDividerLocation());
3644 AppVarna varna = new AppVarna(model, ap);
3650 * Load any saved trees
3658 protected void loadTrees(JalviewModelSequence jms, Viewport view,
3659 AlignFrame af, AlignViewport av, AlignmentPanel ap)
3661 // TODO result of automated refactoring - are all these parameters needed?
3664 for (int t = 0; t < jms.getTreeCount(); t++)
3667 Tree tree = jms.getTree(t);
3669 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
3672 tp = af.ShowNewickTree(
3673 new jalview.io.NewickFile(tree.getNewick()),
3674 tree.getTitle(), tree.getWidth(), tree.getHeight(),
3675 tree.getXpos(), tree.getYpos());
3676 if (tree.getId() != null)
3678 // perhaps bind the tree id to something ?
3683 // update local tree attributes ?
3684 // TODO: should check if tp has been manipulated by user - if so its
3685 // settings shouldn't be modified
3686 tp.setTitle(tree.getTitle());
3687 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(), tree
3688 .getWidth(), tree.getHeight()));
3689 tp.av = av; // af.viewport; // TODO: verify 'associate with all
3692 tp.treeCanvas.av = av; // af.viewport;
3693 tp.treeCanvas.ap = ap; // af.alignPanel;
3698 warn("There was a problem recovering stored Newick tree: \n"
3699 + tree.getNewick());
3703 tp.fitToWindow.setState(tree.getFitToWindow());
3704 tp.fitToWindow_actionPerformed(null);
3706 if (tree.getFontName() != null)
3708 tp.setTreeFont(new java.awt.Font(tree.getFontName(), tree
3709 .getFontStyle(), tree.getFontSize()));
3713 tp.setTreeFont(new java.awt.Font(view.getFontName(), view
3714 .getFontStyle(), tree.getFontSize()));
3717 tp.showPlaceholders(tree.getMarkUnlinked());
3718 tp.showBootstrap(tree.getShowBootstrap());
3719 tp.showDistances(tree.getShowDistances());
3721 tp.treeCanvas.threshold = tree.getThreshold();
3723 if (tree.getCurrentTree())
3725 af.viewport.setCurrentTree(tp.getTree());
3729 } catch (Exception ex)
3731 ex.printStackTrace();
3736 * Load and link any saved structure viewers.
3743 protected void loadPDBStructures(jarInputStreamProvider jprovider,
3744 JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
3747 * Run through all PDB ids on the alignment, and collect mappings between
3748 * distinct view ids and all sequences referring to that view.
3750 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<String, StructureViewerModel>();
3752 for (int i = 0; i < jseqs.length; i++)
3754 if (jseqs[i].getPdbidsCount() > 0)
3756 Pdbids[] ids = jseqs[i].getPdbids();
3757 for (int p = 0; p < ids.length; p++)
3759 final int structureStateCount = ids[p].getStructureStateCount();
3760 for (int s = 0; s < structureStateCount; s++)
3762 // check to see if we haven't already created this structure view
3763 final StructureState structureState = ids[p]
3764 .getStructureState(s);
3765 String sviewid = (structureState.getViewId() == null) ? null
3766 : structureState.getViewId() + uniqueSetSuffix;
3767 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
3768 // Originally : ids[p].getFile()
3769 // : TODO: verify external PDB file recovery still works in normal
3770 // jalview project load
3771 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId(),
3773 jpdb.setId(ids[p].getId());
3775 int x = structureState.getXpos();
3776 int y = structureState.getYpos();
3777 int width = structureState.getWidth();
3778 int height = structureState.getHeight();
3780 // Probably don't need to do this anymore...
3781 // Desktop.desktop.getComponentAt(x, y);
3782 // TODO: NOW: check that this recovers the PDB file correctly.
3783 String pdbFile = loadPDBFile(jprovider, ids[p].getId(),
3785 jalview.datamodel.SequenceI seq = seqRefIds.get(jseqs[i]
3787 if (sviewid == null)
3789 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width
3792 if (!structureViewers.containsKey(sviewid))
3794 structureViewers.put(sviewid,
3795 new StructureViewerModel(x, y, width, height, false,
3796 false, true, structureState.getViewId(),
3797 structureState.getType()));
3798 // Legacy pre-2.7 conversion JAL-823 :
3799 // do not assume any view has to be linked for colour by
3803 // assemble String[] { pdb files }, String[] { id for each
3804 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3805 // seqs_file 2}, boolean[] {
3806 // linkAlignPanel,superposeWithAlignpanel}} from hash
3807 StructureViewerModel jmoldat = structureViewers.get(sviewid);
3808 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
3809 | (structureState.hasAlignwithAlignPanel() ? structureState
3810 .getAlignwithAlignPanel() : false));
3813 * Default colour by linked panel to false if not specified (e.g.
3814 * for pre-2.7 projects)
3816 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
3817 colourWithAlignPanel |= (structureState
3818 .hasColourwithAlignPanel() ? structureState
3819 .getColourwithAlignPanel() : false);
3820 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
3823 * Default colour by viewer to true if not specified (e.g. for
3826 boolean colourByViewer = jmoldat.isColourByViewer();
3827 colourByViewer &= structureState.hasColourByJmol() ? structureState
3828 .getColourByJmol() : true;
3829 jmoldat.setColourByViewer(colourByViewer);
3831 if (jmoldat.getStateData().length() < structureState
3832 .getContent().length())
3835 jmoldat.setStateData(structureState.getContent());
3838 if (ids[p].getFile() != null)
3840 File mapkey = new File(ids[p].getFile());
3841 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
3842 if (seqstrmaps == null)
3844 jmoldat.getFileData().put(
3846 seqstrmaps = jmoldat.new StructureData(pdbFile,
3849 if (!seqstrmaps.getSeqList().contains(seq))
3851 seqstrmaps.getSeqList().add(seq);
3857 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");
3864 // Instantiate the associated structure views
3865 for (Entry<String, StructureViewerModel> entry : structureViewers
3870 createOrLinkStructureViewer(entry, af, ap, jprovider);
3871 } catch (Exception e)
3873 System.err.println("Error loading structure viewer: "
3875 // failed - try the next one
3887 protected void createOrLinkStructureViewer(
3888 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3889 AlignmentPanel ap, jarInputStreamProvider jprovider)
3891 final StructureViewerModel stateData = viewerData.getValue();
3894 * Search for any viewer windows already open from other alignment views
3895 * that exactly match the stored structure state
3897 StructureViewerBase comp = findMatchingViewer(viewerData);
3901 linkStructureViewer(ap, comp, stateData);
3906 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
3907 * "viewer_"+stateData.viewId
3909 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
3911 createChimeraViewer(viewerData, af, jprovider);
3916 * else Jmol (if pre-2.9, stateData contains JMOL state string)
3918 createJmolViewer(viewerData, af, jprovider);
3923 * Create a new Chimera viewer.
3929 protected void createChimeraViewer(
3930 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3931 jarInputStreamProvider jprovider)
3933 StructureViewerModel data = viewerData.getValue();
3934 String chimeraSessionFile = data.getStateData();
3937 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
3939 * NB this is the 'saved' viewId as in the project file XML, _not_ the
3940 * 'uniquified' sviewid used to reconstruct the viewer here
3942 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
3943 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
3946 Set<Entry<File, StructureData>> fileData = data.getFileData()
3948 List<PDBEntry> pdbs = new ArrayList<PDBEntry>();
3949 List<SequenceI[]> allseqs = new ArrayList<SequenceI[]>();
3950 for (Entry<File, StructureData> pdb : fileData)
3952 String filePath = pdb.getValue().getFilePath();
3953 String pdbId = pdb.getValue().getPdbId();
3954 // pdbs.add(new PDBEntry(filePath, pdbId));
3955 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
3956 final List<SequenceI> seqList = pdb.getValue().getSeqList();
3957 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
3961 boolean colourByChimera = data.isColourByViewer();
3962 boolean colourBySequence = data.isColourWithAlignPanel();
3964 // TODO use StructureViewer as a factory here, see JAL-1761
3965 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
3966 final SequenceI[][] seqsArray = allseqs.toArray(new SequenceI[allseqs
3968 String newViewId = viewerData.getKey();
3970 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
3971 af.alignPanel, pdbArray, seqsArray, colourByChimera,
3972 colourBySequence, newViewId);
3973 cvf.setSize(data.getWidth(), data.getHeight());
3974 cvf.setLocation(data.getX(), data.getY());
3978 * Create a new Jmol window. First parse the Jmol state to translate filenames
3979 * loaded into the view, and record the order in which files are shown in the
3980 * Jmol view, so we can add the sequence mappings in same order.
3986 protected void createJmolViewer(
3987 final Entry<String, StructureViewerModel> viewerData,
3988 AlignFrame af, jarInputStreamProvider jprovider)
3990 final StructureViewerModel svattrib = viewerData.getValue();
3991 String state = svattrib.getStateData();
3994 * Pre-2.9: state element value is the Jmol state string
3996 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
3999 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
4001 state = readJarEntry(jprovider,
4002 getViewerJarEntryName(svattrib.getViewId()));
4005 List<String> pdbfilenames = new ArrayList<String>();
4006 List<SequenceI[]> seqmaps = new ArrayList<SequenceI[]>();
4007 List<String> pdbids = new ArrayList<String>();
4008 StringBuilder newFileLoc = new StringBuilder(64);
4009 int cp = 0, ncp, ecp;
4010 Map<File, StructureData> oldFiles = svattrib.getFileData();
4011 while ((ncp = state.indexOf("load ", cp)) > -1)
4015 // look for next filename in load statement
4016 newFileLoc.append(state.substring(cp,
4017 ncp = (state.indexOf("\"", ncp + 1) + 1)));
4018 String oldfilenam = state.substring(ncp,
4019 ecp = state.indexOf("\"", ncp));
4020 // recover the new mapping data for this old filename
4021 // have to normalize filename - since Jmol and jalview do
4023 // translation differently.
4024 StructureData filedat = oldFiles.get(new File(oldfilenam));
4025 if (filedat == null)
4027 String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\");
4028 filedat = oldFiles.get(new File(reformatedOldFilename));
4030 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
4031 pdbfilenames.add(filedat.getFilePath());
4032 pdbids.add(filedat.getPdbId());
4033 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4034 newFileLoc.append("\"");
4035 cp = ecp + 1; // advance beyond last \" and set cursor so we can
4036 // look for next file statement.
4037 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
4041 // just append rest of state
4042 newFileLoc.append(state.substring(cp));
4046 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
4047 newFileLoc = new StringBuilder(state);
4048 newFileLoc.append("; load append ");
4049 for (File id : oldFiles.keySet())
4051 // add this and any other pdb files that should be present in
4053 StructureData filedat = oldFiles.get(id);
4054 newFileLoc.append(filedat.getFilePath());
4055 pdbfilenames.add(filedat.getFilePath());
4056 pdbids.add(filedat.getPdbId());
4057 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4058 newFileLoc.append(" \"");
4059 newFileLoc.append(filedat.getFilePath());
4060 newFileLoc.append("\"");
4063 newFileLoc.append(";");
4066 if (newFileLoc.length() == 0)
4070 int histbug = newFileLoc.indexOf("history = ");
4074 * change "history = [true|false];" to "history = [1|0];"
4077 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
4078 String val = (diff == -1) ? null : newFileLoc
4079 .substring(histbug, diff);
4080 if (val != null && val.length() >= 4)
4082 if (val.contains("e")) // eh? what can it be?
4084 if (val.trim().equals("true"))
4092 newFileLoc.replace(histbug, diff, val);
4097 final String[] pdbf = pdbfilenames.toArray(new String[pdbfilenames
4099 final String[] id = pdbids.toArray(new String[pdbids.size()]);
4100 final SequenceI[][] sq = seqmaps
4101 .toArray(new SequenceI[seqmaps.size()][]);
4102 final String fileloc = newFileLoc.toString();
4103 final String sviewid = viewerData.getKey();
4104 final AlignFrame alf = af;
4105 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
4106 svattrib.getWidth(), svattrib.getHeight());
4109 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
4114 JalviewStructureDisplayI sview = null;
4117 sview = new StructureViewer(alf.alignPanel
4118 .getStructureSelectionManager()).createView(
4119 StructureViewer.ViewerType.JMOL, pdbf, id, sq,
4120 alf.alignPanel, svattrib, fileloc, rect, sviewid);
4121 addNewStructureViewer(sview);
4122 } catch (OutOfMemoryError ex)
4124 new OOMWarning("restoring structure view for PDB id " + id,
4125 (OutOfMemoryError) ex.getCause());
4126 if (sview != null && sview.isVisible())
4128 sview.closeViewer(false);
4129 sview.setVisible(false);
4135 } catch (InvocationTargetException ex)
4137 warn("Unexpected error when opening Jmol view.", ex);
4139 } catch (InterruptedException e)
4141 // e.printStackTrace();
4147 * Generates a name for the entry in the project jar file to hold state
4148 * information for a structure viewer
4153 protected String getViewerJarEntryName(String viewId)
4155 return VIEWER_PREFIX + viewId;
4159 * Returns any open frame that matches given structure viewer data. The match
4160 * is based on the unique viewId, or (for older project versions) the frame's
4166 protected StructureViewerBase findMatchingViewer(
4167 Entry<String, StructureViewerModel> viewerData)
4169 final String sviewid = viewerData.getKey();
4170 final StructureViewerModel svattrib = viewerData.getValue();
4171 StructureViewerBase comp = null;
4172 JInternalFrame[] frames = getAllFrames();
4173 for (JInternalFrame frame : frames)
4175 if (frame instanceof StructureViewerBase)
4178 * Post jalview 2.4 schema includes structure view id
4181 && ((StructureViewerBase) frame).getViewId()
4184 comp = (StructureViewerBase) frame;
4185 break; // break added in 2.9
4188 * Otherwise test for matching position and size of viewer frame
4190 else if (frame.getX() == svattrib.getX()
4191 && frame.getY() == svattrib.getY()
4192 && frame.getHeight() == svattrib.getHeight()
4193 && frame.getWidth() == svattrib.getWidth())
4195 comp = (StructureViewerBase) frame;
4196 // no break in faint hope of an exact match on viewId
4204 * Link an AlignmentPanel to an existing structure viewer.
4209 * @param useinViewerSuperpos
4210 * @param usetoColourbyseq
4211 * @param viewerColouring
4213 protected void linkStructureViewer(AlignmentPanel ap,
4214 StructureViewerBase viewer, StructureViewerModel stateData)
4216 // NOTE: if the jalview project is part of a shared session then
4217 // view synchronization should/could be done here.
4219 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4220 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4221 final boolean viewerColouring = stateData.isColourByViewer();
4222 Map<File, StructureData> oldFiles = stateData.getFileData();
4225 * Add mapping for sequences in this view to an already open viewer
4227 final AAStructureBindingModel binding = viewer.getBinding();
4228 for (File id : oldFiles.keySet())
4230 // add this and any other pdb files that should be present in the
4232 StructureData filedat = oldFiles.get(id);
4233 String pdbFile = filedat.getFilePath();
4234 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4235 binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE);
4236 binding.addSequenceForStructFile(pdbFile, seq);
4238 // and add the AlignmentPanel's reference to the view panel
4239 viewer.addAlignmentPanel(ap);
4240 if (useinViewerSuperpos)
4242 viewer.useAlignmentPanelForSuperposition(ap);
4246 viewer.excludeAlignmentPanelForSuperposition(ap);
4248 if (usetoColourbyseq)
4250 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4254 viewer.excludeAlignmentPanelForColourbyseq(ap);
4259 * Get all frames within the Desktop.
4263 protected JInternalFrame[] getAllFrames()
4265 JInternalFrame[] frames = null;
4266 // TODO is this necessary - is it safe - risk of hanging?
4271 frames = Desktop.desktop.getAllFrames();
4272 } catch (ArrayIndexOutOfBoundsException e)
4274 // occasional No such child exceptions are thrown here...
4278 } catch (InterruptedException f)
4282 } while (frames == null);
4287 * Answers true if 'version' is equal to or later than 'supported', where each
4288 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4289 * changes. Development and test values for 'version' are leniently treated
4293 * - minimum version we are comparing against
4295 * - version of data being processsed
4298 public static boolean isVersionStringLaterThan(String supported,
4301 if (supported == null || version == null
4302 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4303 || version.equalsIgnoreCase("Test")
4304 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4306 System.err.println("Assuming project file with "
4307 + (version == null ? "null" : version)
4308 + " is compatible with Jalview version " + supported);
4313 return StringUtils.compareVersions(version, supported, "b") >= 0;
4317 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4319 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4321 if (newStructureViewers != null)
4323 sview.getBinding().setFinishedLoadingFromArchive(false);
4324 newStructureViewers.add(sview);
4328 protected void setLoadingFinishedForNewStructureViewers()
4330 if (newStructureViewers != null)
4332 for (JalviewStructureDisplayI sview : newStructureViewers)
4334 sview.getBinding().setFinishedLoadingFromArchive(true);
4336 newStructureViewers.clear();
4337 newStructureViewers = null;
4341 AlignFrame loadViewport(String file, JSeq[] JSEQ,
4342 List<SequenceI> hiddenSeqs, AlignmentI al,
4343 JalviewModelSequence jms, Viewport view, String uniqueSeqSetId,
4344 String viewId, List<JvAnnotRow> autoAlan)
4346 AlignFrame af = null;
4347 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
4348 uniqueSeqSetId, viewId);
4350 af.setFileName(file, FileFormat.Jalview);
4352 for (int i = 0; i < JSEQ.length; i++)
4354 af.viewport.setSequenceColour(af.viewport.getAlignment()
4355 .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour()));
4360 af.getViewport().setColourByReferenceSeq(true);
4361 af.getViewport().setDisplayReferenceSeq(true);
4364 af.viewport.setGatherViewsHere(view.getGatheredViews());
4366 if (view.getSequenceSetId() != null)
4368 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4370 af.viewport.setSequenceSetId(uniqueSeqSetId);
4373 // propagate shared settings to this new view
4374 af.viewport.setHistoryList(av.getHistoryList());
4375 af.viewport.setRedoList(av.getRedoList());
4379 viewportsAdded.put(uniqueSeqSetId, af.viewport);
4381 // TODO: check if this method can be called repeatedly without
4382 // side-effects if alignpanel already registered.
4383 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4385 // apply Hidden regions to view.
4386 if (hiddenSeqs != null)
4388 for (int s = 0; s < JSEQ.length; s++)
4390 SequenceGroup hidden = new SequenceGroup();
4391 boolean isRepresentative = false;
4392 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
4394 isRepresentative = true;
4395 SequenceI sequenceToHide = al.getSequenceAt(JSEQ[s]
4396 .getHiddenSequences(r));
4397 hidden.addSequence(sequenceToHide, false);
4398 // remove from hiddenSeqs list so we don't try to hide it twice
4399 hiddenSeqs.remove(sequenceToHide);
4401 if (isRepresentative)
4403 SequenceI representativeSequence = al.getSequenceAt(s);
4404 hidden.addSequence(representativeSequence, false);
4405 af.viewport.hideRepSequences(representativeSequence, hidden);
4409 SequenceI[] hseqs = hiddenSeqs.toArray(new SequenceI[hiddenSeqs
4411 af.viewport.hideSequence(hseqs);
4414 // recover view properties and display parameters
4415 if (view.getViewName() != null)
4417 af.viewport.viewName = view.getViewName();
4418 af.setInitialTabVisible();
4420 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
4423 af.viewport.setShowAnnotation(view.getShowAnnotation());
4424 af.viewport.setAbovePIDThreshold(view.getPidSelected());
4426 af.viewport.setColourText(view.getShowColourText());
4428 af.viewport.setConservationSelected(view.getConservationSelected());
4429 af.viewport.setShowJVSuffix(view.getShowFullId());
4430 af.viewport.setRightAlignIds(view.getRightAlignIds());
4431 af.viewport.setFont(
4432 new java.awt.Font(view.getFontName(), view.getFontStyle(), view
4433 .getFontSize()), true);
4434 ViewStyleI vs = af.viewport.getViewStyle();
4435 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
4436 af.viewport.setViewStyle(vs);
4437 // TODO: allow custom charWidth/Heights to be restored by updating them
4438 // after setting font - which means set above to false
4439 af.viewport.setRenderGaps(view.getRenderGaps());
4440 af.viewport.setWrapAlignment(view.getWrapAlignment());
4441 af.viewport.setShowAnnotation(view.getShowAnnotation());
4443 af.viewport.setShowBoxes(view.getShowBoxes());
4445 af.viewport.setShowText(view.getShowText());
4447 af.viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
4448 af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
4449 af.viewport.setThresholdTextColour(view.getTextColThreshold());
4450 af.viewport.setShowUnconserved(view.hasShowUnconserved() ? view
4451 .isShowUnconserved() : false);
4452 af.viewport.setStartRes(view.getStartRes());
4453 af.viewport.setStartSeq(view.getStartSeq());
4454 af.alignPanel.updateLayout();
4455 ColourSchemeI cs = null;
4456 // apply colourschemes
4457 if (view.getBgColour() != null)
4459 if (view.getBgColour().startsWith("ucs"))
4461 cs = getUserColourScheme(jms, view.getBgColour());
4463 else if (view.getBgColour().startsWith("Annotation"))
4465 AnnotationColours viewAnnColour = view.getAnnotationColours();
4466 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
4473 cs = ColourSchemeProperty.getColour(al, view.getBgColour());
4478 cs.setThreshold(view.getPidThreshold(), true);
4479 cs.setConsensus(af.viewport.getSequenceConsensusHash());
4483 af.viewport.setGlobalColourScheme(cs);
4484 af.viewport.setColourAppliesToAllGroups(false);
4486 if (view.getConservationSelected() && cs != null)
4488 cs.setConservationInc(view.getConsThreshold());
4491 af.changeColour(cs);
4493 af.viewport.setColourAppliesToAllGroups(true);
4495 af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures());
4497 if (view.hasCentreColumnLabels())
4499 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
4501 if (view.hasIgnoreGapsinConsensus())
4503 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
4506 if (view.hasFollowHighlight())
4508 af.viewport.setFollowHighlight(view.getFollowHighlight());
4510 if (view.hasFollowSelection())
4512 af.viewport.followSelection = view.getFollowSelection();
4514 if (view.hasShowConsensusHistogram())
4516 af.viewport.setShowConsensusHistogram(view
4517 .getShowConsensusHistogram());
4521 af.viewport.setShowConsensusHistogram(true);
4523 if (view.hasShowSequenceLogo())
4525 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
4529 af.viewport.setShowSequenceLogo(false);
4531 if (view.hasNormaliseSequenceLogo())
4533 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
4535 if (view.hasShowDbRefTooltip())
4537 af.viewport.setShowDBRefs(view.getShowDbRefTooltip());
4539 if (view.hasShowNPfeatureTooltip())
4541 af.viewport.setShowNPFeats(view.hasShowNPfeatureTooltip());
4543 if (view.hasShowGroupConsensus())
4545 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
4549 af.viewport.setShowGroupConsensus(false);
4551 if (view.hasShowGroupConservation())
4553 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
4557 af.viewport.setShowGroupConservation(false);
4560 // recover featre settings
4561 if (jms.getFeatureSettings() != null)
4563 FeaturesDisplayed fdi;
4564 af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
4565 String[] renderOrder = new String[jms.getFeatureSettings()
4566 .getSettingCount()];
4567 Map<String, FeatureColourI> featureColours = new Hashtable<String, FeatureColourI>();
4568 Map<String, Float> featureOrder = new Hashtable<String, Float>();
4570 for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
4572 Setting setting = jms.getFeatureSettings().getSetting(fs);
4573 if (setting.hasMincolour())
4575 FeatureColourI gc = setting.hasMin() ? new FeatureColour(
4576 new Color(setting.getMincolour()), new Color(
4577 setting.getColour()), setting.getMin(),
4578 setting.getMax()) : new FeatureColour(new Color(
4579 setting.getMincolour()), new Color(setting.getColour()),
4581 if (setting.hasThreshold())
4583 gc.setThreshold(setting.getThreshold());
4584 int threshstate = setting.getThreshstate();
4585 // -1 = None, 0 = Below, 1 = Above threshold
4586 if (threshstate == 0)
4588 gc.setBelowThreshold(true);
4590 else if (threshstate == 1)
4592 gc.setAboveThreshold(true);
4595 gc.setAutoScaled(true); // default
4596 if (setting.hasAutoScale())
4598 gc.setAutoScaled(setting.getAutoScale());
4600 if (setting.hasColourByLabel())
4602 gc.setColourByLabel(setting.getColourByLabel());
4604 // and put in the feature colour table.
4605 featureColours.put(setting.getType(), gc);
4609 featureColours.put(setting.getType(), new FeatureColour(
4610 new Color(setting.getColour())));
4612 renderOrder[fs] = setting.getType();
4613 if (setting.hasOrder())
4615 featureOrder.put(setting.getType(), setting.getOrder());
4619 featureOrder.put(setting.getType(), new Float(fs
4620 / jms.getFeatureSettings().getSettingCount()));
4622 if (setting.getDisplay())
4624 fdi.setVisible(setting.getType());
4627 Map<String, Boolean> fgtable = new Hashtable<String, Boolean>();
4628 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
4630 Group grp = jms.getFeatureSettings().getGroup(gs);
4631 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
4633 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4634 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
4635 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
4636 FeatureRendererSettings frs = new FeatureRendererSettings(
4637 renderOrder, fgtable, featureColours, 1.0f, featureOrder);
4638 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
4639 .transferSettings(frs);
4643 if (view.getHiddenColumnsCount() > 0)
4645 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
4647 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(), view
4648 .getHiddenColumns(c).getEnd() // +1
4652 if (view.getCalcIdParam() != null)
4654 for (CalcIdParam calcIdParam : view.getCalcIdParam())
4656 if (calcIdParam != null)
4658 if (recoverCalcIdParam(calcIdParam, af.viewport))
4663 warn("Couldn't recover parameters for "
4664 + calcIdParam.getCalcId());
4669 af.setMenusFromViewport(af.viewport);
4670 af.setTitle(view.getTitle());
4671 // TODO: we don't need to do this if the viewport is aready visible.
4673 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
4674 * has a 'cdna/protein complement' view, in which case save it in order to
4675 * populate a SplitFrame once all views have been read in.
4677 String complementaryViewId = view.getComplementId();
4678 if (complementaryViewId == null)
4680 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
4682 // recompute any autoannotation
4683 af.alignPanel.updateAnnotation(false, true);
4684 reorderAutoannotation(af, al, autoAlan);
4685 af.alignPanel.alignmentChanged();
4689 splitFrameCandidates.put(view, af);
4694 private ColourSchemeI constructAnnotationColour(
4695 AnnotationColours viewAnnColour, AlignFrame af, AlignmentI al,
4696 JalviewModelSequence jms, boolean checkGroupAnnColour)
4698 boolean propagateAnnColour = false;
4699 ColourSchemeI cs = null;
4700 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
4701 if (checkGroupAnnColour && al.getGroups() != null
4702 && al.getGroups().size() > 0)
4704 // pre 2.8.1 behaviour
4705 // check to see if we should transfer annotation colours
4706 propagateAnnColour = true;
4707 for (jalview.datamodel.SequenceGroup sg : al.getGroups())
4709 if (sg.cs instanceof AnnotationColourGradient)
4711 propagateAnnColour = false;
4715 // int find annotation
4716 if (annAlignment.getAlignmentAnnotation() != null)
4718 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
4720 if (annAlignment.getAlignmentAnnotation()[i].label
4721 .equals(viewAnnColour.getAnnotation()))
4723 if (annAlignment.getAlignmentAnnotation()[i].getThreshold() == null)
4725 annAlignment.getAlignmentAnnotation()[i]
4726 .setThreshold(new jalview.datamodel.GraphLine(
4727 viewAnnColour.getThreshold(), "Threshold",
4728 java.awt.Color.black)
4733 if (viewAnnColour.getColourScheme().equals("None"))
4735 cs = new AnnotationColourGradient(
4736 annAlignment.getAlignmentAnnotation()[i],
4737 new java.awt.Color(viewAnnColour.getMinColour()),
4738 new java.awt.Color(viewAnnColour.getMaxColour()),
4739 viewAnnColour.getAboveThreshold());
4741 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
4743 cs = new AnnotationColourGradient(
4744 annAlignment.getAlignmentAnnotation()[i],
4745 getUserColourScheme(jms,
4746 viewAnnColour.getColourScheme()),
4747 viewAnnColour.getAboveThreshold());
4751 cs = new AnnotationColourGradient(
4752 annAlignment.getAlignmentAnnotation()[i],
4753 ColourSchemeProperty.getColour(al,
4754 viewAnnColour.getColourScheme()),
4755 viewAnnColour.getAboveThreshold());
4757 if (viewAnnColour.hasPerSequence())
4759 ((AnnotationColourGradient) cs).setSeqAssociated(viewAnnColour
4762 if (viewAnnColour.hasPredefinedColours())
4764 ((AnnotationColourGradient) cs)
4765 .setPredefinedColours(viewAnnColour
4766 .isPredefinedColours());
4768 if (propagateAnnColour && al.getGroups() != null)
4770 // Also use these settings for all the groups
4771 for (int g = 0; g < al.getGroups().size(); g++)
4773 jalview.datamodel.SequenceGroup sg = al.getGroups().get(g);
4781 * if (viewAnnColour.getColourScheme().equals("None" )) { sg.cs =
4782 * new AnnotationColourGradient(
4783 * annAlignment.getAlignmentAnnotation()[i], new
4784 * java.awt.Color(viewAnnColour. getMinColour()), new
4785 * java.awt.Color(viewAnnColour. getMaxColour()),
4786 * viewAnnColour.getAboveThreshold()); } else
4789 sg.cs = new AnnotationColourGradient(
4790 annAlignment.getAlignmentAnnotation()[i], sg.cs,
4791 viewAnnColour.getAboveThreshold());
4792 if (cs instanceof AnnotationColourGradient)
4794 if (viewAnnColour.hasPerSequence())
4796 ((AnnotationColourGradient) cs)
4797 .setSeqAssociated(viewAnnColour.isPerSequence());
4799 if (viewAnnColour.hasPredefinedColours())
4801 ((AnnotationColourGradient) cs)
4802 .setPredefinedColours(viewAnnColour
4803 .isPredefinedColours());
4819 private void reorderAutoannotation(AlignFrame af, AlignmentI al,
4820 List<JvAnnotRow> autoAlan)
4822 // copy over visualization settings for autocalculated annotation in the
4824 if (al.getAlignmentAnnotation() != null)
4827 * Kludge for magic autoannotation names (see JAL-811)
4829 String[] magicNames = new String[] { "Consensus", "Quality",
4831 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
4832 Hashtable<String, JvAnnotRow> visan = new Hashtable<String, JvAnnotRow>();
4833 for (String nm : magicNames)
4835 visan.put(nm, nullAnnot);
4837 for (JvAnnotRow auan : autoAlan)
4839 visan.put(auan.template.label
4840 + (auan.template.getCalcId() == null ? "" : "\t"
4841 + auan.template.getCalcId()), auan);
4843 int hSize = al.getAlignmentAnnotation().length;
4844 List<JvAnnotRow> reorder = new ArrayList<JvAnnotRow>();
4845 // work through any autoCalculated annotation already on the view
4846 // removing it if it should be placed in a different location on the
4847 // annotation panel.
4848 List<String> remains = new ArrayList<String>(visan.keySet());
4849 for (int h = 0; h < hSize; h++)
4851 jalview.datamodel.AlignmentAnnotation jalan = al
4852 .getAlignmentAnnotation()[h];
4853 if (jalan.autoCalculated)
4856 JvAnnotRow valan = visan.get(k = jalan.label);
4857 if (jalan.getCalcId() != null)
4859 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
4864 // delete the auto calculated row from the alignment
4865 al.deleteAnnotation(jalan, false);
4869 if (valan != nullAnnot)
4871 if (jalan != valan.template)
4873 // newly created autoannotation row instance
4874 // so keep a reference to the visible annotation row
4875 // and copy over all relevant attributes
4876 if (valan.template.graphHeight >= 0)
4879 jalan.graphHeight = valan.template.graphHeight;
4881 jalan.visible = valan.template.visible;
4883 reorder.add(new JvAnnotRow(valan.order, jalan));
4888 // Add any (possibly stale) autocalculated rows that were not appended to
4889 // the view during construction
4890 for (String other : remains)
4892 JvAnnotRow othera = visan.get(other);
4893 if (othera != nullAnnot && othera.template.getCalcId() != null
4894 && othera.template.getCalcId().length() > 0)
4896 reorder.add(othera);
4899 // now put the automatic annotation in its correct place
4900 int s = 0, srt[] = new int[reorder.size()];
4901 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
4902 for (JvAnnotRow jvar : reorder)
4905 srt[s++] = jvar.order;
4908 jalview.util.QuickSort.sort(srt, rws);
4909 // and re-insert the annotation at its correct position
4910 for (JvAnnotRow jvar : rws)
4912 al.addAnnotation(jvar.template, jvar.order);
4914 af.alignPanel.adjustAnnotationHeight();
4918 Hashtable skipList = null;
4921 * TODO remove this method
4924 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
4925 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
4926 * throw new Error("Implementation Error. No skipList defined for this
4927 * Jalview2XML instance."); } return (AlignFrame)
4928 * skipList.get(view.getSequenceSetId()); }
4932 * Check if the Jalview view contained in object should be skipped or not.
4935 * @return true if view's sequenceSetId is a key in skipList
4937 private boolean skipViewport(JalviewModel object)
4939 if (skipList == null)
4944 if (skipList.containsKey(id = object.getJalviewModelSequence()
4945 .getViewport()[0].getSequenceSetId()))
4947 if (Cache.log != null && Cache.log.isDebugEnabled())
4949 Cache.log.debug("Skipping seuqence set id " + id);
4956 public void addToSkipList(AlignFrame af)
4958 if (skipList == null)
4960 skipList = new Hashtable();
4962 skipList.put(af.getViewport().getSequenceSetId(), af);
4965 public void clearSkipList()
4967 if (skipList != null)
4974 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
4975 boolean ignoreUnrefed)
4977 jalview.datamodel.AlignmentI ds = getDatasetFor(vamsasSet
4979 Vector dseqs = null;
4982 // create a list of new dataset sequences
4983 dseqs = new Vector();
4985 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
4987 Sequence vamsasSeq = vamsasSet.getSequence(i);
4988 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
4990 // create a new dataset
4993 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
4994 dseqs.copyInto(dsseqs);
4995 ds = new jalview.datamodel.Alignment(dsseqs);
4996 debug("Created new dataset " + vamsasSet.getDatasetId()
4997 + " for alignment " + System.identityHashCode(al));
4998 addDatasetRef(vamsasSet.getDatasetId(), ds);
5000 // set the dataset for the newly imported alignment.
5001 if (al.getDataset() == null && !ignoreUnrefed)
5010 * sequence definition to create/merge dataset sequence for
5014 * vector to add new dataset sequence to
5015 * @param ignoreUnrefed
5016 * - when true, don't create new sequences from vamsasSeq if it's id
5017 * doesn't already have an asssociated Jalview sequence.
5019 * - used to reorder the sequence in the alignment according to the
5020 * vamsasSeq array ordering, to preserve ordering of dataset
5022 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
5023 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed, int vseqpos)
5025 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
5027 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
5028 boolean reorder = false;
5029 SequenceI dsq = null;
5030 if (sq != null && sq.getDatasetSequence() != null)
5032 dsq = sq.getDatasetSequence();
5038 if (sq == null && ignoreUnrefed)
5042 String sqid = vamsasSeq.getDsseqid();
5045 // need to create or add a new dataset sequence reference to this sequence
5048 dsq = seqRefIds.get(sqid);
5053 // make a new dataset sequence
5054 dsq = sq.createDatasetSequence();
5057 // make up a new dataset reference for this sequence
5058 sqid = seqHash(dsq);
5060 dsq.setVamsasId(uniqueSetSuffix + sqid);
5061 seqRefIds.put(sqid, dsq);
5066 dseqs.addElement(dsq);
5071 ds.addSequence(dsq);
5077 { // make this dataset sequence sq's dataset sequence
5078 sq.setDatasetSequence(dsq);
5079 // and update the current dataset alignment
5084 if (!dseqs.contains(dsq))
5091 if (ds.findIndex(dsq) < 0)
5093 ds.addSequence(dsq);
5100 // TODO: refactor this as a merge dataset sequence function
5101 // now check that sq (the dataset sequence) sequence really is the union of
5102 // all references to it
5103 // boolean pre = sq.getStart() < dsq.getStart();
5104 // boolean post = sq.getEnd() > dsq.getEnd();
5108 // StringBuffer sb = new StringBuffer();
5109 String newres = jalview.analysis.AlignSeq.extractGaps(
5110 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
5111 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
5112 && newres.length() > dsq.getLength())
5114 // Update with the longer sequence.
5118 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
5119 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
5120 * sb.append(newres.substring(newres.length() - sq.getEnd() -
5121 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
5123 dsq.setSequence(newres);
5125 // TODO: merges will never happen if we 'know' we have the real dataset
5126 // sequence - this should be detected when id==dssid
5128 .println("DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
5129 // + (pre ? "prepended" : "") + " "
5130 // + (post ? "appended" : ""));
5135 // sequence refs are identical. We may need to update the existing dataset
5136 // alignment with this one, though.
5137 if (ds != null && dseqs == null)
5139 int opos = ds.findIndex(dsq);
5140 SequenceI tseq = null;
5141 if (opos != -1 && vseqpos != opos)
5143 // remove from old position
5144 ds.deleteSequence(dsq);
5146 if (vseqpos < ds.getHeight())
5148 if (vseqpos != opos)
5150 // save sequence at destination position
5151 tseq = ds.getSequenceAt(vseqpos);
5152 ds.replaceSequenceAt(vseqpos, dsq);
5153 ds.addSequence(tseq);
5158 ds.addSequence(dsq);
5165 * TODO use AlignmentI here and in related methods - needs
5166 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
5168 Hashtable<String, AlignmentI> datasetIds = null;
5170 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
5172 private AlignmentI getDatasetFor(String datasetId)
5174 if (datasetIds == null)
5176 datasetIds = new Hashtable<String, AlignmentI>();
5179 if (datasetIds.containsKey(datasetId))
5181 return datasetIds.get(datasetId);
5186 private void addDatasetRef(String datasetId, AlignmentI dataset)
5188 if (datasetIds == null)
5190 datasetIds = new Hashtable<String, AlignmentI>();
5192 datasetIds.put(datasetId, dataset);
5196 * make a new dataset ID for this jalview dataset alignment
5201 private String getDatasetIdRef(AlignmentI dataset)
5203 if (dataset.getDataset() != null)
5205 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
5207 String datasetId = makeHashCode(dataset, null);
5208 if (datasetId == null)
5210 // make a new datasetId and record it
5211 if (dataset2Ids == null)
5213 dataset2Ids = new IdentityHashMap<AlignmentI, String>();
5217 datasetId = dataset2Ids.get(dataset);
5219 if (datasetId == null)
5221 datasetId = "ds" + dataset2Ids.size() + 1;
5222 dataset2Ids.put(dataset, datasetId);
5228 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5230 for (int d = 0; d < sequence.getDBRefCount(); d++)
5232 DBRef dr = sequence.getDBRef(d);
5233 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
5234 sequence.getDBRef(d).getSource(), sequence.getDBRef(d)
5235 .getVersion(), sequence.getDBRef(d).getAccessionId());
5236 if (dr.getMapping() != null)
5238 entry.setMap(addMapping(dr.getMapping()));
5240 datasetSequence.addDBRef(entry);
5244 private jalview.datamodel.Mapping addMapping(Mapping m)
5246 SequenceI dsto = null;
5247 // Mapping m = dr.getMapping();
5248 int fr[] = new int[m.getMapListFromCount() * 2];
5249 Enumeration f = m.enumerateMapListFrom();
5250 for (int _i = 0; f.hasMoreElements(); _i += 2)
5252 MapListFrom mf = (MapListFrom) f.nextElement();
5253 fr[_i] = mf.getStart();
5254 fr[_i + 1] = mf.getEnd();
5256 int fto[] = new int[m.getMapListToCount() * 2];
5257 f = m.enumerateMapListTo();
5258 for (int _i = 0; f.hasMoreElements(); _i += 2)
5260 MapListTo mf = (MapListTo) f.nextElement();
5261 fto[_i] = mf.getStart();
5262 fto[_i + 1] = mf.getEnd();
5264 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto,
5265 fr, fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
5266 if (m.getMappingChoice() != null)
5268 MappingChoice mc = m.getMappingChoice();
5269 if (mc.getDseqFor() != null)
5271 String dsfor = "" + mc.getDseqFor();
5272 if (seqRefIds.containsKey(dsfor))
5277 jmap.setTo(seqRefIds.get(dsfor));
5281 frefedSequence.add(newMappingRef(dsfor, jmap));
5287 * local sequence definition
5289 Sequence ms = mc.getSequence();
5290 SequenceI djs = null;
5291 String sqid = ms.getDsseqid();
5292 if (sqid != null && sqid.length() > 0)
5295 * recover dataset sequence
5297 djs = seqRefIds.get(sqid);
5302 .println("Warning - making up dataset sequence id for DbRef sequence map reference");
5303 sqid = ((Object) ms).toString(); // make up a new hascode for
5304 // undefined dataset sequence hash
5305 // (unlikely to happen)
5311 * make a new dataset sequence and add it to refIds hash
5313 djs = new jalview.datamodel.Sequence(ms.getName(),
5315 djs.setStart(jmap.getMap().getToLowest());
5316 djs.setEnd(jmap.getMap().getToHighest());
5317 djs.setVamsasId(uniqueSetSuffix + sqid);
5319 incompleteSeqs.put(sqid, djs);
5320 seqRefIds.put(sqid, djs);
5323 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5332 public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
5333 boolean keepSeqRefs)
5336 JalviewModel jm = saveState(ap, null, null, null);
5341 jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
5345 uniqueSetSuffix = "";
5346 jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
5351 if (this.frefedSequence == null)
5353 frefedSequence = new Vector();
5356 viewportsAdded.clear();
5358 AlignFrame af = loadFromObject(jm, null, false, null);
5359 af.alignPanels.clear();
5360 af.closeMenuItem_actionPerformed(true);
5363 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5364 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5365 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5366 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5367 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5370 return af.alignPanel;
5374 * flag indicating if hashtables should be cleared on finalization TODO this
5375 * flag may not be necessary
5377 private final boolean _cleartables = true;
5379 private Hashtable jvids2vobj;
5384 * @see java.lang.Object#finalize()
5387 protected void finalize() throws Throwable
5389 // really make sure we have no buried refs left.
5394 this.seqRefIds = null;
5395 this.seqsToIds = null;
5399 private void warn(String msg)
5404 private void warn(String msg, Exception e)
5406 if (Cache.log != null)
5410 Cache.log.warn(msg, e);
5414 Cache.log.warn(msg);
5419 System.err.println("Warning: " + msg);
5422 e.printStackTrace();
5427 private void debug(String string)
5429 debug(string, null);
5432 private void debug(String msg, Exception e)
5434 if (Cache.log != null)
5438 Cache.log.debug(msg, e);
5442 Cache.log.debug(msg);
5447 System.err.println("Warning: " + msg);
5450 e.printStackTrace();
5456 * set the object to ID mapping tables used to write/recover objects and XML
5457 * ID strings for the jalview project. If external tables are provided then
5458 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
5459 * object goes out of scope. - also populates the datasetIds hashtable with
5460 * alignment objects containing dataset sequences
5463 * Map from ID strings to jalview datamodel
5465 * Map from jalview datamodel to ID strings
5469 public void setObjectMappingTables(Hashtable vobj2jv,
5470 IdentityHashMap jv2vobj)
5472 this.jv2vobj = jv2vobj;
5473 this.vobj2jv = vobj2jv;
5474 Iterator ds = jv2vobj.keySet().iterator();
5476 while (ds.hasNext())
5478 Object jvobj = ds.next();
5479 id = jv2vobj.get(jvobj).toString();
5480 if (jvobj instanceof jalview.datamodel.Alignment)
5482 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
5484 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
5487 else if (jvobj instanceof jalview.datamodel.Sequence)
5489 // register sequence object so the XML parser can recover it.
5490 if (seqRefIds == null)
5492 seqRefIds = new HashMap<String, SequenceI>();
5494 if (seqsToIds == null)
5496 seqsToIds = new IdentityHashMap<SequenceI, String>();
5498 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
5499 seqsToIds.put((SequenceI) jvobj, id);
5501 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
5504 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
5505 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
5506 if (jvann.annotationId == null)
5508 jvann.annotationId = anid;
5510 if (!jvann.annotationId.equals(anid))
5512 // TODO verify that this is the correct behaviour
5513 this.warn("Overriding Annotation ID for " + anid
5514 + " from different id : " + jvann.annotationId);
5515 jvann.annotationId = anid;
5518 else if (jvobj instanceof String)
5520 if (jvids2vobj == null)
5522 jvids2vobj = new Hashtable();
5523 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
5528 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
5534 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
5535 * objects created from the project archive. If string is null (default for
5536 * construction) then suffix will be set automatically.
5540 public void setUniqueSetSuffix(String string)
5542 uniqueSetSuffix = string;
5547 * uses skipList2 as the skipList for skipping views on sequence sets
5548 * associated with keys in the skipList
5552 public void setSkipList(Hashtable skipList2)
5554 skipList = skipList2;
5558 * Reads the jar entry of given name and returns its contents, or null if the
5559 * entry is not found.
5562 * @param jarEntryName
5565 protected String readJarEntry(jarInputStreamProvider jprovider,
5566 String jarEntryName)
5568 String result = null;
5569 BufferedReader in = null;
5574 * Reopen the jar input stream and traverse its entries to find a matching
5577 JarInputStream jin = jprovider.getJarInputStream();
5578 JarEntry entry = null;
5581 entry = jin.getNextJarEntry();
5582 } while (entry != null && !entry.getName().equals(jarEntryName));
5586 StringBuilder out = new StringBuilder(256);
5587 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
5590 while ((data = in.readLine()) != null)
5594 result = out.toString();
5598 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
5600 } catch (Exception ex)
5602 ex.printStackTrace();
5610 } catch (IOException e)
5621 * Returns an incrementing counter (0, 1, 2...)
5625 private synchronized int nextCounter()