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 if (jds.getSequenceFeatures() != null)
888 jalview.datamodel.SequenceFeature[] sf = jds.getSequenceFeatures();
890 while (index < sf.length)
892 Features features = new Features();
894 features.setBegin(sf[index].getBegin());
895 features.setEnd(sf[index].getEnd());
896 features.setDescription(sf[index].getDescription());
897 features.setType(sf[index].getType());
898 features.setFeatureGroup(sf[index].getFeatureGroup());
899 features.setScore(sf[index].getScore());
900 if (sf[index].links != null)
902 for (int l = 0; l < sf[index].links.size(); l++)
904 OtherData keyValue = new OtherData();
905 keyValue.setKey("LINK_" + l);
906 keyValue.setValue(sf[index].links.elementAt(l).toString());
907 features.addOtherData(keyValue);
910 if (sf[index].otherDetails != null)
913 Iterator<String> keys = sf[index].otherDetails.keySet()
915 while (keys.hasNext())
918 OtherData keyValue = new OtherData();
919 keyValue.setKey(key);
920 keyValue.setValue(sf[index].otherDetails.get(key).toString());
921 features.addOtherData(keyValue);
925 jseq.addFeatures(features);
930 if (jdatasq.getAllPDBEntries() != null)
932 Enumeration en = jdatasq.getAllPDBEntries().elements();
933 while (en.hasMoreElements())
935 Pdbids pdb = new Pdbids();
936 jalview.datamodel.PDBEntry entry = (jalview.datamodel.PDBEntry) en
939 String pdbId = entry.getId();
941 pdb.setType(entry.getType());
944 * Store any structure views associated with this sequence. This
945 * section copes with duplicate entries in the project, so a dataset
946 * only view *should* be coped with sensibly.
948 // This must have been loaded, is it still visible?
949 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
950 String matchedFile = null;
951 for (int f = frames.length - 1; f > -1; f--)
953 if (frames[f] instanceof StructureViewerBase)
955 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
956 matchedFile = saveStructureState(ap, jds, pdb, entry,
957 viewIds, matchedFile, viewFrame);
959 * Only store each structure viewer's state once in the project
960 * jar. First time through only (storeDS==false)
962 String viewId = viewFrame.getViewId();
963 if (!storeDS && !viewIds.contains(viewId))
968 String viewerState = viewFrame.getStateInfo();
969 writeJarEntry(jout, getViewerJarEntryName(viewId),
970 viewerState.getBytes());
971 } catch (IOException e)
973 System.err.println("Error saving viewer state: "
980 if (matchedFile != null || entry.getFile() != null)
982 if (entry.getFile() != null)
985 matchedFile = entry.getFile();
987 pdb.setFile(matchedFile); // entry.getFile());
988 if (pdbfiles == null)
990 pdbfiles = new ArrayList<String>();
993 if (!pdbfiles.contains(pdbId))
996 copyFileToJar(jout, matchedFile, pdbId);
1000 Enumeration<String> props = entry.getProperties();
1001 if (props.hasMoreElements())
1003 PdbentryItem item = new PdbentryItem();
1004 while (props.hasMoreElements())
1006 Property prop = new Property();
1007 String key = props.nextElement();
1009 prop.setValue(entry.getProperty(key).toString());
1010 item.addProperty(prop);
1012 pdb.addPdbentryItem(item);
1015 jseq.addPdbids(pdb);
1019 saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
1024 if (!storeDS && av.hasHiddenRows())
1026 jal = av.getAlignment();
1030 if (storeDS && jal.getCodonFrames() != null)
1032 List<AlignedCodonFrame> jac = jal.getCodonFrames();
1033 for (AlignedCodonFrame acf : jac)
1035 AlcodonFrame alc = new AlcodonFrame();
1036 if (acf.getProtMappings() != null
1037 && acf.getProtMappings().length > 0)
1039 boolean hasMap = false;
1040 SequenceI[] dnas = acf.getdnaSeqs();
1041 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1042 for (int m = 0; m < pmaps.length; m++)
1044 AlcodMap alcmap = new AlcodMap();
1045 alcmap.setDnasq(seqHash(dnas[m]));
1046 alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
1048 alc.addAlcodMap(alcmap);
1053 vamsasSet.addAlcodonFrame(alc);
1056 // TODO: delete this ? dead code from 2.8.3->2.9 ?
1058 // AlcodonFrame alc = new AlcodonFrame();
1059 // vamsasSet.addAlcodonFrame(alc);
1060 // for (int p = 0; p < acf.aaWidth; p++)
1062 // Alcodon cmap = new Alcodon();
1063 // if (acf.codons[p] != null)
1065 // // Null codons indicate a gapped column in the translated peptide
1067 // cmap.setPos1(acf.codons[p][0]);
1068 // cmap.setPos2(acf.codons[p][1]);
1069 // cmap.setPos3(acf.codons[p][2]);
1071 // alc.addAlcodon(cmap);
1073 // if (acf.getProtMappings() != null
1074 // && acf.getProtMappings().length > 0)
1076 // SequenceI[] dnas = acf.getdnaSeqs();
1077 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1078 // for (int m = 0; m < pmaps.length; m++)
1080 // AlcodMap alcmap = new AlcodMap();
1081 // alcmap.setDnasq(seqHash(dnas[m]));
1082 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
1084 // alc.addAlcodMap(alcmap);
1091 // /////////////////////////////////
1092 if (!storeDS && av.currentTree != null)
1094 // FIND ANY ASSOCIATED TREES
1095 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
1096 if (Desktop.desktop != null)
1098 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1100 for (int t = 0; t < frames.length; t++)
1102 if (frames[t] instanceof TreePanel)
1104 TreePanel tp = (TreePanel) frames[t];
1106 if (tp.treeCanvas.av.getAlignment() == jal)
1108 Tree tree = new Tree();
1109 tree.setTitle(tp.getTitle());
1110 tree.setCurrentTree((av.currentTree == tp.getTree()));
1111 tree.setNewick(tp.getTree().print());
1112 tree.setThreshold(tp.treeCanvas.threshold);
1114 tree.setFitToWindow(tp.fitToWindow.getState());
1115 tree.setFontName(tp.getTreeFont().getName());
1116 tree.setFontSize(tp.getTreeFont().getSize());
1117 tree.setFontStyle(tp.getTreeFont().getStyle());
1118 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
1120 tree.setShowBootstrap(tp.bootstrapMenu.getState());
1121 tree.setShowDistances(tp.distanceMenu.getState());
1123 tree.setHeight(tp.getHeight());
1124 tree.setWidth(tp.getWidth());
1125 tree.setXpos(tp.getX());
1126 tree.setYpos(tp.getY());
1127 tree.setId(makeHashCode(tp, null));
1137 * store forward refs from an annotationRow to any groups
1139 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<SequenceGroup, String>();
1142 for (SequenceI sq : jal.getSequences())
1144 // Store annotation on dataset sequences only
1145 AlignmentAnnotation[] aa = sq.getAnnotation();
1146 if (aa != null && aa.length > 0)
1148 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1155 if (jal.getAlignmentAnnotation() != null)
1157 // Store the annotation shown on the alignment.
1158 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1159 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1164 if (jal.getGroups() != null)
1166 JGroup[] groups = new JGroup[jal.getGroups().size()];
1168 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1170 JGroup jGroup = new JGroup();
1171 groups[++i] = jGroup;
1173 jGroup.setStart(sg.getStartRes());
1174 jGroup.setEnd(sg.getEndRes());
1175 jGroup.setName(sg.getName());
1176 if (groupRefs.containsKey(sg))
1178 // group has references so set its ID field
1179 jGroup.setId(groupRefs.get(sg));
1181 ColourSchemeI colourScheme = sg.getColourScheme();
1182 if (colourScheme != null)
1184 ResidueShaderI groupColourScheme = sg
1185 .getGroupColourScheme();
1186 if (groupColourScheme.conservationApplied())
1188 jGroup.setConsThreshold(groupColourScheme.getConservationInc());
1190 if (colourScheme instanceof jalview.schemes.UserColourScheme)
1192 jGroup.setColour(setUserColourScheme(colourScheme,
1197 jGroup.setColour(colourScheme.getSchemeName());
1200 else if (colourScheme instanceof jalview.schemes.AnnotationColourGradient)
1202 jGroup.setColour("AnnotationColourGradient");
1203 jGroup.setAnnotationColours(constructAnnotationColours(
1204 (jalview.schemes.AnnotationColourGradient) colourScheme,
1207 else if (colourScheme instanceof jalview.schemes.UserColourScheme)
1209 jGroup.setColour(setUserColourScheme(colourScheme,
1214 jGroup.setColour(colourScheme.getSchemeName());
1217 jGroup.setPidThreshold(groupColourScheme.getThreshold());
1220 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1221 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1222 jGroup.setDisplayText(sg.getDisplayText());
1223 jGroup.setColourText(sg.getColourText());
1224 jGroup.setTextCol1(sg.textColour.getRGB());
1225 jGroup.setTextCol2(sg.textColour2.getRGB());
1226 jGroup.setTextColThreshold(sg.thresholdTextColour);
1227 jGroup.setShowUnconserved(sg.getShowNonconserved());
1228 jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1229 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1230 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1231 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1232 for (SequenceI seq : sg.getSequences())
1234 jGroup.addSeq(seqHash(seq));
1238 jms.setJGroup(groups);
1242 // /////////SAVE VIEWPORT
1243 Viewport view = new Viewport();
1244 view.setTitle(ap.alignFrame.getTitle());
1245 view.setSequenceSetId(makeHashCode(av.getSequenceSetId(),
1246 av.getSequenceSetId()));
1247 view.setId(av.getViewId());
1248 if (av.getCodingComplement() != null)
1250 view.setComplementId(av.getCodingComplement().getViewId());
1252 view.setViewName(av.viewName);
1253 view.setGatheredViews(av.isGatherViewsHere());
1255 Rectangle size = ap.av.getExplodedGeometry();
1256 Rectangle position = size;
1259 size = ap.alignFrame.getBounds();
1260 if (av.getCodingComplement() != null)
1262 position = ((SplitFrame) ap.alignFrame.getSplitViewContainer())
1270 view.setXpos(position.x);
1271 view.setYpos(position.y);
1273 view.setWidth(size.width);
1274 view.setHeight(size.height);
1276 view.setStartRes(vpRanges.getStartRes());
1277 view.setStartSeq(vpRanges.getStartSeq());
1279 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1281 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1284 else if (av.getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1286 AnnotationColours ac = constructAnnotationColours(
1287 (jalview.schemes.AnnotationColourGradient) av
1288 .getGlobalColourScheme(),
1291 view.setAnnotationColours(ac);
1292 view.setBgColour("AnnotationColourGradient");
1296 view.setBgColour(ColourSchemeProperty.getColourName(av
1297 .getGlobalColourScheme()));
1300 ResidueShaderI vcs = av.getResidueShading();
1301 ColourSchemeI cs = av.getGlobalColourScheme();
1305 if (vcs.conservationApplied())
1307 view.setConsThreshold(vcs.getConservationInc());
1308 if (cs instanceof jalview.schemes.UserColourScheme)
1310 view.setBgColour(setUserColourScheme(cs, userColours, jms));
1313 view.setPidThreshold(vcs.getThreshold());
1316 view.setConservationSelected(av.getConservationSelected());
1317 view.setPidSelected(av.getAbovePIDThreshold());
1318 view.setFontName(av.font.getName());
1319 view.setFontSize(av.font.getSize());
1320 view.setFontStyle(av.font.getStyle());
1321 view.setScaleProteinAsCdna(av.getViewStyle().isScaleProteinAsCdna());
1322 view.setRenderGaps(av.isRenderGaps());
1323 view.setShowAnnotation(av.isShowAnnotation());
1324 view.setShowBoxes(av.getShowBoxes());
1325 view.setShowColourText(av.getColourText());
1326 view.setShowFullId(av.getShowJVSuffix());
1327 view.setRightAlignIds(av.isRightAlignIds());
1328 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1329 view.setShowText(av.getShowText());
1330 view.setShowUnconserved(av.getShowUnconserved());
1331 view.setWrapAlignment(av.getWrapAlignment());
1332 view.setTextCol1(av.getTextColour().getRGB());
1333 view.setTextCol2(av.getTextColour2().getRGB());
1334 view.setTextColThreshold(av.getThresholdTextColour());
1335 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1336 view.setShowSequenceLogo(av.isShowSequenceLogo());
1337 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1338 view.setShowGroupConsensus(av.isShowGroupConsensus());
1339 view.setShowGroupConservation(av.isShowGroupConservation());
1340 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1341 view.setShowDbRefTooltip(av.isShowDBRefs());
1342 view.setFollowHighlight(av.isFollowHighlight());
1343 view.setFollowSelection(av.followSelection);
1344 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1345 if (av.getFeaturesDisplayed() != null)
1347 jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
1349 String[] renderOrder = ap.getSeqPanel().seqCanvas
1350 .getFeatureRenderer().getRenderOrder()
1351 .toArray(new String[0]);
1353 Vector<String> settingsAdded = new Vector<String>();
1354 if (renderOrder != null)
1356 for (String featureType : renderOrder)
1358 FeatureColourI fcol = ap.getSeqPanel().seqCanvas
1359 .getFeatureRenderer().getFeatureStyle(featureType);
1360 Setting setting = new Setting();
1361 setting.setType(featureType);
1362 if (!fcol.isSimpleColour())
1364 setting.setColour(fcol.getMaxColour().getRGB());
1365 setting.setMincolour(fcol.getMinColour().getRGB());
1366 setting.setMin(fcol.getMin());
1367 setting.setMax(fcol.getMax());
1368 setting.setColourByLabel(fcol.isColourByLabel());
1369 setting.setAutoScale(fcol.isAutoScaled());
1370 setting.setThreshold(fcol.getThreshold());
1371 // -1 = No threshold, 0 = Below, 1 = Above
1372 setting.setThreshstate(fcol.isAboveThreshold() ? 1 : (fcol
1373 .isBelowThreshold() ? 0 : -1));
1377 setting.setColour(fcol.getColour().getRGB());
1380 setting.setDisplay(av.getFeaturesDisplayed().isVisible(
1382 float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1383 .getOrder(featureType);
1386 setting.setOrder(rorder);
1388 fs.addSetting(setting);
1389 settingsAdded.addElement(featureType);
1393 // is groups actually supposed to be a map here ?
1394 Iterator<String> en = ap.getSeqPanel().seqCanvas
1395 .getFeatureRenderer().getFeatureGroups().iterator();
1396 Vector<String> groupsAdded = new Vector<String>();
1397 while (en.hasNext())
1399 String grp = en.next();
1400 if (groupsAdded.contains(grp))
1404 Group g = new Group();
1406 g.setDisplay(((Boolean) ap.getSeqPanel().seqCanvas
1407 .getFeatureRenderer().checkGroupVisibility(grp, false))
1410 groupsAdded.addElement(grp);
1412 jms.setFeatureSettings(fs);
1415 if (av.hasHiddenColumns())
1417 jalview.datamodel.HiddenColumns hidden = av.getAlignment()
1418 .getHiddenColumns();
1419 if (hidden == null || hidden.getHiddenRegions() == null)
1421 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1425 for (int c = 0; c < hidden.getHiddenRegions()
1428 int[] region = hidden.getHiddenRegions()
1430 HiddenColumns hc = new HiddenColumns();
1431 hc.setStart(region[0]);
1432 hc.setEnd(region[1]);
1433 view.addHiddenColumns(hc);
1437 if (calcIdSet.size() > 0)
1439 for (String calcId : calcIdSet)
1441 if (calcId.trim().length() > 0)
1443 CalcIdParam cidp = createCalcIdParam(calcId, av);
1444 // Some calcIds have no parameters.
1447 view.addCalcIdParam(cidp);
1453 jms.addViewport(view);
1455 object.setJalviewModelSequence(jms);
1456 object.getVamsasModel().addSequenceSet(vamsasSet);
1458 if (jout != null && fileName != null)
1460 // We may not want to write the object to disk,
1461 // eg we can copy the alignViewport to a new view object
1462 // using save and then load
1465 System.out.println("Writing jar entry " + fileName);
1466 JarEntry entry = new JarEntry(fileName);
1467 jout.putNextEntry(entry);
1468 PrintWriter pout = new PrintWriter(new OutputStreamWriter(jout,
1470 Marshaller marshaller = new Marshaller(pout);
1471 marshaller.marshal(object);
1474 } catch (Exception ex)
1476 // TODO: raise error in GUI if marshalling failed.
1477 ex.printStackTrace();
1484 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1485 * for each viewer, with
1487 * <li>viewer geometry (position, size, split pane divider location)</li>
1488 * <li>index of the selected structure in the viewer (currently shows gapped
1490 * <li>the id of the annotation holding RNA secondary structure</li>
1491 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1493 * Varna viewer state is also written out (in native Varna XML) to separate
1494 * project jar entries. A separate entry is written for each RNA structure
1495 * displayed, with the naming convention
1497 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
1505 * @param storeDataset
1507 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
1508 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
1509 boolean storeDataset)
1511 if (Desktop.desktop == null)
1515 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1516 for (int f = frames.length - 1; f > -1; f--)
1518 if (frames[f] instanceof AppVarna)
1520 AppVarna varna = (AppVarna) frames[f];
1522 * link the sequence to every viewer that is showing it and is linked to
1523 * its alignment panel
1525 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1527 String viewId = varna.getViewId();
1528 RnaViewer rna = new RnaViewer();
1529 rna.setViewId(viewId);
1530 rna.setTitle(varna.getTitle());
1531 rna.setXpos(varna.getX());
1532 rna.setYpos(varna.getY());
1533 rna.setWidth(varna.getWidth());
1534 rna.setHeight(varna.getHeight());
1535 rna.setDividerLocation(varna.getDividerLocation());
1536 rna.setSelectedRna(varna.getSelectedIndex());
1537 jseq.addRnaViewer(rna);
1540 * Store each Varna panel's state once in the project per sequence.
1541 * First time through only (storeDataset==false)
1543 // boolean storeSessions = false;
1544 // String sequenceViewId = viewId + seqsToIds.get(jds);
1545 // if (!storeDataset && !viewIds.contains(sequenceViewId))
1547 // viewIds.add(sequenceViewId);
1548 // storeSessions = true;
1550 for (RnaModel model : varna.getModels())
1552 if (model.seq == jds)
1555 * VARNA saves each view (sequence or alignment secondary
1556 * structure, gapped or trimmed) as a separate XML file
1558 String jarEntryName = rnaSessions.get(model);
1559 if (jarEntryName == null)
1562 String varnaStateFile = varna.getStateInfo(model.rna);
1563 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
1564 copyFileToJar(jout, varnaStateFile, jarEntryName);
1565 rnaSessions.put(model, jarEntryName);
1567 SecondaryStructure ss = new SecondaryStructure();
1568 String annotationId = varna.getAnnotation(jds).annotationId;
1569 ss.setAnnotationId(annotationId);
1570 ss.setViewerState(jarEntryName);
1571 ss.setGapped(model.gapped);
1572 ss.setTitle(model.title);
1573 rna.addSecondaryStructure(ss);
1582 * Copy the contents of a file to a new entry added to the output jar
1586 * @param jarEntryName
1588 protected void copyFileToJar(JarOutputStream jout, String infilePath,
1589 String jarEntryName)
1591 DataInputStream dis = null;
1594 File file = new File(infilePath);
1595 if (file.exists() && jout != null)
1597 dis = new DataInputStream(new FileInputStream(file));
1598 byte[] data = new byte[(int) file.length()];
1599 dis.readFully(data);
1600 writeJarEntry(jout, jarEntryName, data);
1602 } catch (Exception ex)
1604 ex.printStackTrace();
1612 } catch (IOException e)
1621 * Write the data to a new entry of given name in the output jar file
1624 * @param jarEntryName
1626 * @throws IOException
1628 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
1629 byte[] data) throws IOException
1633 System.out.println("Writing jar entry " + jarEntryName);
1634 jout.putNextEntry(new JarEntry(jarEntryName));
1635 DataOutputStream dout = new DataOutputStream(jout);
1636 dout.write(data, 0, data.length);
1643 * Save the state of a structure viewer
1648 * the archive XML element under which to save the state
1651 * @param matchedFile
1655 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
1656 Pdbids pdb, PDBEntry entry, List<String> viewIds,
1657 String matchedFile, StructureViewerBase viewFrame)
1659 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
1662 * Look for any bindings for this viewer to the PDB file of interest
1663 * (including part matches excluding chain id)
1665 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
1667 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
1668 final String pdbId = pdbentry.getId();
1669 if (!pdbId.equals(entry.getId())
1670 && !(entry.getId().length() > 4 && entry.getId()
1671 .toLowerCase().startsWith(pdbId.toLowerCase())))
1674 * not interested in a binding to a different PDB entry here
1678 if (matchedFile == null)
1680 matchedFile = pdbentry.getFile();
1682 else if (!matchedFile.equals(pdbentry.getFile()))
1685 .warn("Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
1686 + pdbentry.getFile());
1690 // can get at it if the ID
1691 // match is ambiguous (e.g.
1694 for (int smap = 0; smap < viewFrame.getBinding().getSequence()[peid].length; smap++)
1696 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
1697 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
1699 StructureState state = new StructureState();
1700 state.setVisible(true);
1701 state.setXpos(viewFrame.getX());
1702 state.setYpos(viewFrame.getY());
1703 state.setWidth(viewFrame.getWidth());
1704 state.setHeight(viewFrame.getHeight());
1705 final String viewId = viewFrame.getViewId();
1706 state.setViewId(viewId);
1707 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
1708 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
1709 state.setColourByJmol(viewFrame.isColouredByViewer());
1710 state.setType(viewFrame.getViewerType().toString());
1711 pdb.addStructureState(state);
1719 * Populates the AnnotationColours xml for save. This captures the settings of
1720 * the options in the 'Colour by Annotation' dialog.
1723 * @param userColours
1727 private AnnotationColours constructAnnotationColours(
1728 AnnotationColourGradient acg, List<UserColourScheme> userColours,
1729 JalviewModelSequence jms)
1731 AnnotationColours ac = new AnnotationColours();
1732 ac.setAboveThreshold(acg.getAboveThreshold());
1733 ac.setThreshold(acg.getAnnotationThreshold());
1734 // 2.10.2 save annotationId (unique) not annotation label
1735 ac.setAnnotation(acg.getAnnotation().annotationId);
1736 if (acg.getBaseColour() instanceof UserColourScheme)
1738 ac.setColourScheme(setUserColourScheme(acg.getBaseColour(),
1743 ac.setColourScheme(ColourSchemeProperty.getColourName(acg.getBaseColour()));
1746 ac.setMaxColour(acg.getMaxColour().getRGB());
1747 ac.setMinColour(acg.getMinColour().getRGB());
1748 ac.setPerSequence(acg.isSeqAssociated());
1749 ac.setPredefinedColours(acg.isPredefinedColours());
1753 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
1754 IdentityHashMap<SequenceGroup, String> groupRefs,
1755 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
1756 SequenceSet vamsasSet)
1759 for (int i = 0; i < aa.length; i++)
1761 Annotation an = new Annotation();
1763 AlignmentAnnotation annotation = aa[i];
1764 if (annotation.annotationId != null)
1766 annotationIds.put(annotation.annotationId, annotation);
1769 an.setId(annotation.annotationId);
1771 an.setVisible(annotation.visible);
1773 an.setDescription(annotation.description);
1775 if (annotation.sequenceRef != null)
1777 // 2.9 JAL-1781 xref on sequence id rather than name
1778 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
1780 if (annotation.groupRef != null)
1782 String groupIdr = groupRefs.get(annotation.groupRef);
1783 if (groupIdr == null)
1785 // make a locally unique String
1787 annotation.groupRef,
1788 groupIdr = ("" + System.currentTimeMillis()
1789 + annotation.groupRef.getName() + groupRefs
1792 an.setGroupRef(groupIdr.toString());
1795 // store all visualization attributes for annotation
1796 an.setGraphHeight(annotation.graphHeight);
1797 an.setCentreColLabels(annotation.centreColLabels);
1798 an.setScaleColLabels(annotation.scaleColLabel);
1799 an.setShowAllColLabels(annotation.showAllColLabels);
1800 an.setBelowAlignment(annotation.belowAlignment);
1802 if (annotation.graph > 0)
1805 an.setGraphType(annotation.graph);
1806 an.setGraphGroup(annotation.graphGroup);
1807 if (annotation.getThreshold() != null)
1809 ThresholdLine line = new ThresholdLine();
1810 line.setLabel(annotation.getThreshold().label);
1811 line.setValue(annotation.getThreshold().value);
1812 line.setColour(annotation.getThreshold().colour.getRGB());
1813 an.setThresholdLine(line);
1821 an.setLabel(annotation.label);
1823 if (annotation == av.getAlignmentQualityAnnot()
1824 || annotation == av.getAlignmentConservationAnnotation()
1825 || annotation == av.getAlignmentConsensusAnnotation()
1826 || annotation.autoCalculated)
1828 // new way of indicating autocalculated annotation -
1829 an.setAutoCalculated(annotation.autoCalculated);
1831 if (annotation.hasScore())
1833 an.setScore(annotation.getScore());
1836 if (annotation.getCalcId() != null)
1838 calcIdSet.add(annotation.getCalcId());
1839 an.setCalcId(annotation.getCalcId());
1841 if (annotation.hasProperties())
1843 for (String pr : annotation.getProperties())
1845 Property prop = new Property();
1847 prop.setValue(annotation.getProperty(pr));
1848 an.addProperty(prop);
1852 AnnotationElement ae;
1853 if (annotation.annotations != null)
1855 an.setScoreOnly(false);
1856 for (int a = 0; a < annotation.annotations.length; a++)
1858 if ((annotation == null) || (annotation.annotations[a] == null))
1863 ae = new AnnotationElement();
1864 if (annotation.annotations[a].description != null)
1866 ae.setDescription(annotation.annotations[a].description);
1868 if (annotation.annotations[a].displayCharacter != null)
1870 ae.setDisplayCharacter(annotation.annotations[a].displayCharacter);
1873 if (!Float.isNaN(annotation.annotations[a].value))
1875 ae.setValue(annotation.annotations[a].value);
1879 if (annotation.annotations[a].secondaryStructure > ' ')
1881 ae.setSecondaryStructure(annotation.annotations[a].secondaryStructure
1885 if (annotation.annotations[a].colour != null
1886 && annotation.annotations[a].colour != java.awt.Color.black)
1888 ae.setColour(annotation.annotations[a].colour.getRGB());
1891 an.addAnnotationElement(ae);
1892 if (annotation.autoCalculated)
1894 // only write one non-null entry into the annotation row -
1895 // sufficient to get the visualization attributes necessary to
1903 an.setScoreOnly(true);
1905 if (!storeDS || (storeDS && !annotation.autoCalculated))
1907 // skip autocalculated annotation - these are only provided for
1909 vamsasSet.addAnnotation(an);
1915 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
1917 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
1918 if (settings != null)
1920 CalcIdParam vCalcIdParam = new CalcIdParam();
1921 vCalcIdParam.setCalcId(calcId);
1922 vCalcIdParam.addServiceURL(settings.getServiceURI());
1923 // generic URI allowing a third party to resolve another instance of the
1924 // service used for this calculation
1925 for (String urls : settings.getServiceURLs())
1927 vCalcIdParam.addServiceURL(urls);
1929 vCalcIdParam.setVersion("1.0");
1930 if (settings.getPreset() != null)
1932 WsParamSetI setting = settings.getPreset();
1933 vCalcIdParam.setName(setting.getName());
1934 vCalcIdParam.setDescription(setting.getDescription());
1938 vCalcIdParam.setName("");
1939 vCalcIdParam.setDescription("Last used parameters");
1941 // need to be able to recover 1) settings 2) user-defined presets or
1942 // recreate settings from preset 3) predefined settings provided by
1943 // service - or settings that can be transferred (or discarded)
1944 vCalcIdParam.setParameters(settings.getWsParamFile().replace("\n",
1946 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
1947 // todo - decide if updateImmediately is needed for any projects.
1949 return vCalcIdParam;
1954 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
1957 if (calcIdParam.getVersion().equals("1.0"))
1959 Jws2Instance service = Jws2Discoverer.getDiscoverer()
1960 .getPreferredServiceFor(calcIdParam.getServiceURL());
1961 if (service != null)
1963 WsParamSetI parmSet = null;
1966 parmSet = service.getParamStore().parseServiceParameterFile(
1967 calcIdParam.getName(), calcIdParam.getDescription(),
1968 calcIdParam.getServiceURL(),
1969 calcIdParam.getParameters().replace("|\\n|", "\n"));
1970 } catch (IOException x)
1972 warn("Couldn't parse parameter data for "
1973 + calcIdParam.getCalcId(), x);
1976 List<ArgumentI> argList = null;
1977 if (calcIdParam.getName().length() > 0)
1979 parmSet = service.getParamStore()
1980 .getPreset(calcIdParam.getName());
1981 if (parmSet != null)
1983 // TODO : check we have a good match with settings in AACon -
1984 // otherwise we'll need to create a new preset
1989 argList = parmSet.getArguments();
1992 AAConSettings settings = new AAConSettings(
1993 calcIdParam.isAutoUpdate(), service, parmSet, argList);
1994 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
1995 calcIdParam.isNeedsUpdate());
2000 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
2004 throw new Error(MessageManager.formatMessage(
2005 "error.unsupported_version_calcIdparam",
2006 new Object[] { calcIdParam.toString() }));
2010 * External mapping between jalview objects and objects yielding a valid and
2011 * unique object ID string. This is null for normal Jalview project IO, but
2012 * non-null when a jalview project is being read or written as part of a
2015 IdentityHashMap jv2vobj = null;
2018 * Construct a unique ID for jvobj using either existing bindings or if none
2019 * exist, the result of the hashcode call for the object.
2022 * jalview data object
2023 * @return unique ID for referring to jvobj
2025 private String makeHashCode(Object jvobj, String altCode)
2027 if (jv2vobj != null)
2029 Object id = jv2vobj.get(jvobj);
2032 return id.toString();
2034 // check string ID mappings
2035 if (jvids2vobj != null && jvobj instanceof String)
2037 id = jvids2vobj.get(jvobj);
2041 return id.toString();
2043 // give up and warn that something has gone wrong
2044 warn("Cannot find ID for object in external mapping : " + jvobj);
2050 * return local jalview object mapped to ID, if it exists
2054 * @return null or object bound to idcode
2056 private Object retrieveExistingObj(String idcode)
2058 if (idcode != null && vobj2jv != null)
2060 return vobj2jv.get(idcode);
2066 * binding from ID strings from external mapping table to jalview data model
2069 private Hashtable vobj2jv;
2071 private Sequence createVamsasSequence(String id, SequenceI jds)
2073 return createVamsasSequence(true, id, jds, null);
2076 private Sequence createVamsasSequence(boolean recurse, String id,
2077 SequenceI jds, SequenceI parentseq)
2079 Sequence vamsasSeq = new Sequence();
2080 vamsasSeq.setId(id);
2081 vamsasSeq.setName(jds.getName());
2082 vamsasSeq.setSequence(jds.getSequenceAsString());
2083 vamsasSeq.setDescription(jds.getDescription());
2084 jalview.datamodel.DBRefEntry[] dbrefs = null;
2085 if (jds.getDatasetSequence() != null)
2087 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
2091 // seqId==dsseqid so we can tell which sequences really are
2092 // dataset sequences only
2093 vamsasSeq.setDsseqid(id);
2094 dbrefs = jds.getDBRefs();
2095 if (parentseq == null)
2102 for (int d = 0; d < dbrefs.length; d++)
2104 DBRef dbref = new DBRef();
2105 dbref.setSource(dbrefs[d].getSource());
2106 dbref.setVersion(dbrefs[d].getVersion());
2107 dbref.setAccessionId(dbrefs[d].getAccessionId());
2108 if (dbrefs[d].hasMap())
2110 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
2112 dbref.setMapping(mp);
2114 vamsasSeq.addDBRef(dbref);
2120 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
2121 SequenceI parentseq, SequenceI jds, boolean recurse)
2124 if (jmp.getMap() != null)
2128 jalview.util.MapList mlst = jmp.getMap();
2129 List<int[]> r = mlst.getFromRanges();
2130 for (int[] range : r)
2132 MapListFrom mfrom = new MapListFrom();
2133 mfrom.setStart(range[0]);
2134 mfrom.setEnd(range[1]);
2135 mp.addMapListFrom(mfrom);
2137 r = mlst.getToRanges();
2138 for (int[] range : r)
2140 MapListTo mto = new MapListTo();
2141 mto.setStart(range[0]);
2142 mto.setEnd(range[1]);
2143 mp.addMapListTo(mto);
2145 mp.setMapFromUnit(mlst.getFromRatio());
2146 mp.setMapToUnit(mlst.getToRatio());
2147 if (jmp.getTo() != null)
2149 MappingChoice mpc = new MappingChoice();
2151 // check/create ID for the sequence referenced by getTo()
2154 SequenceI ps = null;
2155 if (parentseq != jmp.getTo()
2156 && parentseq.getDatasetSequence() != jmp.getTo())
2158 // chaining dbref rather than a handshaking one
2159 jmpid = seqHash(ps = jmp.getTo());
2163 jmpid = seqHash(ps = parentseq);
2165 mpc.setDseqFor(jmpid);
2166 if (!seqRefIds.containsKey(mpc.getDseqFor()))
2168 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2169 seqRefIds.put(mpc.getDseqFor(), ps);
2173 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2176 mp.setMappingChoice(mpc);
2182 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2183 List<UserColourScheme> userColours, JalviewModelSequence jms)
2186 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2187 boolean newucs = false;
2188 if (!userColours.contains(ucs))
2190 userColours.add(ucs);
2193 id = "ucs" + userColours.indexOf(ucs);
2196 // actually create the scheme's entry in the XML model
2197 java.awt.Color[] colours = ucs.getColours();
2198 jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
2199 jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
2201 for (int i = 0; i < colours.length; i++)
2203 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2204 col.setName(ResidueProperties.aa[i]);
2205 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2206 jbucs.addColour(col);
2208 if (ucs.getLowerCaseColours() != null)
2210 colours = ucs.getLowerCaseColours();
2211 for (int i = 0; i < colours.length; i++)
2213 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2214 col.setName(ResidueProperties.aa[i].toLowerCase());
2215 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2216 jbucs.addColour(col);
2221 uc.setUserColourScheme(jbucs);
2222 jms.addUserColours(uc);
2228 jalview.schemes.UserColourScheme getUserColourScheme(
2229 JalviewModelSequence jms, String id)
2231 UserColours[] uc = jms.getUserColours();
2232 UserColours colours = null;
2234 for (int i = 0; i < uc.length; i++)
2236 if (uc[i].getId().equals(id))
2244 java.awt.Color[] newColours = new java.awt.Color[24];
2246 for (int i = 0; i < 24; i++)
2248 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2249 .getUserColourScheme().getColour(i).getRGB(), 16));
2252 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2255 if (colours.getUserColourScheme().getColourCount() > 24)
2257 newColours = new java.awt.Color[23];
2258 for (int i = 0; i < 23; i++)
2260 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2261 .getUserColourScheme().getColour(i + 24).getRGB(), 16));
2263 ucs.setLowerCaseColours(newColours);
2270 * contains last error message (if any) encountered by XML loader.
2272 String errorMessage = null;
2275 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2276 * exceptions are raised during project XML parsing
2278 public boolean attemptversion1parse = true;
2281 * Load a jalview project archive from a jar file
2284 * - HTTP URL or filename
2286 public AlignFrame loadJalviewAlign(final String file)
2289 jalview.gui.AlignFrame af = null;
2293 // create list to store references for any new Jmol viewers created
2294 newStructureViewers = new Vector<JalviewStructureDisplayI>();
2295 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2296 // Workaround is to make sure caller implements the JarInputStreamProvider
2298 // so we can re-open the jar input stream for each entry.
2300 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2301 af = loadJalviewAlign(jprovider);
2303 } catch (MalformedURLException e)
2305 errorMessage = "Invalid URL format for '" + file + "'";
2311 SwingUtilities.invokeAndWait(new Runnable()
2316 setLoadingFinishedForNewStructureViewers();
2319 } catch (Exception x)
2321 System.err.println("Error loading alignment: " + x.getMessage());
2327 private jarInputStreamProvider createjarInputStreamProvider(
2328 final String file) throws MalformedURLException
2331 errorMessage = null;
2332 uniqueSetSuffix = null;
2334 viewportsAdded.clear();
2335 frefedSequence = null;
2337 if (file.startsWith("http://"))
2339 url = new URL(file);
2341 final URL _url = url;
2342 return new jarInputStreamProvider()
2346 public JarInputStream getJarInputStream() throws IOException
2350 return new JarInputStream(_url.openStream());
2354 return new JarInputStream(new FileInputStream(file));
2359 public String getFilename()
2367 * Recover jalview session from a jalview project archive. Caller may
2368 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2369 * themselves. Any null fields will be initialised with default values,
2370 * non-null fields are left alone.
2375 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2377 errorMessage = null;
2378 if (uniqueSetSuffix == null)
2380 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2382 if (seqRefIds == null)
2386 AlignFrame af = null, _af = null;
2387 IdentityHashMap<AlignmentI, AlignmentI> importedDatasets = new IdentityHashMap<AlignmentI, AlignmentI>();
2388 Map<String, AlignFrame> gatherToThisFrame = new HashMap<String, AlignFrame>();
2389 final String file = jprovider.getFilename();
2392 JarInputStream jin = null;
2393 JarEntry jarentry = null;
2398 jin = jprovider.getJarInputStream();
2399 for (int i = 0; i < entryCount; i++)
2401 jarentry = jin.getNextJarEntry();
2404 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2406 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2407 JalviewModel object = new JalviewModel();
2409 Unmarshaller unmar = new Unmarshaller(object);
2410 unmar.setValidation(false);
2411 object = (JalviewModel) unmar.unmarshal(in);
2412 if (true) // !skipViewport(object))
2414 _af = loadFromObject(object, file, true, jprovider);
2416 && object.getJalviewModelSequence().getViewportCount() > 0)
2420 // store a reference to the first view
2423 if (_af.viewport.isGatherViewsHere())
2425 // if this is a gathered view, keep its reference since
2426 // after gathering views, only this frame will remain
2428 gatherToThisFrame.put(_af.viewport.getSequenceSetId(), _af);
2430 // Save dataset to register mappings once all resolved
2431 importedDatasets.put(af.viewport.getAlignment().getDataset(),
2432 af.viewport.getAlignment().getDataset());
2437 else if (jarentry != null)
2439 // Some other file here.
2442 } while (jarentry != null);
2443 resolveFrefedSequences();
2444 } catch (IOException ex)
2446 ex.printStackTrace();
2447 errorMessage = "Couldn't locate Jalview XML file : " + file;
2448 System.err.println("Exception whilst loading jalview XML file : "
2450 } catch (Exception ex)
2452 System.err.println("Parsing as Jalview Version 2 file failed.");
2453 ex.printStackTrace(System.err);
2454 if (attemptversion1parse)
2456 // Is Version 1 Jar file?
2459 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
2460 } catch (Exception ex2)
2462 System.err.println("Exception whilst loading as jalviewXMLV1:");
2463 ex2.printStackTrace();
2467 if (Desktop.instance != null)
2469 Desktop.instance.stopLoading();
2473 System.out.println("Successfully loaded archive file");
2476 ex.printStackTrace();
2478 System.err.println("Exception whilst loading jalview XML file : "
2480 } catch (OutOfMemoryError e)
2482 // Don't use the OOM Window here
2483 errorMessage = "Out of memory loading jalview XML file";
2484 System.err.println("Out of memory whilst loading jalview XML file");
2485 e.printStackTrace();
2489 * Regather multiple views (with the same sequence set id) to the frame (if
2490 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2491 * views instead of separate frames. Note this doesn't restore a state where
2492 * some expanded views in turn have tabbed views - the last "first tab" read
2493 * in will play the role of gatherer for all.
2495 for (AlignFrame fr : gatherToThisFrame.values())
2497 Desktop.instance.gatherViews(fr);
2500 restoreSplitFrames();
2501 for (AlignmentI ds : importedDatasets.keySet())
2503 if (ds.getCodonFrames() != null)
2505 StructureSelectionManager.getStructureSelectionManager(
2506 Desktop.instance).registerMappings(ds.getCodonFrames());
2509 if (errorMessage != null)
2514 if (Desktop.instance != null)
2516 Desktop.instance.stopLoading();
2523 * Try to reconstruct and display SplitFrame windows, where each contains
2524 * complementary dna and protein alignments. Done by pairing up AlignFrame
2525 * objects (created earlier) which have complementary viewport ids associated.
2527 protected void restoreSplitFrames()
2529 List<SplitFrame> gatherTo = new ArrayList<SplitFrame>();
2530 List<AlignFrame> addedToSplitFrames = new ArrayList<AlignFrame>();
2531 Map<String, AlignFrame> dna = new HashMap<String, AlignFrame>();
2534 * Identify the DNA alignments
2536 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2539 AlignFrame af = candidate.getValue();
2540 if (af.getViewport().getAlignment().isNucleotide())
2542 dna.put(candidate.getKey().getId(), af);
2547 * Try to match up the protein complements
2549 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2552 AlignFrame af = candidate.getValue();
2553 if (!af.getViewport().getAlignment().isNucleotide())
2555 String complementId = candidate.getKey().getComplementId();
2556 // only non-null complements should be in the Map
2557 if (complementId != null && dna.containsKey(complementId))
2559 final AlignFrame dnaFrame = dna.get(complementId);
2560 SplitFrame sf = createSplitFrame(dnaFrame, af);
2561 addedToSplitFrames.add(dnaFrame);
2562 addedToSplitFrames.add(af);
2563 dnaFrame.setMenusForViewport();
2564 af.setMenusForViewport();
2565 if (af.viewport.isGatherViewsHere())
2574 * Open any that we failed to pair up (which shouldn't happen!) as
2575 * standalone AlignFrame's.
2577 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2580 AlignFrame af = candidate.getValue();
2581 if (!addedToSplitFrames.contains(af))
2583 Viewport view = candidate.getKey();
2584 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
2586 af.setMenusForViewport();
2587 System.err.println("Failed to restore view " + view.getTitle()
2588 + " to split frame");
2593 * Gather back into tabbed views as flagged.
2595 for (SplitFrame sf : gatherTo)
2597 Desktop.instance.gatherViews(sf);
2600 splitFrameCandidates.clear();
2604 * Construct and display one SplitFrame holding DNA and protein alignments.
2607 * @param proteinFrame
2610 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
2611 AlignFrame proteinFrame)
2613 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
2614 String title = MessageManager.getString("label.linked_view_title");
2615 int width = (int) dnaFrame.getBounds().getWidth();
2616 int height = (int) (dnaFrame.getBounds().getHeight()
2617 + proteinFrame.getBounds().getHeight() + 50);
2620 * SplitFrame location is saved to both enclosed frames
2622 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
2623 Desktop.addInternalFrame(splitFrame, title, width, height);
2626 * And compute cDNA consensus (couldn't do earlier with consensus as
2627 * mappings were not yet present)
2629 proteinFrame.viewport.alignmentChanged(proteinFrame.alignPanel);
2635 * check errorMessage for a valid error message and raise an error box in the
2636 * GUI or write the current errorMessage to stderr and then clear the error
2639 protected void reportErrors()
2641 reportErrors(false);
2644 protected void reportErrors(final boolean saving)
2646 if (errorMessage != null)
2648 final String finalErrorMessage = errorMessage;
2651 javax.swing.SwingUtilities.invokeLater(new Runnable()
2657 .showInternalMessageDialog(Desktop.desktop,
2658 finalErrorMessage, "Error "
2659 + (saving ? "saving" : "loading")
2661 JvOptionPane.WARNING_MESSAGE);
2667 System.err.println("Problem loading Jalview file: " + errorMessage);
2670 errorMessage = null;
2673 Map<String, String> alreadyLoadedPDB = new HashMap<String, String>();
2676 * when set, local views will be updated from view stored in JalviewXML
2677 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2678 * sync if this is set to true.
2680 private final boolean updateLocalViews = false;
2683 * Returns the path to a temporary file holding the PDB file for the given PDB
2684 * id. The first time of asking, searches for a file of that name in the
2685 * Jalview project jar, and copies it to a new temporary file. Any repeat
2686 * requests just return the path to the file previously created.
2692 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId,
2695 if (alreadyLoadedPDB.containsKey(pdbId))
2697 return alreadyLoadedPDB.get(pdbId).toString();
2700 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb",
2702 if (tempFile != null)
2704 alreadyLoadedPDB.put(pdbId, tempFile);
2710 * Copies the jar entry of given name to a new temporary file and returns the
2711 * path to the file, or null if the entry is not found.
2714 * @param jarEntryName
2716 * a prefix for the temporary file name, must be at least three
2719 * null or original file - so new file can be given the same suffix
2723 protected String copyJarEntry(jarInputStreamProvider jprovider,
2724 String jarEntryName, String prefix, String origFile)
2726 BufferedReader in = null;
2727 PrintWriter out = null;
2728 String suffix = ".tmp";
2729 if (origFile == null)
2731 origFile = jarEntryName;
2733 int sfpos = origFile.lastIndexOf(".");
2734 if (sfpos > -1 && sfpos < (origFile.length() - 3))
2736 suffix = "." + origFile.substring(sfpos + 1);
2740 JarInputStream jin = jprovider.getJarInputStream();
2742 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2743 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2744 * FileInputStream(jprovider)); }
2747 JarEntry entry = null;
2750 entry = jin.getNextJarEntry();
2751 } while (entry != null && !entry.getName().equals(jarEntryName));
2754 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
2755 File outFile = File.createTempFile(prefix, suffix);
2756 outFile.deleteOnExit();
2757 out = new PrintWriter(new FileOutputStream(outFile));
2760 while ((data = in.readLine()) != null)
2765 String t = outFile.getAbsolutePath();
2770 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
2772 } catch (Exception ex)
2774 ex.printStackTrace();
2782 } catch (IOException e)
2796 private class JvAnnotRow
2798 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2805 * persisted version of annotation row from which to take vis properties
2807 public jalview.datamodel.AlignmentAnnotation template;
2810 * original position of the annotation row in the alignment
2816 * Load alignment frame from jalview XML DOM object
2821 * filename source string
2822 * @param loadTreesAndStructures
2823 * when false only create Viewport
2825 * data source provider
2826 * @return alignment frame created from view stored in DOM
2828 AlignFrame loadFromObject(JalviewModel object, String file,
2829 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
2831 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
2832 Sequence[] vamsasSeq = vamsasSet.getSequence();
2834 JalviewModelSequence jms = object.getJalviewModelSequence();
2836 Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
2839 // ////////////////////////////////
2842 List<SequenceI> hiddenSeqs = null;
2844 List<SequenceI> tmpseqs = new ArrayList<SequenceI>();
2846 boolean multipleView = false;
2847 SequenceI referenceseqForView = null;
2848 JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
2849 int vi = 0; // counter in vamsasSeq array
2850 for (int i = 0; i < jseqs.length; i++)
2852 String seqId = jseqs[i].getId();
2854 SequenceI tmpSeq = seqRefIds.get(seqId);
2857 if (!incompleteSeqs.containsKey(seqId))
2859 // may not need this check, but keep it for at least 2.9,1 release
2860 if (tmpSeq.getStart() != jseqs[i].getStart()
2861 || tmpSeq.getEnd() != jseqs[i].getEnd())
2864 .println("Warning JAL-2154 regression: updating start/end for sequence "
2865 + tmpSeq.toString() + " to " + jseqs[i]);
2870 incompleteSeqs.remove(seqId);
2872 if (vamsasSeq.length > vi && vamsasSeq[vi].getId().equals(seqId))
2874 // most likely we are reading a dataset XML document so
2875 // update from vamsasSeq section of XML for this sequence
2876 tmpSeq.setName(vamsasSeq[vi].getName());
2877 tmpSeq.setDescription(vamsasSeq[vi].getDescription());
2878 tmpSeq.setSequence(vamsasSeq[vi].getSequence());
2883 // reading multiple views, so vamsasSeq set is a subset of JSeq
2884 multipleView = true;
2886 tmpSeq.setStart(jseqs[i].getStart());
2887 tmpSeq.setEnd(jseqs[i].getEnd());
2888 tmpseqs.add(tmpSeq);
2892 tmpSeq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
2893 vamsasSeq[vi].getSequence());
2894 tmpSeq.setDescription(vamsasSeq[vi].getDescription());
2895 tmpSeq.setStart(jseqs[i].getStart());
2896 tmpSeq.setEnd(jseqs[i].getEnd());
2897 tmpSeq.setVamsasId(uniqueSetSuffix + seqId);
2898 seqRefIds.put(vamsasSeq[vi].getId(), tmpSeq);
2899 tmpseqs.add(tmpSeq);
2903 if (jseqs[i].hasViewreference() && jseqs[i].getViewreference())
2905 referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
2908 if (jseqs[i].getHidden())
2910 if (hiddenSeqs == null)
2912 hiddenSeqs = new ArrayList<SequenceI>();
2915 hiddenSeqs.add(tmpSeq);
2920 // Create the alignment object from the sequence set
2921 // ///////////////////////////////
2922 SequenceI[] orderedSeqs = tmpseqs
2923 .toArray(new SequenceI[tmpseqs.size()]);
2925 AlignmentI al = null;
2926 // so we must create or recover the dataset alignment before going further
2927 // ///////////////////////////////
2928 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
2930 // older jalview projects do not have a dataset - so creat alignment and
2932 al = new Alignment(orderedSeqs);
2933 al.setDataset(null);
2937 boolean isdsal = object.getJalviewModelSequence().getViewportCount() == 0;
2940 // we are importing a dataset record, so
2941 // recover reference to an alignment already materialsed as dataset
2942 al = getDatasetFor(vamsasSet.getDatasetId());
2946 // materialse the alignment
2947 al = new Alignment(orderedSeqs);
2951 addDatasetRef(vamsasSet.getDatasetId(), al);
2954 // finally, verify all data in vamsasSet is actually present in al
2955 // passing on flag indicating if it is actually a stored dataset
2956 recoverDatasetFor(vamsasSet, al, isdsal);
2959 if (referenceseqForView != null)
2961 al.setSeqrep(referenceseqForView);
2963 // / Add the alignment properties
2964 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
2966 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
2967 al.setProperty(ssp.getKey(), ssp.getValue());
2970 // ///////////////////////////////
2972 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
2975 // load sequence features, database references and any associated PDB
2976 // structures for the alignment
2978 // prior to 2.10, this part would only be executed the first time a
2979 // sequence was encountered, but not afterwards.
2980 // now, for 2.10 projects, this is also done if the xml doc includes
2981 // dataset sequences not actually present in any particular view.
2983 for (int i = 0; i < vamsasSeq.length; i++)
2985 if (jseqs[i].getFeaturesCount() > 0)
2987 Features[] features = jseqs[i].getFeatures();
2988 for (int f = 0; f < features.length; f++)
2990 SequenceFeature sf = new SequenceFeature(features[f].getType(),
2991 features[f].getDescription(), features[f].getBegin(),
2992 features[f].getEnd(), features[f].getScore(),
2993 features[f].getFeatureGroup());
2994 sf.setStatus(features[f].getStatus());
2995 for (int od = 0; od < features[f].getOtherDataCount(); od++)
2997 OtherData keyValue = features[f].getOtherData(od);
2998 if (keyValue.getKey().startsWith("LINK"))
3000 sf.addLink(keyValue.getValue());
3004 sf.setValue(keyValue.getKey(), keyValue.getValue());
3008 // adds feature to datasequence's feature set (since Jalview 2.10)
3009 al.getSequenceAt(i).addSequenceFeature(sf);
3012 if (vamsasSeq[i].getDBRefCount() > 0)
3014 // adds dbrefs to datasequence's set (since Jalview 2.10)
3016 al.getSequenceAt(i).getDatasetSequence() == null ? al.getSequenceAt(i)
3017 : al.getSequenceAt(i).getDatasetSequence(),
3020 if (jseqs[i].getPdbidsCount() > 0)
3022 Pdbids[] ids = jseqs[i].getPdbids();
3023 for (int p = 0; p < ids.length; p++)
3025 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
3026 entry.setId(ids[p].getId());
3027 if (ids[p].getType() != null)
3029 if (PDBEntry.Type.getType(ids[p].getType()) != null)
3031 entry.setType(PDBEntry.Type.getType(ids[p].getType()));
3035 entry.setType(PDBEntry.Type.FILE);
3038 // jprovider is null when executing 'New View'
3039 if (ids[p].getFile() != null && jprovider != null)
3041 if (!pdbloaded.containsKey(ids[p].getFile()))
3043 entry.setFile(loadPDBFile(jprovider, ids[p].getId(),
3048 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
3051 if (ids[p].getPdbentryItem() != null)
3053 for (PdbentryItem item : ids[p].getPdbentryItem())
3055 for (Property pr : item.getProperty())
3057 entry.setProperty(pr.getName(), pr.getValue());
3061 StructureSelectionManager.getStructureSelectionManager(
3062 Desktop.instance).registerPDBEntry(entry);
3063 // adds PDBEntry to datasequence's set (since Jalview 2.10)
3064 if (al.getSequenceAt(i).getDatasetSequence() != null)
3066 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
3070 al.getSequenceAt(i).addPDBId(entry);
3075 } // end !multipleview
3077 // ///////////////////////////////
3078 // LOAD SEQUENCE MAPPINGS
3080 if (vamsasSet.getAlcodonFrameCount() > 0)
3082 // TODO Potentially this should only be done once for all views of an
3084 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
3085 for (int i = 0; i < alc.length; i++)
3087 AlignedCodonFrame cf = new AlignedCodonFrame();
3088 if (alc[i].getAlcodMapCount() > 0)
3090 AlcodMap[] maps = alc[i].getAlcodMap();
3091 for (int m = 0; m < maps.length; m++)
3093 SequenceI dnaseq = seqRefIds.get(maps[m].getDnasq());
3095 jalview.datamodel.Mapping mapping = null;
3096 // attach to dna sequence reference.
3097 if (maps[m].getMapping() != null)
3099 mapping = addMapping(maps[m].getMapping());
3100 if (dnaseq != null && mapping.getTo() != null)
3102 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
3107 frefedSequence.add(newAlcodMapRef(maps[m].getDnasq(), cf,
3112 al.addCodonFrame(cf);
3117 // ////////////////////////////////
3119 List<JvAnnotRow> autoAlan = new ArrayList<JvAnnotRow>();
3122 * store any annotations which forward reference a group's ID
3124 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<String, List<AlignmentAnnotation>>();
3126 if (vamsasSet.getAnnotationCount() > 0)
3128 Annotation[] an = vamsasSet.getAnnotation();
3130 for (int i = 0; i < an.length; i++)
3132 Annotation annotation = an[i];
3135 * test if annotation is automatically calculated for this view only
3137 boolean autoForView = false;
3138 if (annotation.getLabel().equals("Quality")
3139 || annotation.getLabel().equals("Conservation")
3140 || annotation.getLabel().equals("Consensus"))
3142 // Kludge for pre 2.5 projects which lacked the autocalculated flag
3144 if (!annotation.hasAutoCalculated())
3146 annotation.setAutoCalculated(true);
3150 || (annotation.hasAutoCalculated() && annotation
3151 .isAutoCalculated()))
3153 // remove ID - we don't recover annotation from other views for
3154 // view-specific annotation
3155 annotation.setId(null);
3158 // set visiblity for other annotation in this view
3159 String annotationId = annotation.getId();
3160 if (annotationId != null && annotationIds.containsKey(annotationId))
3162 AlignmentAnnotation jda = annotationIds.get(annotationId);
3163 // in principle Visible should always be true for annotation displayed
3164 // in multiple views
3165 if (annotation.hasVisible())
3167 jda.visible = annotation.getVisible();
3170 al.addAnnotation(jda);
3174 // Construct new annotation from model.
3175 AnnotationElement[] ae = annotation.getAnnotationElement();
3176 jalview.datamodel.Annotation[] anot = null;
3177 java.awt.Color firstColour = null;
3179 if (!annotation.getScoreOnly())
3181 anot = new jalview.datamodel.Annotation[al.getWidth()];
3182 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
3184 anpos = ae[aa].getPosition();
3186 if (anpos >= anot.length)
3191 anot[anpos] = new jalview.datamodel.Annotation(
3193 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
3194 (ae[aa].getSecondaryStructure() == null || ae[aa]
3195 .getSecondaryStructure().length() == 0) ? ' '
3196 : ae[aa].getSecondaryStructure().charAt(0),
3200 // JBPNote: Consider verifying dataflow for IO of secondary
3201 // structure annotation read from Stockholm files
3202 // this was added to try to ensure that
3203 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
3205 // anot[ae[aa].getPosition()].displayCharacter = "";
3207 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
3208 if (firstColour == null)
3210 firstColour = anot[anpos].colour;
3214 jalview.datamodel.AlignmentAnnotation jaa = null;
3216 if (annotation.getGraph())
3218 float llim = 0, hlim = 0;
3219 // if (autoForView || an[i].isAutoCalculated()) {
3222 jaa = new jalview.datamodel.AlignmentAnnotation(
3223 annotation.getLabel(), annotation.getDescription(), anot,
3224 llim, hlim, annotation.getGraphType());
3226 jaa.graphGroup = annotation.getGraphGroup();
3227 jaa._linecolour = firstColour;
3228 if (annotation.getThresholdLine() != null)
3230 jaa.setThreshold(new jalview.datamodel.GraphLine(annotation
3231 .getThresholdLine().getValue(), annotation
3232 .getThresholdLine().getLabel(), new java.awt.Color(
3233 annotation.getThresholdLine().getColour())));
3236 if (autoForView || annotation.isAutoCalculated())
3238 // Hardwire the symbol display line to ensure that labels for
3239 // histograms are displayed
3245 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
3246 an[i].getDescription(), anot);
3247 jaa._linecolour = firstColour;
3249 // register new annotation
3250 if (an[i].getId() != null)
3252 annotationIds.put(an[i].getId(), jaa);
3253 jaa.annotationId = an[i].getId();
3255 // recover sequence association
3256 String sequenceRef = an[i].getSequenceRef();
3257 if (sequenceRef != null)
3259 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3260 SequenceI sequence = seqRefIds.get(sequenceRef);
3261 if (sequence == null)
3263 // in pre-2.9 projects sequence ref is to sequence name
3264 sequence = al.findName(sequenceRef);
3266 if (sequence != null)
3268 jaa.createSequenceMapping(sequence, 1, true);
3269 sequence.addAlignmentAnnotation(jaa);
3272 // and make a note of any group association
3273 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
3275 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3276 .get(an[i].getGroupRef());
3279 aal = new ArrayList<jalview.datamodel.AlignmentAnnotation>();
3280 groupAnnotRefs.put(an[i].getGroupRef(), aal);
3285 if (an[i].hasScore())
3287 jaa.setScore(an[i].getScore());
3289 if (an[i].hasVisible())
3291 jaa.visible = an[i].getVisible();
3294 if (an[i].hasCentreColLabels())
3296 jaa.centreColLabels = an[i].getCentreColLabels();
3299 if (an[i].hasScaleColLabels())
3301 jaa.scaleColLabel = an[i].getScaleColLabels();
3303 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
3305 // newer files have an 'autoCalculated' flag and store calculation
3306 // state in viewport properties
3307 jaa.autoCalculated = true; // means annotation will be marked for
3308 // update at end of load.
3310 if (an[i].hasGraphHeight())
3312 jaa.graphHeight = an[i].getGraphHeight();
3314 if (an[i].hasBelowAlignment())
3316 jaa.belowAlignment = an[i].isBelowAlignment();
3318 jaa.setCalcId(an[i].getCalcId());
3319 if (an[i].getPropertyCount() > 0)
3321 for (jalview.schemabinding.version2.Property prop : an[i]
3324 jaa.setProperty(prop.getName(), prop.getValue());
3327 if (jaa.autoCalculated)
3329 autoAlan.add(new JvAnnotRow(i, jaa));
3332 // if (!autoForView)
3334 // add autocalculated group annotation and any user created annotation
3336 al.addAnnotation(jaa);
3340 // ///////////////////////
3342 // Create alignment markup and styles for this view
3343 if (jms.getJGroupCount() > 0)
3345 JGroup[] groups = jms.getJGroup();
3346 boolean addAnnotSchemeGroup = false;
3347 for (int i = 0; i < groups.length; i++)
3349 JGroup jGroup = groups[i];
3350 ColourSchemeI cs = null;
3351 if (jGroup.getColour() != null)
3353 if (jGroup.getColour().startsWith("ucs"))
3355 cs = getUserColourScheme(jms, jGroup.getColour());
3357 else if (jGroup.getColour().equals("AnnotationColourGradient")
3358 && jGroup.getAnnotationColours() != null)
3360 addAnnotSchemeGroup = true;
3364 cs = ColourSchemeProperty.getColourScheme(al, jGroup.getColour());
3367 int pidThreshold = jGroup.getPidThreshold();
3369 Vector<SequenceI> seqs = new Vector<SequenceI>();
3371 for (int s = 0; s < jGroup.getSeqCount(); s++)
3373 String seqId = jGroup.getSeq(s) + "";
3374 SequenceI ts = seqRefIds.get(seqId);
3378 seqs.addElement(ts);
3382 if (seqs.size() < 1)
3387 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3388 jGroup.getDisplayBoxes(), jGroup.getDisplayText(),
3389 jGroup.getColourText(), jGroup.getStart(), jGroup.getEnd());
3390 sg.getGroupColourScheme().setThreshold(pidThreshold, true);
3391 sg.getGroupColourScheme().setConservationInc(jGroup.getConsThreshold());
3392 sg.setOutlineColour(new java.awt.Color(jGroup.getOutlineColour()));
3394 sg.textColour = new java.awt.Color(jGroup.getTextCol1());
3395 sg.textColour2 = new java.awt.Color(jGroup.getTextCol2());
3396 sg.setShowNonconserved(jGroup.hasShowUnconserved() ? jGroup
3397 .isShowUnconserved() : false);
3398 sg.thresholdTextColour = jGroup.getTextColThreshold();
3399 if (jGroup.hasShowConsensusHistogram())
3401 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3404 if (jGroup.hasShowSequenceLogo())
3406 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3408 if (jGroup.hasNormaliseSequenceLogo())
3410 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3412 if (jGroup.hasIgnoreGapsinConsensus())
3414 sg.setIgnoreGapsConsensus(jGroup.getIgnoreGapsinConsensus());
3416 if (jGroup.getConsThreshold() != 0)
3418 Conservation c = new Conservation("All", sg.getSequences(null),
3419 0, sg.getWidth() - 1);
3421 c.verdict(false, 25);
3422 sg.cs.setConservation(c);
3425 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3427 // re-instate unique group/annotation row reference
3428 List<AlignmentAnnotation> jaal = groupAnnotRefs.get(jGroup
3432 for (AlignmentAnnotation jaa : jaal)
3435 if (jaa.autoCalculated)
3437 // match up and try to set group autocalc alignment row for this
3439 if (jaa.label.startsWith("Consensus for "))
3441 sg.setConsensus(jaa);
3443 // match up and try to set group autocalc alignment row for this
3445 if (jaa.label.startsWith("Conservation for "))
3447 sg.setConservationRow(jaa);
3454 if (addAnnotSchemeGroup)
3456 // reconstruct the annotation colourscheme
3457 sg.setColourScheme(constructAnnotationColour(
3458 jGroup.getAnnotationColours(), null, al, jms, false));
3464 // only dataset in this model, so just return.
3467 // ///////////////////////////////
3470 // If we just load in the same jar file again, the sequenceSetId
3471 // will be the same, and we end up with multiple references
3472 // to the same sequenceSet. We must modify this id on load
3473 // so that each load of the file gives a unique id
3474 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3475 String viewId = (view.getId() == null ? null : view.getId()
3477 AlignFrame af = null;
3478 AlignViewport av = null;
3479 // now check to see if we really need to create a new viewport.
3480 if (multipleView && viewportsAdded.size() == 0)
3482 // We recovered an alignment for which a viewport already exists.
3483 // TODO: fix up any settings necessary for overlaying stored state onto
3484 // state recovered from another document. (may not be necessary).
3485 // we may need a binding from a viewport in memory to one recovered from
3487 // and then recover its containing af to allow the settings to be applied.
3488 // TODO: fix for vamsas demo
3490 .println("About to recover a viewport for existing alignment: Sequence set ID is "
3492 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3493 if (seqsetobj != null)
3495 if (seqsetobj instanceof String)
3497 uniqueSeqSetId = (String) seqsetobj;
3499 .println("Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
3505 .println("Warning : Collision between sequence set ID string and existing jalview object mapping.");
3511 * indicate that annotation colours are applied across all groups (pre
3512 * Jalview 2.8.1 behaviour)
3514 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan(
3515 "2.8.1", object.getVersion());
3517 AlignmentPanel ap = null;
3518 boolean isnewview = true;
3521 // Check to see if this alignment already has a view id == viewId
3522 jalview.gui.AlignmentPanel views[] = Desktop
3523 .getAlignmentPanels(uniqueSeqSetId);
3524 if (views != null && views.length > 0)
3526 for (int v = 0; v < views.length; v++)
3528 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
3530 // recover the existing alignpanel, alignframe, viewport
3531 af = views[v].alignFrame;
3534 // TODO: could even skip resetting view settings if we don't want to
3535 // change the local settings from other jalview processes
3544 af = loadViewport(file, jseqs, hiddenSeqs, al, jms, view,
3545 uniqueSeqSetId, viewId, autoAlan);
3551 * Load any trees, PDB structures and viewers
3553 * Not done if flag is false (when this method is used for New View)
3555 if (loadTreesAndStructures)
3557 loadTrees(jms, view, af, av, ap);
3558 loadPDBStructures(jprovider, jseqs, af, ap);
3559 loadRnaViewers(jprovider, jseqs, ap);
3561 // and finally return.
3566 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
3567 * panel is restored from separate jar entries, two (gapped and trimmed) per
3568 * sequence and secondary structure.
3570 * Currently each viewer shows just one sequence and structure (gapped and
3571 * trimmed), however this method is designed to support multiple sequences or
3572 * structures in viewers if wanted in future.
3578 private void loadRnaViewers(jarInputStreamProvider jprovider,
3579 JSeq[] jseqs, AlignmentPanel ap)
3582 * scan the sequences for references to viewers; create each one the first
3583 * time it is referenced, add Rna models to existing viewers
3585 for (JSeq jseq : jseqs)
3587 for (int i = 0; i < jseq.getRnaViewerCount(); i++)
3589 RnaViewer viewer = jseq.getRnaViewer(i);
3590 AppVarna appVarna = findOrCreateVarnaViewer(viewer,
3591 uniqueSetSuffix, ap);
3593 for (int j = 0; j < viewer.getSecondaryStructureCount(); j++)
3595 SecondaryStructure ss = viewer.getSecondaryStructure(j);
3596 SequenceI seq = seqRefIds.get(jseq.getId());
3597 AlignmentAnnotation ann = this.annotationIds.get(ss
3598 .getAnnotationId());
3601 * add the structure to the Varna display (with session state copied
3602 * from the jar to a temporary file)
3604 boolean gapped = ss.isGapped();
3605 String rnaTitle = ss.getTitle();
3606 String sessionState = ss.getViewerState();
3607 String tempStateFile = copyJarEntry(jprovider, sessionState,
3609 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
3610 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
3612 appVarna.setInitialSelection(viewer.getSelectedRna());
3618 * Locate and return an already instantiated matching AppVarna, or create one
3622 * @param viewIdSuffix
3626 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
3627 String viewIdSuffix, AlignmentPanel ap)
3630 * on each load a suffix is appended to the saved viewId, to avoid conflicts
3631 * if load is repeated
3633 String postLoadId = viewer.getViewId() + viewIdSuffix;
3634 for (JInternalFrame frame : getAllFrames())
3636 if (frame instanceof AppVarna)
3638 AppVarna varna = (AppVarna) frame;
3639 if (postLoadId.equals(varna.getViewId()))
3641 // this viewer is already instantiated
3642 // could in future here add ap as another 'parent' of the
3643 // AppVarna window; currently just 1-to-many
3650 * viewer not found - make it
3652 RnaViewerModel model = new RnaViewerModel(postLoadId,
3653 viewer.getTitle(), viewer.getXpos(), viewer.getYpos(),
3654 viewer.getWidth(), viewer.getHeight(),
3655 viewer.getDividerLocation());
3656 AppVarna varna = new AppVarna(model, ap);
3662 * Load any saved trees
3670 protected void loadTrees(JalviewModelSequence jms, Viewport view,
3671 AlignFrame af, AlignViewport av, AlignmentPanel ap)
3673 // TODO result of automated refactoring - are all these parameters needed?
3676 for (int t = 0; t < jms.getTreeCount(); t++)
3679 Tree tree = jms.getTree(t);
3681 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
3684 tp = af.showNewickTree(
3685 new jalview.io.NewickFile(tree.getNewick()),
3686 tree.getTitle(), tree.getWidth(), tree.getHeight(),
3687 tree.getXpos(), tree.getYpos());
3688 if (tree.getId() != null)
3690 // perhaps bind the tree id to something ?
3695 // update local tree attributes ?
3696 // TODO: should check if tp has been manipulated by user - if so its
3697 // settings shouldn't be modified
3698 tp.setTitle(tree.getTitle());
3699 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(), tree
3700 .getWidth(), tree.getHeight()));
3701 tp.av = av; // af.viewport; // TODO: verify 'associate with all
3704 tp.treeCanvas.av = av; // af.viewport;
3705 tp.treeCanvas.ap = ap; // af.alignPanel;
3710 warn("There was a problem recovering stored Newick tree: \n"
3711 + tree.getNewick());
3715 tp.fitToWindow.setState(tree.getFitToWindow());
3716 tp.fitToWindow_actionPerformed(null);
3718 if (tree.getFontName() != null)
3720 tp.setTreeFont(new java.awt.Font(tree.getFontName(), tree
3721 .getFontStyle(), tree.getFontSize()));
3725 tp.setTreeFont(new java.awt.Font(view.getFontName(), view
3726 .getFontStyle(), tree.getFontSize()));
3729 tp.showPlaceholders(tree.getMarkUnlinked());
3730 tp.showBootstrap(tree.getShowBootstrap());
3731 tp.showDistances(tree.getShowDistances());
3733 tp.treeCanvas.threshold = tree.getThreshold();
3735 if (tree.getCurrentTree())
3737 af.viewport.setCurrentTree(tp.getTree());
3741 } catch (Exception ex)
3743 ex.printStackTrace();
3748 * Load and link any saved structure viewers.
3755 protected void loadPDBStructures(jarInputStreamProvider jprovider,
3756 JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
3759 * Run through all PDB ids on the alignment, and collect mappings between
3760 * distinct view ids and all sequences referring to that view.
3762 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<String, StructureViewerModel>();
3764 for (int i = 0; i < jseqs.length; i++)
3766 if (jseqs[i].getPdbidsCount() > 0)
3768 Pdbids[] ids = jseqs[i].getPdbids();
3769 for (int p = 0; p < ids.length; p++)
3771 final int structureStateCount = ids[p].getStructureStateCount();
3772 for (int s = 0; s < structureStateCount; s++)
3774 // check to see if we haven't already created this structure view
3775 final StructureState structureState = ids[p]
3776 .getStructureState(s);
3777 String sviewid = (structureState.getViewId() == null) ? null
3778 : structureState.getViewId() + uniqueSetSuffix;
3779 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
3780 // Originally : ids[p].getFile()
3781 // : TODO: verify external PDB file recovery still works in normal
3782 // jalview project load
3783 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId(),
3785 jpdb.setId(ids[p].getId());
3787 int x = structureState.getXpos();
3788 int y = structureState.getYpos();
3789 int width = structureState.getWidth();
3790 int height = structureState.getHeight();
3792 // Probably don't need to do this anymore...
3793 // Desktop.desktop.getComponentAt(x, y);
3794 // TODO: NOW: check that this recovers the PDB file correctly.
3795 String pdbFile = loadPDBFile(jprovider, ids[p].getId(),
3797 jalview.datamodel.SequenceI seq = seqRefIds.get(jseqs[i]
3799 if (sviewid == null)
3801 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width
3804 if (!structureViewers.containsKey(sviewid))
3806 structureViewers.put(sviewid,
3807 new StructureViewerModel(x, y, width, height, false,
3808 false, true, structureState.getViewId(),
3809 structureState.getType()));
3810 // Legacy pre-2.7 conversion JAL-823 :
3811 // do not assume any view has to be linked for colour by
3815 // assemble String[] { pdb files }, String[] { id for each
3816 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3817 // seqs_file 2}, boolean[] {
3818 // linkAlignPanel,superposeWithAlignpanel}} from hash
3819 StructureViewerModel jmoldat = structureViewers.get(sviewid);
3820 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
3821 | (structureState.hasAlignwithAlignPanel() ? structureState
3822 .getAlignwithAlignPanel() : false));
3825 * Default colour by linked panel to false if not specified (e.g.
3826 * for pre-2.7 projects)
3828 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
3829 colourWithAlignPanel |= (structureState
3830 .hasColourwithAlignPanel() ? structureState
3831 .getColourwithAlignPanel() : false);
3832 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
3835 * Default colour by viewer to true if not specified (e.g. for
3838 boolean colourByViewer = jmoldat.isColourByViewer();
3839 colourByViewer &= structureState.hasColourByJmol() ? structureState
3840 .getColourByJmol() : true;
3841 jmoldat.setColourByViewer(colourByViewer);
3843 if (jmoldat.getStateData().length() < structureState
3844 .getContent().length())
3847 jmoldat.setStateData(structureState.getContent());
3850 if (ids[p].getFile() != null)
3852 File mapkey = new File(ids[p].getFile());
3853 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
3854 if (seqstrmaps == null)
3856 jmoldat.getFileData().put(
3858 seqstrmaps = jmoldat.new StructureData(pdbFile,
3861 if (!seqstrmaps.getSeqList().contains(seq))
3863 seqstrmaps.getSeqList().add(seq);
3869 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");
3876 // Instantiate the associated structure views
3877 for (Entry<String, StructureViewerModel> entry : structureViewers
3882 createOrLinkStructureViewer(entry, af, ap, jprovider);
3883 } catch (Exception e)
3885 System.err.println("Error loading structure viewer: "
3887 // failed - try the next one
3899 protected void createOrLinkStructureViewer(
3900 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3901 AlignmentPanel ap, jarInputStreamProvider jprovider)
3903 final StructureViewerModel stateData = viewerData.getValue();
3906 * Search for any viewer windows already open from other alignment views
3907 * that exactly match the stored structure state
3909 StructureViewerBase comp = findMatchingViewer(viewerData);
3913 linkStructureViewer(ap, comp, stateData);
3918 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
3919 * "viewer_"+stateData.viewId
3921 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
3923 createChimeraViewer(viewerData, af, jprovider);
3928 * else Jmol (if pre-2.9, stateData contains JMOL state string)
3930 createJmolViewer(viewerData, af, jprovider);
3935 * Create a new Chimera viewer.
3941 protected void createChimeraViewer(
3942 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3943 jarInputStreamProvider jprovider)
3945 StructureViewerModel data = viewerData.getValue();
3946 String chimeraSessionFile = data.getStateData();
3949 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
3951 * NB this is the 'saved' viewId as in the project file XML, _not_ the
3952 * 'uniquified' sviewid used to reconstruct the viewer here
3954 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
3955 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
3958 Set<Entry<File, StructureData>> fileData = data.getFileData()
3960 List<PDBEntry> pdbs = new ArrayList<PDBEntry>();
3961 List<SequenceI[]> allseqs = new ArrayList<SequenceI[]>();
3962 for (Entry<File, StructureData> pdb : fileData)
3964 String filePath = pdb.getValue().getFilePath();
3965 String pdbId = pdb.getValue().getPdbId();
3966 // pdbs.add(new PDBEntry(filePath, pdbId));
3967 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
3968 final List<SequenceI> seqList = pdb.getValue().getSeqList();
3969 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
3973 boolean colourByChimera = data.isColourByViewer();
3974 boolean colourBySequence = data.isColourWithAlignPanel();
3976 // TODO use StructureViewer as a factory here, see JAL-1761
3977 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
3978 final SequenceI[][] seqsArray = allseqs.toArray(new SequenceI[allseqs
3980 String newViewId = viewerData.getKey();
3982 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
3983 af.alignPanel, pdbArray, seqsArray, colourByChimera,
3984 colourBySequence, newViewId);
3985 cvf.setSize(data.getWidth(), data.getHeight());
3986 cvf.setLocation(data.getX(), data.getY());
3990 * Create a new Jmol window. First parse the Jmol state to translate filenames
3991 * loaded into the view, and record the order in which files are shown in the
3992 * Jmol view, so we can add the sequence mappings in same order.
3998 protected void createJmolViewer(
3999 final Entry<String, StructureViewerModel> viewerData,
4000 AlignFrame af, jarInputStreamProvider jprovider)
4002 final StructureViewerModel svattrib = viewerData.getValue();
4003 String state = svattrib.getStateData();
4006 * Pre-2.9: state element value is the Jmol state string
4008 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
4011 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
4013 state = readJarEntry(jprovider,
4014 getViewerJarEntryName(svattrib.getViewId()));
4017 List<String> pdbfilenames = new ArrayList<String>();
4018 List<SequenceI[]> seqmaps = new ArrayList<SequenceI[]>();
4019 List<String> pdbids = new ArrayList<String>();
4020 StringBuilder newFileLoc = new StringBuilder(64);
4021 int cp = 0, ncp, ecp;
4022 Map<File, StructureData> oldFiles = svattrib.getFileData();
4023 while ((ncp = state.indexOf("load ", cp)) > -1)
4027 // look for next filename in load statement
4028 newFileLoc.append(state.substring(cp,
4029 ncp = (state.indexOf("\"", ncp + 1) + 1)));
4030 String oldfilenam = state.substring(ncp,
4031 ecp = state.indexOf("\"", ncp));
4032 // recover the new mapping data for this old filename
4033 // have to normalize filename - since Jmol and jalview do
4035 // translation differently.
4036 StructureData filedat = oldFiles.get(new File(oldfilenam));
4037 if (filedat == null)
4039 String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\");
4040 filedat = oldFiles.get(new File(reformatedOldFilename));
4042 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
4043 pdbfilenames.add(filedat.getFilePath());
4044 pdbids.add(filedat.getPdbId());
4045 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4046 newFileLoc.append("\"");
4047 cp = ecp + 1; // advance beyond last \" and set cursor so we can
4048 // look for next file statement.
4049 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
4053 // just append rest of state
4054 newFileLoc.append(state.substring(cp));
4058 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
4059 newFileLoc = new StringBuilder(state);
4060 newFileLoc.append("; load append ");
4061 for (File id : oldFiles.keySet())
4063 // add this and any other pdb files that should be present in
4065 StructureData filedat = oldFiles.get(id);
4066 newFileLoc.append(filedat.getFilePath());
4067 pdbfilenames.add(filedat.getFilePath());
4068 pdbids.add(filedat.getPdbId());
4069 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4070 newFileLoc.append(" \"");
4071 newFileLoc.append(filedat.getFilePath());
4072 newFileLoc.append("\"");
4075 newFileLoc.append(";");
4078 if (newFileLoc.length() == 0)
4082 int histbug = newFileLoc.indexOf("history = ");
4086 * change "history = [true|false];" to "history = [1|0];"
4089 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
4090 String val = (diff == -1) ? null : newFileLoc
4091 .substring(histbug, diff);
4092 if (val != null && val.length() >= 4)
4094 if (val.contains("e")) // eh? what can it be?
4096 if (val.trim().equals("true"))
4104 newFileLoc.replace(histbug, diff, val);
4109 final String[] pdbf = pdbfilenames.toArray(new String[pdbfilenames
4111 final String[] id = pdbids.toArray(new String[pdbids.size()]);
4112 final SequenceI[][] sq = seqmaps
4113 .toArray(new SequenceI[seqmaps.size()][]);
4114 final String fileloc = newFileLoc.toString();
4115 final String sviewid = viewerData.getKey();
4116 final AlignFrame alf = af;
4117 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
4118 svattrib.getWidth(), svattrib.getHeight());
4121 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
4126 JalviewStructureDisplayI sview = null;
4129 sview = new StructureViewer(alf.alignPanel
4130 .getStructureSelectionManager()).createView(
4131 StructureViewer.ViewerType.JMOL, pdbf, id, sq,
4132 alf.alignPanel, svattrib, fileloc, rect, sviewid);
4133 addNewStructureViewer(sview);
4134 } catch (OutOfMemoryError ex)
4136 new OOMWarning("restoring structure view for PDB id " + id,
4137 (OutOfMemoryError) ex.getCause());
4138 if (sview != null && sview.isVisible())
4140 sview.closeViewer(false);
4141 sview.setVisible(false);
4147 } catch (InvocationTargetException ex)
4149 warn("Unexpected error when opening Jmol view.", ex);
4151 } catch (InterruptedException e)
4153 // e.printStackTrace();
4159 * Generates a name for the entry in the project jar file to hold state
4160 * information for a structure viewer
4165 protected String getViewerJarEntryName(String viewId)
4167 return VIEWER_PREFIX + viewId;
4171 * Returns any open frame that matches given structure viewer data. The match
4172 * is based on the unique viewId, or (for older project versions) the frame's
4178 protected StructureViewerBase findMatchingViewer(
4179 Entry<String, StructureViewerModel> viewerData)
4181 final String sviewid = viewerData.getKey();
4182 final StructureViewerModel svattrib = viewerData.getValue();
4183 StructureViewerBase comp = null;
4184 JInternalFrame[] frames = getAllFrames();
4185 for (JInternalFrame frame : frames)
4187 if (frame instanceof StructureViewerBase)
4190 * Post jalview 2.4 schema includes structure view id
4193 && ((StructureViewerBase) frame).getViewId()
4196 comp = (StructureViewerBase) frame;
4197 break; // break added in 2.9
4200 * Otherwise test for matching position and size of viewer frame
4202 else if (frame.getX() == svattrib.getX()
4203 && frame.getY() == svattrib.getY()
4204 && frame.getHeight() == svattrib.getHeight()
4205 && frame.getWidth() == svattrib.getWidth())
4207 comp = (StructureViewerBase) frame;
4208 // no break in faint hope of an exact match on viewId
4216 * Link an AlignmentPanel to an existing structure viewer.
4221 * @param useinViewerSuperpos
4222 * @param usetoColourbyseq
4223 * @param viewerColouring
4225 protected void linkStructureViewer(AlignmentPanel ap,
4226 StructureViewerBase viewer, StructureViewerModel stateData)
4228 // NOTE: if the jalview project is part of a shared session then
4229 // view synchronization should/could be done here.
4231 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4232 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4233 final boolean viewerColouring = stateData.isColourByViewer();
4234 Map<File, StructureData> oldFiles = stateData.getFileData();
4237 * Add mapping for sequences in this view to an already open viewer
4239 final AAStructureBindingModel binding = viewer.getBinding();
4240 for (File id : oldFiles.keySet())
4242 // add this and any other pdb files that should be present in the
4244 StructureData filedat = oldFiles.get(id);
4245 String pdbFile = filedat.getFilePath();
4246 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4247 binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE);
4248 binding.addSequenceForStructFile(pdbFile, seq);
4250 // and add the AlignmentPanel's reference to the view panel
4251 viewer.addAlignmentPanel(ap);
4252 if (useinViewerSuperpos)
4254 viewer.useAlignmentPanelForSuperposition(ap);
4258 viewer.excludeAlignmentPanelForSuperposition(ap);
4260 if (usetoColourbyseq)
4262 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4266 viewer.excludeAlignmentPanelForColourbyseq(ap);
4271 * Get all frames within the Desktop.
4275 protected JInternalFrame[] getAllFrames()
4277 JInternalFrame[] frames = null;
4278 // TODO is this necessary - is it safe - risk of hanging?
4283 frames = Desktop.desktop.getAllFrames();
4284 } catch (ArrayIndexOutOfBoundsException e)
4286 // occasional No such child exceptions are thrown here...
4290 } catch (InterruptedException f)
4294 } while (frames == null);
4299 * Answers true if 'version' is equal to or later than 'supported', where each
4300 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4301 * changes. Development and test values for 'version' are leniently treated
4305 * - minimum version we are comparing against
4307 * - version of data being processsed
4310 public static boolean isVersionStringLaterThan(String supported,
4313 if (supported == null || version == null
4314 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4315 || version.equalsIgnoreCase("Test")
4316 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4318 System.err.println("Assuming project file with "
4319 + (version == null ? "null" : version)
4320 + " is compatible with Jalview version " + supported);
4325 return StringUtils.compareVersions(version, supported, "b") >= 0;
4329 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4331 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4333 if (newStructureViewers != null)
4335 sview.getBinding().setFinishedLoadingFromArchive(false);
4336 newStructureViewers.add(sview);
4340 protected void setLoadingFinishedForNewStructureViewers()
4342 if (newStructureViewers != null)
4344 for (JalviewStructureDisplayI sview : newStructureViewers)
4346 sview.getBinding().setFinishedLoadingFromArchive(true);
4348 newStructureViewers.clear();
4349 newStructureViewers = null;
4353 AlignFrame loadViewport(String file, JSeq[] JSEQ,
4354 List<SequenceI> hiddenSeqs, AlignmentI al,
4355 JalviewModelSequence jms, Viewport view, String uniqueSeqSetId,
4356 String viewId, List<JvAnnotRow> autoAlan)
4358 AlignFrame af = null;
4359 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
4360 uniqueSeqSetId, viewId);
4362 af.setFileName(file, FileFormat.Jalview);
4364 for (int i = 0; i < JSEQ.length; i++)
4366 af.viewport.setSequenceColour(af.viewport.getAlignment()
4367 .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour()));
4372 af.getViewport().setColourByReferenceSeq(true);
4373 af.getViewport().setDisplayReferenceSeq(true);
4376 af.viewport.setGatherViewsHere(view.getGatheredViews());
4378 if (view.getSequenceSetId() != null)
4380 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4382 af.viewport.setSequenceSetId(uniqueSeqSetId);
4385 // propagate shared settings to this new view
4386 af.viewport.setHistoryList(av.getHistoryList());
4387 af.viewport.setRedoList(av.getRedoList());
4391 viewportsAdded.put(uniqueSeqSetId, af.viewport);
4393 // TODO: check if this method can be called repeatedly without
4394 // side-effects if alignpanel already registered.
4395 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4397 // apply Hidden regions to view.
4398 if (hiddenSeqs != null)
4400 for (int s = 0; s < JSEQ.length; s++)
4402 SequenceGroup hidden = new SequenceGroup();
4403 boolean isRepresentative = false;
4404 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
4406 isRepresentative = true;
4407 SequenceI sequenceToHide = al.getSequenceAt(JSEQ[s]
4408 .getHiddenSequences(r));
4409 hidden.addSequence(sequenceToHide, false);
4410 // remove from hiddenSeqs list so we don't try to hide it twice
4411 hiddenSeqs.remove(sequenceToHide);
4413 if (isRepresentative)
4415 SequenceI representativeSequence = al.getSequenceAt(s);
4416 hidden.addSequence(representativeSequence, false);
4417 af.viewport.hideRepSequences(representativeSequence, hidden);
4421 SequenceI[] hseqs = hiddenSeqs.toArray(new SequenceI[hiddenSeqs
4423 af.viewport.hideSequence(hseqs);
4426 // recover view properties and display parameters
4427 if (view.getViewName() != null)
4429 af.viewport.viewName = view.getViewName();
4430 af.setInitialTabVisible();
4432 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
4435 af.viewport.setShowAnnotation(view.getShowAnnotation());
4436 af.viewport.setAbovePIDThreshold(view.getPidSelected());
4437 af.viewport.setThreshold(view.getPidThreshold());
4439 af.viewport.setColourText(view.getShowColourText());
4441 af.viewport.setConservationSelected(view.getConservationSelected());
4442 af.viewport.setIncrement(view.getConsThreshold());
4443 af.viewport.setShowJVSuffix(view.getShowFullId());
4444 af.viewport.setRightAlignIds(view.getRightAlignIds());
4445 af.viewport.setFont(
4446 new java.awt.Font(view.getFontName(), view.getFontStyle(), view
4447 .getFontSize()), true);
4448 ViewStyleI vs = af.viewport.getViewStyle();
4449 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
4450 af.viewport.setViewStyle(vs);
4451 // TODO: allow custom charWidth/Heights to be restored by updating them
4452 // after setting font - which means set above to false
4453 af.viewport.setRenderGaps(view.getRenderGaps());
4454 af.viewport.setWrapAlignment(view.getWrapAlignment());
4455 af.viewport.setShowAnnotation(view.getShowAnnotation());
4457 af.viewport.setShowBoxes(view.getShowBoxes());
4459 af.viewport.setShowText(view.getShowText());
4461 af.viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
4462 af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
4463 af.viewport.setThresholdTextColour(view.getTextColThreshold());
4464 af.viewport.setShowUnconserved(view.hasShowUnconserved() ? view
4465 .isShowUnconserved() : false);
4466 af.viewport.getRanges().setStartRes(view.getStartRes());
4467 af.viewport.getRanges().setStartSeq(view.getStartSeq());
4468 af.alignPanel.updateLayout();
4469 ColourSchemeI cs = null;
4470 // apply colourschemes
4471 if (view.getBgColour() != null)
4473 if (view.getBgColour().startsWith("ucs"))
4475 cs = getUserColourScheme(jms, view.getBgColour());
4477 else if (view.getBgColour().startsWith("Annotation"))
4479 AnnotationColours viewAnnColour = view.getAnnotationColours();
4480 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
4487 cs = ColourSchemeProperty.getColourScheme(al, view.getBgColour());
4491 af.viewport.setGlobalColourScheme(cs);
4492 af.viewport.getResidueShading().setThreshold(
4493 view.getPidThreshold(), true);
4494 af.viewport.getResidueShading().setConsensus(
4495 af.viewport.getSequenceConsensusHash());
4496 af.viewport.setColourAppliesToAllGroups(false);
4498 if (view.getConservationSelected() && cs != null)
4500 af.viewport.getResidueShading().setConservationInc(
4501 view.getConsThreshold());
4504 af.changeColour(cs);
4506 af.viewport.setColourAppliesToAllGroups(true);
4508 af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures());
4510 if (view.hasCentreColumnLabels())
4512 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
4514 if (view.hasIgnoreGapsinConsensus())
4516 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
4519 if (view.hasFollowHighlight())
4521 af.viewport.setFollowHighlight(view.getFollowHighlight());
4523 if (view.hasFollowSelection())
4525 af.viewport.followSelection = view.getFollowSelection();
4527 if (view.hasShowConsensusHistogram())
4529 af.viewport.setShowConsensusHistogram(view
4530 .getShowConsensusHistogram());
4534 af.viewport.setShowConsensusHistogram(true);
4536 if (view.hasShowSequenceLogo())
4538 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
4542 af.viewport.setShowSequenceLogo(false);
4544 if (view.hasNormaliseSequenceLogo())
4546 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
4548 if (view.hasShowDbRefTooltip())
4550 af.viewport.setShowDBRefs(view.getShowDbRefTooltip());
4552 if (view.hasShowNPfeatureTooltip())
4554 af.viewport.setShowNPFeats(view.hasShowNPfeatureTooltip());
4556 if (view.hasShowGroupConsensus())
4558 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
4562 af.viewport.setShowGroupConsensus(false);
4564 if (view.hasShowGroupConservation())
4566 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
4570 af.viewport.setShowGroupConservation(false);
4573 // recover featre settings
4574 if (jms.getFeatureSettings() != null)
4576 FeaturesDisplayed fdi;
4577 af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
4578 String[] renderOrder = new String[jms.getFeatureSettings()
4579 .getSettingCount()];
4580 Map<String, FeatureColourI> featureColours = new Hashtable<String, FeatureColourI>();
4581 Map<String, Float> featureOrder = new Hashtable<String, Float>();
4583 for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
4585 Setting setting = jms.getFeatureSettings().getSetting(fs);
4586 if (setting.hasMincolour())
4588 FeatureColourI gc = setting.hasMin() ? new FeatureColour(
4589 new Color(setting.getMincolour()), new Color(
4590 setting.getColour()), setting.getMin(),
4591 setting.getMax()) : new FeatureColour(new Color(
4592 setting.getMincolour()), new Color(setting.getColour()),
4594 if (setting.hasThreshold())
4596 gc.setThreshold(setting.getThreshold());
4597 int threshstate = setting.getThreshstate();
4598 // -1 = None, 0 = Below, 1 = Above threshold
4599 if (threshstate == 0)
4601 gc.setBelowThreshold(true);
4603 else if (threshstate == 1)
4605 gc.setAboveThreshold(true);
4608 gc.setAutoScaled(true); // default
4609 if (setting.hasAutoScale())
4611 gc.setAutoScaled(setting.getAutoScale());
4613 if (setting.hasColourByLabel())
4615 gc.setColourByLabel(setting.getColourByLabel());
4617 // and put in the feature colour table.
4618 featureColours.put(setting.getType(), gc);
4622 featureColours.put(setting.getType(), new FeatureColour(
4623 new Color(setting.getColour())));
4625 renderOrder[fs] = setting.getType();
4626 if (setting.hasOrder())
4628 featureOrder.put(setting.getType(), setting.getOrder());
4632 featureOrder.put(setting.getType(), new Float(fs
4633 / jms.getFeatureSettings().getSettingCount()));
4635 if (setting.getDisplay())
4637 fdi.setVisible(setting.getType());
4640 Map<String, Boolean> fgtable = new Hashtable<String, Boolean>();
4641 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
4643 Group grp = jms.getFeatureSettings().getGroup(gs);
4644 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
4646 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4647 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
4648 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
4649 FeatureRendererSettings frs = new FeatureRendererSettings(
4650 renderOrder, fgtable, featureColours, 1.0f, featureOrder);
4651 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
4652 .transferSettings(frs);
4656 if (view.getHiddenColumnsCount() > 0)
4658 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
4660 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(), view
4661 .getHiddenColumns(c).getEnd() // +1
4665 if (view.getCalcIdParam() != null)
4667 for (CalcIdParam calcIdParam : view.getCalcIdParam())
4669 if (calcIdParam != null)
4671 if (recoverCalcIdParam(calcIdParam, af.viewport))
4676 warn("Couldn't recover parameters for "
4677 + calcIdParam.getCalcId());
4682 af.setMenusFromViewport(af.viewport);
4683 af.setTitle(view.getTitle());
4684 // TODO: we don't need to do this if the viewport is aready visible.
4686 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
4687 * has a 'cdna/protein complement' view, in which case save it in order to
4688 * populate a SplitFrame once all views have been read in.
4690 String complementaryViewId = view.getComplementId();
4691 if (complementaryViewId == null)
4693 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
4695 // recompute any autoannotation
4696 af.alignPanel.updateAnnotation(false, true);
4697 reorderAutoannotation(af, al, autoAlan);
4698 af.alignPanel.alignmentChanged();
4702 splitFrameCandidates.put(view, af);
4708 * Reads saved data to restore Colour by Annotation settings
4710 * @param viewAnnColour
4714 * @param checkGroupAnnColour
4717 private ColourSchemeI constructAnnotationColour(
4718 AnnotationColours viewAnnColour, AlignFrame af, AlignmentI al,
4719 JalviewModelSequence jms, boolean checkGroupAnnColour)
4721 boolean propagateAnnColour = false;
4722 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
4723 if (checkGroupAnnColour && al.getGroups() != null
4724 && al.getGroups().size() > 0)
4726 // pre 2.8.1 behaviour
4727 // check to see if we should transfer annotation colours
4728 propagateAnnColour = true;
4729 for (SequenceGroup sg : al.getGroups())
4731 if (sg.getColourScheme() instanceof AnnotationColourGradient)
4733 propagateAnnColour = false;
4739 * 2.10.2- : saved annotationId is AlignmentAnnotation.annotationId
4741 String annotationId = viewAnnColour.getAnnotation();
4742 AlignmentAnnotation matchedAnnotation = annotationIds.get(annotationId);
4745 * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
4747 if (matchedAnnotation == null && annAlignment.getAlignmentAnnotation() != null)
4749 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
4752 .equals(annAlignment.getAlignmentAnnotation()[i].label))
4754 matchedAnnotation = annAlignment.getAlignmentAnnotation()[i];
4759 if (matchedAnnotation == null)
4761 System.err.println("Failed to match annotation colour scheme for "
4765 if (matchedAnnotation.getThreshold() == null)
4767 matchedAnnotation.setThreshold(new GraphLine(viewAnnColour.getThreshold(),
4768 "Threshold", Color.black));
4771 AnnotationColourGradient cs = null;
4772 if (viewAnnColour.getColourScheme().equals("None"))
4774 cs = new AnnotationColourGradient(matchedAnnotation, new Color(
4775 viewAnnColour.getMinColour()), new Color(
4776 viewAnnColour.getMaxColour()),
4777 viewAnnColour.getAboveThreshold());
4779 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
4781 cs = new AnnotationColourGradient(matchedAnnotation, getUserColourScheme(
4782 jms, viewAnnColour.getColourScheme()),
4783 viewAnnColour.getAboveThreshold());
4787 cs = new AnnotationColourGradient(matchedAnnotation,
4788 ColourSchemeProperty.getColourScheme(al,
4789 viewAnnColour.getColourScheme()),
4790 viewAnnColour.getAboveThreshold());
4793 boolean perSequenceOnly = viewAnnColour.isPerSequence();
4794 boolean useOriginalColours = viewAnnColour.isPredefinedColours();
4795 cs.setSeqAssociated(perSequenceOnly);
4796 cs.setPredefinedColours(useOriginalColours);
4798 if (propagateAnnColour && al.getGroups() != null)
4800 // Also use these settings for all the groups
4801 for (int g = 0; g < al.getGroups().size(); g++)
4803 SequenceGroup sg = al.getGroups().get(g);
4804 if (sg.getGroupColourScheme() == null)
4809 AnnotationColourGradient groupScheme = new AnnotationColourGradient(
4810 matchedAnnotation, sg.getColourScheme(),
4811 viewAnnColour.getAboveThreshold());
4812 sg.setColourScheme(groupScheme);
4813 groupScheme.setSeqAssociated(perSequenceOnly);
4814 groupScheme.setPredefinedColours(useOriginalColours);
4820 private void reorderAutoannotation(AlignFrame af, AlignmentI al,
4821 List<JvAnnotRow> autoAlan)
4823 // copy over visualization settings for autocalculated annotation in the
4825 if (al.getAlignmentAnnotation() != null)
4828 * Kludge for magic autoannotation names (see JAL-811)
4830 String[] magicNames = new String[] { "Consensus", "Quality",
4832 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
4833 Hashtable<String, JvAnnotRow> visan = new Hashtable<String, JvAnnotRow>();
4834 for (String nm : magicNames)
4836 visan.put(nm, nullAnnot);
4838 for (JvAnnotRow auan : autoAlan)
4840 visan.put(auan.template.label
4841 + (auan.template.getCalcId() == null ? "" : "\t"
4842 + auan.template.getCalcId()), auan);
4844 int hSize = al.getAlignmentAnnotation().length;
4845 List<JvAnnotRow> reorder = new ArrayList<JvAnnotRow>();
4846 // work through any autoCalculated annotation already on the view
4847 // removing it if it should be placed in a different location on the
4848 // annotation panel.
4849 List<String> remains = new ArrayList<String>(visan.keySet());
4850 for (int h = 0; h < hSize; h++)
4852 jalview.datamodel.AlignmentAnnotation jalan = al
4853 .getAlignmentAnnotation()[h];
4854 if (jalan.autoCalculated)
4857 JvAnnotRow valan = visan.get(k = jalan.label);
4858 if (jalan.getCalcId() != null)
4860 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
4865 // delete the auto calculated row from the alignment
4866 al.deleteAnnotation(jalan, false);
4870 if (valan != nullAnnot)
4872 if (jalan != valan.template)
4874 // newly created autoannotation row instance
4875 // so keep a reference to the visible annotation row
4876 // and copy over all relevant attributes
4877 if (valan.template.graphHeight >= 0)
4880 jalan.graphHeight = valan.template.graphHeight;
4882 jalan.visible = valan.template.visible;
4884 reorder.add(new JvAnnotRow(valan.order, jalan));
4889 // Add any (possibly stale) autocalculated rows that were not appended to
4890 // the view during construction
4891 for (String other : remains)
4893 JvAnnotRow othera = visan.get(other);
4894 if (othera != nullAnnot && othera.template.getCalcId() != null
4895 && othera.template.getCalcId().length() > 0)
4897 reorder.add(othera);
4900 // now put the automatic annotation in its correct place
4901 int s = 0, srt[] = new int[reorder.size()];
4902 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
4903 for (JvAnnotRow jvar : reorder)
4906 srt[s++] = jvar.order;
4909 jalview.util.QuickSort.sort(srt, rws);
4910 // and re-insert the annotation at its correct position
4911 for (JvAnnotRow jvar : rws)
4913 al.addAnnotation(jvar.template, jvar.order);
4915 af.alignPanel.adjustAnnotationHeight();
4919 Hashtable skipList = null;
4922 * TODO remove this method
4925 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
4926 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
4927 * throw new Error("Implementation Error. No skipList defined for this
4928 * Jalview2XML instance."); } return (AlignFrame)
4929 * skipList.get(view.getSequenceSetId()); }
4933 * Check if the Jalview view contained in object should be skipped or not.
4936 * @return true if view's sequenceSetId is a key in skipList
4938 private boolean skipViewport(JalviewModel object)
4940 if (skipList == null)
4945 if (skipList.containsKey(id = object.getJalviewModelSequence()
4946 .getViewport()[0].getSequenceSetId()))
4948 if (Cache.log != null && Cache.log.isDebugEnabled())
4950 Cache.log.debug("Skipping seuqence set id " + id);
4957 public void addToSkipList(AlignFrame af)
4959 if (skipList == null)
4961 skipList = new Hashtable();
4963 skipList.put(af.getViewport().getSequenceSetId(), af);
4966 public void clearSkipList()
4968 if (skipList != null)
4975 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
4976 boolean ignoreUnrefed)
4978 jalview.datamodel.AlignmentI ds = getDatasetFor(vamsasSet
4980 Vector dseqs = null;
4983 // create a list of new dataset sequences
4984 dseqs = new Vector();
4986 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
4988 Sequence vamsasSeq = vamsasSet.getSequence(i);
4989 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
4991 // create a new dataset
4994 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
4995 dseqs.copyInto(dsseqs);
4996 ds = new jalview.datamodel.Alignment(dsseqs);
4997 debug("Created new dataset " + vamsasSet.getDatasetId()
4998 + " for alignment " + System.identityHashCode(al));
4999 addDatasetRef(vamsasSet.getDatasetId(), ds);
5001 // set the dataset for the newly imported alignment.
5002 if (al.getDataset() == null && !ignoreUnrefed)
5011 * sequence definition to create/merge dataset sequence for
5015 * vector to add new dataset sequence to
5016 * @param ignoreUnrefed
5017 * - when true, don't create new sequences from vamsasSeq if it's id
5018 * doesn't already have an asssociated Jalview sequence.
5020 * - used to reorder the sequence in the alignment according to the
5021 * vamsasSeq array ordering, to preserve ordering of dataset
5023 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
5024 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed, int vseqpos)
5026 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
5028 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
5029 boolean reorder = false;
5030 SequenceI dsq = null;
5031 if (sq != null && sq.getDatasetSequence() != null)
5033 dsq = sq.getDatasetSequence();
5039 if (sq == null && ignoreUnrefed)
5043 String sqid = vamsasSeq.getDsseqid();
5046 // need to create or add a new dataset sequence reference to this sequence
5049 dsq = seqRefIds.get(sqid);
5054 // make a new dataset sequence
5055 dsq = sq.createDatasetSequence();
5058 // make up a new dataset reference for this sequence
5059 sqid = seqHash(dsq);
5061 dsq.setVamsasId(uniqueSetSuffix + sqid);
5062 seqRefIds.put(sqid, dsq);
5067 dseqs.addElement(dsq);
5072 ds.addSequence(dsq);
5078 { // make this dataset sequence sq's dataset sequence
5079 sq.setDatasetSequence(dsq);
5080 // and update the current dataset alignment
5085 if (!dseqs.contains(dsq))
5092 if (ds.findIndex(dsq) < 0)
5094 ds.addSequence(dsq);
5101 // TODO: refactor this as a merge dataset sequence function
5102 // now check that sq (the dataset sequence) sequence really is the union of
5103 // all references to it
5104 // boolean pre = sq.getStart() < dsq.getStart();
5105 // boolean post = sq.getEnd() > dsq.getEnd();
5109 // StringBuffer sb = new StringBuffer();
5110 String newres = jalview.analysis.AlignSeq.extractGaps(
5111 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
5112 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
5113 && newres.length() > dsq.getLength())
5115 // Update with the longer sequence.
5119 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
5120 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
5121 * sb.append(newres.substring(newres.length() - sq.getEnd() -
5122 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
5124 dsq.setSequence(newres);
5126 // TODO: merges will never happen if we 'know' we have the real dataset
5127 // sequence - this should be detected when id==dssid
5129 .println("DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
5130 // + (pre ? "prepended" : "") + " "
5131 // + (post ? "appended" : ""));
5136 // sequence refs are identical. We may need to update the existing dataset
5137 // alignment with this one, though.
5138 if (ds != null && dseqs == null)
5140 int opos = ds.findIndex(dsq);
5141 SequenceI tseq = null;
5142 if (opos != -1 && vseqpos != opos)
5144 // remove from old position
5145 ds.deleteSequence(dsq);
5147 if (vseqpos < ds.getHeight())
5149 if (vseqpos != opos)
5151 // save sequence at destination position
5152 tseq = ds.getSequenceAt(vseqpos);
5153 ds.replaceSequenceAt(vseqpos, dsq);
5154 ds.addSequence(tseq);
5159 ds.addSequence(dsq);
5166 * TODO use AlignmentI here and in related methods - needs
5167 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
5169 Hashtable<String, AlignmentI> datasetIds = null;
5171 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
5173 private AlignmentI getDatasetFor(String datasetId)
5175 if (datasetIds == null)
5177 datasetIds = new Hashtable<String, AlignmentI>();
5180 if (datasetIds.containsKey(datasetId))
5182 return datasetIds.get(datasetId);
5187 private void addDatasetRef(String datasetId, AlignmentI dataset)
5189 if (datasetIds == null)
5191 datasetIds = new Hashtable<String, AlignmentI>();
5193 datasetIds.put(datasetId, dataset);
5197 * make a new dataset ID for this jalview dataset alignment
5202 private String getDatasetIdRef(AlignmentI dataset)
5204 if (dataset.getDataset() != null)
5206 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
5208 String datasetId = makeHashCode(dataset, null);
5209 if (datasetId == null)
5211 // make a new datasetId and record it
5212 if (dataset2Ids == null)
5214 dataset2Ids = new IdentityHashMap<AlignmentI, String>();
5218 datasetId = dataset2Ids.get(dataset);
5220 if (datasetId == null)
5222 datasetId = "ds" + dataset2Ids.size() + 1;
5223 dataset2Ids.put(dataset, datasetId);
5229 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5231 for (int d = 0; d < sequence.getDBRefCount(); d++)
5233 DBRef dr = sequence.getDBRef(d);
5234 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
5235 sequence.getDBRef(d).getSource(), sequence.getDBRef(d)
5236 .getVersion(), sequence.getDBRef(d).getAccessionId());
5237 if (dr.getMapping() != null)
5239 entry.setMap(addMapping(dr.getMapping()));
5241 datasetSequence.addDBRef(entry);
5245 private jalview.datamodel.Mapping addMapping(Mapping m)
5247 SequenceI dsto = null;
5248 // Mapping m = dr.getMapping();
5249 int fr[] = new int[m.getMapListFromCount() * 2];
5250 Enumeration f = m.enumerateMapListFrom();
5251 for (int _i = 0; f.hasMoreElements(); _i += 2)
5253 MapListFrom mf = (MapListFrom) f.nextElement();
5254 fr[_i] = mf.getStart();
5255 fr[_i + 1] = mf.getEnd();
5257 int fto[] = new int[m.getMapListToCount() * 2];
5258 f = m.enumerateMapListTo();
5259 for (int _i = 0; f.hasMoreElements(); _i += 2)
5261 MapListTo mf = (MapListTo) f.nextElement();
5262 fto[_i] = mf.getStart();
5263 fto[_i + 1] = mf.getEnd();
5265 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto,
5266 fr, fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
5267 if (m.getMappingChoice() != null)
5269 MappingChoice mc = m.getMappingChoice();
5270 if (mc.getDseqFor() != null)
5272 String dsfor = "" + mc.getDseqFor();
5273 if (seqRefIds.containsKey(dsfor))
5278 jmap.setTo(seqRefIds.get(dsfor));
5282 frefedSequence.add(newMappingRef(dsfor, jmap));
5288 * local sequence definition
5290 Sequence ms = mc.getSequence();
5291 SequenceI djs = null;
5292 String sqid = ms.getDsseqid();
5293 if (sqid != null && sqid.length() > 0)
5296 * recover dataset sequence
5298 djs = seqRefIds.get(sqid);
5303 .println("Warning - making up dataset sequence id for DbRef sequence map reference");
5304 sqid = ((Object) ms).toString(); // make up a new hascode for
5305 // undefined dataset sequence hash
5306 // (unlikely to happen)
5312 * make a new dataset sequence and add it to refIds hash
5314 djs = new jalview.datamodel.Sequence(ms.getName(),
5316 djs.setStart(jmap.getMap().getToLowest());
5317 djs.setEnd(jmap.getMap().getToHighest());
5318 djs.setVamsasId(uniqueSetSuffix + sqid);
5320 incompleteSeqs.put(sqid, djs);
5321 seqRefIds.put(sqid, djs);
5324 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5333 public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
5334 boolean keepSeqRefs)
5337 JalviewModel jm = saveState(ap, null, null, null);
5342 jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
5346 uniqueSetSuffix = "";
5347 jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
5352 if (this.frefedSequence == null)
5354 frefedSequence = new Vector();
5357 viewportsAdded.clear();
5359 AlignFrame af = loadFromObject(jm, null, false, null);
5360 af.alignPanels.clear();
5361 af.closeMenuItem_actionPerformed(true);
5364 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5365 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5366 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5367 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5368 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5371 return af.alignPanel;
5375 * flag indicating if hashtables should be cleared on finalization TODO this
5376 * flag may not be necessary
5378 private final boolean _cleartables = true;
5380 private Hashtable jvids2vobj;
5385 * @see java.lang.Object#finalize()
5388 protected void finalize() throws Throwable
5390 // really make sure we have no buried refs left.
5395 this.seqRefIds = null;
5396 this.seqsToIds = null;
5400 private void warn(String msg)
5405 private void warn(String msg, Exception e)
5407 if (Cache.log != null)
5411 Cache.log.warn(msg, e);
5415 Cache.log.warn(msg);
5420 System.err.println("Warning: " + msg);
5423 e.printStackTrace();
5428 private void debug(String string)
5430 debug(string, null);
5433 private void debug(String msg, Exception e)
5435 if (Cache.log != null)
5439 Cache.log.debug(msg, e);
5443 Cache.log.debug(msg);
5448 System.err.println("Warning: " + msg);
5451 e.printStackTrace();
5457 * set the object to ID mapping tables used to write/recover objects and XML
5458 * ID strings for the jalview project. If external tables are provided then
5459 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
5460 * object goes out of scope. - also populates the datasetIds hashtable with
5461 * alignment objects containing dataset sequences
5464 * Map from ID strings to jalview datamodel
5466 * Map from jalview datamodel to ID strings
5470 public void setObjectMappingTables(Hashtable vobj2jv,
5471 IdentityHashMap jv2vobj)
5473 this.jv2vobj = jv2vobj;
5474 this.vobj2jv = vobj2jv;
5475 Iterator ds = jv2vobj.keySet().iterator();
5477 while (ds.hasNext())
5479 Object jvobj = ds.next();
5480 id = jv2vobj.get(jvobj).toString();
5481 if (jvobj instanceof jalview.datamodel.Alignment)
5483 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
5485 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
5488 else if (jvobj instanceof jalview.datamodel.Sequence)
5490 // register sequence object so the XML parser can recover it.
5491 if (seqRefIds == null)
5493 seqRefIds = new HashMap<String, SequenceI>();
5495 if (seqsToIds == null)
5497 seqsToIds = new IdentityHashMap<SequenceI, String>();
5499 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
5500 seqsToIds.put((SequenceI) jvobj, id);
5502 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
5505 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
5506 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
5507 if (jvann.annotationId == null)
5509 jvann.annotationId = anid;
5511 if (!jvann.annotationId.equals(anid))
5513 // TODO verify that this is the correct behaviour
5514 this.warn("Overriding Annotation ID for " + anid
5515 + " from different id : " + jvann.annotationId);
5516 jvann.annotationId = anid;
5519 else if (jvobj instanceof String)
5521 if (jvids2vobj == null)
5523 jvids2vobj = new Hashtable();
5524 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
5529 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
5535 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
5536 * objects created from the project archive. If string is null (default for
5537 * construction) then suffix will be set automatically.
5541 public void setUniqueSetSuffix(String string)
5543 uniqueSetSuffix = string;
5548 * uses skipList2 as the skipList for skipping views on sequence sets
5549 * associated with keys in the skipList
5553 public void setSkipList(Hashtable skipList2)
5555 skipList = skipList2;
5559 * Reads the jar entry of given name and returns its contents, or null if the
5560 * entry is not found.
5563 * @param jarEntryName
5566 protected String readJarEntry(jarInputStreamProvider jprovider,
5567 String jarEntryName)
5569 String result = null;
5570 BufferedReader in = null;
5575 * Reopen the jar input stream and traverse its entries to find a matching
5578 JarInputStream jin = jprovider.getJarInputStream();
5579 JarEntry entry = null;
5582 entry = jin.getNextJarEntry();
5583 } while (entry != null && !entry.getName().equals(jarEntryName));
5587 StringBuilder out = new StringBuilder(256);
5588 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
5591 while ((data = in.readLine()) != null)
5595 result = out.toString();
5599 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
5601 } catch (Exception ex)
5603 ex.printStackTrace();
5611 } catch (IOException e)
5622 * Returns an incrementing counter (0, 1, 2...)
5626 private synchronized int nextCounter()