2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import jalview.analysis.Conservation;
24 import jalview.api.FeatureColourI;
25 import jalview.api.ViewStyleI;
26 import jalview.api.structures.JalviewStructureDisplayI;
27 import jalview.bin.Cache;
28 import jalview.datamodel.AlignedCodonFrame;
29 import jalview.datamodel.Alignment;
30 import jalview.datamodel.AlignmentAnnotation;
31 import jalview.datamodel.AlignmentI;
32 import jalview.datamodel.GraphLine;
33 import jalview.datamodel.PDBEntry;
34 import jalview.datamodel.RnaViewerModel;
35 import jalview.datamodel.SequenceFeature;
36 import jalview.datamodel.SequenceGroup;
37 import jalview.datamodel.SequenceI;
38 import jalview.datamodel.StructureViewerModel;
39 import jalview.datamodel.StructureViewerModel.StructureData;
40 import jalview.ext.varna.RnaModel;
41 import jalview.gui.StructureViewer.ViewerType;
42 import jalview.io.DataSourceType;
43 import jalview.io.FileFormat;
44 import jalview.renderer.ResidueShaderI;
45 import jalview.schemabinding.version2.AlcodMap;
46 import jalview.schemabinding.version2.AlcodonFrame;
47 import jalview.schemabinding.version2.Annotation;
48 import jalview.schemabinding.version2.AnnotationColours;
49 import jalview.schemabinding.version2.AnnotationElement;
50 import jalview.schemabinding.version2.CalcIdParam;
51 import jalview.schemabinding.version2.DBRef;
52 import jalview.schemabinding.version2.Features;
53 import jalview.schemabinding.version2.Group;
54 import jalview.schemabinding.version2.HiddenColumns;
55 import jalview.schemabinding.version2.JGroup;
56 import jalview.schemabinding.version2.JSeq;
57 import jalview.schemabinding.version2.JalviewModel;
58 import jalview.schemabinding.version2.JalviewModelSequence;
59 import jalview.schemabinding.version2.MapListFrom;
60 import jalview.schemabinding.version2.MapListTo;
61 import jalview.schemabinding.version2.Mapping;
62 import jalview.schemabinding.version2.MappingChoice;
63 import jalview.schemabinding.version2.OtherData;
64 import jalview.schemabinding.version2.PdbentryItem;
65 import jalview.schemabinding.version2.Pdbids;
66 import jalview.schemabinding.version2.Property;
67 import jalview.schemabinding.version2.RnaViewer;
68 import jalview.schemabinding.version2.SecondaryStructure;
69 import jalview.schemabinding.version2.Sequence;
70 import jalview.schemabinding.version2.SequenceSet;
71 import jalview.schemabinding.version2.SequenceSetProperties;
72 import jalview.schemabinding.version2.Setting;
73 import jalview.schemabinding.version2.StructureState;
74 import jalview.schemabinding.version2.ThresholdLine;
75 import jalview.schemabinding.version2.Tree;
76 import jalview.schemabinding.version2.UserColours;
77 import jalview.schemabinding.version2.Viewport;
78 import jalview.schemes.AnnotationColourGradient;
79 import jalview.schemes.ColourSchemeI;
80 import jalview.schemes.ColourSchemeProperty;
81 import jalview.schemes.FeatureColour;
82 import jalview.schemes.ResidueProperties;
83 import jalview.schemes.UserColourScheme;
84 import jalview.structure.StructureSelectionManager;
85 import jalview.structures.models.AAStructureBindingModel;
86 import jalview.util.MessageManager;
87 import jalview.util.Platform;
88 import jalview.util.StringUtils;
89 import jalview.util.jarInputStreamProvider;
90 import jalview.viewmodel.AlignmentViewport;
91 import jalview.viewmodel.ViewportRanges;
92 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
93 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
94 import jalview.ws.jws2.Jws2Discoverer;
95 import jalview.ws.jws2.dm.AAConSettings;
96 import jalview.ws.jws2.jabaws2.Jws2Instance;
97 import jalview.ws.params.ArgumentI;
98 import jalview.ws.params.AutoCalcSetting;
99 import jalview.ws.params.WsParamSetI;
101 import java.awt.Color;
102 import java.awt.Rectangle;
103 import java.io.BufferedReader;
104 import java.io.DataInputStream;
105 import java.io.DataOutputStream;
107 import java.io.FileInputStream;
108 import java.io.FileOutputStream;
109 import java.io.IOException;
110 import java.io.InputStreamReader;
111 import java.io.OutputStreamWriter;
112 import java.io.PrintWriter;
113 import java.lang.reflect.InvocationTargetException;
114 import java.net.MalformedURLException;
116 import java.util.ArrayList;
117 import java.util.Arrays;
118 import java.util.Enumeration;
119 import java.util.HashMap;
120 import java.util.HashSet;
121 import java.util.Hashtable;
122 import java.util.IdentityHashMap;
123 import java.util.Iterator;
124 import java.util.LinkedHashMap;
125 import java.util.List;
126 import java.util.Map;
127 import java.util.Map.Entry;
128 import java.util.Set;
129 import java.util.Vector;
130 import java.util.jar.JarEntry;
131 import java.util.jar.JarInputStream;
132 import java.util.jar.JarOutputStream;
134 import javax.swing.JInternalFrame;
135 import javax.swing.SwingUtilities;
137 import org.exolab.castor.xml.Marshaller;
138 import org.exolab.castor.xml.Unmarshaller;
141 * Write out the current jalview desktop state as a Jalview XML stream.
143 * Note: the vamsas objects referred to here are primitive versions of the
144 * VAMSAS project schema elements - they are not the same and most likely never
148 * @version $Revision: 1.134 $
150 public class Jalview2XML
152 private static final String VIEWER_PREFIX = "viewer_";
154 private static final String RNA_PREFIX = "rna_";
156 private static final String UTF_8 = "UTF-8";
158 // use this with nextCounter() to make unique names for entities
159 private int counter = 0;
162 * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
163 * of sequence objects are created.
165 IdentityHashMap<SequenceI, String> seqsToIds = null;
168 * jalview XML Sequence ID to jalview sequence object reference (both dataset
169 * and alignment sequences. Populated as XML reps of sequence objects are
172 Map<String, SequenceI> seqRefIds = null;
174 Map<String, SequenceI> incompleteSeqs = null;
176 List<SeqFref> frefedSequence = null;
178 boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
181 * Map of reconstructed AlignFrame objects that appear to have come from
182 * SplitFrame objects (have a dna/protein complement view).
184 private Map<Viewport, AlignFrame> splitFrameCandidates = new HashMap<Viewport, AlignFrame>();
187 * Map from displayed rna structure models to their saved session state jar
190 private Map<RnaModel, String> rnaSessions = new HashMap<RnaModel, String>();
193 * create/return unique hash string for sq
196 * @return new or existing unique string for sq
198 String seqHash(SequenceI sq)
200 if (seqsToIds == null)
204 if (seqsToIds.containsKey(sq))
206 return seqsToIds.get(sq);
210 // create sequential key
211 String key = "sq" + (seqsToIds.size() + 1);
212 key = makeHashCode(sq, key); // check we don't have an external reference
214 seqsToIds.put(sq, key);
223 if (seqRefIds != null)
227 if (seqsToIds != null)
231 if (incompleteSeqs != null)
233 incompleteSeqs.clear();
241 warn("clearSeqRefs called when _cleartables was not set. Doing nothing.");
242 // seqRefIds = new Hashtable();
243 // seqsToIds = new IdentityHashMap();
249 if (seqsToIds == null)
251 seqsToIds = new IdentityHashMap<SequenceI, String>();
253 if (seqRefIds == null)
255 seqRefIds = new HashMap<String, SequenceI>();
257 if (incompleteSeqs == null)
259 incompleteSeqs = new HashMap<String, SequenceI>();
261 if (frefedSequence == null)
263 frefedSequence = new ArrayList<SeqFref>();
271 public Jalview2XML(boolean raiseGUI)
273 this.raiseGUI = raiseGUI;
277 * base class for resolving forward references to sequences by their ID
282 abstract class SeqFref
288 public SeqFref(String _sref, String type)
294 public String getSref()
299 public SequenceI getSrefSeq()
301 return seqRefIds.get(sref);
304 public boolean isResolvable()
306 return seqRefIds.get(sref) != null;
309 public SequenceI getSrefDatasetSeq()
311 SequenceI sq = seqRefIds.get(sref);
314 while (sq.getDatasetSequence() != null)
316 sq = sq.getDatasetSequence();
323 * @return true if the forward reference was fully resolved
325 abstract boolean resolve();
328 public String toString()
330 return type + " reference to " + sref;
335 * create forward reference for a mapping
341 public SeqFref newMappingRef(final String sref,
342 final jalview.datamodel.Mapping _jmap)
344 SeqFref fref = new SeqFref(sref, "Mapping")
346 public jalview.datamodel.Mapping jmap = _jmap;
351 SequenceI seq = getSrefDatasetSeq();
363 public SeqFref newAlcodMapRef(final String sref,
364 final AlignedCodonFrame _cf, final jalview.datamodel.Mapping _jmap)
367 SeqFref fref = new SeqFref(sref, "Codon Frame")
369 AlignedCodonFrame cf = _cf;
371 public jalview.datamodel.Mapping mp = _jmap;
374 public boolean isResolvable()
376 return super.isResolvable() && mp.getTo() != null;
382 SequenceI seq = getSrefDatasetSeq();
387 cf.addMap(seq, mp.getTo(), mp.getMap());
394 public void resolveFrefedSequences()
396 Iterator<SeqFref> nextFref = frefedSequence.iterator();
397 int toresolve = frefedSequence.size();
398 int unresolved = 0, failedtoresolve = 0;
399 while (nextFref.hasNext())
401 SeqFref ref = nextFref.next();
402 if (ref.isResolvable())
414 } catch (Exception x)
417 .println("IMPLEMENTATION ERROR: Failed to resolve forward reference for sequence "
430 System.err.println("Jalview Project Import: There were " + unresolved
431 + " forward references left unresolved on the stack.");
433 if (failedtoresolve > 0)
435 System.err.println("SERIOUS! " + failedtoresolve
436 + " resolvable forward references failed to resolve.");
438 if (incompleteSeqs != null && incompleteSeqs.size() > 0)
440 System.err.println("Jalview Project Import: There are "
441 + incompleteSeqs.size()
442 + " sequences which may have incomplete metadata.");
443 if (incompleteSeqs.size() < 10)
445 for (SequenceI s : incompleteSeqs.values())
447 System.err.println(s.toString());
453 .println("Too many to report. Skipping output of incomplete sequences.");
459 * This maintains a map of viewports, the key being the seqSetId. Important to
460 * set historyItem and redoList for multiple views
462 Map<String, AlignViewport> viewportsAdded = new HashMap<String, AlignViewport>();
464 Map<String, AlignmentAnnotation> annotationIds = new HashMap<String, AlignmentAnnotation>();
466 String uniqueSetSuffix = "";
469 * List of pdbfiles added to Jar
471 List<String> pdbfiles = null;
473 // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
474 public void saveState(File statefile)
476 FileOutputStream fos = null;
479 fos = new FileOutputStream(statefile);
480 JarOutputStream jout = new JarOutputStream(fos);
483 } catch (Exception e)
485 // TODO: inform user of the problem - they need to know if their data was
487 if (errorMessage == null)
489 errorMessage = "Couldn't write Jalview Archive to output file '"
490 + statefile + "' - See console error log for details";
494 errorMessage += "(output file was '" + statefile + "')";
504 } catch (IOException e)
514 * Writes a jalview project archive to the given Jar output stream.
518 public void saveState(JarOutputStream jout)
520 AlignFrame[] frames = Desktop.getAlignFrames();
526 saveAllFrames(Arrays.asList(frames), jout);
530 * core method for storing state for a set of AlignFrames.
533 * - frames involving all data to be exported (including containing
536 * - project output stream
538 private void saveAllFrames(List<AlignFrame> frames, JarOutputStream jout)
540 Hashtable<String, AlignFrame> dsses = new Hashtable<String, AlignFrame>();
543 * ensure cached data is clear before starting
545 // todo tidy up seqRefIds, seqsToIds initialisation / reset
547 splitFrameCandidates.clear();
552 // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
553 // //////////////////////////////////////////////////
555 List<String> shortNames = new ArrayList<String>();
556 List<String> viewIds = new ArrayList<String>();
559 for (int i = frames.size() - 1; i > -1; i--)
561 AlignFrame af = frames.get(i);
565 .containsKey(af.getViewport().getSequenceSetId()))
570 String shortName = makeFilename(af, shortNames);
572 int ap, apSize = af.alignPanels.size();
574 for (ap = 0; ap < apSize; ap++)
576 AlignmentPanel apanel = af.alignPanels.get(ap);
577 String fileName = apSize == 1 ? shortName : ap + shortName;
578 if (!fileName.endsWith(".xml"))
580 fileName = fileName + ".xml";
583 saveState(apanel, fileName, jout, viewIds);
585 String dssid = getDatasetIdRef(af.getViewport().getAlignment()
587 if (!dsses.containsKey(dssid))
589 dsses.put(dssid, af);
594 writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix,
600 } catch (Exception foo)
605 } catch (Exception ex)
607 // TODO: inform user of the problem - they need to know if their data was
609 if (errorMessage == null)
611 errorMessage = "Couldn't write Jalview Archive - see error output for details";
613 ex.printStackTrace();
618 * Generates a distinct file name, based on the title of the AlignFrame, by
619 * appending _n for increasing n until an unused name is generated. The new
620 * name (without its extension) is added to the list.
624 * @return the generated name, with .xml extension
626 protected String makeFilename(AlignFrame af, List<String> namesUsed)
628 String shortName = af.getTitle();
630 if (shortName.indexOf(File.separatorChar) > -1)
632 shortName = shortName.substring(shortName
633 .lastIndexOf(File.separatorChar) + 1);
638 while (namesUsed.contains(shortName))
640 if (shortName.endsWith("_" + (count - 1)))
642 shortName = shortName.substring(0, shortName.lastIndexOf("_"));
645 shortName = shortName.concat("_" + count);
649 namesUsed.add(shortName);
651 if (!shortName.endsWith(".xml"))
653 shortName = shortName + ".xml";
658 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
659 public boolean saveAlignment(AlignFrame af, String jarFile,
664 FileOutputStream fos = new FileOutputStream(jarFile);
665 JarOutputStream jout = new JarOutputStream(fos);
666 List<AlignFrame> frames = new ArrayList<AlignFrame>();
668 // resolve splitframes
669 if (af.getViewport().getCodingComplement() != null)
671 frames = ((SplitFrame) af.getSplitViewContainer()).getAlignFrames();
677 saveAllFrames(frames, jout);
681 } catch (Exception foo)
687 } catch (Exception ex)
689 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
690 ex.printStackTrace();
695 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
696 String fileName, JarOutputStream jout)
699 for (String dssids : dsses.keySet())
701 AlignFrame _af = dsses.get(dssids);
702 String jfileName = fileName + " Dataset for " + _af.getTitle();
703 if (!jfileName.endsWith(".xml"))
705 jfileName = jfileName + ".xml";
707 saveState(_af.alignPanel, jfileName, true, jout, null);
712 * create a JalviewModel from an alignment view and marshall it to a
716 * panel to create jalview model for
718 * name of alignment panel written to output stream
725 public JalviewModel saveState(AlignmentPanel ap, String fileName,
726 JarOutputStream jout, List<String> viewIds)
728 return saveState(ap, fileName, false, jout, viewIds);
732 * create a JalviewModel from an alignment view and marshall it to a
736 * panel to create jalview model for
738 * name of alignment panel written to output stream
740 * when true, only write the dataset for the alignment, not the data
741 * associated with the view.
747 public JalviewModel saveState(AlignmentPanel ap, String fileName,
748 boolean storeDS, JarOutputStream jout, List<String> viewIds)
752 viewIds = new ArrayList<String>();
757 List<UserColourScheme> userColours = new ArrayList<UserColourScheme>();
759 AlignViewport av = ap.av;
760 ViewportRanges vpRanges = av.getRanges();
762 JalviewModel object = new JalviewModel();
763 object.setVamsasModel(new jalview.schemabinding.version2.VamsasModel());
765 object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
766 object.setVersion(jalview.bin.Cache.getDefault("VERSION",
767 "Development Build"));
770 * rjal is full height alignment, jal is actual alignment with full metadata
771 * but excludes hidden sequences.
773 jalview.datamodel.AlignmentI rjal = av.getAlignment(), jal = rjal;
775 if (av.hasHiddenRows())
777 rjal = jal.getHiddenSequences().getFullAlignment();
780 SequenceSet vamsasSet = new SequenceSet();
782 JalviewModelSequence jms = new JalviewModelSequence();
784 vamsasSet.setGapChar(jal.getGapCharacter() + "");
786 if (jal.getDataset() != null)
788 // dataset id is the dataset's hashcode
789 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
792 // switch jal and the dataset
793 jal = jal.getDataset();
797 if (jal.getProperties() != null)
799 Enumeration en = jal.getProperties().keys();
800 while (en.hasMoreElements())
802 String key = en.nextElement().toString();
803 SequenceSetProperties ssp = new SequenceSetProperties();
805 ssp.setValue(jal.getProperties().get(key).toString());
806 vamsasSet.addSequenceSetProperties(ssp);
811 Set<String> calcIdSet = new HashSet<String>();
812 // record the set of vamsas sequence XML POJO we create.
813 HashMap<String, Sequence> vamsasSetIds = new HashMap<String, Sequence>();
815 for (final SequenceI jds : rjal.getSequences())
817 final SequenceI jdatasq = jds.getDatasetSequence() == null ? jds
818 : jds.getDatasetSequence();
819 String id = seqHash(jds);
820 if (vamsasSetIds.get(id) == null)
822 if (seqRefIds.get(id) != null && !storeDS)
824 // This happens for two reasons: 1. multiple views are being
826 // 2. the hashCode has collided with another sequence's code. This
828 // HAPPEN! (PF00072.15.stk does this)
829 // JBPNote: Uncomment to debug writing out of files that do not read
830 // back in due to ArrayOutOfBoundExceptions.
831 // System.err.println("vamsasSeq backref: "+id+"");
832 // System.err.println(jds.getName()+"
833 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
834 // System.err.println("Hashcode: "+seqHash(jds));
835 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
836 // System.err.println(rsq.getName()+"
837 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
838 // System.err.println("Hashcode: "+seqHash(rsq));
842 vamsasSeq = createVamsasSequence(id, jds);
843 vamsasSet.addSequence(vamsasSeq);
844 vamsasSetIds.put(id, vamsasSeq);
845 seqRefIds.put(id, jds);
849 jseq.setStart(jds.getStart());
850 jseq.setEnd(jds.getEnd());
851 jseq.setColour(av.getSequenceColour(jds).getRGB());
853 jseq.setId(id); // jseq id should be a string not a number
856 // Store any sequences this sequence represents
857 if (av.hasHiddenRows())
859 // use rjal, contains the full height alignment
860 jseq.setHidden(av.getAlignment().getHiddenSequences()
863 if (av.isHiddenRepSequence(jds))
865 jalview.datamodel.SequenceI[] reps = av
866 .getRepresentedSequences(jds).getSequencesInOrder(rjal);
868 for (int h = 0; h < reps.length; h++)
872 jseq.addHiddenSequences(rjal.findIndex(reps[h]));
877 // mark sequence as reference - if it is the reference for this view
880 jseq.setViewreference(jds == jal.getSeqrep());
884 // TODO: omit sequence features from each alignment view's XML dump if we
885 // are storing dataset
886 List<jalview.datamodel.SequenceFeature> sfs = jds
887 .getSequenceFeatures();
888 for (SequenceFeature sf : sfs)
890 Features features = new Features();
892 features.setBegin(sf.getBegin());
893 features.setEnd(sf.getEnd());
894 features.setDescription(sf.getDescription());
895 features.setType(sf.getType());
896 features.setFeatureGroup(sf.getFeatureGroup());
897 features.setScore(sf.getScore());
898 if (sf.links != null)
900 for (int l = 0; l < sf.links.size(); l++)
902 OtherData keyValue = new OtherData();
903 keyValue.setKey("LINK_" + l);
904 keyValue.setValue(sf.links.elementAt(l).toString());
905 features.addOtherData(keyValue);
908 if (sf.otherDetails != null)
911 Iterator<String> keys = sf.otherDetails.keySet().iterator();
912 while (keys.hasNext())
915 OtherData keyValue = new OtherData();
916 keyValue.setKey(key);
917 keyValue.setValue(sf.otherDetails.get(key).toString());
918 features.addOtherData(keyValue);
922 jseq.addFeatures(features);
925 if (jdatasq.getAllPDBEntries() != null)
927 Enumeration en = jdatasq.getAllPDBEntries().elements();
928 while (en.hasMoreElements())
930 Pdbids pdb = new Pdbids();
931 jalview.datamodel.PDBEntry entry = (jalview.datamodel.PDBEntry) en
934 String pdbId = entry.getId();
936 pdb.setType(entry.getType());
939 * Store any structure views associated with this sequence. This
940 * section copes with duplicate entries in the project, so a dataset
941 * only view *should* be coped with sensibly.
943 // This must have been loaded, is it still visible?
944 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
945 String matchedFile = null;
946 for (int f = frames.length - 1; f > -1; f--)
948 if (frames[f] instanceof StructureViewerBase)
950 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
951 matchedFile = saveStructureState(ap, jds, pdb, entry,
952 viewIds, matchedFile, viewFrame);
954 * Only store each structure viewer's state once in the project
955 * jar. First time through only (storeDS==false)
957 String viewId = viewFrame.getViewId();
958 if (!storeDS && !viewIds.contains(viewId))
963 String viewerState = viewFrame.getStateInfo();
964 writeJarEntry(jout, getViewerJarEntryName(viewId),
965 viewerState.getBytes());
966 } catch (IOException e)
968 System.err.println("Error saving viewer state: "
975 if (matchedFile != null || entry.getFile() != null)
977 if (entry.getFile() != null)
980 matchedFile = entry.getFile();
982 pdb.setFile(matchedFile); // entry.getFile());
983 if (pdbfiles == null)
985 pdbfiles = new ArrayList<String>();
988 if (!pdbfiles.contains(pdbId))
991 copyFileToJar(jout, matchedFile, pdbId);
995 Enumeration<String> props = entry.getProperties();
996 if (props.hasMoreElements())
998 PdbentryItem item = new PdbentryItem();
999 while (props.hasMoreElements())
1001 Property prop = new Property();
1002 String key = props.nextElement();
1004 prop.setValue(entry.getProperty(key).toString());
1005 item.addProperty(prop);
1007 pdb.addPdbentryItem(item);
1010 jseq.addPdbids(pdb);
1014 saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
1019 if (!storeDS && av.hasHiddenRows())
1021 jal = av.getAlignment();
1025 if (storeDS && jal.getCodonFrames() != null)
1027 List<AlignedCodonFrame> jac = jal.getCodonFrames();
1028 for (AlignedCodonFrame acf : jac)
1030 AlcodonFrame alc = new AlcodonFrame();
1031 if (acf.getProtMappings() != null
1032 && acf.getProtMappings().length > 0)
1034 boolean hasMap = false;
1035 SequenceI[] dnas = acf.getdnaSeqs();
1036 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1037 for (int m = 0; m < pmaps.length; m++)
1039 AlcodMap alcmap = new AlcodMap();
1040 alcmap.setDnasq(seqHash(dnas[m]));
1041 alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
1043 alc.addAlcodMap(alcmap);
1048 vamsasSet.addAlcodonFrame(alc);
1051 // TODO: delete this ? dead code from 2.8.3->2.9 ?
1053 // AlcodonFrame alc = new AlcodonFrame();
1054 // vamsasSet.addAlcodonFrame(alc);
1055 // for (int p = 0; p < acf.aaWidth; p++)
1057 // Alcodon cmap = new Alcodon();
1058 // if (acf.codons[p] != null)
1060 // // Null codons indicate a gapped column in the translated peptide
1062 // cmap.setPos1(acf.codons[p][0]);
1063 // cmap.setPos2(acf.codons[p][1]);
1064 // cmap.setPos3(acf.codons[p][2]);
1066 // alc.addAlcodon(cmap);
1068 // if (acf.getProtMappings() != null
1069 // && acf.getProtMappings().length > 0)
1071 // SequenceI[] dnas = acf.getdnaSeqs();
1072 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1073 // for (int m = 0; m < pmaps.length; m++)
1075 // AlcodMap alcmap = new AlcodMap();
1076 // alcmap.setDnasq(seqHash(dnas[m]));
1077 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
1079 // alc.addAlcodMap(alcmap);
1086 // /////////////////////////////////
1087 if (!storeDS && av.currentTree != null)
1089 // FIND ANY ASSOCIATED TREES
1090 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
1091 if (Desktop.desktop != null)
1093 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1095 for (int t = 0; t < frames.length; t++)
1097 if (frames[t] instanceof TreePanel)
1099 TreePanel tp = (TreePanel) frames[t];
1101 if (tp.treeCanvas.av.getAlignment() == jal)
1103 Tree tree = new Tree();
1104 tree.setTitle(tp.getTitle());
1105 tree.setCurrentTree((av.currentTree == tp.getTree()));
1106 tree.setNewick(tp.getTree().print());
1107 tree.setThreshold(tp.treeCanvas.threshold);
1109 tree.setFitToWindow(tp.fitToWindow.getState());
1110 tree.setFontName(tp.getTreeFont().getName());
1111 tree.setFontSize(tp.getTreeFont().getSize());
1112 tree.setFontStyle(tp.getTreeFont().getStyle());
1113 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
1115 tree.setShowBootstrap(tp.bootstrapMenu.getState());
1116 tree.setShowDistances(tp.distanceMenu.getState());
1118 tree.setHeight(tp.getHeight());
1119 tree.setWidth(tp.getWidth());
1120 tree.setXpos(tp.getX());
1121 tree.setYpos(tp.getY());
1122 tree.setId(makeHashCode(tp, null));
1132 * store forward refs from an annotationRow to any groups
1134 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<SequenceGroup, String>();
1137 for (SequenceI sq : jal.getSequences())
1139 // Store annotation on dataset sequences only
1140 AlignmentAnnotation[] aa = sq.getAnnotation();
1141 if (aa != null && aa.length > 0)
1143 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1150 if (jal.getAlignmentAnnotation() != null)
1152 // Store the annotation shown on the alignment.
1153 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1154 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1159 if (jal.getGroups() != null)
1161 JGroup[] groups = new JGroup[jal.getGroups().size()];
1163 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1165 JGroup jGroup = new JGroup();
1166 groups[++i] = jGroup;
1168 jGroup.setStart(sg.getStartRes());
1169 jGroup.setEnd(sg.getEndRes());
1170 jGroup.setName(sg.getName());
1171 if (groupRefs.containsKey(sg))
1173 // group has references so set its ID field
1174 jGroup.setId(groupRefs.get(sg));
1176 ColourSchemeI colourScheme = sg.getColourScheme();
1177 if (colourScheme != null)
1179 ResidueShaderI groupColourScheme = sg
1180 .getGroupColourScheme();
1181 if (groupColourScheme.conservationApplied())
1183 jGroup.setConsThreshold(groupColourScheme.getConservationInc());
1185 if (colourScheme instanceof jalview.schemes.UserColourScheme)
1187 jGroup.setColour(setUserColourScheme(colourScheme,
1192 jGroup.setColour(colourScheme.getSchemeName());
1195 else if (colourScheme instanceof jalview.schemes.AnnotationColourGradient)
1197 jGroup.setColour("AnnotationColourGradient");
1198 jGroup.setAnnotationColours(constructAnnotationColours(
1199 (jalview.schemes.AnnotationColourGradient) colourScheme,
1202 else if (colourScheme instanceof jalview.schemes.UserColourScheme)
1204 jGroup.setColour(setUserColourScheme(colourScheme,
1209 jGroup.setColour(colourScheme.getSchemeName());
1212 jGroup.setPidThreshold(groupColourScheme.getThreshold());
1215 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1216 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1217 jGroup.setDisplayText(sg.getDisplayText());
1218 jGroup.setColourText(sg.getColourText());
1219 jGroup.setTextCol1(sg.textColour.getRGB());
1220 jGroup.setTextCol2(sg.textColour2.getRGB());
1221 jGroup.setTextColThreshold(sg.thresholdTextColour);
1222 jGroup.setShowUnconserved(sg.getShowNonconserved());
1223 jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1224 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1225 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1226 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1227 for (SequenceI seq : sg.getSequences())
1229 jGroup.addSeq(seqHash(seq));
1233 jms.setJGroup(groups);
1237 // /////////SAVE VIEWPORT
1238 Viewport view = new Viewport();
1239 view.setTitle(ap.alignFrame.getTitle());
1240 view.setSequenceSetId(makeHashCode(av.getSequenceSetId(),
1241 av.getSequenceSetId()));
1242 view.setId(av.getViewId());
1243 if (av.getCodingComplement() != null)
1245 view.setComplementId(av.getCodingComplement().getViewId());
1247 view.setViewName(av.viewName);
1248 view.setGatheredViews(av.isGatherViewsHere());
1250 Rectangle size = ap.av.getExplodedGeometry();
1251 Rectangle position = size;
1254 size = ap.alignFrame.getBounds();
1255 if (av.getCodingComplement() != null)
1257 position = ((SplitFrame) ap.alignFrame.getSplitViewContainer())
1265 view.setXpos(position.x);
1266 view.setYpos(position.y);
1268 view.setWidth(size.width);
1269 view.setHeight(size.height);
1271 view.setStartRes(vpRanges.getStartRes());
1272 view.setStartSeq(vpRanges.getStartSeq());
1274 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1276 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1279 else if (av.getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1281 AnnotationColours ac = constructAnnotationColours(
1282 (jalview.schemes.AnnotationColourGradient) av
1283 .getGlobalColourScheme(),
1286 view.setAnnotationColours(ac);
1287 view.setBgColour("AnnotationColourGradient");
1291 view.setBgColour(ColourSchemeProperty.getColourName(av
1292 .getGlobalColourScheme()));
1295 ResidueShaderI vcs = av.getResidueShading();
1296 ColourSchemeI cs = av.getGlobalColourScheme();
1300 if (vcs.conservationApplied())
1302 view.setConsThreshold(vcs.getConservationInc());
1303 if (cs instanceof jalview.schemes.UserColourScheme)
1305 view.setBgColour(setUserColourScheme(cs, userColours, jms));
1308 view.setPidThreshold(vcs.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 jalview.datamodel.HiddenColumns hidden = av.getAlignment()
1413 .getHiddenColumns();
1414 if (hidden == null || hidden.getHiddenRegions() == null)
1416 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1420 for (int c = 0; c < hidden.getHiddenRegions()
1423 int[] region = hidden.getHiddenRegions()
1425 HiddenColumns hc = new HiddenColumns();
1426 hc.setStart(region[0]);
1427 hc.setEnd(region[1]);
1428 view.addHiddenColumns(hc);
1432 if (calcIdSet.size() > 0)
1434 for (String calcId : calcIdSet)
1436 if (calcId.trim().length() > 0)
1438 CalcIdParam cidp = createCalcIdParam(calcId, av);
1439 // Some calcIds have no parameters.
1442 view.addCalcIdParam(cidp);
1448 jms.addViewport(view);
1450 object.setJalviewModelSequence(jms);
1451 object.getVamsasModel().addSequenceSet(vamsasSet);
1453 if (jout != null && fileName != null)
1455 // We may not want to write the object to disk,
1456 // eg we can copy the alignViewport to a new view object
1457 // using save and then load
1460 System.out.println("Writing jar entry " + fileName);
1461 JarEntry entry = new JarEntry(fileName);
1462 jout.putNextEntry(entry);
1463 PrintWriter pout = new PrintWriter(new OutputStreamWriter(jout,
1465 Marshaller marshaller = new Marshaller(pout);
1466 marshaller.marshal(object);
1469 } catch (Exception ex)
1471 // TODO: raise error in GUI if marshalling failed.
1472 ex.printStackTrace();
1479 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1480 * for each viewer, with
1482 * <li>viewer geometry (position, size, split pane divider location)</li>
1483 * <li>index of the selected structure in the viewer (currently shows gapped
1485 * <li>the id of the annotation holding RNA secondary structure</li>
1486 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1488 * Varna viewer state is also written out (in native Varna XML) to separate
1489 * project jar entries. A separate entry is written for each RNA structure
1490 * displayed, with the naming convention
1492 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
1500 * @param storeDataset
1502 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
1503 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
1504 boolean storeDataset)
1506 if (Desktop.desktop == null)
1510 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1511 for (int f = frames.length - 1; f > -1; f--)
1513 if (frames[f] instanceof AppVarna)
1515 AppVarna varna = (AppVarna) frames[f];
1517 * link the sequence to every viewer that is showing it and is linked to
1518 * its alignment panel
1520 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1522 String viewId = varna.getViewId();
1523 RnaViewer rna = new RnaViewer();
1524 rna.setViewId(viewId);
1525 rna.setTitle(varna.getTitle());
1526 rna.setXpos(varna.getX());
1527 rna.setYpos(varna.getY());
1528 rna.setWidth(varna.getWidth());
1529 rna.setHeight(varna.getHeight());
1530 rna.setDividerLocation(varna.getDividerLocation());
1531 rna.setSelectedRna(varna.getSelectedIndex());
1532 jseq.addRnaViewer(rna);
1535 * Store each Varna panel's state once in the project per sequence.
1536 * First time through only (storeDataset==false)
1538 // boolean storeSessions = false;
1539 // String sequenceViewId = viewId + seqsToIds.get(jds);
1540 // if (!storeDataset && !viewIds.contains(sequenceViewId))
1542 // viewIds.add(sequenceViewId);
1543 // storeSessions = true;
1545 for (RnaModel model : varna.getModels())
1547 if (model.seq == jds)
1550 * VARNA saves each view (sequence or alignment secondary
1551 * structure, gapped or trimmed) as a separate XML file
1553 String jarEntryName = rnaSessions.get(model);
1554 if (jarEntryName == null)
1557 String varnaStateFile = varna.getStateInfo(model.rna);
1558 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
1559 copyFileToJar(jout, varnaStateFile, jarEntryName);
1560 rnaSessions.put(model, jarEntryName);
1562 SecondaryStructure ss = new SecondaryStructure();
1563 String annotationId = varna.getAnnotation(jds).annotationId;
1564 ss.setAnnotationId(annotationId);
1565 ss.setViewerState(jarEntryName);
1566 ss.setGapped(model.gapped);
1567 ss.setTitle(model.title);
1568 rna.addSecondaryStructure(ss);
1577 * Copy the contents of a file to a new entry added to the output jar
1581 * @param jarEntryName
1583 protected void copyFileToJar(JarOutputStream jout, String infilePath,
1584 String jarEntryName)
1586 DataInputStream dis = null;
1589 File file = new File(infilePath);
1590 if (file.exists() && jout != null)
1592 dis = new DataInputStream(new FileInputStream(file));
1593 byte[] data = new byte[(int) file.length()];
1594 dis.readFully(data);
1595 writeJarEntry(jout, jarEntryName, data);
1597 } catch (Exception ex)
1599 ex.printStackTrace();
1607 } catch (IOException e)
1616 * Write the data to a new entry of given name in the output jar file
1619 * @param jarEntryName
1621 * @throws IOException
1623 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
1624 byte[] data) throws IOException
1628 System.out.println("Writing jar entry " + jarEntryName);
1629 jout.putNextEntry(new JarEntry(jarEntryName));
1630 DataOutputStream dout = new DataOutputStream(jout);
1631 dout.write(data, 0, data.length);
1638 * Save the state of a structure viewer
1643 * the archive XML element under which to save the state
1646 * @param matchedFile
1650 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
1651 Pdbids pdb, PDBEntry entry, List<String> viewIds,
1652 String matchedFile, StructureViewerBase viewFrame)
1654 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
1657 * Look for any bindings for this viewer to the PDB file of interest
1658 * (including part matches excluding chain id)
1660 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
1662 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
1663 final String pdbId = pdbentry.getId();
1664 if (!pdbId.equals(entry.getId())
1665 && !(entry.getId().length() > 4 && entry.getId()
1666 .toLowerCase().startsWith(pdbId.toLowerCase())))
1669 * not interested in a binding to a different PDB entry here
1673 if (matchedFile == null)
1675 matchedFile = pdbentry.getFile();
1677 else if (!matchedFile.equals(pdbentry.getFile()))
1680 .warn("Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
1681 + pdbentry.getFile());
1685 // can get at it if the ID
1686 // match is ambiguous (e.g.
1689 for (int smap = 0; smap < viewFrame.getBinding().getSequence()[peid].length; smap++)
1691 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
1692 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
1694 StructureState state = new StructureState();
1695 state.setVisible(true);
1696 state.setXpos(viewFrame.getX());
1697 state.setYpos(viewFrame.getY());
1698 state.setWidth(viewFrame.getWidth());
1699 state.setHeight(viewFrame.getHeight());
1700 final String viewId = viewFrame.getViewId();
1701 state.setViewId(viewId);
1702 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
1703 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
1704 state.setColourByJmol(viewFrame.isColouredByViewer());
1705 state.setType(viewFrame.getViewerType().toString());
1706 pdb.addStructureState(state);
1714 * Populates the AnnotationColours xml for save. This captures the settings of
1715 * the options in the 'Colour by Annotation' dialog.
1718 * @param userColours
1722 private AnnotationColours constructAnnotationColours(
1723 AnnotationColourGradient acg, List<UserColourScheme> userColours,
1724 JalviewModelSequence jms)
1726 AnnotationColours ac = new AnnotationColours();
1727 ac.setAboveThreshold(acg.getAboveThreshold());
1728 ac.setThreshold(acg.getAnnotationThreshold());
1729 // 2.10.2 save annotationId (unique) not annotation label
1730 ac.setAnnotation(acg.getAnnotation().annotationId);
1731 if (acg.getBaseColour() instanceof UserColourScheme)
1733 ac.setColourScheme(setUserColourScheme(acg.getBaseColour(),
1738 ac.setColourScheme(ColourSchemeProperty.getColourName(acg.getBaseColour()));
1741 ac.setMaxColour(acg.getMaxColour().getRGB());
1742 ac.setMinColour(acg.getMinColour().getRGB());
1743 ac.setPerSequence(acg.isSeqAssociated());
1744 ac.setPredefinedColours(acg.isPredefinedColours());
1748 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
1749 IdentityHashMap<SequenceGroup, String> groupRefs,
1750 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
1751 SequenceSet vamsasSet)
1754 for (int i = 0; i < aa.length; i++)
1756 Annotation an = new Annotation();
1758 AlignmentAnnotation annotation = aa[i];
1759 if (annotation.annotationId != null)
1761 annotationIds.put(annotation.annotationId, annotation);
1764 an.setId(annotation.annotationId);
1766 an.setVisible(annotation.visible);
1768 an.setDescription(annotation.description);
1770 if (annotation.sequenceRef != null)
1772 // 2.9 JAL-1781 xref on sequence id rather than name
1773 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
1775 if (annotation.groupRef != null)
1777 String groupIdr = groupRefs.get(annotation.groupRef);
1778 if (groupIdr == null)
1780 // make a locally unique String
1782 annotation.groupRef,
1783 groupIdr = ("" + System.currentTimeMillis()
1784 + annotation.groupRef.getName() + groupRefs
1787 an.setGroupRef(groupIdr.toString());
1790 // store all visualization attributes for annotation
1791 an.setGraphHeight(annotation.graphHeight);
1792 an.setCentreColLabels(annotation.centreColLabels);
1793 an.setScaleColLabels(annotation.scaleColLabel);
1794 an.setShowAllColLabels(annotation.showAllColLabels);
1795 an.setBelowAlignment(annotation.belowAlignment);
1797 if (annotation.graph > 0)
1800 an.setGraphType(annotation.graph);
1801 an.setGraphGroup(annotation.graphGroup);
1802 if (annotation.getThreshold() != null)
1804 ThresholdLine line = new ThresholdLine();
1805 line.setLabel(annotation.getThreshold().label);
1806 line.setValue(annotation.getThreshold().value);
1807 line.setColour(annotation.getThreshold().colour.getRGB());
1808 an.setThresholdLine(line);
1816 an.setLabel(annotation.label);
1818 if (annotation == av.getAlignmentQualityAnnot()
1819 || annotation == av.getAlignmentConservationAnnotation()
1820 || annotation == av.getAlignmentConsensusAnnotation()
1821 || annotation.autoCalculated)
1823 // new way of indicating autocalculated annotation -
1824 an.setAutoCalculated(annotation.autoCalculated);
1826 if (annotation.hasScore())
1828 an.setScore(annotation.getScore());
1831 if (annotation.getCalcId() != null)
1833 calcIdSet.add(annotation.getCalcId());
1834 an.setCalcId(annotation.getCalcId());
1836 if (annotation.hasProperties())
1838 for (String pr : annotation.getProperties())
1840 Property prop = new Property();
1842 prop.setValue(annotation.getProperty(pr));
1843 an.addProperty(prop);
1847 AnnotationElement ae;
1848 if (annotation.annotations != null)
1850 an.setScoreOnly(false);
1851 for (int a = 0; a < annotation.annotations.length; a++)
1853 if ((annotation == null) || (annotation.annotations[a] == null))
1858 ae = new AnnotationElement();
1859 if (annotation.annotations[a].description != null)
1861 ae.setDescription(annotation.annotations[a].description);
1863 if (annotation.annotations[a].displayCharacter != null)
1865 ae.setDisplayCharacter(annotation.annotations[a].displayCharacter);
1868 if (!Float.isNaN(annotation.annotations[a].value))
1870 ae.setValue(annotation.annotations[a].value);
1874 if (annotation.annotations[a].secondaryStructure > ' ')
1876 ae.setSecondaryStructure(annotation.annotations[a].secondaryStructure
1880 if (annotation.annotations[a].colour != null
1881 && annotation.annotations[a].colour != java.awt.Color.black)
1883 ae.setColour(annotation.annotations[a].colour.getRGB());
1886 an.addAnnotationElement(ae);
1887 if (annotation.autoCalculated)
1889 // only write one non-null entry into the annotation row -
1890 // sufficient to get the visualization attributes necessary to
1898 an.setScoreOnly(true);
1900 if (!storeDS || (storeDS && !annotation.autoCalculated))
1902 // skip autocalculated annotation - these are only provided for
1904 vamsasSet.addAnnotation(an);
1910 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
1912 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
1913 if (settings != null)
1915 CalcIdParam vCalcIdParam = new CalcIdParam();
1916 vCalcIdParam.setCalcId(calcId);
1917 vCalcIdParam.addServiceURL(settings.getServiceURI());
1918 // generic URI allowing a third party to resolve another instance of the
1919 // service used for this calculation
1920 for (String urls : settings.getServiceURLs())
1922 vCalcIdParam.addServiceURL(urls);
1924 vCalcIdParam.setVersion("1.0");
1925 if (settings.getPreset() != null)
1927 WsParamSetI setting = settings.getPreset();
1928 vCalcIdParam.setName(setting.getName());
1929 vCalcIdParam.setDescription(setting.getDescription());
1933 vCalcIdParam.setName("");
1934 vCalcIdParam.setDescription("Last used parameters");
1936 // need to be able to recover 1) settings 2) user-defined presets or
1937 // recreate settings from preset 3) predefined settings provided by
1938 // service - or settings that can be transferred (or discarded)
1939 vCalcIdParam.setParameters(settings.getWsParamFile().replace("\n",
1941 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
1942 // todo - decide if updateImmediately is needed for any projects.
1944 return vCalcIdParam;
1949 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
1952 if (calcIdParam.getVersion().equals("1.0"))
1954 Jws2Instance service = Jws2Discoverer.getDiscoverer()
1955 .getPreferredServiceFor(calcIdParam.getServiceURL());
1956 if (service != null)
1958 WsParamSetI parmSet = null;
1961 parmSet = service.getParamStore().parseServiceParameterFile(
1962 calcIdParam.getName(), calcIdParam.getDescription(),
1963 calcIdParam.getServiceURL(),
1964 calcIdParam.getParameters().replace("|\\n|", "\n"));
1965 } catch (IOException x)
1967 warn("Couldn't parse parameter data for "
1968 + calcIdParam.getCalcId(), x);
1971 List<ArgumentI> argList = null;
1972 if (calcIdParam.getName().length() > 0)
1974 parmSet = service.getParamStore()
1975 .getPreset(calcIdParam.getName());
1976 if (parmSet != null)
1978 // TODO : check we have a good match with settings in AACon -
1979 // otherwise we'll need to create a new preset
1984 argList = parmSet.getArguments();
1987 AAConSettings settings = new AAConSettings(
1988 calcIdParam.isAutoUpdate(), service, parmSet, argList);
1989 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
1990 calcIdParam.isNeedsUpdate());
1995 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
1999 throw new Error(MessageManager.formatMessage(
2000 "error.unsupported_version_calcIdparam",
2001 new Object[] { calcIdParam.toString() }));
2005 * External mapping between jalview objects and objects yielding a valid and
2006 * unique object ID string. This is null for normal Jalview project IO, but
2007 * non-null when a jalview project is being read or written as part of a
2010 IdentityHashMap jv2vobj = null;
2013 * Construct a unique ID for jvobj using either existing bindings or if none
2014 * exist, the result of the hashcode call for the object.
2017 * jalview data object
2018 * @return unique ID for referring to jvobj
2020 private String makeHashCode(Object jvobj, String altCode)
2022 if (jv2vobj != null)
2024 Object id = jv2vobj.get(jvobj);
2027 return id.toString();
2029 // check string ID mappings
2030 if (jvids2vobj != null && jvobj instanceof String)
2032 id = jvids2vobj.get(jvobj);
2036 return id.toString();
2038 // give up and warn that something has gone wrong
2039 warn("Cannot find ID for object in external mapping : " + jvobj);
2045 * return local jalview object mapped to ID, if it exists
2049 * @return null or object bound to idcode
2051 private Object retrieveExistingObj(String idcode)
2053 if (idcode != null && vobj2jv != null)
2055 return vobj2jv.get(idcode);
2061 * binding from ID strings from external mapping table to jalview data model
2064 private Hashtable vobj2jv;
2066 private Sequence createVamsasSequence(String id, SequenceI jds)
2068 return createVamsasSequence(true, id, jds, null);
2071 private Sequence createVamsasSequence(boolean recurse, String id,
2072 SequenceI jds, SequenceI parentseq)
2074 Sequence vamsasSeq = new Sequence();
2075 vamsasSeq.setId(id);
2076 vamsasSeq.setName(jds.getName());
2077 vamsasSeq.setSequence(jds.getSequenceAsString());
2078 vamsasSeq.setDescription(jds.getDescription());
2079 jalview.datamodel.DBRefEntry[] dbrefs = null;
2080 if (jds.getDatasetSequence() != null)
2082 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
2086 // seqId==dsseqid so we can tell which sequences really are
2087 // dataset sequences only
2088 vamsasSeq.setDsseqid(id);
2089 dbrefs = jds.getDBRefs();
2090 if (parentseq == null)
2097 for (int d = 0; d < dbrefs.length; d++)
2099 DBRef dbref = new DBRef();
2100 dbref.setSource(dbrefs[d].getSource());
2101 dbref.setVersion(dbrefs[d].getVersion());
2102 dbref.setAccessionId(dbrefs[d].getAccessionId());
2103 if (dbrefs[d].hasMap())
2105 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
2107 dbref.setMapping(mp);
2109 vamsasSeq.addDBRef(dbref);
2115 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
2116 SequenceI parentseq, SequenceI jds, boolean recurse)
2119 if (jmp.getMap() != null)
2123 jalview.util.MapList mlst = jmp.getMap();
2124 List<int[]> r = mlst.getFromRanges();
2125 for (int[] range : r)
2127 MapListFrom mfrom = new MapListFrom();
2128 mfrom.setStart(range[0]);
2129 mfrom.setEnd(range[1]);
2130 mp.addMapListFrom(mfrom);
2132 r = mlst.getToRanges();
2133 for (int[] range : r)
2135 MapListTo mto = new MapListTo();
2136 mto.setStart(range[0]);
2137 mto.setEnd(range[1]);
2138 mp.addMapListTo(mto);
2140 mp.setMapFromUnit(mlst.getFromRatio());
2141 mp.setMapToUnit(mlst.getToRatio());
2142 if (jmp.getTo() != null)
2144 MappingChoice mpc = new MappingChoice();
2146 // check/create ID for the sequence referenced by getTo()
2149 SequenceI ps = null;
2150 if (parentseq != jmp.getTo()
2151 && parentseq.getDatasetSequence() != jmp.getTo())
2153 // chaining dbref rather than a handshaking one
2154 jmpid = seqHash(ps = jmp.getTo());
2158 jmpid = seqHash(ps = parentseq);
2160 mpc.setDseqFor(jmpid);
2161 if (!seqRefIds.containsKey(mpc.getDseqFor()))
2163 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2164 seqRefIds.put(mpc.getDseqFor(), ps);
2168 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2171 mp.setMappingChoice(mpc);
2177 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2178 List<UserColourScheme> userColours, JalviewModelSequence jms)
2181 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2182 boolean newucs = false;
2183 if (!userColours.contains(ucs))
2185 userColours.add(ucs);
2188 id = "ucs" + userColours.indexOf(ucs);
2191 // actually create the scheme's entry in the XML model
2192 java.awt.Color[] colours = ucs.getColours();
2193 jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
2194 jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
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]);
2200 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2201 jbucs.addColour(col);
2203 if (ucs.getLowerCaseColours() != null)
2205 colours = ucs.getLowerCaseColours();
2206 for (int i = 0; i < colours.length; i++)
2208 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2209 col.setName(ResidueProperties.aa[i].toLowerCase());
2210 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2211 jbucs.addColour(col);
2216 uc.setUserColourScheme(jbucs);
2217 jms.addUserColours(uc);
2223 jalview.schemes.UserColourScheme getUserColourScheme(
2224 JalviewModelSequence jms, String id)
2226 UserColours[] uc = jms.getUserColours();
2227 UserColours colours = null;
2229 for (int i = 0; i < uc.length; i++)
2231 if (uc[i].getId().equals(id))
2239 java.awt.Color[] newColours = new java.awt.Color[24];
2241 for (int i = 0; i < 24; i++)
2243 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2244 .getUserColourScheme().getColour(i).getRGB(), 16));
2247 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2250 if (colours.getUserColourScheme().getColourCount() > 24)
2252 newColours = new java.awt.Color[23];
2253 for (int i = 0; i < 23; i++)
2255 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2256 .getUserColourScheme().getColour(i + 24).getRGB(), 16));
2258 ucs.setLowerCaseColours(newColours);
2265 * contains last error message (if any) encountered by XML loader.
2267 String errorMessage = null;
2270 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2271 * exceptions are raised during project XML parsing
2273 public boolean attemptversion1parse = true;
2276 * Load a jalview project archive from a jar file
2279 * - HTTP URL or filename
2281 public AlignFrame loadJalviewAlign(final String file)
2284 jalview.gui.AlignFrame af = null;
2288 // create list to store references for any new Jmol viewers created
2289 newStructureViewers = new Vector<JalviewStructureDisplayI>();
2290 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2291 // Workaround is to make sure caller implements the JarInputStreamProvider
2293 // so we can re-open the jar input stream for each entry.
2295 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2296 af = loadJalviewAlign(jprovider);
2298 } catch (MalformedURLException e)
2300 errorMessage = "Invalid URL format for '" + file + "'";
2306 SwingUtilities.invokeAndWait(new Runnable()
2311 setLoadingFinishedForNewStructureViewers();
2314 } catch (Exception x)
2316 System.err.println("Error loading alignment: " + x.getMessage());
2322 private jarInputStreamProvider createjarInputStreamProvider(
2323 final String file) throws MalformedURLException
2326 errorMessage = null;
2327 uniqueSetSuffix = null;
2329 viewportsAdded.clear();
2330 frefedSequence = null;
2332 if (file.startsWith("http://"))
2334 url = new URL(file);
2336 final URL _url = url;
2337 return new jarInputStreamProvider()
2341 public JarInputStream getJarInputStream() throws IOException
2345 return new JarInputStream(_url.openStream());
2349 return new JarInputStream(new FileInputStream(file));
2354 public String getFilename()
2362 * Recover jalview session from a jalview project archive. Caller may
2363 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2364 * themselves. Any null fields will be initialised with default values,
2365 * non-null fields are left alone.
2370 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2372 errorMessage = null;
2373 if (uniqueSetSuffix == null)
2375 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2377 if (seqRefIds == null)
2381 AlignFrame af = null, _af = null;
2382 IdentityHashMap<AlignmentI, AlignmentI> importedDatasets = new IdentityHashMap<AlignmentI, AlignmentI>();
2383 Map<String, AlignFrame> gatherToThisFrame = new HashMap<String, AlignFrame>();
2384 final String file = jprovider.getFilename();
2387 JarInputStream jin = null;
2388 JarEntry jarentry = null;
2393 jin = jprovider.getJarInputStream();
2394 for (int i = 0; i < entryCount; i++)
2396 jarentry = jin.getNextJarEntry();
2399 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2401 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2402 JalviewModel object = new JalviewModel();
2404 Unmarshaller unmar = new Unmarshaller(object);
2405 unmar.setValidation(false);
2406 object = (JalviewModel) unmar.unmarshal(in);
2407 if (true) // !skipViewport(object))
2409 _af = loadFromObject(object, file, true, jprovider);
2411 && object.getJalviewModelSequence().getViewportCount() > 0)
2415 // store a reference to the first view
2418 if (_af.viewport.isGatherViewsHere())
2420 // if this is a gathered view, keep its reference since
2421 // after gathering views, only this frame will remain
2423 gatherToThisFrame.put(_af.viewport.getSequenceSetId(), _af);
2425 // Save dataset to register mappings once all resolved
2426 importedDatasets.put(af.viewport.getAlignment().getDataset(),
2427 af.viewport.getAlignment().getDataset());
2432 else if (jarentry != null)
2434 // Some other file here.
2437 } while (jarentry != null);
2438 resolveFrefedSequences();
2439 } catch (IOException ex)
2441 ex.printStackTrace();
2442 errorMessage = "Couldn't locate Jalview XML file : " + file;
2443 System.err.println("Exception whilst loading jalview XML file : "
2445 } catch (Exception ex)
2447 System.err.println("Parsing as Jalview Version 2 file failed.");
2448 ex.printStackTrace(System.err);
2449 if (attemptversion1parse)
2451 // Is Version 1 Jar file?
2454 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
2455 } catch (Exception ex2)
2457 System.err.println("Exception whilst loading as jalviewXMLV1:");
2458 ex2.printStackTrace();
2462 if (Desktop.instance != null)
2464 Desktop.instance.stopLoading();
2468 System.out.println("Successfully loaded archive file");
2471 ex.printStackTrace();
2473 System.err.println("Exception whilst loading jalview XML file : "
2475 } catch (OutOfMemoryError e)
2477 // Don't use the OOM Window here
2478 errorMessage = "Out of memory loading jalview XML file";
2479 System.err.println("Out of memory whilst loading jalview XML file");
2480 e.printStackTrace();
2484 * Regather multiple views (with the same sequence set id) to the frame (if
2485 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2486 * views instead of separate frames. Note this doesn't restore a state where
2487 * some expanded views in turn have tabbed views - the last "first tab" read
2488 * in will play the role of gatherer for all.
2490 for (AlignFrame fr : gatherToThisFrame.values())
2492 Desktop.instance.gatherViews(fr);
2495 restoreSplitFrames();
2496 for (AlignmentI ds : importedDatasets.keySet())
2498 if (ds.getCodonFrames() != null)
2500 StructureSelectionManager.getStructureSelectionManager(
2501 Desktop.instance).registerMappings(ds.getCodonFrames());
2504 if (errorMessage != null)
2509 if (Desktop.instance != null)
2511 Desktop.instance.stopLoading();
2518 * Try to reconstruct and display SplitFrame windows, where each contains
2519 * complementary dna and protein alignments. Done by pairing up AlignFrame
2520 * objects (created earlier) which have complementary viewport ids associated.
2522 protected void restoreSplitFrames()
2524 List<SplitFrame> gatherTo = new ArrayList<SplitFrame>();
2525 List<AlignFrame> addedToSplitFrames = new ArrayList<AlignFrame>();
2526 Map<String, AlignFrame> dna = new HashMap<String, AlignFrame>();
2529 * Identify the DNA alignments
2531 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2534 AlignFrame af = candidate.getValue();
2535 if (af.getViewport().getAlignment().isNucleotide())
2537 dna.put(candidate.getKey().getId(), af);
2542 * Try to match up the protein complements
2544 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2547 AlignFrame af = candidate.getValue();
2548 if (!af.getViewport().getAlignment().isNucleotide())
2550 String complementId = candidate.getKey().getComplementId();
2551 // only non-null complements should be in the Map
2552 if (complementId != null && dna.containsKey(complementId))
2554 final AlignFrame dnaFrame = dna.get(complementId);
2555 SplitFrame sf = createSplitFrame(dnaFrame, af);
2556 addedToSplitFrames.add(dnaFrame);
2557 addedToSplitFrames.add(af);
2558 dnaFrame.setMenusForViewport();
2559 af.setMenusForViewport();
2560 if (af.viewport.isGatherViewsHere())
2569 * Open any that we failed to pair up (which shouldn't happen!) as
2570 * standalone AlignFrame's.
2572 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2575 AlignFrame af = candidate.getValue();
2576 if (!addedToSplitFrames.contains(af))
2578 Viewport view = candidate.getKey();
2579 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
2581 af.setMenusForViewport();
2582 System.err.println("Failed to restore view " + view.getTitle()
2583 + " to split frame");
2588 * Gather back into tabbed views as flagged.
2590 for (SplitFrame sf : gatherTo)
2592 Desktop.instance.gatherViews(sf);
2595 splitFrameCandidates.clear();
2599 * Construct and display one SplitFrame holding DNA and protein alignments.
2602 * @param proteinFrame
2605 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
2606 AlignFrame proteinFrame)
2608 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
2609 String title = MessageManager.getString("label.linked_view_title");
2610 int width = (int) dnaFrame.getBounds().getWidth();
2611 int height = (int) (dnaFrame.getBounds().getHeight()
2612 + proteinFrame.getBounds().getHeight() + 50);
2615 * SplitFrame location is saved to both enclosed frames
2617 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
2618 Desktop.addInternalFrame(splitFrame, title, width, height);
2621 * And compute cDNA consensus (couldn't do earlier with consensus as
2622 * mappings were not yet present)
2624 proteinFrame.viewport.alignmentChanged(proteinFrame.alignPanel);
2630 * check errorMessage for a valid error message and raise an error box in the
2631 * GUI or write the current errorMessage to stderr and then clear the error
2634 protected void reportErrors()
2636 reportErrors(false);
2639 protected void reportErrors(final boolean saving)
2641 if (errorMessage != null)
2643 final String finalErrorMessage = errorMessage;
2646 javax.swing.SwingUtilities.invokeLater(new Runnable()
2652 .showInternalMessageDialog(Desktop.desktop,
2653 finalErrorMessage, "Error "
2654 + (saving ? "saving" : "loading")
2656 JvOptionPane.WARNING_MESSAGE);
2662 System.err.println("Problem loading Jalview file: " + errorMessage);
2665 errorMessage = null;
2668 Map<String, String> alreadyLoadedPDB = new HashMap<String, String>();
2671 * when set, local views will be updated from view stored in JalviewXML
2672 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2673 * sync if this is set to true.
2675 private final boolean updateLocalViews = false;
2678 * Returns the path to a temporary file holding the PDB file for the given PDB
2679 * id. The first time of asking, searches for a file of that name in the
2680 * Jalview project jar, and copies it to a new temporary file. Any repeat
2681 * requests just return the path to the file previously created.
2687 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId,
2690 if (alreadyLoadedPDB.containsKey(pdbId))
2692 return alreadyLoadedPDB.get(pdbId).toString();
2695 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb",
2697 if (tempFile != null)
2699 alreadyLoadedPDB.put(pdbId, tempFile);
2705 * Copies the jar entry of given name to a new temporary file and returns the
2706 * path to the file, or null if the entry is not found.
2709 * @param jarEntryName
2711 * a prefix for the temporary file name, must be at least three
2714 * null or original file - so new file can be given the same suffix
2718 protected String copyJarEntry(jarInputStreamProvider jprovider,
2719 String jarEntryName, String prefix, String origFile)
2721 BufferedReader in = null;
2722 PrintWriter out = null;
2723 String suffix = ".tmp";
2724 if (origFile == null)
2726 origFile = jarEntryName;
2728 int sfpos = origFile.lastIndexOf(".");
2729 if (sfpos > -1 && sfpos < (origFile.length() - 3))
2731 suffix = "." + origFile.substring(sfpos + 1);
2735 JarInputStream jin = jprovider.getJarInputStream();
2737 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2738 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2739 * FileInputStream(jprovider)); }
2742 JarEntry entry = null;
2745 entry = jin.getNextJarEntry();
2746 } while (entry != null && !entry.getName().equals(jarEntryName));
2749 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
2750 File outFile = File.createTempFile(prefix, suffix);
2751 outFile.deleteOnExit();
2752 out = new PrintWriter(new FileOutputStream(outFile));
2755 while ((data = in.readLine()) != null)
2760 String t = outFile.getAbsolutePath();
2765 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
2767 } catch (Exception ex)
2769 ex.printStackTrace();
2777 } catch (IOException e)
2791 private class JvAnnotRow
2793 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2800 * persisted version of annotation row from which to take vis properties
2802 public jalview.datamodel.AlignmentAnnotation template;
2805 * original position of the annotation row in the alignment
2811 * Load alignment frame from jalview XML DOM object
2816 * filename source string
2817 * @param loadTreesAndStructures
2818 * when false only create Viewport
2820 * data source provider
2821 * @return alignment frame created from view stored in DOM
2823 AlignFrame loadFromObject(JalviewModel object, String file,
2824 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
2826 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
2827 Sequence[] vamsasSeq = vamsasSet.getSequence();
2829 JalviewModelSequence jms = object.getJalviewModelSequence();
2831 Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
2834 // ////////////////////////////////
2837 List<SequenceI> hiddenSeqs = null;
2839 List<SequenceI> tmpseqs = new ArrayList<SequenceI>();
2841 boolean multipleView = false;
2842 SequenceI referenceseqForView = null;
2843 JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
2844 int vi = 0; // counter in vamsasSeq array
2845 for (int i = 0; i < jseqs.length; i++)
2847 String seqId = jseqs[i].getId();
2849 SequenceI tmpSeq = seqRefIds.get(seqId);
2852 if (!incompleteSeqs.containsKey(seqId))
2854 // may not need this check, but keep it for at least 2.9,1 release
2855 if (tmpSeq.getStart() != jseqs[i].getStart()
2856 || tmpSeq.getEnd() != jseqs[i].getEnd())
2859 .println("Warning JAL-2154 regression: updating start/end for sequence "
2860 + tmpSeq.toString() + " to " + jseqs[i]);
2865 incompleteSeqs.remove(seqId);
2867 if (vamsasSeq.length > vi && vamsasSeq[vi].getId().equals(seqId))
2869 // most likely we are reading a dataset XML document so
2870 // update from vamsasSeq section of XML for this sequence
2871 tmpSeq.setName(vamsasSeq[vi].getName());
2872 tmpSeq.setDescription(vamsasSeq[vi].getDescription());
2873 tmpSeq.setSequence(vamsasSeq[vi].getSequence());
2878 // reading multiple views, so vamsasSeq set is a subset of JSeq
2879 multipleView = true;
2881 tmpSeq.setStart(jseqs[i].getStart());
2882 tmpSeq.setEnd(jseqs[i].getEnd());
2883 tmpseqs.add(tmpSeq);
2887 tmpSeq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
2888 vamsasSeq[vi].getSequence());
2889 tmpSeq.setDescription(vamsasSeq[vi].getDescription());
2890 tmpSeq.setStart(jseqs[i].getStart());
2891 tmpSeq.setEnd(jseqs[i].getEnd());
2892 tmpSeq.setVamsasId(uniqueSetSuffix + seqId);
2893 seqRefIds.put(vamsasSeq[vi].getId(), tmpSeq);
2894 tmpseqs.add(tmpSeq);
2898 if (jseqs[i].hasViewreference() && jseqs[i].getViewreference())
2900 referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
2903 if (jseqs[i].getHidden())
2905 if (hiddenSeqs == null)
2907 hiddenSeqs = new ArrayList<SequenceI>();
2910 hiddenSeqs.add(tmpSeq);
2915 // Create the alignment object from the sequence set
2916 // ///////////////////////////////
2917 SequenceI[] orderedSeqs = tmpseqs
2918 .toArray(new SequenceI[tmpseqs.size()]);
2920 AlignmentI al = null;
2921 // so we must create or recover the dataset alignment before going further
2922 // ///////////////////////////////
2923 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
2925 // older jalview projects do not have a dataset - so creat alignment and
2927 al = new Alignment(orderedSeqs);
2928 al.setDataset(null);
2932 boolean isdsal = object.getJalviewModelSequence().getViewportCount() == 0;
2935 // we are importing a dataset record, so
2936 // recover reference to an alignment already materialsed as dataset
2937 al = getDatasetFor(vamsasSet.getDatasetId());
2941 // materialse the alignment
2942 al = new Alignment(orderedSeqs);
2946 addDatasetRef(vamsasSet.getDatasetId(), al);
2949 // finally, verify all data in vamsasSet is actually present in al
2950 // passing on flag indicating if it is actually a stored dataset
2951 recoverDatasetFor(vamsasSet, al, isdsal);
2954 if (referenceseqForView != null)
2956 al.setSeqrep(referenceseqForView);
2958 // / Add the alignment properties
2959 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
2961 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
2962 al.setProperty(ssp.getKey(), ssp.getValue());
2965 // ///////////////////////////////
2967 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
2970 // load sequence features, database references and any associated PDB
2971 // structures for the alignment
2973 // prior to 2.10, this part would only be executed the first time a
2974 // sequence was encountered, but not afterwards.
2975 // now, for 2.10 projects, this is also done if the xml doc includes
2976 // dataset sequences not actually present in any particular view.
2978 for (int i = 0; i < vamsasSeq.length; i++)
2980 if (jseqs[i].getFeaturesCount() > 0)
2982 Features[] features = jseqs[i].getFeatures();
2983 for (int f = 0; f < features.length; f++)
2985 SequenceFeature sf = new SequenceFeature(features[f].getType(),
2986 features[f].getDescription(), features[f].getBegin(),
2987 features[f].getEnd(), features[f].getScore(),
2988 features[f].getFeatureGroup());
2989 sf.setStatus(features[f].getStatus());
2990 for (int od = 0; od < features[f].getOtherDataCount(); od++)
2992 OtherData keyValue = features[f].getOtherData(od);
2993 if (keyValue.getKey().startsWith("LINK"))
2995 sf.addLink(keyValue.getValue());
2999 sf.setValue(keyValue.getKey(), keyValue.getValue());
3003 // adds feature to datasequence's feature set (since Jalview 2.10)
3004 al.getSequenceAt(i).addSequenceFeature(sf);
3007 if (vamsasSeq[i].getDBRefCount() > 0)
3009 // adds dbrefs to datasequence's set (since Jalview 2.10)
3011 al.getSequenceAt(i).getDatasetSequence() == null ? al.getSequenceAt(i)
3012 : al.getSequenceAt(i).getDatasetSequence(),
3015 if (jseqs[i].getPdbidsCount() > 0)
3017 Pdbids[] ids = jseqs[i].getPdbids();
3018 for (int p = 0; p < ids.length; p++)
3020 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
3021 entry.setId(ids[p].getId());
3022 if (ids[p].getType() != null)
3024 if (PDBEntry.Type.getType(ids[p].getType()) != null)
3026 entry.setType(PDBEntry.Type.getType(ids[p].getType()));
3030 entry.setType(PDBEntry.Type.FILE);
3033 // jprovider is null when executing 'New View'
3034 if (ids[p].getFile() != null && jprovider != null)
3036 if (!pdbloaded.containsKey(ids[p].getFile()))
3038 entry.setFile(loadPDBFile(jprovider, ids[p].getId(),
3043 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
3046 if (ids[p].getPdbentryItem() != null)
3048 for (PdbentryItem item : ids[p].getPdbentryItem())
3050 for (Property pr : item.getProperty())
3052 entry.setProperty(pr.getName(), pr.getValue());
3056 StructureSelectionManager.getStructureSelectionManager(
3057 Desktop.instance).registerPDBEntry(entry);
3058 // adds PDBEntry to datasequence's set (since Jalview 2.10)
3059 if (al.getSequenceAt(i).getDatasetSequence() != null)
3061 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
3065 al.getSequenceAt(i).addPDBId(entry);
3070 } // end !multipleview
3072 // ///////////////////////////////
3073 // LOAD SEQUENCE MAPPINGS
3075 if (vamsasSet.getAlcodonFrameCount() > 0)
3077 // TODO Potentially this should only be done once for all views of an
3079 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
3080 for (int i = 0; i < alc.length; i++)
3082 AlignedCodonFrame cf = new AlignedCodonFrame();
3083 if (alc[i].getAlcodMapCount() > 0)
3085 AlcodMap[] maps = alc[i].getAlcodMap();
3086 for (int m = 0; m < maps.length; m++)
3088 SequenceI dnaseq = seqRefIds.get(maps[m].getDnasq());
3090 jalview.datamodel.Mapping mapping = null;
3091 // attach to dna sequence reference.
3092 if (maps[m].getMapping() != null)
3094 mapping = addMapping(maps[m].getMapping());
3095 if (dnaseq != null && mapping.getTo() != null)
3097 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
3102 frefedSequence.add(newAlcodMapRef(maps[m].getDnasq(), cf,
3107 al.addCodonFrame(cf);
3112 // ////////////////////////////////
3114 List<JvAnnotRow> autoAlan = new ArrayList<JvAnnotRow>();
3117 * store any annotations which forward reference a group's ID
3119 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<String, List<AlignmentAnnotation>>();
3121 if (vamsasSet.getAnnotationCount() > 0)
3123 Annotation[] an = vamsasSet.getAnnotation();
3125 for (int i = 0; i < an.length; i++)
3127 Annotation annotation = an[i];
3130 * test if annotation is automatically calculated for this view only
3132 boolean autoForView = false;
3133 if (annotation.getLabel().equals("Quality")
3134 || annotation.getLabel().equals("Conservation")
3135 || annotation.getLabel().equals("Consensus"))
3137 // Kludge for pre 2.5 projects which lacked the autocalculated flag
3139 if (!annotation.hasAutoCalculated())
3141 annotation.setAutoCalculated(true);
3145 || (annotation.hasAutoCalculated() && annotation
3146 .isAutoCalculated()))
3148 // remove ID - we don't recover annotation from other views for
3149 // view-specific annotation
3150 annotation.setId(null);
3153 // set visiblity for other annotation in this view
3154 String annotationId = annotation.getId();
3155 if (annotationId != null && annotationIds.containsKey(annotationId))
3157 AlignmentAnnotation jda = annotationIds.get(annotationId);
3158 // in principle Visible should always be true for annotation displayed
3159 // in multiple views
3160 if (annotation.hasVisible())
3162 jda.visible = annotation.getVisible();
3165 al.addAnnotation(jda);
3169 // Construct new annotation from model.
3170 AnnotationElement[] ae = annotation.getAnnotationElement();
3171 jalview.datamodel.Annotation[] anot = null;
3172 java.awt.Color firstColour = null;
3174 if (!annotation.getScoreOnly())
3176 anot = new jalview.datamodel.Annotation[al.getWidth()];
3177 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
3179 anpos = ae[aa].getPosition();
3181 if (anpos >= anot.length)
3186 anot[anpos] = new jalview.datamodel.Annotation(
3188 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
3189 (ae[aa].getSecondaryStructure() == null || ae[aa]
3190 .getSecondaryStructure().length() == 0) ? ' '
3191 : ae[aa].getSecondaryStructure().charAt(0),
3195 // JBPNote: Consider verifying dataflow for IO of secondary
3196 // structure annotation read from Stockholm files
3197 // this was added to try to ensure that
3198 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
3200 // anot[ae[aa].getPosition()].displayCharacter = "";
3202 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
3203 if (firstColour == null)
3205 firstColour = anot[anpos].colour;
3209 jalview.datamodel.AlignmentAnnotation jaa = null;
3211 if (annotation.getGraph())
3213 float llim = 0, hlim = 0;
3214 // if (autoForView || an[i].isAutoCalculated()) {
3217 jaa = new jalview.datamodel.AlignmentAnnotation(
3218 annotation.getLabel(), annotation.getDescription(), anot,
3219 llim, hlim, annotation.getGraphType());
3221 jaa.graphGroup = annotation.getGraphGroup();
3222 jaa._linecolour = firstColour;
3223 if (annotation.getThresholdLine() != null)
3225 jaa.setThreshold(new jalview.datamodel.GraphLine(annotation
3226 .getThresholdLine().getValue(), annotation
3227 .getThresholdLine().getLabel(), new java.awt.Color(
3228 annotation.getThresholdLine().getColour())));
3231 if (autoForView || annotation.isAutoCalculated())
3233 // Hardwire the symbol display line to ensure that labels for
3234 // histograms are displayed
3240 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
3241 an[i].getDescription(), anot);
3242 jaa._linecolour = firstColour;
3244 // register new annotation
3245 if (an[i].getId() != null)
3247 annotationIds.put(an[i].getId(), jaa);
3248 jaa.annotationId = an[i].getId();
3250 // recover sequence association
3251 String sequenceRef = an[i].getSequenceRef();
3252 if (sequenceRef != null)
3254 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3255 SequenceI sequence = seqRefIds.get(sequenceRef);
3256 if (sequence == null)
3258 // in pre-2.9 projects sequence ref is to sequence name
3259 sequence = al.findName(sequenceRef);
3261 if (sequence != null)
3263 jaa.createSequenceMapping(sequence, 1, true);
3264 sequence.addAlignmentAnnotation(jaa);
3267 // and make a note of any group association
3268 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
3270 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3271 .get(an[i].getGroupRef());
3274 aal = new ArrayList<jalview.datamodel.AlignmentAnnotation>();
3275 groupAnnotRefs.put(an[i].getGroupRef(), aal);
3280 if (an[i].hasScore())
3282 jaa.setScore(an[i].getScore());
3284 if (an[i].hasVisible())
3286 jaa.visible = an[i].getVisible();
3289 if (an[i].hasCentreColLabels())
3291 jaa.centreColLabels = an[i].getCentreColLabels();
3294 if (an[i].hasScaleColLabels())
3296 jaa.scaleColLabel = an[i].getScaleColLabels();
3298 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
3300 // newer files have an 'autoCalculated' flag and store calculation
3301 // state in viewport properties
3302 jaa.autoCalculated = true; // means annotation will be marked for
3303 // update at end of load.
3305 if (an[i].hasGraphHeight())
3307 jaa.graphHeight = an[i].getGraphHeight();
3309 if (an[i].hasBelowAlignment())
3311 jaa.belowAlignment = an[i].isBelowAlignment();
3313 jaa.setCalcId(an[i].getCalcId());
3314 if (an[i].getPropertyCount() > 0)
3316 for (jalview.schemabinding.version2.Property prop : an[i]
3319 jaa.setProperty(prop.getName(), prop.getValue());
3322 if (jaa.autoCalculated)
3324 autoAlan.add(new JvAnnotRow(i, jaa));
3327 // if (!autoForView)
3329 // add autocalculated group annotation and any user created annotation
3331 al.addAnnotation(jaa);
3335 // ///////////////////////
3337 // Create alignment markup and styles for this view
3338 if (jms.getJGroupCount() > 0)
3340 JGroup[] groups = jms.getJGroup();
3341 boolean addAnnotSchemeGroup = false;
3342 for (int i = 0; i < groups.length; i++)
3344 JGroup jGroup = groups[i];
3345 ColourSchemeI cs = null;
3346 if (jGroup.getColour() != null)
3348 if (jGroup.getColour().startsWith("ucs"))
3350 cs = getUserColourScheme(jms, jGroup.getColour());
3352 else if (jGroup.getColour().equals("AnnotationColourGradient")
3353 && jGroup.getAnnotationColours() != null)
3355 addAnnotSchemeGroup = true;
3359 cs = ColourSchemeProperty.getColourScheme(al, jGroup.getColour());
3362 int pidThreshold = jGroup.getPidThreshold();
3364 Vector<SequenceI> seqs = new Vector<SequenceI>();
3366 for (int s = 0; s < jGroup.getSeqCount(); s++)
3368 String seqId = jGroup.getSeq(s) + "";
3369 SequenceI ts = seqRefIds.get(seqId);
3373 seqs.addElement(ts);
3377 if (seqs.size() < 1)
3382 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3383 jGroup.getDisplayBoxes(), jGroup.getDisplayText(),
3384 jGroup.getColourText(), jGroup.getStart(), jGroup.getEnd());
3385 sg.getGroupColourScheme().setThreshold(pidThreshold, true);
3386 sg.getGroupColourScheme().setConservationInc(jGroup.getConsThreshold());
3387 sg.setOutlineColour(new java.awt.Color(jGroup.getOutlineColour()));
3389 sg.textColour = new java.awt.Color(jGroup.getTextCol1());
3390 sg.textColour2 = new java.awt.Color(jGroup.getTextCol2());
3391 sg.setShowNonconserved(jGroup.hasShowUnconserved() ? jGroup
3392 .isShowUnconserved() : false);
3393 sg.thresholdTextColour = jGroup.getTextColThreshold();
3394 if (jGroup.hasShowConsensusHistogram())
3396 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3399 if (jGroup.hasShowSequenceLogo())
3401 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3403 if (jGroup.hasNormaliseSequenceLogo())
3405 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3407 if (jGroup.hasIgnoreGapsinConsensus())
3409 sg.setIgnoreGapsConsensus(jGroup.getIgnoreGapsinConsensus());
3411 if (jGroup.getConsThreshold() != 0)
3413 Conservation c = new Conservation("All", sg.getSequences(null),
3414 0, sg.getWidth() - 1);
3416 c.verdict(false, 25);
3417 sg.cs.setConservation(c);
3420 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3422 // re-instate unique group/annotation row reference
3423 List<AlignmentAnnotation> jaal = groupAnnotRefs.get(jGroup
3427 for (AlignmentAnnotation jaa : jaal)
3430 if (jaa.autoCalculated)
3432 // match up and try to set group autocalc alignment row for this
3434 if (jaa.label.startsWith("Consensus for "))
3436 sg.setConsensus(jaa);
3438 // match up and try to set group autocalc alignment row for this
3440 if (jaa.label.startsWith("Conservation for "))
3442 sg.setConservationRow(jaa);
3449 if (addAnnotSchemeGroup)
3451 // reconstruct the annotation colourscheme
3452 sg.setColourScheme(constructAnnotationColour(
3453 jGroup.getAnnotationColours(), null, al, jms, false));
3459 // only dataset in this model, so just return.
3462 // ///////////////////////////////
3465 // If we just load in the same jar file again, the sequenceSetId
3466 // will be the same, and we end up with multiple references
3467 // to the same sequenceSet. We must modify this id on load
3468 // so that each load of the file gives a unique id
3469 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3470 String viewId = (view.getId() == null ? null : view.getId()
3472 AlignFrame af = null;
3473 AlignViewport av = null;
3474 // now check to see if we really need to create a new viewport.
3475 if (multipleView && viewportsAdded.size() == 0)
3477 // We recovered an alignment for which a viewport already exists.
3478 // TODO: fix up any settings necessary for overlaying stored state onto
3479 // state recovered from another document. (may not be necessary).
3480 // we may need a binding from a viewport in memory to one recovered from
3482 // and then recover its containing af to allow the settings to be applied.
3483 // TODO: fix for vamsas demo
3485 .println("About to recover a viewport for existing alignment: Sequence set ID is "
3487 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3488 if (seqsetobj != null)
3490 if (seqsetobj instanceof String)
3492 uniqueSeqSetId = (String) seqsetobj;
3494 .println("Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
3500 .println("Warning : Collision between sequence set ID string and existing jalview object mapping.");
3506 * indicate that annotation colours are applied across all groups (pre
3507 * Jalview 2.8.1 behaviour)
3509 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan(
3510 "2.8.1", object.getVersion());
3512 AlignmentPanel ap = null;
3513 boolean isnewview = true;
3516 // Check to see if this alignment already has a view id == viewId
3517 jalview.gui.AlignmentPanel views[] = Desktop
3518 .getAlignmentPanels(uniqueSeqSetId);
3519 if (views != null && views.length > 0)
3521 for (int v = 0; v < views.length; v++)
3523 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
3525 // recover the existing alignpanel, alignframe, viewport
3526 af = views[v].alignFrame;
3529 // TODO: could even skip resetting view settings if we don't want to
3530 // change the local settings from other jalview processes
3539 af = loadViewport(file, jseqs, hiddenSeqs, al, jms, view,
3540 uniqueSeqSetId, viewId, autoAlan);
3546 * Load any trees, PDB structures and viewers
3548 * Not done if flag is false (when this method is used for New View)
3550 if (loadTreesAndStructures)
3552 loadTrees(jms, view, af, av, ap);
3553 loadPDBStructures(jprovider, jseqs, af, ap);
3554 loadRnaViewers(jprovider, jseqs, ap);
3556 // and finally return.
3561 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
3562 * panel is restored from separate jar entries, two (gapped and trimmed) per
3563 * sequence and secondary structure.
3565 * Currently each viewer shows just one sequence and structure (gapped and
3566 * trimmed), however this method is designed to support multiple sequences or
3567 * structures in viewers if wanted in future.
3573 private void loadRnaViewers(jarInputStreamProvider jprovider,
3574 JSeq[] jseqs, AlignmentPanel ap)
3577 * scan the sequences for references to viewers; create each one the first
3578 * time it is referenced, add Rna models to existing viewers
3580 for (JSeq jseq : jseqs)
3582 for (int i = 0; i < jseq.getRnaViewerCount(); i++)
3584 RnaViewer viewer = jseq.getRnaViewer(i);
3585 AppVarna appVarna = findOrCreateVarnaViewer(viewer,
3586 uniqueSetSuffix, ap);
3588 for (int j = 0; j < viewer.getSecondaryStructureCount(); j++)
3590 SecondaryStructure ss = viewer.getSecondaryStructure(j);
3591 SequenceI seq = seqRefIds.get(jseq.getId());
3592 AlignmentAnnotation ann = this.annotationIds.get(ss
3593 .getAnnotationId());
3596 * add the structure to the Varna display (with session state copied
3597 * from the jar to a temporary file)
3599 boolean gapped = ss.isGapped();
3600 String rnaTitle = ss.getTitle();
3601 String sessionState = ss.getViewerState();
3602 String tempStateFile = copyJarEntry(jprovider, sessionState,
3604 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
3605 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
3607 appVarna.setInitialSelection(viewer.getSelectedRna());
3613 * Locate and return an already instantiated matching AppVarna, or create one
3617 * @param viewIdSuffix
3621 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
3622 String viewIdSuffix, AlignmentPanel ap)
3625 * on each load a suffix is appended to the saved viewId, to avoid conflicts
3626 * if load is repeated
3628 String postLoadId = viewer.getViewId() + viewIdSuffix;
3629 for (JInternalFrame frame : getAllFrames())
3631 if (frame instanceof AppVarna)
3633 AppVarna varna = (AppVarna) frame;
3634 if (postLoadId.equals(varna.getViewId()))
3636 // this viewer is already instantiated
3637 // could in future here add ap as another 'parent' of the
3638 // AppVarna window; currently just 1-to-many
3645 * viewer not found - make it
3647 RnaViewerModel model = new RnaViewerModel(postLoadId,
3648 viewer.getTitle(), viewer.getXpos(), viewer.getYpos(),
3649 viewer.getWidth(), viewer.getHeight(),
3650 viewer.getDividerLocation());
3651 AppVarna varna = new AppVarna(model, ap);
3657 * Load any saved trees
3665 protected void loadTrees(JalviewModelSequence jms, Viewport view,
3666 AlignFrame af, AlignViewport av, AlignmentPanel ap)
3668 // TODO result of automated refactoring - are all these parameters needed?
3671 for (int t = 0; t < jms.getTreeCount(); t++)
3674 Tree tree = jms.getTree(t);
3676 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
3679 tp = af.showNewickTree(
3680 new jalview.io.NewickFile(tree.getNewick()),
3681 tree.getTitle(), tree.getWidth(), tree.getHeight(),
3682 tree.getXpos(), tree.getYpos());
3683 if (tree.getId() != null)
3685 // perhaps bind the tree id to something ?
3690 // update local tree attributes ?
3691 // TODO: should check if tp has been manipulated by user - if so its
3692 // settings shouldn't be modified
3693 tp.setTitle(tree.getTitle());
3694 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(), tree
3695 .getWidth(), tree.getHeight()));
3696 tp.av = av; // af.viewport; // TODO: verify 'associate with all
3699 tp.treeCanvas.av = av; // af.viewport;
3700 tp.treeCanvas.ap = ap; // af.alignPanel;
3705 warn("There was a problem recovering stored Newick tree: \n"
3706 + tree.getNewick());
3710 tp.fitToWindow.setState(tree.getFitToWindow());
3711 tp.fitToWindow_actionPerformed(null);
3713 if (tree.getFontName() != null)
3715 tp.setTreeFont(new java.awt.Font(tree.getFontName(), tree
3716 .getFontStyle(), tree.getFontSize()));
3720 tp.setTreeFont(new java.awt.Font(view.getFontName(), view
3721 .getFontStyle(), tree.getFontSize()));
3724 tp.showPlaceholders(tree.getMarkUnlinked());
3725 tp.showBootstrap(tree.getShowBootstrap());
3726 tp.showDistances(tree.getShowDistances());
3728 tp.treeCanvas.threshold = tree.getThreshold();
3730 if (tree.getCurrentTree())
3732 af.viewport.setCurrentTree(tp.getTree());
3736 } catch (Exception ex)
3738 ex.printStackTrace();
3743 * Load and link any saved structure viewers.
3750 protected void loadPDBStructures(jarInputStreamProvider jprovider,
3751 JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
3754 * Run through all PDB ids on the alignment, and collect mappings between
3755 * distinct view ids and all sequences referring to that view.
3757 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<String, StructureViewerModel>();
3759 for (int i = 0; i < jseqs.length; i++)
3761 if (jseqs[i].getPdbidsCount() > 0)
3763 Pdbids[] ids = jseqs[i].getPdbids();
3764 for (int p = 0; p < ids.length; p++)
3766 final int structureStateCount = ids[p].getStructureStateCount();
3767 for (int s = 0; s < structureStateCount; s++)
3769 // check to see if we haven't already created this structure view
3770 final StructureState structureState = ids[p]
3771 .getStructureState(s);
3772 String sviewid = (structureState.getViewId() == null) ? null
3773 : structureState.getViewId() + uniqueSetSuffix;
3774 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
3775 // Originally : ids[p].getFile()
3776 // : TODO: verify external PDB file recovery still works in normal
3777 // jalview project load
3778 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId(),
3780 jpdb.setId(ids[p].getId());
3782 int x = structureState.getXpos();
3783 int y = structureState.getYpos();
3784 int width = structureState.getWidth();
3785 int height = structureState.getHeight();
3787 // Probably don't need to do this anymore...
3788 // Desktop.desktop.getComponentAt(x, y);
3789 // TODO: NOW: check that this recovers the PDB file correctly.
3790 String pdbFile = loadPDBFile(jprovider, ids[p].getId(),
3792 jalview.datamodel.SequenceI seq = seqRefIds.get(jseqs[i]
3794 if (sviewid == null)
3796 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width
3799 if (!structureViewers.containsKey(sviewid))
3801 structureViewers.put(sviewid,
3802 new StructureViewerModel(x, y, width, height, false,
3803 false, true, structureState.getViewId(),
3804 structureState.getType()));
3805 // Legacy pre-2.7 conversion JAL-823 :
3806 // do not assume any view has to be linked for colour by
3810 // assemble String[] { pdb files }, String[] { id for each
3811 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3812 // seqs_file 2}, boolean[] {
3813 // linkAlignPanel,superposeWithAlignpanel}} from hash
3814 StructureViewerModel jmoldat = structureViewers.get(sviewid);
3815 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
3816 | (structureState.hasAlignwithAlignPanel() ? structureState
3817 .getAlignwithAlignPanel() : false));
3820 * Default colour by linked panel to false if not specified (e.g.
3821 * for pre-2.7 projects)
3823 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
3824 colourWithAlignPanel |= (structureState
3825 .hasColourwithAlignPanel() ? structureState
3826 .getColourwithAlignPanel() : false);
3827 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
3830 * Default colour by viewer to true if not specified (e.g. for
3833 boolean colourByViewer = jmoldat.isColourByViewer();
3834 colourByViewer &= structureState.hasColourByJmol() ? structureState
3835 .getColourByJmol() : true;
3836 jmoldat.setColourByViewer(colourByViewer);
3838 if (jmoldat.getStateData().length() < structureState
3839 .getContent().length())
3842 jmoldat.setStateData(structureState.getContent());
3845 if (ids[p].getFile() != null)
3847 File mapkey = new File(ids[p].getFile());
3848 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
3849 if (seqstrmaps == null)
3851 jmoldat.getFileData().put(
3853 seqstrmaps = jmoldat.new StructureData(pdbFile,
3856 if (!seqstrmaps.getSeqList().contains(seq))
3858 seqstrmaps.getSeqList().add(seq);
3864 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");
3871 // Instantiate the associated structure views
3872 for (Entry<String, StructureViewerModel> entry : structureViewers
3877 createOrLinkStructureViewer(entry, af, ap, jprovider);
3878 } catch (Exception e)
3880 System.err.println("Error loading structure viewer: "
3882 // failed - try the next one
3894 protected void createOrLinkStructureViewer(
3895 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3896 AlignmentPanel ap, jarInputStreamProvider jprovider)
3898 final StructureViewerModel stateData = viewerData.getValue();
3901 * Search for any viewer windows already open from other alignment views
3902 * that exactly match the stored structure state
3904 StructureViewerBase comp = findMatchingViewer(viewerData);
3908 linkStructureViewer(ap, comp, stateData);
3913 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
3914 * "viewer_"+stateData.viewId
3916 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
3918 createChimeraViewer(viewerData, af, jprovider);
3923 * else Jmol (if pre-2.9, stateData contains JMOL state string)
3925 createJmolViewer(viewerData, af, jprovider);
3930 * Create a new Chimera viewer.
3936 protected void createChimeraViewer(
3937 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3938 jarInputStreamProvider jprovider)
3940 StructureViewerModel data = viewerData.getValue();
3941 String chimeraSessionFile = data.getStateData();
3944 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
3946 * NB this is the 'saved' viewId as in the project file XML, _not_ the
3947 * 'uniquified' sviewid used to reconstruct the viewer here
3949 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
3950 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
3953 Set<Entry<File, StructureData>> fileData = data.getFileData()
3955 List<PDBEntry> pdbs = new ArrayList<PDBEntry>();
3956 List<SequenceI[]> allseqs = new ArrayList<SequenceI[]>();
3957 for (Entry<File, StructureData> pdb : fileData)
3959 String filePath = pdb.getValue().getFilePath();
3960 String pdbId = pdb.getValue().getPdbId();
3961 // pdbs.add(new PDBEntry(filePath, pdbId));
3962 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
3963 final List<SequenceI> seqList = pdb.getValue().getSeqList();
3964 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
3968 boolean colourByChimera = data.isColourByViewer();
3969 boolean colourBySequence = data.isColourWithAlignPanel();
3971 // TODO use StructureViewer as a factory here, see JAL-1761
3972 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
3973 final SequenceI[][] seqsArray = allseqs.toArray(new SequenceI[allseqs
3975 String newViewId = viewerData.getKey();
3977 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
3978 af.alignPanel, pdbArray, seqsArray, colourByChimera,
3979 colourBySequence, newViewId);
3980 cvf.setSize(data.getWidth(), data.getHeight());
3981 cvf.setLocation(data.getX(), data.getY());
3985 * Create a new Jmol window. First parse the Jmol state to translate filenames
3986 * loaded into the view, and record the order in which files are shown in the
3987 * Jmol view, so we can add the sequence mappings in same order.
3993 protected void createJmolViewer(
3994 final Entry<String, StructureViewerModel> viewerData,
3995 AlignFrame af, jarInputStreamProvider jprovider)
3997 final StructureViewerModel svattrib = viewerData.getValue();
3998 String state = svattrib.getStateData();
4001 * Pre-2.9: state element value is the Jmol state string
4003 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
4006 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
4008 state = readJarEntry(jprovider,
4009 getViewerJarEntryName(svattrib.getViewId()));
4012 List<String> pdbfilenames = new ArrayList<String>();
4013 List<SequenceI[]> seqmaps = new ArrayList<SequenceI[]>();
4014 List<String> pdbids = new ArrayList<String>();
4015 StringBuilder newFileLoc = new StringBuilder(64);
4016 int cp = 0, ncp, ecp;
4017 Map<File, StructureData> oldFiles = svattrib.getFileData();
4018 while ((ncp = state.indexOf("load ", cp)) > -1)
4022 // look for next filename in load statement
4023 newFileLoc.append(state.substring(cp,
4024 ncp = (state.indexOf("\"", ncp + 1) + 1)));
4025 String oldfilenam = state.substring(ncp,
4026 ecp = state.indexOf("\"", ncp));
4027 // recover the new mapping data for this old filename
4028 // have to normalize filename - since Jmol and jalview do
4030 // translation differently.
4031 StructureData filedat = oldFiles.get(new File(oldfilenam));
4032 if (filedat == null)
4034 String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\");
4035 filedat = oldFiles.get(new File(reformatedOldFilename));
4037 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
4038 pdbfilenames.add(filedat.getFilePath());
4039 pdbids.add(filedat.getPdbId());
4040 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4041 newFileLoc.append("\"");
4042 cp = ecp + 1; // advance beyond last \" and set cursor so we can
4043 // look for next file statement.
4044 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
4048 // just append rest of state
4049 newFileLoc.append(state.substring(cp));
4053 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
4054 newFileLoc = new StringBuilder(state);
4055 newFileLoc.append("; load append ");
4056 for (File id : oldFiles.keySet())
4058 // add this and any other pdb files that should be present in
4060 StructureData filedat = oldFiles.get(id);
4061 newFileLoc.append(filedat.getFilePath());
4062 pdbfilenames.add(filedat.getFilePath());
4063 pdbids.add(filedat.getPdbId());
4064 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4065 newFileLoc.append(" \"");
4066 newFileLoc.append(filedat.getFilePath());
4067 newFileLoc.append("\"");
4070 newFileLoc.append(";");
4073 if (newFileLoc.length() == 0)
4077 int histbug = newFileLoc.indexOf("history = ");
4081 * change "history = [true|false];" to "history = [1|0];"
4084 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
4085 String val = (diff == -1) ? null : newFileLoc
4086 .substring(histbug, diff);
4087 if (val != null && val.length() >= 4)
4089 if (val.contains("e")) // eh? what can it be?
4091 if (val.trim().equals("true"))
4099 newFileLoc.replace(histbug, diff, val);
4104 final String[] pdbf = pdbfilenames.toArray(new String[pdbfilenames
4106 final String[] id = pdbids.toArray(new String[pdbids.size()]);
4107 final SequenceI[][] sq = seqmaps
4108 .toArray(new SequenceI[seqmaps.size()][]);
4109 final String fileloc = newFileLoc.toString();
4110 final String sviewid = viewerData.getKey();
4111 final AlignFrame alf = af;
4112 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
4113 svattrib.getWidth(), svattrib.getHeight());
4116 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
4121 JalviewStructureDisplayI sview = null;
4124 sview = new StructureViewer(alf.alignPanel
4125 .getStructureSelectionManager()).createView(
4126 StructureViewer.ViewerType.JMOL, pdbf, id, sq,
4127 alf.alignPanel, svattrib, fileloc, rect, sviewid);
4128 addNewStructureViewer(sview);
4129 } catch (OutOfMemoryError ex)
4131 new OOMWarning("restoring structure view for PDB id " + id,
4132 (OutOfMemoryError) ex.getCause());
4133 if (sview != null && sview.isVisible())
4135 sview.closeViewer(false);
4136 sview.setVisible(false);
4142 } catch (InvocationTargetException ex)
4144 warn("Unexpected error when opening Jmol view.", ex);
4146 } catch (InterruptedException e)
4148 // e.printStackTrace();
4154 * Generates a name for the entry in the project jar file to hold state
4155 * information for a structure viewer
4160 protected String getViewerJarEntryName(String viewId)
4162 return VIEWER_PREFIX + viewId;
4166 * Returns any open frame that matches given structure viewer data. The match
4167 * is based on the unique viewId, or (for older project versions) the frame's
4173 protected StructureViewerBase findMatchingViewer(
4174 Entry<String, StructureViewerModel> viewerData)
4176 final String sviewid = viewerData.getKey();
4177 final StructureViewerModel svattrib = viewerData.getValue();
4178 StructureViewerBase comp = null;
4179 JInternalFrame[] frames = getAllFrames();
4180 for (JInternalFrame frame : frames)
4182 if (frame instanceof StructureViewerBase)
4185 * Post jalview 2.4 schema includes structure view id
4188 && ((StructureViewerBase) frame).getViewId()
4191 comp = (StructureViewerBase) frame;
4192 break; // break added in 2.9
4195 * Otherwise test for matching position and size of viewer frame
4197 else if (frame.getX() == svattrib.getX()
4198 && frame.getY() == svattrib.getY()
4199 && frame.getHeight() == svattrib.getHeight()
4200 && frame.getWidth() == svattrib.getWidth())
4202 comp = (StructureViewerBase) frame;
4203 // no break in faint hope of an exact match on viewId
4211 * Link an AlignmentPanel to an existing structure viewer.
4216 * @param useinViewerSuperpos
4217 * @param usetoColourbyseq
4218 * @param viewerColouring
4220 protected void linkStructureViewer(AlignmentPanel ap,
4221 StructureViewerBase viewer, StructureViewerModel stateData)
4223 // NOTE: if the jalview project is part of a shared session then
4224 // view synchronization should/could be done here.
4226 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4227 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4228 final boolean viewerColouring = stateData.isColourByViewer();
4229 Map<File, StructureData> oldFiles = stateData.getFileData();
4232 * Add mapping for sequences in this view to an already open viewer
4234 final AAStructureBindingModel binding = viewer.getBinding();
4235 for (File id : oldFiles.keySet())
4237 // add this and any other pdb files that should be present in the
4239 StructureData filedat = oldFiles.get(id);
4240 String pdbFile = filedat.getFilePath();
4241 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4242 binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE);
4243 binding.addSequenceForStructFile(pdbFile, seq);
4245 // and add the AlignmentPanel's reference to the view panel
4246 viewer.addAlignmentPanel(ap);
4247 if (useinViewerSuperpos)
4249 viewer.useAlignmentPanelForSuperposition(ap);
4253 viewer.excludeAlignmentPanelForSuperposition(ap);
4255 if (usetoColourbyseq)
4257 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4261 viewer.excludeAlignmentPanelForColourbyseq(ap);
4266 * Get all frames within the Desktop.
4270 protected JInternalFrame[] getAllFrames()
4272 JInternalFrame[] frames = null;
4273 // TODO is this necessary - is it safe - risk of hanging?
4278 frames = Desktop.desktop.getAllFrames();
4279 } catch (ArrayIndexOutOfBoundsException e)
4281 // occasional No such child exceptions are thrown here...
4285 } catch (InterruptedException f)
4289 } while (frames == null);
4294 * Answers true if 'version' is equal to or later than 'supported', where each
4295 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4296 * changes. Development and test values for 'version' are leniently treated
4300 * - minimum version we are comparing against
4302 * - version of data being processsed
4305 public static boolean isVersionStringLaterThan(String supported,
4308 if (supported == null || version == null
4309 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4310 || version.equalsIgnoreCase("Test")
4311 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4313 System.err.println("Assuming project file with "
4314 + (version == null ? "null" : version)
4315 + " is compatible with Jalview version " + supported);
4320 return StringUtils.compareVersions(version, supported, "b") >= 0;
4324 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4326 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4328 if (newStructureViewers != null)
4330 sview.getBinding().setFinishedLoadingFromArchive(false);
4331 newStructureViewers.add(sview);
4335 protected void setLoadingFinishedForNewStructureViewers()
4337 if (newStructureViewers != null)
4339 for (JalviewStructureDisplayI sview : newStructureViewers)
4341 sview.getBinding().setFinishedLoadingFromArchive(true);
4343 newStructureViewers.clear();
4344 newStructureViewers = null;
4348 AlignFrame loadViewport(String file, JSeq[] JSEQ,
4349 List<SequenceI> hiddenSeqs, AlignmentI al,
4350 JalviewModelSequence jms, Viewport view, String uniqueSeqSetId,
4351 String viewId, List<JvAnnotRow> autoAlan)
4353 AlignFrame af = null;
4354 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
4355 uniqueSeqSetId, viewId);
4357 af.setFileName(file, FileFormat.Jalview);
4359 for (int i = 0; i < JSEQ.length; i++)
4361 af.viewport.setSequenceColour(af.viewport.getAlignment()
4362 .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour()));
4367 af.getViewport().setColourByReferenceSeq(true);
4368 af.getViewport().setDisplayReferenceSeq(true);
4371 af.viewport.setGatherViewsHere(view.getGatheredViews());
4373 if (view.getSequenceSetId() != null)
4375 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4377 af.viewport.setSequenceSetId(uniqueSeqSetId);
4380 // propagate shared settings to this new view
4381 af.viewport.setHistoryList(av.getHistoryList());
4382 af.viewport.setRedoList(av.getRedoList());
4386 viewportsAdded.put(uniqueSeqSetId, af.viewport);
4388 // TODO: check if this method can be called repeatedly without
4389 // side-effects if alignpanel already registered.
4390 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4392 // apply Hidden regions to view.
4393 if (hiddenSeqs != null)
4395 for (int s = 0; s < JSEQ.length; s++)
4397 SequenceGroup hidden = new SequenceGroup();
4398 boolean isRepresentative = false;
4399 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
4401 isRepresentative = true;
4402 SequenceI sequenceToHide = al.getSequenceAt(JSEQ[s]
4403 .getHiddenSequences(r));
4404 hidden.addSequence(sequenceToHide, false);
4405 // remove from hiddenSeqs list so we don't try to hide it twice
4406 hiddenSeqs.remove(sequenceToHide);
4408 if (isRepresentative)
4410 SequenceI representativeSequence = al.getSequenceAt(s);
4411 hidden.addSequence(representativeSequence, false);
4412 af.viewport.hideRepSequences(representativeSequence, hidden);
4416 SequenceI[] hseqs = hiddenSeqs.toArray(new SequenceI[hiddenSeqs
4418 af.viewport.hideSequence(hseqs);
4421 // recover view properties and display parameters
4422 if (view.getViewName() != null)
4424 af.viewport.viewName = view.getViewName();
4425 af.setInitialTabVisible();
4427 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
4430 af.viewport.setShowAnnotation(view.getShowAnnotation());
4431 af.viewport.setAbovePIDThreshold(view.getPidSelected());
4432 af.viewport.setThreshold(view.getPidThreshold());
4434 af.viewport.setColourText(view.getShowColourText());
4436 af.viewport.setConservationSelected(view.getConservationSelected());
4437 af.viewport.setIncrement(view.getConsThreshold());
4438 af.viewport.setShowJVSuffix(view.getShowFullId());
4439 af.viewport.setRightAlignIds(view.getRightAlignIds());
4440 af.viewport.setFont(
4441 new java.awt.Font(view.getFontName(), view.getFontStyle(), view
4442 .getFontSize()), true);
4443 ViewStyleI vs = af.viewport.getViewStyle();
4444 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
4445 af.viewport.setViewStyle(vs);
4446 // TODO: allow custom charWidth/Heights to be restored by updating them
4447 // after setting font - which means set above to false
4448 af.viewport.setRenderGaps(view.getRenderGaps());
4449 af.viewport.setWrapAlignment(view.getWrapAlignment());
4450 af.viewport.setShowAnnotation(view.getShowAnnotation());
4452 af.viewport.setShowBoxes(view.getShowBoxes());
4454 af.viewport.setShowText(view.getShowText());
4456 af.viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
4457 af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
4458 af.viewport.setThresholdTextColour(view.getTextColThreshold());
4459 af.viewport.setShowUnconserved(view.hasShowUnconserved() ? view
4460 .isShowUnconserved() : false);
4461 af.viewport.getRanges().setStartRes(view.getStartRes());
4462 // startSeq set in af.alignPanel.updateLayout below
4463 af.alignPanel.updateLayout();
4464 ColourSchemeI cs = null;
4465 // apply colourschemes
4466 if (view.getBgColour() != null)
4468 if (view.getBgColour().startsWith("ucs"))
4470 cs = getUserColourScheme(jms, view.getBgColour());
4472 else if (view.getBgColour().startsWith("Annotation"))
4474 AnnotationColours viewAnnColour = view.getAnnotationColours();
4475 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
4482 cs = ColourSchemeProperty.getColourScheme(al, view.getBgColour());
4486 af.viewport.setGlobalColourScheme(cs);
4487 af.viewport.getResidueShading().setThreshold(
4488 view.getPidThreshold(), true);
4489 af.viewport.getResidueShading().setConsensus(
4490 af.viewport.getSequenceConsensusHash());
4491 af.viewport.setColourAppliesToAllGroups(false);
4493 if (view.getConservationSelected() && cs != null)
4495 af.viewport.getResidueShading().setConservationInc(
4496 view.getConsThreshold());
4499 af.changeColour(cs);
4501 af.viewport.setColourAppliesToAllGroups(true);
4503 af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures());
4505 if (view.hasCentreColumnLabels())
4507 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
4509 if (view.hasIgnoreGapsinConsensus())
4511 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
4514 if (view.hasFollowHighlight())
4516 af.viewport.setFollowHighlight(view.getFollowHighlight());
4518 if (view.hasFollowSelection())
4520 af.viewport.followSelection = view.getFollowSelection();
4522 if (view.hasShowConsensusHistogram())
4524 af.viewport.setShowConsensusHistogram(view
4525 .getShowConsensusHistogram());
4529 af.viewport.setShowConsensusHistogram(true);
4531 if (view.hasShowSequenceLogo())
4533 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
4537 af.viewport.setShowSequenceLogo(false);
4539 if (view.hasNormaliseSequenceLogo())
4541 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
4543 if (view.hasShowDbRefTooltip())
4545 af.viewport.setShowDBRefs(view.getShowDbRefTooltip());
4547 if (view.hasShowNPfeatureTooltip())
4549 af.viewport.setShowNPFeats(view.hasShowNPfeatureTooltip());
4551 if (view.hasShowGroupConsensus())
4553 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
4557 af.viewport.setShowGroupConsensus(false);
4559 if (view.hasShowGroupConservation())
4561 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
4565 af.viewport.setShowGroupConservation(false);
4568 // recover featre settings
4569 if (jms.getFeatureSettings() != null)
4571 FeaturesDisplayed fdi;
4572 af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
4573 String[] renderOrder = new String[jms.getFeatureSettings()
4574 .getSettingCount()];
4575 Map<String, FeatureColourI> featureColours = new Hashtable<String, FeatureColourI>();
4576 Map<String, Float> featureOrder = new Hashtable<String, Float>();
4578 for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
4580 Setting setting = jms.getFeatureSettings().getSetting(fs);
4581 if (setting.hasMincolour())
4583 FeatureColourI gc = setting.hasMin() ? new FeatureColour(
4584 new Color(setting.getMincolour()), new Color(
4585 setting.getColour()), setting.getMin(),
4586 setting.getMax()) : new FeatureColour(new Color(
4587 setting.getMincolour()), new Color(setting.getColour()),
4589 if (setting.hasThreshold())
4591 gc.setThreshold(setting.getThreshold());
4592 int threshstate = setting.getThreshstate();
4593 // -1 = None, 0 = Below, 1 = Above threshold
4594 if (threshstate == 0)
4596 gc.setBelowThreshold(true);
4598 else if (threshstate == 1)
4600 gc.setAboveThreshold(true);
4603 gc.setAutoScaled(true); // default
4604 if (setting.hasAutoScale())
4606 gc.setAutoScaled(setting.getAutoScale());
4608 if (setting.hasColourByLabel())
4610 gc.setColourByLabel(setting.getColourByLabel());
4612 // and put in the feature colour table.
4613 featureColours.put(setting.getType(), gc);
4617 featureColours.put(setting.getType(), new FeatureColour(
4618 new Color(setting.getColour())));
4620 renderOrder[fs] = setting.getType();
4621 if (setting.hasOrder())
4623 featureOrder.put(setting.getType(), setting.getOrder());
4627 featureOrder.put(setting.getType(), new Float(fs
4628 / jms.getFeatureSettings().getSettingCount()));
4630 if (setting.getDisplay())
4632 fdi.setVisible(setting.getType());
4635 Map<String, Boolean> fgtable = new Hashtable<String, Boolean>();
4636 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
4638 Group grp = jms.getFeatureSettings().getGroup(gs);
4639 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
4641 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4642 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
4643 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
4644 FeatureRendererSettings frs = new FeatureRendererSettings(
4645 renderOrder, fgtable, featureColours, 1.0f, featureOrder);
4646 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
4647 .transferSettings(frs);
4651 if (view.getHiddenColumnsCount() > 0)
4653 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
4655 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(), view
4656 .getHiddenColumns(c).getEnd() // +1
4660 if (view.getCalcIdParam() != null)
4662 for (CalcIdParam calcIdParam : view.getCalcIdParam())
4664 if (calcIdParam != null)
4666 if (recoverCalcIdParam(calcIdParam, af.viewport))
4671 warn("Couldn't recover parameters for "
4672 + calcIdParam.getCalcId());
4677 af.setMenusFromViewport(af.viewport);
4678 af.setTitle(view.getTitle());
4679 // TODO: we don't need to do this if the viewport is aready visible.
4681 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
4682 * has a 'cdna/protein complement' view, in which case save it in order to
4683 * populate a SplitFrame once all views have been read in.
4685 String complementaryViewId = view.getComplementId();
4686 if (complementaryViewId == null)
4688 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
4690 // recompute any autoannotation
4691 af.alignPanel.updateAnnotation(false, true);
4692 reorderAutoannotation(af, al, autoAlan);
4693 af.alignPanel.alignmentChanged();
4697 splitFrameCandidates.put(view, af);
4703 * Reads saved data to restore Colour by Annotation settings
4705 * @param viewAnnColour
4709 * @param checkGroupAnnColour
4712 private ColourSchemeI constructAnnotationColour(
4713 AnnotationColours viewAnnColour, AlignFrame af, AlignmentI al,
4714 JalviewModelSequence jms, boolean checkGroupAnnColour)
4716 boolean propagateAnnColour = false;
4717 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
4718 if (checkGroupAnnColour && al.getGroups() != null
4719 && al.getGroups().size() > 0)
4721 // pre 2.8.1 behaviour
4722 // check to see if we should transfer annotation colours
4723 propagateAnnColour = true;
4724 for (SequenceGroup sg : al.getGroups())
4726 if (sg.getColourScheme() instanceof AnnotationColourGradient)
4728 propagateAnnColour = false;
4734 * 2.10.2- : saved annotationId is AlignmentAnnotation.annotationId
4736 String annotationId = viewAnnColour.getAnnotation();
4737 AlignmentAnnotation matchedAnnotation = annotationIds.get(annotationId);
4740 * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
4742 if (matchedAnnotation == null && annAlignment.getAlignmentAnnotation() != null)
4744 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
4747 .equals(annAlignment.getAlignmentAnnotation()[i].label))
4749 matchedAnnotation = annAlignment.getAlignmentAnnotation()[i];
4754 if (matchedAnnotation == null)
4756 System.err.println("Failed to match annotation colour scheme for "
4760 if (matchedAnnotation.getThreshold() == null)
4762 matchedAnnotation.setThreshold(new GraphLine(viewAnnColour.getThreshold(),
4763 "Threshold", Color.black));
4766 AnnotationColourGradient cs = null;
4767 if (viewAnnColour.getColourScheme().equals("None"))
4769 cs = new AnnotationColourGradient(matchedAnnotation, new Color(
4770 viewAnnColour.getMinColour()), new Color(
4771 viewAnnColour.getMaxColour()),
4772 viewAnnColour.getAboveThreshold());
4774 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
4776 cs = new AnnotationColourGradient(matchedAnnotation, getUserColourScheme(
4777 jms, viewAnnColour.getColourScheme()),
4778 viewAnnColour.getAboveThreshold());
4782 cs = new AnnotationColourGradient(matchedAnnotation,
4783 ColourSchemeProperty.getColourScheme(al,
4784 viewAnnColour.getColourScheme()),
4785 viewAnnColour.getAboveThreshold());
4788 boolean perSequenceOnly = viewAnnColour.isPerSequence();
4789 boolean useOriginalColours = viewAnnColour.isPredefinedColours();
4790 cs.setSeqAssociated(perSequenceOnly);
4791 cs.setPredefinedColours(useOriginalColours);
4793 if (propagateAnnColour && al.getGroups() != null)
4795 // Also use these settings for all the groups
4796 for (int g = 0; g < al.getGroups().size(); g++)
4798 SequenceGroup sg = al.getGroups().get(g);
4799 if (sg.getGroupColourScheme() == null)
4804 AnnotationColourGradient groupScheme = new AnnotationColourGradient(
4805 matchedAnnotation, sg.getColourScheme(),
4806 viewAnnColour.getAboveThreshold());
4807 sg.setColourScheme(groupScheme);
4808 groupScheme.setSeqAssociated(perSequenceOnly);
4809 groupScheme.setPredefinedColours(useOriginalColours);
4815 private void reorderAutoannotation(AlignFrame af, AlignmentI al,
4816 List<JvAnnotRow> autoAlan)
4818 // copy over visualization settings for autocalculated annotation in the
4820 if (al.getAlignmentAnnotation() != null)
4823 * Kludge for magic autoannotation names (see JAL-811)
4825 String[] magicNames = new String[] { "Consensus", "Quality",
4827 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
4828 Hashtable<String, JvAnnotRow> visan = new Hashtable<String, JvAnnotRow>();
4829 for (String nm : magicNames)
4831 visan.put(nm, nullAnnot);
4833 for (JvAnnotRow auan : autoAlan)
4835 visan.put(auan.template.label
4836 + (auan.template.getCalcId() == null ? "" : "\t"
4837 + auan.template.getCalcId()), auan);
4839 int hSize = al.getAlignmentAnnotation().length;
4840 List<JvAnnotRow> reorder = new ArrayList<JvAnnotRow>();
4841 // work through any autoCalculated annotation already on the view
4842 // removing it if it should be placed in a different location on the
4843 // annotation panel.
4844 List<String> remains = new ArrayList<String>(visan.keySet());
4845 for (int h = 0; h < hSize; h++)
4847 jalview.datamodel.AlignmentAnnotation jalan = al
4848 .getAlignmentAnnotation()[h];
4849 if (jalan.autoCalculated)
4852 JvAnnotRow valan = visan.get(k = jalan.label);
4853 if (jalan.getCalcId() != null)
4855 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
4860 // delete the auto calculated row from the alignment
4861 al.deleteAnnotation(jalan, false);
4865 if (valan != nullAnnot)
4867 if (jalan != valan.template)
4869 // newly created autoannotation row instance
4870 // so keep a reference to the visible annotation row
4871 // and copy over all relevant attributes
4872 if (valan.template.graphHeight >= 0)
4875 jalan.graphHeight = valan.template.graphHeight;
4877 jalan.visible = valan.template.visible;
4879 reorder.add(new JvAnnotRow(valan.order, jalan));
4884 // Add any (possibly stale) autocalculated rows that were not appended to
4885 // the view during construction
4886 for (String other : remains)
4888 JvAnnotRow othera = visan.get(other);
4889 if (othera != nullAnnot && othera.template.getCalcId() != null
4890 && othera.template.getCalcId().length() > 0)
4892 reorder.add(othera);
4895 // now put the automatic annotation in its correct place
4896 int s = 0, srt[] = new int[reorder.size()];
4897 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
4898 for (JvAnnotRow jvar : reorder)
4901 srt[s++] = jvar.order;
4904 jalview.util.QuickSort.sort(srt, rws);
4905 // and re-insert the annotation at its correct position
4906 for (JvAnnotRow jvar : rws)
4908 al.addAnnotation(jvar.template, jvar.order);
4910 af.alignPanel.adjustAnnotationHeight();
4914 Hashtable skipList = null;
4917 * TODO remove this method
4920 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
4921 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
4922 * throw new Error("Implementation Error. No skipList defined for this
4923 * Jalview2XML instance."); } return (AlignFrame)
4924 * skipList.get(view.getSequenceSetId()); }
4928 * Check if the Jalview view contained in object should be skipped or not.
4931 * @return true if view's sequenceSetId is a key in skipList
4933 private boolean skipViewport(JalviewModel object)
4935 if (skipList == null)
4940 if (skipList.containsKey(id = object.getJalviewModelSequence()
4941 .getViewport()[0].getSequenceSetId()))
4943 if (Cache.log != null && Cache.log.isDebugEnabled())
4945 Cache.log.debug("Skipping seuqence set id " + id);
4952 public void addToSkipList(AlignFrame af)
4954 if (skipList == null)
4956 skipList = new Hashtable();
4958 skipList.put(af.getViewport().getSequenceSetId(), af);
4961 public void clearSkipList()
4963 if (skipList != null)
4970 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
4971 boolean ignoreUnrefed)
4973 jalview.datamodel.AlignmentI ds = getDatasetFor(vamsasSet
4975 Vector dseqs = null;
4978 // create a list of new dataset sequences
4979 dseqs = new Vector();
4981 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
4983 Sequence vamsasSeq = vamsasSet.getSequence(i);
4984 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
4986 // create a new dataset
4989 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
4990 dseqs.copyInto(dsseqs);
4991 ds = new jalview.datamodel.Alignment(dsseqs);
4992 debug("Created new dataset " + vamsasSet.getDatasetId()
4993 + " for alignment " + System.identityHashCode(al));
4994 addDatasetRef(vamsasSet.getDatasetId(), ds);
4996 // set the dataset for the newly imported alignment.
4997 if (al.getDataset() == null && !ignoreUnrefed)
5006 * sequence definition to create/merge dataset sequence for
5010 * vector to add new dataset sequence to
5011 * @param ignoreUnrefed
5012 * - when true, don't create new sequences from vamsasSeq if it's id
5013 * doesn't already have an asssociated Jalview sequence.
5015 * - used to reorder the sequence in the alignment according to the
5016 * vamsasSeq array ordering, to preserve ordering of dataset
5018 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
5019 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed, int vseqpos)
5021 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
5023 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
5024 boolean reorder = false;
5025 SequenceI dsq = null;
5026 if (sq != null && sq.getDatasetSequence() != null)
5028 dsq = sq.getDatasetSequence();
5034 if (sq == null && ignoreUnrefed)
5038 String sqid = vamsasSeq.getDsseqid();
5041 // need to create or add a new dataset sequence reference to this sequence
5044 dsq = seqRefIds.get(sqid);
5049 // make a new dataset sequence
5050 dsq = sq.createDatasetSequence();
5053 // make up a new dataset reference for this sequence
5054 sqid = seqHash(dsq);
5056 dsq.setVamsasId(uniqueSetSuffix + sqid);
5057 seqRefIds.put(sqid, dsq);
5062 dseqs.addElement(dsq);
5067 ds.addSequence(dsq);
5073 { // make this dataset sequence sq's dataset sequence
5074 sq.setDatasetSequence(dsq);
5075 // and update the current dataset alignment
5080 if (!dseqs.contains(dsq))
5087 if (ds.findIndex(dsq) < 0)
5089 ds.addSequence(dsq);
5096 // TODO: refactor this as a merge dataset sequence function
5097 // now check that sq (the dataset sequence) sequence really is the union of
5098 // all references to it
5099 // boolean pre = sq.getStart() < dsq.getStart();
5100 // boolean post = sq.getEnd() > dsq.getEnd();
5104 // StringBuffer sb = new StringBuffer();
5105 String newres = jalview.analysis.AlignSeq.extractGaps(
5106 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
5107 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
5108 && newres.length() > dsq.getLength())
5110 // Update with the longer sequence.
5114 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
5115 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
5116 * sb.append(newres.substring(newres.length() - sq.getEnd() -
5117 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
5119 dsq.setSequence(newres);
5121 // TODO: merges will never happen if we 'know' we have the real dataset
5122 // sequence - this should be detected when id==dssid
5124 .println("DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
5125 // + (pre ? "prepended" : "") + " "
5126 // + (post ? "appended" : ""));
5131 // sequence refs are identical. We may need to update the existing dataset
5132 // alignment with this one, though.
5133 if (ds != null && dseqs == null)
5135 int opos = ds.findIndex(dsq);
5136 SequenceI tseq = null;
5137 if (opos != -1 && vseqpos != opos)
5139 // remove from old position
5140 ds.deleteSequence(dsq);
5142 if (vseqpos < ds.getHeight())
5144 if (vseqpos != opos)
5146 // save sequence at destination position
5147 tseq = ds.getSequenceAt(vseqpos);
5148 ds.replaceSequenceAt(vseqpos, dsq);
5149 ds.addSequence(tseq);
5154 ds.addSequence(dsq);
5161 * TODO use AlignmentI here and in related methods - needs
5162 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
5164 Hashtable<String, AlignmentI> datasetIds = null;
5166 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
5168 private AlignmentI getDatasetFor(String datasetId)
5170 if (datasetIds == null)
5172 datasetIds = new Hashtable<String, AlignmentI>();
5175 if (datasetIds.containsKey(datasetId))
5177 return datasetIds.get(datasetId);
5182 private void addDatasetRef(String datasetId, AlignmentI dataset)
5184 if (datasetIds == null)
5186 datasetIds = new Hashtable<String, AlignmentI>();
5188 datasetIds.put(datasetId, dataset);
5192 * make a new dataset ID for this jalview dataset alignment
5197 private String getDatasetIdRef(AlignmentI dataset)
5199 if (dataset.getDataset() != null)
5201 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
5203 String datasetId = makeHashCode(dataset, null);
5204 if (datasetId == null)
5206 // make a new datasetId and record it
5207 if (dataset2Ids == null)
5209 dataset2Ids = new IdentityHashMap<AlignmentI, String>();
5213 datasetId = dataset2Ids.get(dataset);
5215 if (datasetId == null)
5217 datasetId = "ds" + dataset2Ids.size() + 1;
5218 dataset2Ids.put(dataset, datasetId);
5224 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5226 for (int d = 0; d < sequence.getDBRefCount(); d++)
5228 DBRef dr = sequence.getDBRef(d);
5229 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
5230 sequence.getDBRef(d).getSource(), sequence.getDBRef(d)
5231 .getVersion(), sequence.getDBRef(d).getAccessionId());
5232 if (dr.getMapping() != null)
5234 entry.setMap(addMapping(dr.getMapping()));
5236 datasetSequence.addDBRef(entry);
5240 private jalview.datamodel.Mapping addMapping(Mapping m)
5242 SequenceI dsto = null;
5243 // Mapping m = dr.getMapping();
5244 int fr[] = new int[m.getMapListFromCount() * 2];
5245 Enumeration f = m.enumerateMapListFrom();
5246 for (int _i = 0; f.hasMoreElements(); _i += 2)
5248 MapListFrom mf = (MapListFrom) f.nextElement();
5249 fr[_i] = mf.getStart();
5250 fr[_i + 1] = mf.getEnd();
5252 int fto[] = new int[m.getMapListToCount() * 2];
5253 f = m.enumerateMapListTo();
5254 for (int _i = 0; f.hasMoreElements(); _i += 2)
5256 MapListTo mf = (MapListTo) f.nextElement();
5257 fto[_i] = mf.getStart();
5258 fto[_i + 1] = mf.getEnd();
5260 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto,
5261 fr, fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
5262 if (m.getMappingChoice() != null)
5264 MappingChoice mc = m.getMappingChoice();
5265 if (mc.getDseqFor() != null)
5267 String dsfor = "" + mc.getDseqFor();
5268 if (seqRefIds.containsKey(dsfor))
5273 jmap.setTo(seqRefIds.get(dsfor));
5277 frefedSequence.add(newMappingRef(dsfor, jmap));
5283 * local sequence definition
5285 Sequence ms = mc.getSequence();
5286 SequenceI djs = null;
5287 String sqid = ms.getDsseqid();
5288 if (sqid != null && sqid.length() > 0)
5291 * recover dataset sequence
5293 djs = seqRefIds.get(sqid);
5298 .println("Warning - making up dataset sequence id for DbRef sequence map reference");
5299 sqid = ((Object) ms).toString(); // make up a new hascode for
5300 // undefined dataset sequence hash
5301 // (unlikely to happen)
5307 * make a new dataset sequence and add it to refIds hash
5309 djs = new jalview.datamodel.Sequence(ms.getName(),
5311 djs.setStart(jmap.getMap().getToLowest());
5312 djs.setEnd(jmap.getMap().getToHighest());
5313 djs.setVamsasId(uniqueSetSuffix + sqid);
5315 incompleteSeqs.put(sqid, djs);
5316 seqRefIds.put(sqid, djs);
5319 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5328 public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
5329 boolean keepSeqRefs)
5332 JalviewModel jm = saveState(ap, null, null, null);
5337 jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
5341 uniqueSetSuffix = "";
5342 jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
5347 if (this.frefedSequence == null)
5349 frefedSequence = new Vector();
5352 viewportsAdded.clear();
5354 AlignFrame af = loadFromObject(jm, null, false, null);
5355 af.alignPanels.clear();
5356 af.closeMenuItem_actionPerformed(true);
5359 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5360 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5361 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5362 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5363 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5366 return af.alignPanel;
5370 * flag indicating if hashtables should be cleared on finalization TODO this
5371 * flag may not be necessary
5373 private final boolean _cleartables = true;
5375 private Hashtable jvids2vobj;
5380 * @see java.lang.Object#finalize()
5383 protected void finalize() throws Throwable
5385 // really make sure we have no buried refs left.
5390 this.seqRefIds = null;
5391 this.seqsToIds = null;
5395 private void warn(String msg)
5400 private void warn(String msg, Exception e)
5402 if (Cache.log != null)
5406 Cache.log.warn(msg, e);
5410 Cache.log.warn(msg);
5415 System.err.println("Warning: " + msg);
5418 e.printStackTrace();
5423 private void debug(String string)
5425 debug(string, null);
5428 private void debug(String msg, Exception e)
5430 if (Cache.log != null)
5434 Cache.log.debug(msg, e);
5438 Cache.log.debug(msg);
5443 System.err.println("Warning: " + msg);
5446 e.printStackTrace();
5452 * set the object to ID mapping tables used to write/recover objects and XML
5453 * ID strings for the jalview project. If external tables are provided then
5454 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
5455 * object goes out of scope. - also populates the datasetIds hashtable with
5456 * alignment objects containing dataset sequences
5459 * Map from ID strings to jalview datamodel
5461 * Map from jalview datamodel to ID strings
5465 public void setObjectMappingTables(Hashtable vobj2jv,
5466 IdentityHashMap jv2vobj)
5468 this.jv2vobj = jv2vobj;
5469 this.vobj2jv = vobj2jv;
5470 Iterator ds = jv2vobj.keySet().iterator();
5472 while (ds.hasNext())
5474 Object jvobj = ds.next();
5475 id = jv2vobj.get(jvobj).toString();
5476 if (jvobj instanceof jalview.datamodel.Alignment)
5478 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
5480 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
5483 else if (jvobj instanceof jalview.datamodel.Sequence)
5485 // register sequence object so the XML parser can recover it.
5486 if (seqRefIds == null)
5488 seqRefIds = new HashMap<String, SequenceI>();
5490 if (seqsToIds == null)
5492 seqsToIds = new IdentityHashMap<SequenceI, String>();
5494 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
5495 seqsToIds.put((SequenceI) jvobj, id);
5497 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
5500 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
5501 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
5502 if (jvann.annotationId == null)
5504 jvann.annotationId = anid;
5506 if (!jvann.annotationId.equals(anid))
5508 // TODO verify that this is the correct behaviour
5509 this.warn("Overriding Annotation ID for " + anid
5510 + " from different id : " + jvann.annotationId);
5511 jvann.annotationId = anid;
5514 else if (jvobj instanceof String)
5516 if (jvids2vobj == null)
5518 jvids2vobj = new Hashtable();
5519 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
5524 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
5530 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
5531 * objects created from the project archive. If string is null (default for
5532 * construction) then suffix will be set automatically.
5536 public void setUniqueSetSuffix(String string)
5538 uniqueSetSuffix = string;
5543 * uses skipList2 as the skipList for skipping views on sequence sets
5544 * associated with keys in the skipList
5548 public void setSkipList(Hashtable skipList2)
5550 skipList = skipList2;
5554 * Reads the jar entry of given name and returns its contents, or null if the
5555 * entry is not found.
5558 * @param jarEntryName
5561 protected String readJarEntry(jarInputStreamProvider jprovider,
5562 String jarEntryName)
5564 String result = null;
5565 BufferedReader in = null;
5570 * Reopen the jar input stream and traverse its entries to find a matching
5573 JarInputStream jin = jprovider.getJarInputStream();
5574 JarEntry entry = null;
5577 entry = jin.getNextJarEntry();
5578 } while (entry != null && !entry.getName().equals(jarEntryName));
5582 StringBuilder out = new StringBuilder(256);
5583 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
5586 while ((data = in.readLine()) != null)
5590 result = out.toString();
5594 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
5596 } catch (Exception ex)
5598 ex.printStackTrace();
5606 } catch (IOException e)
5617 * Returns an incrementing counter (0, 1, 2...)
5621 private synchronized int nextCounter()