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.api.FeatureColourI;
24 import jalview.api.ViewStyleI;
25 import jalview.api.structures.JalviewStructureDisplayI;
26 import jalview.bin.Cache;
27 import jalview.datamodel.AlignedCodonFrame;
28 import jalview.datamodel.Alignment;
29 import jalview.datamodel.AlignmentAnnotation;
30 import jalview.datamodel.AlignmentI;
31 import jalview.datamodel.PDBEntry;
32 import jalview.datamodel.RnaViewerModel;
33 import jalview.datamodel.SequenceGroup;
34 import jalview.datamodel.SequenceI;
35 import jalview.datamodel.StructureViewerModel;
36 import jalview.datamodel.StructureViewerModel.StructureData;
37 import jalview.ext.varna.RnaModel;
38 import jalview.gui.StructureViewer.ViewerType;
39 import jalview.schemabinding.version2.AlcodMap;
40 import jalview.schemabinding.version2.AlcodonFrame;
41 import jalview.schemabinding.version2.Annotation;
42 import jalview.schemabinding.version2.AnnotationColours;
43 import jalview.schemabinding.version2.AnnotationElement;
44 import jalview.schemabinding.version2.CalcIdParam;
45 import jalview.schemabinding.version2.DBRef;
46 import jalview.schemabinding.version2.Features;
47 import jalview.schemabinding.version2.Group;
48 import jalview.schemabinding.version2.HiddenColumns;
49 import jalview.schemabinding.version2.JGroup;
50 import jalview.schemabinding.version2.JSeq;
51 import jalview.schemabinding.version2.JalviewModel;
52 import jalview.schemabinding.version2.JalviewModelSequence;
53 import jalview.schemabinding.version2.MapListFrom;
54 import jalview.schemabinding.version2.MapListTo;
55 import jalview.schemabinding.version2.Mapping;
56 import jalview.schemabinding.version2.MappingChoice;
57 import jalview.schemabinding.version2.OtherData;
58 import jalview.schemabinding.version2.PdbentryItem;
59 import jalview.schemabinding.version2.Pdbids;
60 import jalview.schemabinding.version2.Property;
61 import jalview.schemabinding.version2.RnaViewer;
62 import jalview.schemabinding.version2.SecondaryStructure;
63 import jalview.schemabinding.version2.Sequence;
64 import jalview.schemabinding.version2.SequenceSet;
65 import jalview.schemabinding.version2.SequenceSetProperties;
66 import jalview.schemabinding.version2.Setting;
67 import jalview.schemabinding.version2.StructureState;
68 import jalview.schemabinding.version2.ThresholdLine;
69 import jalview.schemabinding.version2.Tree;
70 import jalview.schemabinding.version2.UserColours;
71 import jalview.schemabinding.version2.Viewport;
72 import jalview.schemes.AnnotationColourGradient;
73 import jalview.schemes.ColourSchemeI;
74 import jalview.schemes.ColourSchemeProperty;
75 import jalview.schemes.FeatureColour;
76 import jalview.schemes.ResidueColourScheme;
77 import jalview.schemes.ResidueProperties;
78 import jalview.schemes.UserColourScheme;
79 import jalview.structure.StructureSelectionManager;
80 import jalview.structures.models.AAStructureBindingModel;
81 import jalview.util.MessageManager;
82 import jalview.util.Platform;
83 import jalview.util.StringUtils;
84 import jalview.util.jarInputStreamProvider;
85 import jalview.viewmodel.AlignmentViewport;
86 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
87 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
88 import jalview.ws.jws2.Jws2Discoverer;
89 import jalview.ws.jws2.dm.AAConSettings;
90 import jalview.ws.jws2.jabaws2.Jws2Instance;
91 import jalview.ws.params.ArgumentI;
92 import jalview.ws.params.AutoCalcSetting;
93 import jalview.ws.params.WsParamSetI;
95 import java.awt.Color;
96 import java.awt.Rectangle;
97 import java.io.BufferedReader;
98 import java.io.DataInputStream;
99 import java.io.DataOutputStream;
101 import java.io.FileInputStream;
102 import java.io.FileOutputStream;
103 import java.io.IOException;
104 import java.io.InputStreamReader;
105 import java.io.OutputStreamWriter;
106 import java.io.PrintWriter;
107 import java.lang.reflect.InvocationTargetException;
108 import java.net.MalformedURLException;
110 import java.util.ArrayList;
111 import java.util.Arrays;
112 import java.util.Enumeration;
113 import java.util.HashMap;
114 import java.util.HashSet;
115 import java.util.Hashtable;
116 import java.util.IdentityHashMap;
117 import java.util.Iterator;
118 import java.util.LinkedHashMap;
119 import java.util.List;
120 import java.util.Map;
121 import java.util.Map.Entry;
122 import java.util.Set;
123 import java.util.Vector;
124 import java.util.jar.JarEntry;
125 import java.util.jar.JarInputStream;
126 import java.util.jar.JarOutputStream;
128 import javax.swing.JInternalFrame;
129 import javax.swing.JOptionPane;
130 import javax.swing.SwingUtilities;
132 import org.exolab.castor.xml.Marshaller;
133 import org.exolab.castor.xml.Unmarshaller;
136 * Write out the current jalview desktop state as a Jalview XML stream.
138 * Note: the vamsas objects referred to here are primitive versions of the
139 * VAMSAS project schema elements - they are not the same and most likely never
143 * @version $Revision: 1.134 $
145 public class Jalview2XML
147 private static final String VIEWER_PREFIX = "viewer_";
149 private static final String RNA_PREFIX = "rna_";
151 private static final String UTF_8 = "UTF-8";
153 // use this with nextCounter() to make unique names for entities
154 private int counter = 0;
157 * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
158 * of sequence objects are created.
160 IdentityHashMap<SequenceI, String> seqsToIds = null;
163 * jalview XML Sequence ID to jalview sequence object reference (both dataset
164 * and alignment sequences. Populated as XML reps of sequence objects are
167 Map<String, SequenceI> seqRefIds = null;
169 Map<String, SequenceI> incompleteSeqs = null;
171 List<SeqFref> frefedSequence = null;
173 boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
176 * Map of reconstructed AlignFrame objects that appear to have come from
177 * SplitFrame objects (have a dna/protein complement view).
179 private Map<Viewport, AlignFrame> splitFrameCandidates = new HashMap<Viewport, AlignFrame>();
182 * Map from displayed rna structure models to their saved session state jar
185 private Map<RnaModel, String> rnaSessions = new HashMap<RnaModel, String>();
188 * create/return unique hash string for sq
191 * @return new or existing unique string for sq
193 String seqHash(SequenceI sq)
195 if (seqsToIds == null)
199 if (seqsToIds.containsKey(sq))
201 return seqsToIds.get(sq);
205 // create sequential key
206 String key = "sq" + (seqsToIds.size() + 1);
207 key = makeHashCode(sq, key); // check we don't have an external reference
209 seqsToIds.put(sq, key);
218 if (seqRefIds != null)
222 if (seqsToIds != null)
226 if (incompleteSeqs != null)
228 incompleteSeqs.clear();
236 warn("clearSeqRefs called when _cleartables was not set. Doing nothing.");
237 // seqRefIds = new Hashtable();
238 // seqsToIds = new IdentityHashMap();
244 if (seqsToIds == null)
246 seqsToIds = new IdentityHashMap<SequenceI, String>();
248 if (seqRefIds == null)
250 seqRefIds = new HashMap<String, SequenceI>();
252 if (incompleteSeqs == null)
254 incompleteSeqs = new HashMap<String, SequenceI>();
256 if (frefedSequence == null)
258 frefedSequence = new ArrayList<SeqFref>();
266 public Jalview2XML(boolean raiseGUI)
268 this.raiseGUI = raiseGUI;
272 * base class for resolving forward references to sequences by their ID
277 abstract class SeqFref
283 public SeqFref(String _sref, String type)
289 public String getSref()
294 public SequenceI getSrefSeq()
296 return seqRefIds.get(sref);
299 public boolean isResolvable()
301 return seqRefIds.get(sref) != null;
304 public SequenceI getSrefDatasetSeq()
306 SequenceI sq = seqRefIds.get(sref);
309 while (sq.getDatasetSequence() != null)
311 sq = sq.getDatasetSequence();
317 * @return true if the forward reference was fully resolved
319 abstract boolean resolve();
322 public String toString()
324 return type + " reference to " + sref;
329 * create forward reference for a mapping
335 public SeqFref newMappingRef(final String sref,
336 final jalview.datamodel.Mapping _jmap)
338 SeqFref fref = new SeqFref(sref, "Mapping")
340 public jalview.datamodel.Mapping jmap = _jmap;
345 SequenceI seq = getSrefDatasetSeq();
357 public SeqFref newAlcodMapRef(final String sref,
358 final AlignedCodonFrame _cf, final jalview.datamodel.Mapping _jmap)
361 SeqFref fref = new SeqFref(sref, "Codon Frame")
363 AlignedCodonFrame cf = _cf;
365 public jalview.datamodel.Mapping mp = _jmap;
368 public boolean isResolvable()
370 return super.isResolvable() && mp.getTo() != null;
376 SequenceI seq = getSrefDatasetSeq();
381 cf.addMap(seq, mp.getTo(), mp.getMap());
388 public void resolveFrefedSequences()
390 Iterator<SeqFref> nextFref=frefedSequence.iterator();
391 int toresolve=frefedSequence.size();
392 int unresolved=0,failedtoresolve=0;
393 while (nextFref.hasNext()) {
394 SeqFref ref = nextFref.next();
395 if (ref.isResolvable())
404 } catch (Exception x) {
405 System.err.println("IMPLEMENTATION ERROR: Failed to resolve forward reference for sequence "+ref.getSref());
415 System.err.println("Jalview Project Import: There were " + unresolved
416 + " forward references left unresolved on the stack.");
418 if (failedtoresolve>0)
420 System.err.println("SERIOUS! " + failedtoresolve
421 + " resolvable forward references failed to resolve.");
423 if (incompleteSeqs != null && incompleteSeqs.size() > 0)
425 System.err.println("Jalview Project Import: There are "
426 + incompleteSeqs.size()
427 + " sequences which may have incomplete metadata.");
428 if (incompleteSeqs.size() < 10)
430 for (SequenceI s : incompleteSeqs.values())
432 System.err.println(s.toString());
438 .println("Too many to report. Skipping output of incomplete sequences.");
444 * This maintains a map of viewports, the key being the seqSetId. Important to
445 * set historyItem and redoList for multiple views
447 Map<String, AlignViewport> viewportsAdded = new HashMap<String, AlignViewport>();
449 Map<String, AlignmentAnnotation> annotationIds = new HashMap<String, AlignmentAnnotation>();
451 String uniqueSetSuffix = "";
454 * List of pdbfiles added to Jar
456 List<String> pdbfiles = null;
458 // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
459 public void saveState(File statefile)
461 FileOutputStream fos = null;
464 fos = new FileOutputStream(statefile);
465 JarOutputStream jout = new JarOutputStream(fos);
468 } catch (Exception e)
470 // TODO: inform user of the problem - they need to know if their data was
472 if (errorMessage == null)
474 errorMessage = "Couldn't write Jalview Archive to output file '"
475 + statefile + "' - See console error log for details";
479 errorMessage += "(output file was '" + statefile + "')";
489 } catch (IOException e)
499 * Writes a jalview project archive to the given Jar output stream.
503 public void saveState(JarOutputStream jout)
505 AlignFrame[] frames = Desktop.getAlignFrames();
511 saveAllFrames(Arrays.asList(frames), jout);
515 * core method for storing state for a set of AlignFrames.
518 * - frames involving all data to be exported (including containing
521 * - project output stream
523 private void saveAllFrames(List<AlignFrame> frames, JarOutputStream jout)
525 Hashtable<String, AlignFrame> dsses = new Hashtable<String, AlignFrame>();
528 * ensure cached data is clear before starting
530 // todo tidy up seqRefIds, seqsToIds initialisation / reset
532 splitFrameCandidates.clear();
537 // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
538 // //////////////////////////////////////////////////
540 List<String> shortNames = new ArrayList<String>();
541 List<String> viewIds = new ArrayList<String>();
544 for (int i = frames.size() - 1; i > -1; i--)
546 AlignFrame af = frames.get(i);
550 .containsKey(af.getViewport().getSequenceSetId()))
555 String shortName = makeFilename(af, shortNames);
557 int ap, apSize = af.alignPanels.size();
559 for (ap = 0; ap < apSize; ap++)
561 AlignmentPanel apanel = af.alignPanels.get(ap);
562 String fileName = apSize == 1 ? shortName : ap + shortName;
563 if (!fileName.endsWith(".xml"))
565 fileName = fileName + ".xml";
568 saveState(apanel, fileName, jout, viewIds);
570 String dssid = getDatasetIdRef(af.getViewport().getAlignment()
572 if (!dsses.containsKey(dssid))
574 dsses.put(dssid, af);
579 writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix,
585 } catch (Exception foo)
590 } catch (Exception ex)
592 // TODO: inform user of the problem - they need to know if their data was
594 if (errorMessage == null)
596 errorMessage = "Couldn't write Jalview Archive - see error output for details";
598 ex.printStackTrace();
603 * Generates a distinct file name, based on the title of the AlignFrame, by
604 * appending _n for increasing n until an unused name is generated. The new
605 * name (without its extension) is added to the list.
609 * @return the generated name, with .xml extension
611 protected String makeFilename(AlignFrame af, List<String> namesUsed)
613 String shortName = af.getTitle();
615 if (shortName.indexOf(File.separatorChar) > -1)
617 shortName = shortName.substring(shortName
618 .lastIndexOf(File.separatorChar) + 1);
623 while (namesUsed.contains(shortName))
625 if (shortName.endsWith("_" + (count - 1)))
627 shortName = shortName.substring(0, shortName.lastIndexOf("_"));
630 shortName = shortName.concat("_" + count);
634 namesUsed.add(shortName);
636 if (!shortName.endsWith(".xml"))
638 shortName = shortName + ".xml";
643 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
644 public boolean saveAlignment(AlignFrame af, String jarFile,
649 FileOutputStream fos = new FileOutputStream(jarFile);
650 JarOutputStream jout = new JarOutputStream(fos);
651 List<AlignFrame> frames = new ArrayList<AlignFrame>();
653 // resolve splitframes
654 if (af.getViewport().getCodingComplement() != null)
656 frames = ((SplitFrame) af.getSplitViewContainer()).getAlignFrames();
662 saveAllFrames(frames, jout);
666 } catch (Exception foo)
672 } catch (Exception ex)
674 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
675 ex.printStackTrace();
680 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
681 String fileName, JarOutputStream jout)
684 for (String dssids : dsses.keySet())
686 AlignFrame _af = dsses.get(dssids);
687 String jfileName = fileName + " Dataset for " + _af.getTitle();
688 if (!jfileName.endsWith(".xml"))
690 jfileName = jfileName + ".xml";
692 saveState(_af.alignPanel, jfileName, true, jout, null);
697 * create a JalviewModel from an alignment view and marshall it to a
701 * panel to create jalview model for
703 * name of alignment panel written to output stream
710 public JalviewModel saveState(AlignmentPanel ap, String fileName,
711 JarOutputStream jout, List<String> viewIds)
713 return saveState(ap, fileName, false, jout, viewIds);
717 * create a JalviewModel from an alignment view and marshall it to a
721 * panel to create jalview model for
723 * name of alignment panel written to output stream
725 * when true, only write the dataset for the alignment, not the data
726 * associated with the view.
732 public JalviewModel saveState(AlignmentPanel ap, String fileName,
733 boolean storeDS, JarOutputStream jout, List<String> viewIds)
737 viewIds = new ArrayList<String>();
742 List<UserColourScheme> userColours = new ArrayList<UserColourScheme>();
744 AlignViewport av = ap.av;
746 JalviewModel object = new JalviewModel();
747 object.setVamsasModel(new jalview.schemabinding.version2.VamsasModel());
749 object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
750 object.setVersion(jalview.bin.Cache.getDefault("VERSION",
751 "Development Build"));
754 * rjal is full height alignment, jal is actual alignment with full metadata
755 * but excludes hidden sequences.
757 jalview.datamodel.AlignmentI rjal = av.getAlignment(), jal = rjal;
759 if (av.hasHiddenRows())
761 rjal = jal.getHiddenSequences().getFullAlignment();
764 SequenceSet vamsasSet = new SequenceSet();
766 JalviewModelSequence jms = new JalviewModelSequence();
768 vamsasSet.setGapChar(jal.getGapCharacter() + "");
770 if (jal.getDataset() != null)
772 // dataset id is the dataset's hashcode
773 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
776 // switch jal and the dataset
777 jal = jal.getDataset();
781 if (jal.getProperties() != null)
783 Enumeration en = jal.getProperties().keys();
784 while (en.hasMoreElements())
786 String key = en.nextElement().toString();
787 SequenceSetProperties ssp = new SequenceSetProperties();
789 ssp.setValue(jal.getProperties().get(key).toString());
790 vamsasSet.addSequenceSetProperties(ssp);
795 Set<String> calcIdSet = new HashSet<String>();
796 // record the set of vamsas sequence XML POJO we create.
797 HashMap<String,Sequence> vamsasSetIds = new HashMap<String,Sequence>();
799 for (final SequenceI jds : rjal.getSequences())
801 final SequenceI jdatasq = jds.getDatasetSequence() == null ? jds
802 : jds.getDatasetSequence();
803 String id = seqHash(jds);
804 if (vamsasSetIds.get(id) == null)
806 if (seqRefIds.get(id) != null && !storeDS)
808 // This happens for two reasons: 1. multiple views are being
810 // 2. the hashCode has collided with another sequence's code. This
812 // HAPPEN! (PF00072.15.stk does this)
813 // JBPNote: Uncomment to debug writing out of files that do not read
814 // back in due to ArrayOutOfBoundExceptions.
815 // System.err.println("vamsasSeq backref: "+id+"");
816 // System.err.println(jds.getName()+"
817 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
818 // System.err.println("Hashcode: "+seqHash(jds));
819 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
820 // System.err.println(rsq.getName()+"
821 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
822 // System.err.println("Hashcode: "+seqHash(rsq));
826 vamsasSeq = createVamsasSequence(id, jds);
827 vamsasSet.addSequence(vamsasSeq);
828 vamsasSetIds.put(id, vamsasSeq);
829 seqRefIds.put(id, jds);
833 jseq.setStart(jds.getStart());
834 jseq.setEnd(jds.getEnd());
835 jseq.setColour(av.getSequenceColour(jds).getRGB());
837 jseq.setId(id); // jseq id should be a string not a number
840 // Store any sequences this sequence represents
841 if (av.hasHiddenRows())
843 // use rjal, contains the full height alignment
844 jseq.setHidden(av.getAlignment().getHiddenSequences()
847 if (av.isHiddenRepSequence(jds))
849 jalview.datamodel.SequenceI[] reps = av
850 .getRepresentedSequences(jds)
851 .getSequencesInOrder(rjal);
853 for (int h = 0; h < reps.length; h++)
857 jseq.addHiddenSequences(rjal.findIndex(reps[h]));
862 // mark sequence as reference - if it is the reference for this view
865 jseq.setViewreference(jds == jal.getSeqrep());
869 // TODO: omit sequence features from each alignment view's XML dump if we
870 // are storing dataset
871 if (jds.getSequenceFeatures() != null)
873 jalview.datamodel.SequenceFeature[] sf = jds.getSequenceFeatures();
875 while (index < sf.length)
877 Features features = new Features();
879 features.setBegin(sf[index].getBegin());
880 features.setEnd(sf[index].getEnd());
881 features.setDescription(sf[index].getDescription());
882 features.setType(sf[index].getType());
883 features.setFeatureGroup(sf[index].getFeatureGroup());
884 features.setScore(sf[index].getScore());
885 if (sf[index].links != null)
887 for (int l = 0; l < sf[index].links.size(); l++)
889 OtherData keyValue = new OtherData();
890 keyValue.setKey("LINK_" + l);
891 keyValue.setValue(sf[index].links.elementAt(l).toString());
892 features.addOtherData(keyValue);
895 if (sf[index].otherDetails != null)
898 Iterator<String> keys = sf[index].otherDetails.keySet()
900 while (keys.hasNext())
903 OtherData keyValue = new OtherData();
904 keyValue.setKey(key);
905 keyValue.setValue(sf[index].otherDetails.get(key).toString());
906 features.addOtherData(keyValue);
910 jseq.addFeatures(features);
915 if (jdatasq.getAllPDBEntries() != null)
917 Enumeration en = jdatasq.getAllPDBEntries().elements();
918 while (en.hasMoreElements())
920 Pdbids pdb = new Pdbids();
921 jalview.datamodel.PDBEntry entry = (jalview.datamodel.PDBEntry) en
924 String pdbId = entry.getId();
926 pdb.setType(entry.getType());
929 * Store any structure views associated with this sequence. This
930 * section copes with duplicate entries in the project, so a dataset
931 * only view *should* be coped with sensibly.
933 // This must have been loaded, is it still visible?
934 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
935 String matchedFile = null;
936 for (int f = frames.length - 1; f > -1; f--)
938 if (frames[f] instanceof StructureViewerBase)
940 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
941 matchedFile = saveStructureState(ap, jds, pdb, entry,
942 viewIds, matchedFile, viewFrame);
944 * Only store each structure viewer's state once in the project
945 * jar. First time through only (storeDS==false)
947 String viewId = viewFrame.getViewId();
948 if (!storeDS && !viewIds.contains(viewId))
953 String viewerState = viewFrame.getStateInfo();
954 writeJarEntry(jout, getViewerJarEntryName(viewId),
955 viewerState.getBytes());
956 } catch (IOException e)
958 System.err.println("Error saving viewer state: "
965 if (matchedFile != null || entry.getFile() != null)
967 if (entry.getFile() != null)
970 matchedFile = entry.getFile();
972 pdb.setFile(matchedFile); // entry.getFile());
973 if (pdbfiles == null)
975 pdbfiles = new ArrayList<String>();
978 if (!pdbfiles.contains(pdbId))
981 copyFileToJar(jout, matchedFile, pdbId);
985 if (entry.getProperty() != null && !entry.getProperty().isEmpty())
987 PdbentryItem item = new PdbentryItem();
988 Hashtable properties = entry.getProperty();
989 Enumeration en2 = properties.keys();
990 while (en2.hasMoreElements())
992 Property prop = new Property();
993 String key = en2.nextElement().toString();
995 prop.setValue(properties.get(key).toString());
996 item.addProperty(prop);
998 pdb.addPdbentryItem(item);
1001 jseq.addPdbids(pdb);
1005 saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
1010 if (!storeDS && av.hasHiddenRows())
1012 jal = av.getAlignment();
1016 if (storeDS && jal.getCodonFrames() != null)
1018 List<AlignedCodonFrame> jac = jal.getCodonFrames();
1019 for (AlignedCodonFrame acf : jac)
1021 AlcodonFrame alc = new AlcodonFrame();
1022 if (acf.getProtMappings() != null
1023 && acf.getProtMappings().length > 0)
1025 boolean hasMap = false;
1026 SequenceI[] dnas = acf.getdnaSeqs();
1027 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1028 for (int m = 0; m < pmaps.length; m++)
1030 AlcodMap alcmap = new AlcodMap();
1031 alcmap.setDnasq(seqHash(dnas[m]));
1032 alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
1034 alc.addAlcodMap(alcmap);
1039 vamsasSet.addAlcodonFrame(alc);
1042 // TODO: delete this ? dead code from 2.8.3->2.9 ?
1044 // AlcodonFrame alc = new AlcodonFrame();
1045 // vamsasSet.addAlcodonFrame(alc);
1046 // for (int p = 0; p < acf.aaWidth; p++)
1048 // Alcodon cmap = new Alcodon();
1049 // if (acf.codons[p] != null)
1051 // // Null codons indicate a gapped column in the translated peptide
1053 // cmap.setPos1(acf.codons[p][0]);
1054 // cmap.setPos2(acf.codons[p][1]);
1055 // cmap.setPos3(acf.codons[p][2]);
1057 // alc.addAlcodon(cmap);
1059 // if (acf.getProtMappings() != null
1060 // && acf.getProtMappings().length > 0)
1062 // SequenceI[] dnas = acf.getdnaSeqs();
1063 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1064 // for (int m = 0; m < pmaps.length; m++)
1066 // AlcodMap alcmap = new AlcodMap();
1067 // alcmap.setDnasq(seqHash(dnas[m]));
1068 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
1070 // alc.addAlcodMap(alcmap);
1077 // /////////////////////////////////
1078 if (!storeDS && av.currentTree != null)
1080 // FIND ANY ASSOCIATED TREES
1081 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
1082 if (Desktop.desktop != null)
1084 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1086 for (int t = 0; t < frames.length; t++)
1088 if (frames[t] instanceof TreePanel)
1090 TreePanel tp = (TreePanel) frames[t];
1092 if (tp.treeCanvas.av.getAlignment() == jal)
1094 Tree tree = new Tree();
1095 tree.setTitle(tp.getTitle());
1096 tree.setCurrentTree((av.currentTree == tp.getTree()));
1097 tree.setNewick(tp.getTree().toString());
1098 tree.setThreshold(tp.treeCanvas.threshold);
1100 tree.setFitToWindow(tp.fitToWindow.getState());
1101 tree.setFontName(tp.getTreeFont().getName());
1102 tree.setFontSize(tp.getTreeFont().getSize());
1103 tree.setFontStyle(tp.getTreeFont().getStyle());
1104 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
1106 tree.setShowBootstrap(tp.bootstrapMenu.getState());
1107 tree.setShowDistances(tp.distanceMenu.getState());
1109 tree.setHeight(tp.getHeight());
1110 tree.setWidth(tp.getWidth());
1111 tree.setXpos(tp.getX());
1112 tree.setYpos(tp.getY());
1113 tree.setId(makeHashCode(tp, null));
1123 * store forward refs from an annotationRow to any groups
1125 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<SequenceGroup, String>();
1128 for (SequenceI sq : jal.getSequences())
1130 // Store annotation on dataset sequences only
1131 AlignmentAnnotation[] aa = sq.getAnnotation();
1132 if (aa != null && aa.length > 0)
1134 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1141 if (jal.getAlignmentAnnotation() != null)
1143 // Store the annotation shown on the alignment.
1144 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1145 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1150 if (jal.getGroups() != null)
1152 JGroup[] groups = new JGroup[jal.getGroups().size()];
1154 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1156 JGroup jGroup = new JGroup();
1157 groups[++i] = jGroup;
1159 jGroup.setStart(sg.getStartRes());
1160 jGroup.setEnd(sg.getEndRes());
1161 jGroup.setName(sg.getName());
1162 if (groupRefs.containsKey(sg))
1164 // group has references so set its ID field
1165 jGroup.setId(groupRefs.get(sg));
1169 if (sg.cs.conservationApplied())
1171 jGroup.setConsThreshold(sg.cs.getConservationInc());
1173 if (sg.cs instanceof jalview.schemes.UserColourScheme)
1175 jGroup.setColour(setUserColourScheme(sg.cs, userColours, jms));
1179 jGroup.setColour(ColourSchemeProperty.getColourName(sg.cs));
1182 else if (sg.cs instanceof jalview.schemes.AnnotationColourGradient)
1184 jGroup.setColour("AnnotationColourGradient");
1185 jGroup.setAnnotationColours(constructAnnotationColours(
1186 (jalview.schemes.AnnotationColourGradient) sg.cs,
1189 else if (sg.cs instanceof jalview.schemes.UserColourScheme)
1191 jGroup.setColour(setUserColourScheme(sg.cs, userColours, jms));
1195 jGroup.setColour(ColourSchemeProperty.getColourName(sg.cs));
1198 jGroup.setPidThreshold(sg.cs.getThreshold());
1201 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1202 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1203 jGroup.setDisplayText(sg.getDisplayText());
1204 jGroup.setColourText(sg.getColourText());
1205 jGroup.setTextCol1(sg.textColour.getRGB());
1206 jGroup.setTextCol2(sg.textColour2.getRGB());
1207 jGroup.setTextColThreshold(sg.thresholdTextColour);
1208 jGroup.setShowUnconserved(sg.getShowNonconserved());
1209 jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1210 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1211 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1212 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1213 for (SequenceI seq : sg.getSequences())
1215 jGroup.addSeq(seqHash(seq));
1219 jms.setJGroup(groups);
1223 // /////////SAVE VIEWPORT
1224 Viewport view = new Viewport();
1225 view.setTitle(ap.alignFrame.getTitle());
1226 view.setSequenceSetId(makeHashCode(av.getSequenceSetId(),
1227 av.getSequenceSetId()));
1228 view.setId(av.getViewId());
1229 if (av.getCodingComplement() != null)
1231 view.setComplementId(av.getCodingComplement().getViewId());
1233 view.setViewName(av.viewName);
1234 view.setGatheredViews(av.isGatherViewsHere());
1236 Rectangle size = ap.av.getExplodedGeometry();
1237 Rectangle position = size;
1240 size = ap.alignFrame.getBounds();
1241 if (av.getCodingComplement() != null)
1243 position = ((SplitFrame) ap.alignFrame.getSplitViewContainer())
1251 view.setXpos(position.x);
1252 view.setYpos(position.y);
1254 view.setWidth(size.width);
1255 view.setHeight(size.height);
1257 view.setStartRes(av.startRes);
1258 view.setStartSeq(av.startSeq);
1260 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1262 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1265 else if (av.getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1267 AnnotationColours ac = constructAnnotationColours(
1268 (jalview.schemes.AnnotationColourGradient) av
1269 .getGlobalColourScheme(),
1272 view.setAnnotationColours(ac);
1273 view.setBgColour("AnnotationColourGradient");
1277 view.setBgColour(ColourSchemeProperty.getColourName(av
1278 .getGlobalColourScheme()));
1281 ColourSchemeI cs = av.getGlobalColourScheme();
1285 if (cs.conservationApplied())
1287 view.setConsThreshold(cs.getConservationInc());
1288 if (cs instanceof jalview.schemes.UserColourScheme)
1290 view.setBgColour(setUserColourScheme(cs, userColours, jms));
1294 if (cs instanceof ResidueColourScheme)
1296 view.setPidThreshold(cs.getThreshold());
1300 view.setConservationSelected(av.getConservationSelected());
1301 view.setPidSelected(av.getAbovePIDThreshold());
1302 view.setFontName(av.font.getName());
1303 view.setFontSize(av.font.getSize());
1304 view.setFontStyle(av.font.getStyle());
1305 view.setScaleProteinAsCdna(av.getViewStyle().isScaleProteinAsCdna());
1306 view.setRenderGaps(av.isRenderGaps());
1307 view.setShowAnnotation(av.isShowAnnotation());
1308 view.setShowBoxes(av.getShowBoxes());
1309 view.setShowColourText(av.getColourText());
1310 view.setShowFullId(av.getShowJVSuffix());
1311 view.setRightAlignIds(av.isRightAlignIds());
1312 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1313 view.setShowText(av.getShowText());
1314 view.setShowUnconserved(av.getShowUnconserved());
1315 view.setWrapAlignment(av.getWrapAlignment());
1316 view.setTextCol1(av.getTextColour().getRGB());
1317 view.setTextCol2(av.getTextColour2().getRGB());
1318 view.setTextColThreshold(av.getThresholdTextColour());
1319 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1320 view.setShowSequenceLogo(av.isShowSequenceLogo());
1321 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1322 view.setShowGroupConsensus(av.isShowGroupConsensus());
1323 view.setShowGroupConservation(av.isShowGroupConservation());
1324 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1325 view.setShowDbRefTooltip(av.isShowDBRefs());
1326 view.setFollowHighlight(av.isFollowHighlight());
1327 view.setFollowSelection(av.followSelection);
1328 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1329 if (av.getFeaturesDisplayed() != null)
1331 jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
1333 String[] renderOrder = ap.getSeqPanel().seqCanvas
1334 .getFeatureRenderer().getRenderOrder()
1335 .toArray(new String[0]);
1337 Vector<String> settingsAdded = new Vector<String>();
1338 if (renderOrder != null)
1340 for (String featureType : renderOrder)
1342 FeatureColourI fcol = ap.getSeqPanel().seqCanvas
1343 .getFeatureRenderer()
1344 .getFeatureStyle(featureType);
1345 Setting setting = new Setting();
1346 setting.setType(featureType);
1347 if (!fcol.isSimpleColour())
1349 setting.setColour(fcol.getMaxColour().getRGB());
1350 setting.setMincolour(fcol.getMinColour().getRGB());
1351 setting.setMin(fcol.getMin());
1352 setting.setMax(fcol.getMax());
1353 setting.setColourByLabel(fcol.isColourByLabel());
1354 setting.setAutoScale(fcol.isAutoScaled());
1355 setting.setThreshold(fcol.getThreshold());
1356 // -1 = No threshold, 0 = Below, 1 = Above
1357 setting.setThreshstate(fcol.isAboveThreshold() ? 1
1358 : (fcol.isBelowThreshold() ? 0 : -1));
1362 setting.setColour(fcol.getColour().getRGB());
1365 setting.setDisplay(av.getFeaturesDisplayed().isVisible(
1367 float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1368 .getOrder(featureType);
1371 setting.setOrder(rorder);
1373 fs.addSetting(setting);
1374 settingsAdded.addElement(featureType);
1378 // is groups actually supposed to be a map here ?
1379 Iterator<String> en = ap.getSeqPanel().seqCanvas
1380 .getFeatureRenderer()
1381 .getFeatureGroups().iterator();
1382 Vector<String> groupsAdded = new Vector<String>();
1383 while (en.hasNext())
1385 String grp = en.next();
1386 if (groupsAdded.contains(grp))
1390 Group g = new Group();
1392 g.setDisplay(((Boolean) ap.getSeqPanel().seqCanvas
1393 .getFeatureRenderer().checkGroupVisibility(grp, false))
1396 groupsAdded.addElement(grp);
1398 jms.setFeatureSettings(fs);
1401 if (av.hasHiddenColumns())
1403 if (av.getColumnSelection() == null
1404 || av.getColumnSelection().getHiddenColumns() == null)
1406 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1410 for (int c = 0; c < av.getColumnSelection().getHiddenColumns()
1413 int[] region = av.getColumnSelection().getHiddenColumns()
1415 HiddenColumns hc = new HiddenColumns();
1416 hc.setStart(region[0]);
1417 hc.setEnd(region[1]);
1418 view.addHiddenColumns(hc);
1422 if (calcIdSet.size() > 0)
1424 for (String calcId : calcIdSet)
1426 if (calcId.trim().length() > 0)
1428 CalcIdParam cidp = createCalcIdParam(calcId, av);
1429 // Some calcIds have no parameters.
1432 view.addCalcIdParam(cidp);
1438 jms.addViewport(view);
1440 object.setJalviewModelSequence(jms);
1441 object.getVamsasModel().addSequenceSet(vamsasSet);
1443 if (jout != null && fileName != null)
1445 // We may not want to write the object to disk,
1446 // eg we can copy the alignViewport to a new view object
1447 // using save and then load
1450 System.out.println("Writing jar entry " + fileName);
1451 JarEntry entry = new JarEntry(fileName);
1452 jout.putNextEntry(entry);
1453 PrintWriter pout = new PrintWriter(new OutputStreamWriter(jout,
1455 Marshaller marshaller = new Marshaller(pout);
1456 marshaller.marshal(object);
1459 } catch (Exception ex)
1461 // TODO: raise error in GUI if marshalling failed.
1462 ex.printStackTrace();
1469 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1470 * for each viewer, with
1472 * <li>viewer geometry (position, size, split pane divider location)</li>
1473 * <li>index of the selected structure in the viewer (currently shows gapped
1475 * <li>the id of the annotation holding RNA secondary structure</li>
1476 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1478 * Varna viewer state is also written out (in native Varna XML) to separate
1479 * project jar entries. A separate entry is written for each RNA structure
1480 * displayed, with the naming convention
1482 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
1490 * @param storeDataset
1492 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
1493 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
1494 boolean storeDataset)
1496 if (Desktop.desktop == null)
1500 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1501 for (int f = frames.length - 1; f > -1; f--)
1503 if (frames[f] instanceof AppVarna)
1505 AppVarna varna = (AppVarna) frames[f];
1507 * link the sequence to every viewer that is showing it and is linked to
1508 * its alignment panel
1510 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1512 String viewId = varna.getViewId();
1513 RnaViewer rna = new RnaViewer();
1514 rna.setViewId(viewId);
1515 rna.setTitle(varna.getTitle());
1516 rna.setXpos(varna.getX());
1517 rna.setYpos(varna.getY());
1518 rna.setWidth(varna.getWidth());
1519 rna.setHeight(varna.getHeight());
1520 rna.setDividerLocation(varna.getDividerLocation());
1521 rna.setSelectedRna(varna.getSelectedIndex());
1522 jseq.addRnaViewer(rna);
1525 * Store each Varna panel's state once in the project per sequence.
1526 * First time through only (storeDataset==false)
1528 // boolean storeSessions = false;
1529 // String sequenceViewId = viewId + seqsToIds.get(jds);
1530 // if (!storeDataset && !viewIds.contains(sequenceViewId))
1532 // viewIds.add(sequenceViewId);
1533 // storeSessions = true;
1535 for (RnaModel model : varna.getModels())
1537 if (model.seq == jds)
1540 * VARNA saves each view (sequence or alignment secondary
1541 * structure, gapped or trimmed) as a separate XML file
1543 String jarEntryName = rnaSessions.get(model);
1544 if (jarEntryName == null)
1547 String varnaStateFile = varna.getStateInfo(model.rna);
1548 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
1549 copyFileToJar(jout, varnaStateFile, jarEntryName);
1550 rnaSessions.put(model, jarEntryName);
1552 SecondaryStructure ss = new SecondaryStructure();
1553 String annotationId = varna.getAnnotation(jds).annotationId;
1554 ss.setAnnotationId(annotationId);
1555 ss.setViewerState(jarEntryName);
1556 ss.setGapped(model.gapped);
1557 ss.setTitle(model.title);
1558 rna.addSecondaryStructure(ss);
1567 * Copy the contents of a file to a new entry added to the output jar
1571 * @param jarEntryName
1573 protected void copyFileToJar(JarOutputStream jout, String infilePath,
1574 String jarEntryName)
1576 DataInputStream dis = null;
1579 File file = new File(infilePath);
1580 if (file.exists() && jout != null)
1582 dis = new DataInputStream(new FileInputStream(file));
1583 byte[] data = new byte[(int) file.length()];
1584 dis.readFully(data);
1585 writeJarEntry(jout, jarEntryName, data);
1587 } catch (Exception ex)
1589 ex.printStackTrace();
1597 } catch (IOException e)
1606 * Write the data to a new entry of given name in the output jar file
1609 * @param jarEntryName
1611 * @throws IOException
1613 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
1614 byte[] data) throws IOException
1618 System.out.println("Writing jar entry " + jarEntryName);
1619 jout.putNextEntry(new JarEntry(jarEntryName));
1620 DataOutputStream dout = new DataOutputStream(jout);
1621 dout.write(data, 0, data.length);
1628 * Save the state of a structure viewer
1633 * the archive XML element under which to save the state
1636 * @param matchedFile
1640 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
1641 Pdbids pdb, PDBEntry entry, List<String> viewIds,
1642 String matchedFile, StructureViewerBase viewFrame)
1644 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
1647 * Look for any bindings for this viewer to the PDB file of interest
1648 * (including part matches excluding chain id)
1650 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
1652 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
1653 final String pdbId = pdbentry.getId();
1654 if (!pdbId.equals(entry.getId())
1655 && !(entry.getId().length() > 4 && entry.getId()
1656 .toLowerCase().startsWith(pdbId.toLowerCase())))
1659 * not interested in a binding to a different PDB entry here
1663 if (matchedFile == null)
1665 matchedFile = pdbentry.getFile();
1667 else if (!matchedFile.equals(pdbentry.getFile()))
1670 .warn("Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
1671 + pdbentry.getFile());
1675 // can get at it if the ID
1676 // match is ambiguous (e.g.
1679 for (int smap = 0; smap < viewFrame.getBinding().getSequence()[peid].length; smap++)
1681 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
1682 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
1684 StructureState state = new StructureState();
1685 state.setVisible(true);
1686 state.setXpos(viewFrame.getX());
1687 state.setYpos(viewFrame.getY());
1688 state.setWidth(viewFrame.getWidth());
1689 state.setHeight(viewFrame.getHeight());
1690 final String viewId = viewFrame.getViewId();
1691 state.setViewId(viewId);
1692 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
1693 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
1694 state.setColourByJmol(viewFrame.isColouredByViewer());
1695 state.setType(viewFrame.getViewerType().toString());
1696 pdb.addStructureState(state);
1703 private AnnotationColours constructAnnotationColours(
1704 AnnotationColourGradient acg, List<UserColourScheme> userColours,
1705 JalviewModelSequence jms)
1707 AnnotationColours ac = new AnnotationColours();
1708 ac.setAboveThreshold(acg.getAboveThreshold());
1709 ac.setThreshold(acg.getAnnotationThreshold());
1710 ac.setAnnotation(acg.getAnnotation());
1711 if (acg.getBaseColour() instanceof jalview.schemes.UserColourScheme)
1713 ac.setColourScheme(setUserColourScheme(acg.getBaseColour(),
1718 ac.setColourScheme(ColourSchemeProperty.getColourName(acg
1722 ac.setMaxColour(acg.getMaxColour().getRGB());
1723 ac.setMinColour(acg.getMinColour().getRGB());
1724 ac.setPerSequence(acg.isSeqAssociated());
1725 ac.setPredefinedColours(acg.isPredefinedColours());
1729 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
1730 IdentityHashMap<SequenceGroup, String> groupRefs,
1731 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
1732 SequenceSet vamsasSet)
1735 for (int i = 0; i < aa.length; i++)
1737 Annotation an = new Annotation();
1739 AlignmentAnnotation annotation = aa[i];
1740 if (annotation.annotationId != null)
1742 annotationIds.put(annotation.annotationId, annotation);
1745 an.setId(annotation.annotationId);
1747 an.setVisible(annotation.visible);
1749 an.setDescription(annotation.description);
1751 if (annotation.sequenceRef != null)
1753 // 2.9 JAL-1781 xref on sequence id rather than name
1754 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
1756 if (annotation.groupRef != null)
1758 String groupIdr = groupRefs.get(annotation.groupRef);
1759 if (groupIdr == null)
1761 // make a locally unique String
1763 annotation.groupRef,
1764 groupIdr = ("" + System.currentTimeMillis()
1765 + annotation.groupRef.getName() + groupRefs
1768 an.setGroupRef(groupIdr.toString());
1771 // store all visualization attributes for annotation
1772 an.setGraphHeight(annotation.graphHeight);
1773 an.setCentreColLabels(annotation.centreColLabels);
1774 an.setScaleColLabels(annotation.scaleColLabel);
1775 an.setShowAllColLabels(annotation.showAllColLabels);
1776 an.setBelowAlignment(annotation.belowAlignment);
1778 if (annotation.graph > 0)
1781 an.setGraphType(annotation.graph);
1782 an.setGraphGroup(annotation.graphGroup);
1783 if (annotation.getThreshold() != null)
1785 ThresholdLine line = new ThresholdLine();
1786 line.setLabel(annotation.getThreshold().label);
1787 line.setValue(annotation.getThreshold().value);
1788 line.setColour(annotation.getThreshold().colour.getRGB());
1789 an.setThresholdLine(line);
1797 an.setLabel(annotation.label);
1799 if (annotation == av.getAlignmentQualityAnnot()
1800 || annotation == av.getAlignmentConservationAnnotation()
1801 || annotation == av.getAlignmentConsensusAnnotation()
1802 || annotation.autoCalculated)
1804 // new way of indicating autocalculated annotation -
1805 an.setAutoCalculated(annotation.autoCalculated);
1807 if (annotation.hasScore())
1809 an.setScore(annotation.getScore());
1812 if (annotation.getCalcId() != null)
1814 calcIdSet.add(annotation.getCalcId());
1815 an.setCalcId(annotation.getCalcId());
1817 if (annotation.hasProperties())
1819 for (String pr : annotation.getProperties())
1821 Property prop = new Property();
1823 prop.setValue(annotation.getProperty(pr));
1824 an.addProperty(prop);
1828 AnnotationElement ae;
1829 if (annotation.annotations != null)
1831 an.setScoreOnly(false);
1832 for (int a = 0; a < annotation.annotations.length; a++)
1834 if ((annotation == null) || (annotation.annotations[a] == null))
1839 ae = new AnnotationElement();
1840 if (annotation.annotations[a].description != null)
1842 ae.setDescription(annotation.annotations[a].description);
1844 if (annotation.annotations[a].displayCharacter != null)
1846 ae.setDisplayCharacter(annotation.annotations[a].displayCharacter);
1849 if (!Float.isNaN(annotation.annotations[a].value))
1851 ae.setValue(annotation.annotations[a].value);
1855 if (annotation.annotations[a].secondaryStructure > ' ')
1857 ae.setSecondaryStructure(annotation.annotations[a].secondaryStructure
1861 if (annotation.annotations[a].colour != null
1862 && annotation.annotations[a].colour != java.awt.Color.black)
1864 ae.setColour(annotation.annotations[a].colour.getRGB());
1867 an.addAnnotationElement(ae);
1868 if (annotation.autoCalculated)
1870 // only write one non-null entry into the annotation row -
1871 // sufficient to get the visualization attributes necessary to
1879 an.setScoreOnly(true);
1881 if (!storeDS || (storeDS && !annotation.autoCalculated))
1883 // skip autocalculated annotation - these are only provided for
1885 vamsasSet.addAnnotation(an);
1891 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
1893 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
1894 if (settings != null)
1896 CalcIdParam vCalcIdParam = new CalcIdParam();
1897 vCalcIdParam.setCalcId(calcId);
1898 vCalcIdParam.addServiceURL(settings.getServiceURI());
1899 // generic URI allowing a third party to resolve another instance of the
1900 // service used for this calculation
1901 for (String urls : settings.getServiceURLs())
1903 vCalcIdParam.addServiceURL(urls);
1905 vCalcIdParam.setVersion("1.0");
1906 if (settings.getPreset() != null)
1908 WsParamSetI setting = settings.getPreset();
1909 vCalcIdParam.setName(setting.getName());
1910 vCalcIdParam.setDescription(setting.getDescription());
1914 vCalcIdParam.setName("");
1915 vCalcIdParam.setDescription("Last used parameters");
1917 // need to be able to recover 1) settings 2) user-defined presets or
1918 // recreate settings from preset 3) predefined settings provided by
1919 // service - or settings that can be transferred (or discarded)
1920 vCalcIdParam.setParameters(settings.getWsParamFile().replace("\n",
1922 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
1923 // todo - decide if updateImmediately is needed for any projects.
1925 return vCalcIdParam;
1930 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
1933 if (calcIdParam.getVersion().equals("1.0"))
1935 Jws2Instance service = Jws2Discoverer.getDiscoverer()
1936 .getPreferredServiceFor(calcIdParam.getServiceURL());
1937 if (service != null)
1939 WsParamSetI parmSet = null;
1942 parmSet = service.getParamStore().parseServiceParameterFile(
1943 calcIdParam.getName(), calcIdParam.getDescription(),
1944 calcIdParam.getServiceURL(),
1945 calcIdParam.getParameters().replace("|\\n|", "\n"));
1946 } catch (IOException x)
1948 warn("Couldn't parse parameter data for "
1949 + calcIdParam.getCalcId(), x);
1952 List<ArgumentI> argList = null;
1953 if (calcIdParam.getName().length() > 0)
1955 parmSet = service.getParamStore()
1956 .getPreset(calcIdParam.getName());
1957 if (parmSet != null)
1959 // TODO : check we have a good match with settings in AACon -
1960 // otherwise we'll need to create a new preset
1965 argList = parmSet.getArguments();
1968 AAConSettings settings = new AAConSettings(
1969 calcIdParam.isAutoUpdate(), service, parmSet, argList);
1970 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
1971 calcIdParam.isNeedsUpdate());
1976 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
1980 throw new Error(MessageManager.formatMessage(
1981 "error.unsupported_version_calcIdparam",
1982 new Object[] { calcIdParam.toString() }));
1986 * External mapping between jalview objects and objects yielding a valid and
1987 * unique object ID string. This is null for normal Jalview project IO, but
1988 * non-null when a jalview project is being read or written as part of a
1991 IdentityHashMap jv2vobj = null;
1994 * Construct a unique ID for jvobj using either existing bindings or if none
1995 * exist, the result of the hashcode call for the object.
1998 * jalview data object
1999 * @return unique ID for referring to jvobj
2001 private String makeHashCode(Object jvobj, String altCode)
2003 if (jv2vobj != null)
2005 Object id = jv2vobj.get(jvobj);
2008 return id.toString();
2010 // check string ID mappings
2011 if (jvids2vobj != null && jvobj instanceof String)
2013 id = jvids2vobj.get(jvobj);
2017 return id.toString();
2019 // give up and warn that something has gone wrong
2020 warn("Cannot find ID for object in external mapping : " + jvobj);
2026 * return local jalview object mapped to ID, if it exists
2030 * @return null or object bound to idcode
2032 private Object retrieveExistingObj(String idcode)
2034 if (idcode != null && vobj2jv != null)
2036 return vobj2jv.get(idcode);
2042 * binding from ID strings from external mapping table to jalview data model
2045 private Hashtable vobj2jv;
2047 private Sequence createVamsasSequence(String id, SequenceI jds)
2049 return createVamsasSequence(true, id, jds, null);
2052 private Sequence createVamsasSequence(boolean recurse, String id,
2053 SequenceI jds, SequenceI parentseq)
2055 Sequence vamsasSeq = new Sequence();
2056 vamsasSeq.setId(id);
2057 vamsasSeq.setName(jds.getName());
2058 vamsasSeq.setSequence(jds.getSequenceAsString());
2059 vamsasSeq.setDescription(jds.getDescription());
2060 jalview.datamodel.DBRefEntry[] dbrefs = null;
2061 if (jds.getDatasetSequence() != null)
2063 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
2067 // seqId==dsseqid so we can tell which sequences really are
2068 // dataset sequences only
2069 vamsasSeq.setDsseqid(id);
2070 dbrefs = jds.getDBRefs();
2071 if (parentseq == null)
2078 for (int d = 0; d < dbrefs.length; d++)
2080 DBRef dbref = new DBRef();
2081 dbref.setSource(dbrefs[d].getSource());
2082 dbref.setVersion(dbrefs[d].getVersion());
2083 dbref.setAccessionId(dbrefs[d].getAccessionId());
2084 if (dbrefs[d].hasMap())
2086 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
2088 dbref.setMapping(mp);
2090 vamsasSeq.addDBRef(dbref);
2096 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
2097 SequenceI parentseq, SequenceI jds, boolean recurse)
2100 if (jmp.getMap() != null)
2104 jalview.util.MapList mlst = jmp.getMap();
2105 List<int[]> r = mlst.getFromRanges();
2106 for (int[] range : r)
2108 MapListFrom mfrom = new MapListFrom();
2109 mfrom.setStart(range[0]);
2110 mfrom.setEnd(range[1]);
2111 mp.addMapListFrom(mfrom);
2113 r = mlst.getToRanges();
2114 for (int[] range : r)
2116 MapListTo mto = new MapListTo();
2117 mto.setStart(range[0]);
2118 mto.setEnd(range[1]);
2119 mp.addMapListTo(mto);
2121 mp.setMapFromUnit(mlst.getFromRatio());
2122 mp.setMapToUnit(mlst.getToRatio());
2123 if (jmp.getTo() != null)
2125 MappingChoice mpc = new MappingChoice();
2127 // check/create ID for the sequence referenced by getTo()
2130 SequenceI ps = null;
2131 if (parentseq != jmp.getTo()
2132 && parentseq.getDatasetSequence() != jmp.getTo())
2134 // chaining dbref rather than a handshaking one
2135 jmpid = seqHash(ps = jmp.getTo());
2139 jmpid = seqHash(ps = parentseq);
2141 mpc.setDseqFor(jmpid);
2142 if (!seqRefIds.containsKey(mpc.getDseqFor()))
2144 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2145 seqRefIds.put(mpc.getDseqFor(), ps);
2149 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2152 mp.setMappingChoice(mpc);
2158 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2159 List<UserColourScheme> userColours, JalviewModelSequence jms)
2162 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2163 boolean newucs = false;
2164 if (!userColours.contains(ucs))
2166 userColours.add(ucs);
2169 id = "ucs" + userColours.indexOf(ucs);
2172 // actually create the scheme's entry in the XML model
2173 java.awt.Color[] colours = ucs.getColours();
2174 jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
2175 jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
2177 for (int i = 0; i < colours.length; i++)
2179 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2180 col.setName(ResidueProperties.aa[i]);
2181 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2182 jbucs.addColour(col);
2184 if (ucs.getLowerCaseColours() != null)
2186 colours = ucs.getLowerCaseColours();
2187 for (int i = 0; i < colours.length; i++)
2189 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2190 col.setName(ResidueProperties.aa[i].toLowerCase());
2191 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2192 jbucs.addColour(col);
2197 uc.setUserColourScheme(jbucs);
2198 jms.addUserColours(uc);
2204 jalview.schemes.UserColourScheme getUserColourScheme(
2205 JalviewModelSequence jms, String id)
2207 UserColours[] uc = jms.getUserColours();
2208 UserColours colours = null;
2210 for (int i = 0; i < uc.length; i++)
2212 if (uc[i].getId().equals(id))
2220 java.awt.Color[] newColours = new java.awt.Color[24];
2222 for (int i = 0; i < 24; i++)
2224 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2225 .getUserColourScheme().getColour(i).getRGB(), 16));
2228 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2231 if (colours.getUserColourScheme().getColourCount() > 24)
2233 newColours = new java.awt.Color[23];
2234 for (int i = 0; i < 23; i++)
2236 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2237 .getUserColourScheme().getColour(i + 24).getRGB(), 16));
2239 ucs.setLowerCaseColours(newColours);
2246 * contains last error message (if any) encountered by XML loader.
2248 String errorMessage = null;
2251 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2252 * exceptions are raised during project XML parsing
2254 public boolean attemptversion1parse = true;
2257 * Load a jalview project archive from a jar file
2260 * - HTTP URL or filename
2262 public AlignFrame loadJalviewAlign(final String file)
2265 jalview.gui.AlignFrame af = null;
2269 // create list to store references for any new Jmol viewers created
2270 newStructureViewers = new Vector<JalviewStructureDisplayI>();
2271 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2272 // Workaround is to make sure caller implements the JarInputStreamProvider
2274 // so we can re-open the jar input stream for each entry.
2276 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2277 af = loadJalviewAlign(jprovider);
2279 } catch (MalformedURLException e)
2281 errorMessage = "Invalid URL format for '" + file + "'";
2287 SwingUtilities.invokeAndWait(new Runnable()
2292 setLoadingFinishedForNewStructureViewers();
2295 } catch (Exception x)
2297 System.err.println("Error loading alignment: " + x.getMessage());
2303 private jarInputStreamProvider createjarInputStreamProvider(
2304 final String file) throws MalformedURLException
2307 errorMessage = null;
2308 uniqueSetSuffix = null;
2310 viewportsAdded.clear();
2311 frefedSequence = null;
2313 if (file.startsWith("http://"))
2315 url = new URL(file);
2317 final URL _url = url;
2318 return new jarInputStreamProvider()
2322 public JarInputStream getJarInputStream() throws IOException
2326 return new JarInputStream(_url.openStream());
2330 return new JarInputStream(new FileInputStream(file));
2335 public String getFilename()
2343 * Recover jalview session from a jalview project archive. Caller may
2344 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2345 * themselves. Any null fields will be initialised with default values,
2346 * non-null fields are left alone.
2351 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2353 errorMessage = null;
2354 if (uniqueSetSuffix == null)
2356 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2358 if (seqRefIds == null)
2362 AlignFrame af = null, _af = null;
2363 IdentityHashMap<AlignmentI, AlignmentI> importedDatasets = new IdentityHashMap<AlignmentI, AlignmentI>();
2364 Map<String, AlignFrame> gatherToThisFrame = new HashMap<String, AlignFrame>();
2365 final String file = jprovider.getFilename();
2368 JarInputStream jin = null;
2369 JarEntry jarentry = null;
2374 jin = jprovider.getJarInputStream();
2375 for (int i = 0; i < entryCount; i++)
2377 jarentry = jin.getNextJarEntry();
2380 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2382 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2383 JalviewModel object = new JalviewModel();
2385 Unmarshaller unmar = new Unmarshaller(object);
2386 unmar.setValidation(false);
2387 object = (JalviewModel) unmar.unmarshal(in);
2388 if (true) // !skipViewport(object))
2390 _af = loadFromObject(object, file, true, jprovider);
2392 && object.getJalviewModelSequence().getViewportCount() > 0)
2396 // store a reference to the first view
2399 if (_af.viewport.isGatherViewsHere())
2401 // if this is a gathered view, keep its reference since
2402 // after gathering views, only this frame will remain
2404 gatherToThisFrame.put(_af.viewport.getSequenceSetId(), _af);
2406 // Save dataset to register mappings once all resolved
2407 importedDatasets.put(af.viewport.getAlignment().getDataset(),
2408 af.viewport.getAlignment().getDataset());
2413 else if (jarentry != null)
2415 // Some other file here.
2418 } while (jarentry != null);
2419 resolveFrefedSequences();
2420 } catch (IOException ex)
2422 ex.printStackTrace();
2423 errorMessage = "Couldn't locate Jalview XML file : " + file;
2424 System.err.println("Exception whilst loading jalview XML file : "
2426 } catch (Exception ex)
2428 System.err.println("Parsing as Jalview Version 2 file failed.");
2429 ex.printStackTrace(System.err);
2430 if (attemptversion1parse)
2432 // Is Version 1 Jar file?
2435 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
2436 } catch (Exception ex2)
2438 System.err.println("Exception whilst loading as jalviewXMLV1:");
2439 ex2.printStackTrace();
2443 if (Desktop.instance != null)
2445 Desktop.instance.stopLoading();
2449 System.out.println("Successfully loaded archive file");
2452 ex.printStackTrace();
2454 System.err.println("Exception whilst loading jalview XML file : "
2456 } catch (OutOfMemoryError e)
2458 // Don't use the OOM Window here
2459 errorMessage = "Out of memory loading jalview XML file";
2460 System.err.println("Out of memory whilst loading jalview XML file");
2461 e.printStackTrace();
2465 * Regather multiple views (with the same sequence set id) to the frame (if
2466 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2467 * views instead of separate frames. Note this doesn't restore a state where
2468 * some expanded views in turn have tabbed views - the last "first tab" read
2469 * in will play the role of gatherer for all.
2471 for (AlignFrame fr : gatherToThisFrame.values())
2473 Desktop.instance.gatherViews(fr);
2476 restoreSplitFrames();
2477 for (AlignmentI ds : importedDatasets.keySet())
2479 if (ds.getCodonFrames() != null)
2481 StructureSelectionManager.getStructureSelectionManager(
2482 Desktop.instance).registerMappings(ds.getCodonFrames());
2485 if (errorMessage != null)
2490 if (Desktop.instance != null)
2492 Desktop.instance.stopLoading();
2499 * Try to reconstruct and display SplitFrame windows, where each contains
2500 * complementary dna and protein alignments. Done by pairing up AlignFrame
2501 * objects (created earlier) which have complementary viewport ids associated.
2503 protected void restoreSplitFrames()
2505 List<SplitFrame> gatherTo = new ArrayList<SplitFrame>();
2506 List<AlignFrame> addedToSplitFrames = new ArrayList<AlignFrame>();
2507 Map<String, AlignFrame> dna = new HashMap<String, AlignFrame>();
2510 * Identify the DNA alignments
2512 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2515 AlignFrame af = candidate.getValue();
2516 if (af.getViewport().getAlignment().isNucleotide())
2518 dna.put(candidate.getKey().getId(), af);
2523 * Try to match up the protein complements
2525 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2528 AlignFrame af = candidate.getValue();
2529 if (!af.getViewport().getAlignment().isNucleotide())
2531 String complementId = candidate.getKey().getComplementId();
2532 // only non-null complements should be in the Map
2533 if (complementId != null && dna.containsKey(complementId))
2535 final AlignFrame dnaFrame = dna.get(complementId);
2536 SplitFrame sf = createSplitFrame(dnaFrame, af);
2537 addedToSplitFrames.add(dnaFrame);
2538 addedToSplitFrames.add(af);
2539 if (af.viewport.isGatherViewsHere())
2548 * Open any that we failed to pair up (which shouldn't happen!) as
2549 * standalone AlignFrame's.
2551 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2554 AlignFrame af = candidate.getValue();
2555 if (!addedToSplitFrames.contains(af))
2557 Viewport view = candidate.getKey();
2558 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
2560 System.err.println("Failed to restore view " + view.getTitle()
2561 + " to split frame");
2566 * Gather back into tabbed views as flagged.
2568 for (SplitFrame sf : gatherTo)
2570 Desktop.instance.gatherViews(sf);
2573 splitFrameCandidates.clear();
2577 * Construct and display one SplitFrame holding DNA and protein alignments.
2580 * @param proteinFrame
2583 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
2584 AlignFrame proteinFrame)
2586 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
2587 String title = MessageManager.getString("label.linked_view_title");
2588 int width = (int) dnaFrame.getBounds().getWidth();
2589 int height = (int) (dnaFrame.getBounds().getHeight()
2590 + proteinFrame.getBounds().getHeight() + 50);
2593 * SplitFrame location is saved to both enclosed frames
2595 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
2596 Desktop.addInternalFrame(splitFrame, title, width, height);
2599 * And compute cDNA consensus (couldn't do earlier with consensus as
2600 * mappings were not yet present)
2602 proteinFrame.viewport.alignmentChanged(proteinFrame.alignPanel);
2608 * check errorMessage for a valid error message and raise an error box in the
2609 * GUI or write the current errorMessage to stderr and then clear the error
2612 protected void reportErrors()
2614 reportErrors(false);
2617 protected void reportErrors(final boolean saving)
2619 if (errorMessage != null)
2621 final String finalErrorMessage = errorMessage;
2624 javax.swing.SwingUtilities.invokeLater(new Runnable()
2629 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2630 finalErrorMessage, "Error "
2631 + (saving ? "saving" : "loading")
2632 + " Jalview file", JOptionPane.WARNING_MESSAGE);
2638 System.err.println("Problem loading Jalview file: " + errorMessage);
2641 errorMessage = null;
2644 Map<String, String> alreadyLoadedPDB = new HashMap<String, String>();
2647 * when set, local views will be updated from view stored in JalviewXML
2648 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2649 * sync if this is set to true.
2651 private final boolean updateLocalViews = false;
2654 * Returns the path to a temporary file holding the PDB file for the given PDB
2655 * id. The first time of asking, searches for a file of that name in the
2656 * Jalview project jar, and copies it to a new temporary file. Any repeat
2657 * requests just return the path to the file previously created.
2663 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId)
2665 if (alreadyLoadedPDB.containsKey(pdbId))
2667 return alreadyLoadedPDB.get(pdbId).toString();
2670 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb");
2671 if (tempFile != null)
2673 alreadyLoadedPDB.put(pdbId, tempFile);
2679 * Copies the jar entry of given name to a new temporary file and returns the
2680 * path to the file, or null if the entry is not found.
2683 * @param jarEntryName
2685 * a prefix for the temporary file name, must be at least three
2689 protected String copyJarEntry(jarInputStreamProvider jprovider,
2690 String jarEntryName, String prefix)
2692 BufferedReader in = null;
2693 PrintWriter out = null;
2697 JarInputStream jin = jprovider.getJarInputStream();
2699 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2700 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2701 * FileInputStream(jprovider)); }
2704 JarEntry entry = null;
2707 entry = jin.getNextJarEntry();
2708 } while (entry != null && !entry.getName().equals(jarEntryName));
2711 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
2712 File outFile = File.createTempFile(prefix, ".tmp");
2713 outFile.deleteOnExit();
2714 out = new PrintWriter(new FileOutputStream(outFile));
2717 while ((data = in.readLine()) != null)
2722 String t = outFile.getAbsolutePath();
2727 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
2729 } catch (Exception ex)
2731 ex.printStackTrace();
2739 } catch (IOException e)
2753 private class JvAnnotRow
2755 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2762 * persisted version of annotation row from which to take vis properties
2764 public jalview.datamodel.AlignmentAnnotation template;
2767 * original position of the annotation row in the alignment
2773 * Load alignment frame from jalview XML DOM object
2778 * filename source string
2779 * @param loadTreesAndStructures
2780 * when false only create Viewport
2782 * data source provider
2783 * @return alignment frame created from view stored in DOM
2785 AlignFrame loadFromObject(JalviewModel object, String file,
2786 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
2788 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
2789 Sequence[] vamsasSeq = vamsasSet.getSequence();
2791 JalviewModelSequence jms = object.getJalviewModelSequence();
2793 Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
2796 // ////////////////////////////////
2799 List<SequenceI> hiddenSeqs = null;
2802 List<SequenceI> tmpseqs = new ArrayList<SequenceI>();
2804 boolean multipleView = false;
2805 SequenceI referenceseqForView = null;
2806 JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
2807 int vi = 0; // counter in vamsasSeq array
2808 for (int i = 0; i < jseqs.length; i++)
2810 String seqId = jseqs[i].getId();
2812 SequenceI tmpSeq = seqRefIds.get(seqId);
2815 if (!incompleteSeqs.containsKey(seqId))
2817 // may not need this check, but keep it for at least 2.9,1 release
2818 if (tmpSeq.getStart()!=jseqs[i].getStart() || tmpSeq.getEnd()!=jseqs[i].getEnd())
2821 .println("Warning JAL-2154 regression: updating start/end for sequence "
2822 + tmpSeq.toString() + " to " + jseqs[i]);
2825 incompleteSeqs.remove(seqId);
2827 if (vamsasSeq.length > vi && vamsasSeq[vi].getId().equals(seqId))
2829 // most likely we are reading a dataset XML document so
2830 // update from vamsasSeq section of XML for this sequence
2831 tmpSeq.setName(vamsasSeq[vi].getName());
2832 tmpSeq.setDescription(vamsasSeq[vi].getDescription());
2833 tmpSeq.setSequence(vamsasSeq[vi].getSequence());
2838 // reading multiple views, so vamsasSeq set is a subset of JSeq
2839 multipleView = true;
2841 tmpSeq.setStart(jseqs[i].getStart());
2842 tmpSeq.setEnd(jseqs[i].getEnd());
2843 tmpseqs.add(tmpSeq);
2847 tmpSeq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
2848 vamsasSeq[vi].getSequence());
2849 tmpSeq.setDescription(vamsasSeq[vi].getDescription());
2850 tmpSeq.setStart(jseqs[i].getStart());
2851 tmpSeq.setEnd(jseqs[i].getEnd());
2852 tmpSeq.setVamsasId(uniqueSetSuffix + seqId);
2853 seqRefIds.put(vamsasSeq[vi].getId(), tmpSeq);
2854 tmpseqs.add(tmpSeq);
2858 if (jseqs[i].hasViewreference() && jseqs[i].getViewreference())
2860 referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
2863 if (jseqs[i].getHidden())
2865 if (hiddenSeqs == null)
2867 hiddenSeqs = new ArrayList<SequenceI>();
2870 hiddenSeqs.add(tmpSeq);
2875 // Create the alignment object from the sequence set
2876 // ///////////////////////////////
2877 SequenceI[] orderedSeqs = tmpseqs
2878 .toArray(new SequenceI[tmpseqs.size()]);
2880 AlignmentI al = null;
2881 // so we must create or recover the dataset alignment before going further
2882 // ///////////////////////////////
2883 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
2885 // older jalview projects do not have a dataset - so creat alignment and
2887 al = new Alignment(orderedSeqs);
2888 al.setDataset(null);
2892 boolean isdsal = object.getJalviewModelSequence().getViewportCount() == 0;
2895 // we are importing a dataset record, so
2896 // recover reference to an alignment already materialsed as dataset
2897 al = getDatasetFor(vamsasSet.getDatasetId());
2901 // materialse the alignment
2902 al = new Alignment(orderedSeqs);
2906 addDatasetRef(vamsasSet.getDatasetId(), al);
2909 // finally, verify all data in vamsasSet is actually present in al
2910 // passing on flag indicating if it is actually a stored dataset
2911 recoverDatasetFor(vamsasSet, al, isdsal);
2914 if (referenceseqForView != null)
2916 al.setSeqrep(referenceseqForView);
2918 // / Add the alignment properties
2919 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
2921 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
2922 al.setProperty(ssp.getKey(), ssp.getValue());
2925 // ///////////////////////////////
2927 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
2930 // load sequence features, database references and any associated PDB
2931 // structures for the alignment
2933 // prior to 2.10, this part would only be executed the first time a
2934 // sequence was encountered, but not afterwards.
2935 // now, for 2.10 projects, this is also done if the xml doc includes
2936 // dataset sequences not actually present in any particular view.
2938 for (int i = 0; i < vamsasSeq.length; i++)
2940 if (jseqs[i].getFeaturesCount() > 0)
2942 Features[] features = jseqs[i].getFeatures();
2943 for (int f = 0; f < features.length; f++)
2945 jalview.datamodel.SequenceFeature sf = new jalview.datamodel.SequenceFeature(
2946 features[f].getType(), features[f].getDescription(),
2947 features[f].getStatus(), features[f].getBegin(),
2948 features[f].getEnd(), features[f].getFeatureGroup());
2950 sf.setScore(features[f].getScore());
2951 for (int od = 0; od < features[f].getOtherDataCount(); od++)
2953 OtherData keyValue = features[f].getOtherData(od);
2954 if (keyValue.getKey().startsWith("LINK"))
2956 sf.addLink(keyValue.getValue());
2960 sf.setValue(keyValue.getKey(), keyValue.getValue());
2964 // adds feature to datasequence's feature set (since Jalview 2.10)
2965 al.getSequenceAt(i).addSequenceFeature(sf);
2968 if (vamsasSeq[i].getDBRefCount() > 0)
2970 // adds dbrefs to datasequence's set (since Jalview 2.10)
2972 al.getSequenceAt(i).getDatasetSequence() == null ? al.getSequenceAt(i)
2973 : al.getSequenceAt(i).getDatasetSequence(),
2976 if (jseqs[i].getPdbidsCount() > 0)
2978 Pdbids[] ids = jseqs[i].getPdbids();
2979 for (int p = 0; p < ids.length; p++)
2981 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
2982 entry.setId(ids[p].getId());
2983 if (ids[p].getType() != null)
2985 if (ids[p].getType().equalsIgnoreCase("PDB"))
2987 entry.setType(PDBEntry.Type.PDB);
2991 entry.setType(PDBEntry.Type.FILE);
2994 if (ids[p].getFile() != null)
2996 if (!pdbloaded.containsKey(ids[p].getFile()))
2998 entry.setFile(loadPDBFile(jprovider, ids[p].getId()));
3002 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
3005 if (ids[p].getPdbentryItem() != null)
3007 entry.setProperty(new Hashtable());
3008 for (PdbentryItem item : ids[p].getPdbentryItem())
3010 for (Property pr : item.getProperty())
3012 entry.getProperty().put(pr.getName(), pr.getValue());
3016 StructureSelectionManager.getStructureSelectionManager(
3017 Desktop.instance).registerPDBEntry(entry);
3018 // adds PDBEntry to datasequence's set (since Jalview 2.10)
3019 if (al.getSequenceAt(i).getDatasetSequence() != null)
3021 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
3025 al.getSequenceAt(i).addPDBId(entry);
3030 } // end !multipleview
3032 // ///////////////////////////////
3033 // LOAD SEQUENCE MAPPINGS
3035 if (vamsasSet.getAlcodonFrameCount() > 0)
3037 // TODO Potentially this should only be done once for all views of an
3039 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
3040 for (int i = 0; i < alc.length; i++)
3042 AlignedCodonFrame cf = new AlignedCodonFrame();
3043 if (alc[i].getAlcodMapCount() > 0)
3045 AlcodMap[] maps = alc[i].getAlcodMap();
3046 for (int m = 0; m < maps.length; m++)
3048 SequenceI dnaseq = seqRefIds.get(maps[m].getDnasq());
3050 jalview.datamodel.Mapping mapping = null;
3051 // attach to dna sequence reference.
3052 if (maps[m].getMapping() != null)
3054 mapping = addMapping(maps[m].getMapping());
3055 if (dnaseq != null && mapping.getTo() != null)
3057 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
3062 frefedSequence.add(newAlcodMapRef(maps[m].getDnasq(), cf,
3067 al.addCodonFrame(cf);
3072 // ////////////////////////////////
3074 List<JvAnnotRow> autoAlan = new ArrayList<JvAnnotRow>();
3077 * store any annotations which forward reference a group's ID
3079 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<String, List<AlignmentAnnotation>>();
3081 if (vamsasSet.getAnnotationCount() > 0)
3083 Annotation[] an = vamsasSet.getAnnotation();
3085 for (int i = 0; i < an.length; i++)
3087 Annotation annotation = an[i];
3090 * test if annotation is automatically calculated for this view only
3092 boolean autoForView = false;
3093 if (annotation.getLabel().equals("Quality")
3094 || annotation.getLabel().equals("Conservation")
3095 || annotation.getLabel().equals("Consensus"))
3097 // Kludge for pre 2.5 projects which lacked the autocalculated flag
3099 if (!annotation.hasAutoCalculated())
3101 annotation.setAutoCalculated(true);
3105 || (annotation.hasAutoCalculated() && annotation
3106 .isAutoCalculated()))
3108 // remove ID - we don't recover annotation from other views for
3109 // view-specific annotation
3110 annotation.setId(null);
3113 // set visiblity for other annotation in this view
3114 String annotationId = annotation.getId();
3115 if (annotationId != null && annotationIds.containsKey(annotationId))
3117 AlignmentAnnotation jda = annotationIds.get(annotationId);
3118 // in principle Visible should always be true for annotation displayed
3119 // in multiple views
3120 if (annotation.hasVisible())
3122 jda.visible = annotation.getVisible();
3125 al.addAnnotation(jda);
3129 // Construct new annotation from model.
3130 AnnotationElement[] ae = annotation.getAnnotationElement();
3131 jalview.datamodel.Annotation[] anot = null;
3132 java.awt.Color firstColour = null;
3134 if (!annotation.getScoreOnly())
3136 anot = new jalview.datamodel.Annotation[al.getWidth()];
3137 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
3139 anpos = ae[aa].getPosition();
3141 if (anpos >= anot.length)
3146 anot[anpos] = new jalview.datamodel.Annotation(
3148 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
3149 (ae[aa].getSecondaryStructure() == null || ae[aa]
3150 .getSecondaryStructure().length() == 0) ? ' '
3151 : ae[aa].getSecondaryStructure().charAt(0),
3155 // JBPNote: Consider verifying dataflow for IO of secondary
3156 // structure annotation read from Stockholm files
3157 // this was added to try to ensure that
3158 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
3160 // anot[ae[aa].getPosition()].displayCharacter = "";
3162 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
3163 if (firstColour == null)
3165 firstColour = anot[anpos].colour;
3169 jalview.datamodel.AlignmentAnnotation jaa = null;
3171 if (annotation.getGraph())
3173 float llim = 0, hlim = 0;
3174 // if (autoForView || an[i].isAutoCalculated()) {
3177 jaa = new jalview.datamodel.AlignmentAnnotation(
3178 annotation.getLabel(), annotation.getDescription(), anot,
3179 llim, hlim, annotation.getGraphType());
3181 jaa.graphGroup = annotation.getGraphGroup();
3182 jaa._linecolour = firstColour;
3183 if (annotation.getThresholdLine() != null)
3185 jaa.setThreshold(new jalview.datamodel.GraphLine(annotation
3186 .getThresholdLine().getValue(), annotation
3187 .getThresholdLine().getLabel(), new java.awt.Color(
3188 annotation.getThresholdLine().getColour())));
3191 if (autoForView || annotation.isAutoCalculated())
3193 // Hardwire the symbol display line to ensure that labels for
3194 // histograms are displayed
3200 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
3201 an[i].getDescription(), anot);
3202 jaa._linecolour = firstColour;
3204 // register new annotation
3205 if (an[i].getId() != null)
3207 annotationIds.put(an[i].getId(), jaa);
3208 jaa.annotationId = an[i].getId();
3210 // recover sequence association
3211 String sequenceRef = an[i].getSequenceRef();
3212 if (sequenceRef != null)
3214 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3215 SequenceI sequence = seqRefIds.get(sequenceRef);
3216 if (sequence == null)
3218 // in pre-2.9 projects sequence ref is to sequence name
3219 sequence = al.findName(sequenceRef);
3221 if (sequence != null)
3223 jaa.createSequenceMapping(sequence, 1, true);
3224 sequence.addAlignmentAnnotation(jaa);
3227 // and make a note of any group association
3228 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
3230 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3231 .get(an[i].getGroupRef());
3234 aal = new ArrayList<jalview.datamodel.AlignmentAnnotation>();
3235 groupAnnotRefs.put(an[i].getGroupRef(), aal);
3240 if (an[i].hasScore())
3242 jaa.setScore(an[i].getScore());
3244 if (an[i].hasVisible())
3246 jaa.visible = an[i].getVisible();
3249 if (an[i].hasCentreColLabels())
3251 jaa.centreColLabels = an[i].getCentreColLabels();
3254 if (an[i].hasScaleColLabels())
3256 jaa.scaleColLabel = an[i].getScaleColLabels();
3258 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
3260 // newer files have an 'autoCalculated' flag and store calculation
3261 // state in viewport properties
3262 jaa.autoCalculated = true; // means annotation will be marked for
3263 // update at end of load.
3265 if (an[i].hasGraphHeight())
3267 jaa.graphHeight = an[i].getGraphHeight();
3269 if (an[i].hasBelowAlignment())
3271 jaa.belowAlignment = an[i].isBelowAlignment();
3273 jaa.setCalcId(an[i].getCalcId());
3274 if (an[i].getPropertyCount() > 0)
3276 for (jalview.schemabinding.version2.Property prop : an[i]
3279 jaa.setProperty(prop.getName(), prop.getValue());
3282 if (jaa.autoCalculated)
3284 autoAlan.add(new JvAnnotRow(i, jaa));
3287 // if (!autoForView)
3289 // add autocalculated group annotation and any user created annotation
3291 al.addAnnotation(jaa);
3295 // ///////////////////////
3297 // Create alignment markup and styles for this view
3298 if (jms.getJGroupCount() > 0)
3300 JGroup[] groups = jms.getJGroup();
3301 boolean addAnnotSchemeGroup = false;
3302 for (int i = 0; i < groups.length; i++)
3304 JGroup jGroup = groups[i];
3305 ColourSchemeI cs = null;
3306 if (jGroup.getColour() != null)
3308 if (jGroup.getColour().startsWith("ucs"))
3310 cs = getUserColourScheme(jms, jGroup.getColour());
3312 else if (jGroup.getColour().equals("AnnotationColourGradient")
3313 && jGroup.getAnnotationColours() != null)
3315 addAnnotSchemeGroup = true;
3320 cs = ColourSchemeProperty.getColour(al, jGroup.getColour());
3325 cs.setThreshold(jGroup.getPidThreshold(), true);
3329 Vector<SequenceI> seqs = new Vector<SequenceI>();
3331 for (int s = 0; s < jGroup.getSeqCount(); s++)
3333 String seqId = jGroup.getSeq(s) + "";
3334 SequenceI ts = seqRefIds.get(seqId);
3338 seqs.addElement(ts);
3342 if (seqs.size() < 1)
3347 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3348 jGroup.getDisplayBoxes(), jGroup.getDisplayText(),
3349 jGroup.getColourText(), jGroup.getStart(), jGroup.getEnd());
3351 sg.setOutlineColour(new java.awt.Color(jGroup.getOutlineColour()));
3353 sg.textColour = new java.awt.Color(jGroup.getTextCol1());
3354 sg.textColour2 = new java.awt.Color(jGroup.getTextCol2());
3355 sg.setShowNonconserved(jGroup.hasShowUnconserved() ? jGroup
3356 .isShowUnconserved() : false);
3357 sg.thresholdTextColour = jGroup.getTextColThreshold();
3358 if (jGroup.hasShowConsensusHistogram())
3360 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3363 if (jGroup.hasShowSequenceLogo())
3365 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3367 if (jGroup.hasNormaliseSequenceLogo())
3369 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3371 if (jGroup.hasIgnoreGapsinConsensus())
3373 sg.setIgnoreGapsConsensus(jGroup.getIgnoreGapsinConsensus());
3375 if (jGroup.getConsThreshold() != 0)
3377 jalview.analysis.Conservation c = new jalview.analysis.Conservation(
3378 "All", ResidueProperties.propHash, 3,
3379 sg.getSequences(null), 0, sg.getWidth() - 1);
3381 c.verdict(false, 25);
3382 sg.cs.setConservation(c);
3385 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3387 // re-instate unique group/annotation row reference
3388 List<AlignmentAnnotation> jaal = groupAnnotRefs.get(jGroup
3392 for (AlignmentAnnotation jaa : jaal)
3395 if (jaa.autoCalculated)
3397 // match up and try to set group autocalc alignment row for this
3399 if (jaa.label.startsWith("Consensus for "))
3401 sg.setConsensus(jaa);
3403 // match up and try to set group autocalc alignment row for this
3405 if (jaa.label.startsWith("Conservation for "))
3407 sg.setConservationRow(jaa);
3414 if (addAnnotSchemeGroup)
3416 // reconstruct the annotation colourscheme
3417 sg.cs = constructAnnotationColour(jGroup.getAnnotationColours(),
3418 null, al, jms, false);
3424 // only dataset in this model, so just return.
3427 // ///////////////////////////////
3430 // If we just load in the same jar file again, the sequenceSetId
3431 // will be the same, and we end up with multiple references
3432 // to the same sequenceSet. We must modify this id on load
3433 // so that each load of the file gives a unique id
3434 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3435 String viewId = (view.getId() == null ? null : view.getId()
3437 AlignFrame af = null;
3438 AlignViewport av = null;
3439 // now check to see if we really need to create a new viewport.
3440 if (multipleView && viewportsAdded.size() == 0)
3442 // We recovered an alignment for which a viewport already exists.
3443 // TODO: fix up any settings necessary for overlaying stored state onto
3444 // state recovered from another document. (may not be necessary).
3445 // we may need a binding from a viewport in memory to one recovered from
3447 // and then recover its containing af to allow the settings to be applied.
3448 // TODO: fix for vamsas demo
3450 .println("About to recover a viewport for existing alignment: Sequence set ID is "
3452 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3453 if (seqsetobj != null)
3455 if (seqsetobj instanceof String)
3457 uniqueSeqSetId = (String) seqsetobj;
3459 .println("Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
3465 .println("Warning : Collision between sequence set ID string and existing jalview object mapping.");
3471 * indicate that annotation colours are applied across all groups (pre
3472 * Jalview 2.8.1 behaviour)
3474 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan(
3475 "2.8.1", object.getVersion());
3477 AlignmentPanel ap = null;
3478 boolean isnewview = true;
3481 // Check to see if this alignment already has a view id == viewId
3482 jalview.gui.AlignmentPanel views[] = Desktop
3483 .getAlignmentPanels(uniqueSeqSetId);
3484 if (views != null && views.length > 0)
3486 for (int v = 0; v < views.length; v++)
3488 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
3490 // recover the existing alignpanel, alignframe, viewport
3491 af = views[v].alignFrame;
3494 // TODO: could even skip resetting view settings if we don't want to
3495 // change the local settings from other jalview processes
3504 af = loadViewport(file, jseqs, hiddenSeqs, al, jms, view,
3505 uniqueSeqSetId, viewId, autoAlan);
3511 * Load any trees, PDB structures and viewers
3513 * Not done if flag is false (when this method is used for New View)
3515 if (loadTreesAndStructures)
3517 loadTrees(jms, view, af, av, ap);
3518 loadPDBStructures(jprovider, jseqs, af, ap);
3519 loadRnaViewers(jprovider, jseqs, ap);
3521 // and finally return.
3526 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
3527 * panel is restored from separate jar entries, two (gapped and trimmed) per
3528 * sequence and secondary structure.
3530 * Currently each viewer shows just one sequence and structure (gapped and
3531 * trimmed), however this method is designed to support multiple sequences or
3532 * structures in viewers if wanted in future.
3538 private void loadRnaViewers(jarInputStreamProvider jprovider,
3539 JSeq[] jseqs, AlignmentPanel ap)
3542 * scan the sequences for references to viewers; create each one the first
3543 * time it is referenced, add Rna models to existing viewers
3545 for (JSeq jseq : jseqs)
3547 for (int i = 0; i < jseq.getRnaViewerCount(); i++)
3549 RnaViewer viewer = jseq.getRnaViewer(i);
3550 AppVarna appVarna = findOrCreateVarnaViewer(viewer,
3551 uniqueSetSuffix, ap);
3553 for (int j = 0; j < viewer.getSecondaryStructureCount(); j++)
3555 SecondaryStructure ss = viewer.getSecondaryStructure(j);
3556 SequenceI seq = seqRefIds.get(jseq.getId());
3557 AlignmentAnnotation ann = this.annotationIds.get(ss
3558 .getAnnotationId());
3561 * add the structure to the Varna display (with session state copied
3562 * from the jar to a temporary file)
3564 boolean gapped = ss.isGapped();
3565 String rnaTitle = ss.getTitle();
3566 String sessionState = ss.getViewerState();
3567 String tempStateFile = copyJarEntry(jprovider, sessionState,
3569 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
3570 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
3572 appVarna.setInitialSelection(viewer.getSelectedRna());
3578 * Locate and return an already instantiated matching AppVarna, or create one
3582 * @param viewIdSuffix
3586 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
3587 String viewIdSuffix, AlignmentPanel ap)
3590 * on each load a suffix is appended to the saved viewId, to avoid conflicts
3591 * if load is repeated
3593 String postLoadId = viewer.getViewId() + viewIdSuffix;
3594 for (JInternalFrame frame : getAllFrames())
3596 if (frame instanceof AppVarna)
3598 AppVarna varna = (AppVarna) frame;
3599 if (postLoadId.equals(varna.getViewId()))
3601 // this viewer is already instantiated
3602 // could in future here add ap as another 'parent' of the
3603 // AppVarna window; currently just 1-to-many
3610 * viewer not found - make it
3612 RnaViewerModel model = new RnaViewerModel(postLoadId,
3613 viewer.getTitle(), viewer.getXpos(), viewer.getYpos(),
3614 viewer.getWidth(), viewer.getHeight(),
3615 viewer.getDividerLocation());
3616 AppVarna varna = new AppVarna(model, ap);
3622 * Load any saved trees
3630 protected void loadTrees(JalviewModelSequence jms, Viewport view,
3631 AlignFrame af, AlignViewport av, AlignmentPanel ap)
3633 // TODO result of automated refactoring - are all these parameters needed?
3636 for (int t = 0; t < jms.getTreeCount(); t++)
3639 Tree tree = jms.getTree(t);
3641 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
3644 tp = af.ShowNewickTree(
3645 new jalview.io.NewickFile(tree.getNewick()),
3646 tree.getTitle(), tree.getWidth(), tree.getHeight(),
3647 tree.getXpos(), tree.getYpos());
3648 if (tree.getId() != null)
3650 // perhaps bind the tree id to something ?
3655 // update local tree attributes ?
3656 // TODO: should check if tp has been manipulated by user - if so its
3657 // settings shouldn't be modified
3658 tp.setTitle(tree.getTitle());
3659 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(), tree
3660 .getWidth(), tree.getHeight()));
3661 tp.av = av; // af.viewport; // TODO: verify 'associate with all
3664 tp.treeCanvas.av = av; // af.viewport;
3665 tp.treeCanvas.ap = ap; // af.alignPanel;
3670 warn("There was a problem recovering stored Newick tree: \n"
3671 + tree.getNewick());
3675 tp.fitToWindow.setState(tree.getFitToWindow());
3676 tp.fitToWindow_actionPerformed(null);
3678 if (tree.getFontName() != null)
3680 tp.setTreeFont(new java.awt.Font(tree.getFontName(), tree
3681 .getFontStyle(), tree.getFontSize()));
3685 tp.setTreeFont(new java.awt.Font(view.getFontName(), view
3686 .getFontStyle(), tree.getFontSize()));
3689 tp.showPlaceholders(tree.getMarkUnlinked());
3690 tp.showBootstrap(tree.getShowBootstrap());
3691 tp.showDistances(tree.getShowDistances());
3693 tp.treeCanvas.threshold = tree.getThreshold();
3695 if (tree.getCurrentTree())
3697 af.viewport.setCurrentTree(tp.getTree());
3701 } catch (Exception ex)
3703 ex.printStackTrace();
3708 * Load and link any saved structure viewers.
3715 protected void loadPDBStructures(jarInputStreamProvider jprovider,
3716 JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
3719 * Run through all PDB ids on the alignment, and collect mappings between
3720 * distinct view ids and all sequences referring to that view.
3722 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<String, StructureViewerModel>();
3724 for (int i = 0; i < jseqs.length; i++)
3726 if (jseqs[i].getPdbidsCount() > 0)
3728 Pdbids[] ids = jseqs[i].getPdbids();
3729 for (int p = 0; p < ids.length; p++)
3731 final int structureStateCount = ids[p].getStructureStateCount();
3732 for (int s = 0; s < structureStateCount; s++)
3734 // check to see if we haven't already created this structure view
3735 final StructureState structureState = ids[p]
3736 .getStructureState(s);
3737 String sviewid = (structureState.getViewId() == null) ? null
3738 : structureState.getViewId() + uniqueSetSuffix;
3739 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
3740 // Originally : ids[p].getFile()
3741 // : TODO: verify external PDB file recovery still works in normal
3742 // jalview project load
3743 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId()));
3744 jpdb.setId(ids[p].getId());
3746 int x = structureState.getXpos();
3747 int y = structureState.getYpos();
3748 int width = structureState.getWidth();
3749 int height = structureState.getHeight();
3751 // Probably don't need to do this anymore...
3752 // Desktop.desktop.getComponentAt(x, y);
3753 // TODO: NOW: check that this recovers the PDB file correctly.
3754 String pdbFile = loadPDBFile(jprovider, ids[p].getId());
3755 jalview.datamodel.SequenceI seq = seqRefIds.get(jseqs[i]
3757 if (sviewid == null)
3759 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width
3762 if (!structureViewers.containsKey(sviewid))
3764 structureViewers.put(sviewid,
3765 new StructureViewerModel(x, y, width, height, false,
3766 false, true, structureState.getViewId(),
3767 structureState.getType()));
3768 // Legacy pre-2.7 conversion JAL-823 :
3769 // do not assume any view has to be linked for colour by
3773 // assemble String[] { pdb files }, String[] { id for each
3774 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3775 // seqs_file 2}, boolean[] {
3776 // linkAlignPanel,superposeWithAlignpanel}} from hash
3777 StructureViewerModel jmoldat = structureViewers.get(sviewid);
3778 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
3779 | (structureState.hasAlignwithAlignPanel() ? structureState
3780 .getAlignwithAlignPanel() : false));
3783 * Default colour by linked panel to false if not specified (e.g.
3784 * for pre-2.7 projects)
3786 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
3787 colourWithAlignPanel |= (structureState
3788 .hasColourwithAlignPanel() ? structureState
3789 .getColourwithAlignPanel() : false);
3790 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
3793 * Default colour by viewer to true if not specified (e.g. for
3796 boolean colourByViewer = jmoldat.isColourByViewer();
3797 colourByViewer &= structureState.hasColourByJmol() ? structureState
3798 .getColourByJmol() : true;
3799 jmoldat.setColourByViewer(colourByViewer);
3801 if (jmoldat.getStateData().length() < structureState
3802 .getContent().length())
3805 jmoldat.setStateData(structureState.getContent());
3808 if (ids[p].getFile() != null)
3810 File mapkey = new File(ids[p].getFile());
3811 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
3812 if (seqstrmaps == null)
3814 jmoldat.getFileData().put(
3816 seqstrmaps = jmoldat.new StructureData(pdbFile,
3819 if (!seqstrmaps.getSeqList().contains(seq))
3821 seqstrmaps.getSeqList().add(seq);
3827 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");
3834 // Instantiate the associated structure views
3835 for (Entry<String, StructureViewerModel> entry : structureViewers
3840 createOrLinkStructureViewer(entry, af, ap, jprovider);
3841 } catch (Exception e)
3843 System.err.println("Error loading structure viewer: "
3845 // failed - try the next one
3857 protected void createOrLinkStructureViewer(
3858 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3859 AlignmentPanel ap, jarInputStreamProvider jprovider)
3861 final StructureViewerModel stateData = viewerData.getValue();
3864 * Search for any viewer windows already open from other alignment views
3865 * that exactly match the stored structure state
3867 StructureViewerBase comp = findMatchingViewer(viewerData);
3871 linkStructureViewer(ap, comp, stateData);
3876 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
3877 * "viewer_"+stateData.viewId
3879 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
3881 createChimeraViewer(viewerData, af, jprovider);
3886 * else Jmol (if pre-2.9, stateData contains JMOL state string)
3888 createJmolViewer(viewerData, af, jprovider);
3893 * Create a new Chimera viewer.
3899 protected void createChimeraViewer(
3900 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3901 jarInputStreamProvider jprovider)
3903 StructureViewerModel data = viewerData.getValue();
3904 String chimeraSessionFile = data.getStateData();
3907 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
3909 * NB this is the 'saved' viewId as in the project file XML, _not_ the
3910 * 'uniquified' sviewid used to reconstruct the viewer here
3912 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
3913 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
3916 Set<Entry<File, StructureData>> fileData = data.getFileData()
3918 List<PDBEntry> pdbs = new ArrayList<PDBEntry>();
3919 List<SequenceI[]> allseqs = new ArrayList<SequenceI[]>();
3920 for (Entry<File, StructureData> pdb : fileData)
3922 String filePath = pdb.getValue().getFilePath();
3923 String pdbId = pdb.getValue().getPdbId();
3924 // pdbs.add(new PDBEntry(filePath, pdbId));
3925 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
3926 final List<SequenceI> seqList = pdb.getValue().getSeqList();
3927 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
3931 boolean colourByChimera = data.isColourByViewer();
3932 boolean colourBySequence = data.isColourWithAlignPanel();
3934 // TODO use StructureViewer as a factory here, see JAL-1761
3935 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
3936 final SequenceI[][] seqsArray = allseqs.toArray(new SequenceI[allseqs
3938 String newViewId = viewerData.getKey();
3940 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
3941 af.alignPanel, pdbArray, seqsArray, colourByChimera,
3942 colourBySequence, newViewId);
3943 cvf.setSize(data.getWidth(), data.getHeight());
3944 cvf.setLocation(data.getX(), data.getY());
3948 * Create a new Jmol window. First parse the Jmol state to translate filenames
3949 * loaded into the view, and record the order in which files are shown in the
3950 * Jmol view, so we can add the sequence mappings in same order.
3956 protected void createJmolViewer(
3957 final Entry<String, StructureViewerModel> viewerData,
3958 AlignFrame af, jarInputStreamProvider jprovider)
3960 final StructureViewerModel svattrib = viewerData.getValue();
3961 String state = svattrib.getStateData();
3964 * Pre-2.9: state element value is the Jmol state string
3966 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
3969 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
3971 state = readJarEntry(jprovider,
3972 getViewerJarEntryName(svattrib.getViewId()));
3975 List<String> pdbfilenames = new ArrayList<String>();
3976 List<SequenceI[]> seqmaps = new ArrayList<SequenceI[]>();
3977 List<String> pdbids = new ArrayList<String>();
3978 StringBuilder newFileLoc = new StringBuilder(64);
3979 int cp = 0, ncp, ecp;
3980 Map<File, StructureData> oldFiles = svattrib.getFileData();
3981 while ((ncp = state.indexOf("load ", cp)) > -1)
3985 // look for next filename in load statement
3986 newFileLoc.append(state.substring(cp,
3987 ncp = (state.indexOf("\"", ncp + 1) + 1)));
3988 String oldfilenam = state.substring(ncp,
3989 ecp = state.indexOf("\"", ncp));
3990 // recover the new mapping data for this old filename
3991 // have to normalize filename - since Jmol and jalview do
3993 // translation differently.
3994 StructureData filedat = oldFiles.get(new File(oldfilenam));
3995 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
3996 pdbfilenames.add(filedat.getFilePath());
3997 pdbids.add(filedat.getPdbId());
3998 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
3999 newFileLoc.append("\"");
4000 cp = ecp + 1; // advance beyond last \" and set cursor so we can
4001 // look for next file statement.
4002 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
4006 // just append rest of state
4007 newFileLoc.append(state.substring(cp));
4011 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
4012 newFileLoc = new StringBuilder(state);
4013 newFileLoc.append("; load append ");
4014 for (File id : oldFiles.keySet())
4016 // add this and any other pdb files that should be present in
4018 StructureData filedat = oldFiles.get(id);
4019 newFileLoc.append(filedat.getFilePath());
4020 pdbfilenames.add(filedat.getFilePath());
4021 pdbids.add(filedat.getPdbId());
4022 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4023 newFileLoc.append(" \"");
4024 newFileLoc.append(filedat.getFilePath());
4025 newFileLoc.append("\"");
4028 newFileLoc.append(";");
4031 if (newFileLoc.length() == 0)
4035 int histbug = newFileLoc.indexOf("history = ");
4039 * change "history = [true|false];" to "history = [1|0];"
4042 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
4043 String val = (diff == -1) ? null : newFileLoc
4044 .substring(histbug, diff);
4045 if (val != null && val.length() >= 4)
4047 if (val.contains("e")) // eh? what can it be?
4049 if (val.trim().equals("true"))
4057 newFileLoc.replace(histbug, diff, val);
4062 final String[] pdbf = pdbfilenames.toArray(new String[pdbfilenames
4064 final String[] id = pdbids.toArray(new String[pdbids.size()]);
4065 final SequenceI[][] sq = seqmaps
4066 .toArray(new SequenceI[seqmaps.size()][]);
4067 final String fileloc = newFileLoc.toString();
4068 final String sviewid = viewerData.getKey();
4069 final AlignFrame alf = af;
4070 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
4071 svattrib.getWidth(), svattrib.getHeight());
4074 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
4079 JalviewStructureDisplayI sview = null;
4082 sview = new StructureViewer(alf.alignPanel
4083 .getStructureSelectionManager()).createView(
4084 StructureViewer.ViewerType.JMOL, pdbf, id, sq,
4085 alf.alignPanel, svattrib, fileloc, rect, sviewid);
4086 addNewStructureViewer(sview);
4087 } catch (OutOfMemoryError ex)
4089 new OOMWarning("restoring structure view for PDB id " + id,
4090 (OutOfMemoryError) ex.getCause());
4091 if (sview != null && sview.isVisible())
4093 sview.closeViewer(false);
4094 sview.setVisible(false);
4100 } catch (InvocationTargetException ex)
4102 warn("Unexpected error when opening Jmol view.", ex);
4104 } catch (InterruptedException e)
4106 // e.printStackTrace();
4112 * Generates a name for the entry in the project jar file to hold state
4113 * information for a structure viewer
4118 protected String getViewerJarEntryName(String viewId)
4120 return VIEWER_PREFIX + viewId;
4124 * Returns any open frame that matches given structure viewer data. The match
4125 * is based on the unique viewId, or (for older project versions) the frame's
4131 protected StructureViewerBase findMatchingViewer(
4132 Entry<String, StructureViewerModel> viewerData)
4134 final String sviewid = viewerData.getKey();
4135 final StructureViewerModel svattrib = viewerData.getValue();
4136 StructureViewerBase comp = null;
4137 JInternalFrame[] frames = getAllFrames();
4138 for (JInternalFrame frame : frames)
4140 if (frame instanceof StructureViewerBase)
4143 * Post jalview 2.4 schema includes structure view id
4146 && ((StructureViewerBase) frame).getViewId()
4149 comp = (StructureViewerBase) frame;
4150 break; // break added in 2.9
4153 * Otherwise test for matching position and size of viewer frame
4155 else if (frame.getX() == svattrib.getX()
4156 && frame.getY() == svattrib.getY()
4157 && frame.getHeight() == svattrib.getHeight()
4158 && frame.getWidth() == svattrib.getWidth())
4160 comp = (StructureViewerBase) frame;
4161 // no break in faint hope of an exact match on viewId
4169 * Link an AlignmentPanel to an existing structure viewer.
4174 * @param useinViewerSuperpos
4175 * @param usetoColourbyseq
4176 * @param viewerColouring
4178 protected void linkStructureViewer(AlignmentPanel ap,
4179 StructureViewerBase viewer, StructureViewerModel stateData)
4181 // NOTE: if the jalview project is part of a shared session then
4182 // view synchronization should/could be done here.
4184 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4185 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4186 final boolean viewerColouring = stateData.isColourByViewer();
4187 Map<File, StructureData> oldFiles = stateData.getFileData();
4190 * Add mapping for sequences in this view to an already open viewer
4192 final AAStructureBindingModel binding = viewer.getBinding();
4193 for (File id : oldFiles.keySet())
4195 // add this and any other pdb files that should be present in the
4197 StructureData filedat = oldFiles.get(id);
4198 String pdbFile = filedat.getFilePath();
4199 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4200 binding.getSsm().setMapping(seq, null, pdbFile,
4201 jalview.io.AppletFormatAdapter.FILE);
4202 binding.addSequenceForStructFile(pdbFile, seq);
4204 // and add the AlignmentPanel's reference to the view panel
4205 viewer.addAlignmentPanel(ap);
4206 if (useinViewerSuperpos)
4208 viewer.useAlignmentPanelForSuperposition(ap);
4212 viewer.excludeAlignmentPanelForSuperposition(ap);
4214 if (usetoColourbyseq)
4216 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4220 viewer.excludeAlignmentPanelForColourbyseq(ap);
4225 * Get all frames within the Desktop.
4229 protected JInternalFrame[] getAllFrames()
4231 JInternalFrame[] frames = null;
4232 // TODO is this necessary - is it safe - risk of hanging?
4237 frames = Desktop.desktop.getAllFrames();
4238 } catch (ArrayIndexOutOfBoundsException e)
4240 // occasional No such child exceptions are thrown here...
4244 } catch (InterruptedException f)
4248 } while (frames == null);
4253 * Answers true if 'version' is equal to or later than 'supported', where each
4254 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4255 * changes. Development and test values for 'version' are leniently treated
4259 * - minimum version we are comparing against
4261 * - version of data being processsed
4264 public static boolean isVersionStringLaterThan(String supported,
4267 if (supported == null || version == null
4268 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4269 || version.equalsIgnoreCase("Test")
4270 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4272 System.err.println("Assuming project file with "
4273 + (version == null ? "null" : version)
4274 + " is compatible with Jalview version " + supported);
4279 return StringUtils.compareVersions(version, supported, "b") >= 0;
4283 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4285 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4287 if (newStructureViewers != null)
4289 sview.getBinding().setFinishedLoadingFromArchive(false);
4290 newStructureViewers.add(sview);
4294 protected void setLoadingFinishedForNewStructureViewers()
4296 if (newStructureViewers != null)
4298 for (JalviewStructureDisplayI sview : newStructureViewers)
4300 sview.getBinding().setFinishedLoadingFromArchive(true);
4302 newStructureViewers.clear();
4303 newStructureViewers = null;
4307 AlignFrame loadViewport(String file, JSeq[] JSEQ,
4308 List<SequenceI> hiddenSeqs, AlignmentI al,
4309 JalviewModelSequence jms, Viewport view, String uniqueSeqSetId,
4310 String viewId, List<JvAnnotRow> autoAlan)
4312 AlignFrame af = null;
4313 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
4314 uniqueSeqSetId, viewId);
4316 af.setFileName(file, "Jalview");
4318 for (int i = 0; i < JSEQ.length; i++)
4320 af.viewport.setSequenceColour(af.viewport.getAlignment()
4321 .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour()));
4326 af.getViewport().setColourByReferenceSeq(true);
4327 af.getViewport().setDisplayReferenceSeq(true);
4330 af.viewport.setGatherViewsHere(view.getGatheredViews());
4332 if (view.getSequenceSetId() != null)
4334 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4336 af.viewport.setSequenceSetId(uniqueSeqSetId);
4339 // propagate shared settings to this new view
4340 af.viewport.setHistoryList(av.getHistoryList());
4341 af.viewport.setRedoList(av.getRedoList());
4345 viewportsAdded.put(uniqueSeqSetId, af.viewport);
4347 // TODO: check if this method can be called repeatedly without
4348 // side-effects if alignpanel already registered.
4349 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4351 // apply Hidden regions to view.
4352 if (hiddenSeqs != null)
4354 for (int s = 0; s < JSEQ.length; s++)
4356 SequenceGroup hidden = new SequenceGroup();
4357 boolean isRepresentative = false;
4358 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
4360 isRepresentative = true;
4361 SequenceI sequenceToHide = al.getSequenceAt(JSEQ[s]
4362 .getHiddenSequences(r));
4363 hidden.addSequence(sequenceToHide, false);
4364 // remove from hiddenSeqs list so we don't try to hide it twice
4365 hiddenSeqs.remove(sequenceToHide);
4367 if (isRepresentative)
4369 SequenceI representativeSequence = al.getSequenceAt(s);
4370 hidden.addSequence(representativeSequence, false);
4371 af.viewport.hideRepSequences(representativeSequence, hidden);
4375 SequenceI[] hseqs = hiddenSeqs.toArray(new SequenceI[hiddenSeqs
4377 af.viewport.hideSequence(hseqs);
4380 // recover view properties and display parameters
4381 if (view.getViewName() != null)
4383 af.viewport.viewName = view.getViewName();
4384 af.setInitialTabVisible();
4386 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
4389 af.viewport.setShowAnnotation(view.getShowAnnotation());
4390 af.viewport.setAbovePIDThreshold(view.getPidSelected());
4392 af.viewport.setColourText(view.getShowColourText());
4394 af.viewport.setConservationSelected(view.getConservationSelected());
4395 af.viewport.setShowJVSuffix(view.getShowFullId());
4396 af.viewport.setRightAlignIds(view.getRightAlignIds());
4397 af.viewport.setFont(
4398 new java.awt.Font(view.getFontName(), view.getFontStyle(), view
4399 .getFontSize()), true);
4400 ViewStyleI vs = af.viewport.getViewStyle();
4401 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
4402 af.viewport.setViewStyle(vs);
4403 // TODO: allow custom charWidth/Heights to be restored by updating them
4404 // after setting font - which means set above to false
4405 af.viewport.setRenderGaps(view.getRenderGaps());
4406 af.viewport.setWrapAlignment(view.getWrapAlignment());
4407 af.viewport.setShowAnnotation(view.getShowAnnotation());
4409 af.viewport.setShowBoxes(view.getShowBoxes());
4411 af.viewport.setShowText(view.getShowText());
4413 af.viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
4414 af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
4415 af.viewport.setThresholdTextColour(view.getTextColThreshold());
4416 af.viewport.setShowUnconserved(view.hasShowUnconserved() ? view
4417 .isShowUnconserved() : false);
4418 af.viewport.setStartRes(view.getStartRes());
4419 af.viewport.setStartSeq(view.getStartSeq());
4420 af.alignPanel.updateLayout();
4421 ColourSchemeI cs = null;
4422 // apply colourschemes
4423 if (view.getBgColour() != null)
4425 if (view.getBgColour().startsWith("ucs"))
4427 cs = getUserColourScheme(jms, view.getBgColour());
4429 else if (view.getBgColour().startsWith("Annotation"))
4431 AnnotationColours viewAnnColour = view.getAnnotationColours();
4432 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
4439 cs = ColourSchemeProperty.getColour(al, view.getBgColour());
4444 cs.setThreshold(view.getPidThreshold(), true);
4445 cs.setConsensus(af.viewport.getSequenceConsensusHash());
4449 af.viewport.setGlobalColourScheme(cs);
4450 af.viewport.setColourAppliesToAllGroups(false);
4452 if (view.getConservationSelected() && cs != null)
4454 cs.setConservationInc(view.getConsThreshold());
4457 af.changeColour(cs);
4459 af.viewport.setColourAppliesToAllGroups(true);
4461 af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures());
4463 if (view.hasCentreColumnLabels())
4465 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
4467 if (view.hasIgnoreGapsinConsensus())
4469 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
4472 if (view.hasFollowHighlight())
4474 af.viewport.setFollowHighlight(view.getFollowHighlight());
4476 if (view.hasFollowSelection())
4478 af.viewport.followSelection = view.getFollowSelection();
4480 if (view.hasShowConsensusHistogram())
4482 af.viewport.setShowConsensusHistogram(view
4483 .getShowConsensusHistogram());
4487 af.viewport.setShowConsensusHistogram(true);
4489 if (view.hasShowSequenceLogo())
4491 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
4495 af.viewport.setShowSequenceLogo(false);
4497 if (view.hasNormaliseSequenceLogo())
4499 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
4501 if (view.hasShowDbRefTooltip())
4503 af.viewport.setShowDBRefs(view.getShowDbRefTooltip());
4505 if (view.hasShowNPfeatureTooltip())
4507 af.viewport.setShowNPFeats(view.hasShowNPfeatureTooltip());
4509 if (view.hasShowGroupConsensus())
4511 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
4515 af.viewport.setShowGroupConsensus(false);
4517 if (view.hasShowGroupConservation())
4519 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
4523 af.viewport.setShowGroupConservation(false);
4526 // recover featre settings
4527 if (jms.getFeatureSettings() != null)
4529 FeaturesDisplayed fdi;
4530 af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
4531 String[] renderOrder = new String[jms.getFeatureSettings()
4532 .getSettingCount()];
4533 Map<String, FeatureColourI> featureColours = new Hashtable<String, FeatureColourI>();
4534 Map<String, Float> featureOrder = new Hashtable<String, Float>();
4536 for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
4538 Setting setting = jms.getFeatureSettings().getSetting(fs);
4539 if (setting.hasMincolour())
4541 FeatureColourI gc = setting.hasMin() ? new FeatureColour(
4542 new Color(setting.getMincolour()), new Color(
4543 setting.getColour()), setting.getMin(),
4544 setting.getMax()) : new FeatureColour(new Color(
4545 setting.getMincolour()), new Color(setting.getColour()),
4547 if (setting.hasThreshold())
4549 gc.setThreshold(setting.getThreshold());
4550 int threshstate = setting.getThreshstate();
4551 // -1 = None, 0 = Below, 1 = Above threshold
4552 if (threshstate == 0)
4554 gc.setBelowThreshold(true);
4556 else if (threshstate == 1)
4558 gc.setAboveThreshold(true);
4561 gc.setAutoScaled(true); // default
4562 if (setting.hasAutoScale())
4564 gc.setAutoScaled(setting.getAutoScale());
4566 if (setting.hasColourByLabel())
4568 gc.setColourByLabel(setting.getColourByLabel());
4570 // and put in the feature colour table.
4571 featureColours.put(setting.getType(), gc);
4575 featureColours.put(setting.getType(), new FeatureColour(
4576 new Color(setting.getColour())));
4578 renderOrder[fs] = setting.getType();
4579 if (setting.hasOrder())
4581 featureOrder.put(setting.getType(), setting.getOrder());
4585 featureOrder.put(setting.getType(), new Float(fs
4586 / jms.getFeatureSettings().getSettingCount()));
4588 if (setting.getDisplay())
4590 fdi.setVisible(setting.getType());
4593 Map<String, Boolean> fgtable = new Hashtable<String, Boolean>();
4594 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
4596 Group grp = jms.getFeatureSettings().getGroup(gs);
4597 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
4599 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4600 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
4601 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
4602 FeatureRendererSettings frs = new FeatureRendererSettings(
4603 renderOrder, fgtable, featureColours, 1.0f, featureOrder);
4604 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
4605 .transferSettings(frs);
4609 if (view.getHiddenColumnsCount() > 0)
4611 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
4613 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(), view
4614 .getHiddenColumns(c).getEnd() // +1
4618 if (view.getCalcIdParam() != null)
4620 for (CalcIdParam calcIdParam : view.getCalcIdParam())
4622 if (calcIdParam != null)
4624 if (recoverCalcIdParam(calcIdParam, af.viewport))
4629 warn("Couldn't recover parameters for "
4630 + calcIdParam.getCalcId());
4635 af.setMenusFromViewport(af.viewport);
4636 af.setTitle(view.getTitle());
4637 // TODO: we don't need to do this if the viewport is aready visible.
4639 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
4640 * has a 'cdna/protein complement' view, in which case save it in order to
4641 * populate a SplitFrame once all views have been read in.
4643 String complementaryViewId = view.getComplementId();
4644 if (complementaryViewId == null)
4646 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
4648 // recompute any autoannotation
4649 af.alignPanel.updateAnnotation(false, true);
4650 reorderAutoannotation(af, al, autoAlan);
4651 af.alignPanel.alignmentChanged();
4655 splitFrameCandidates.put(view, af);
4660 private ColourSchemeI constructAnnotationColour(
4661 AnnotationColours viewAnnColour, AlignFrame af, AlignmentI al,
4662 JalviewModelSequence jms, boolean checkGroupAnnColour)
4664 boolean propagateAnnColour = false;
4665 ColourSchemeI cs = null;
4666 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
4667 if (checkGroupAnnColour && al.getGroups() != null
4668 && al.getGroups().size() > 0)
4670 // pre 2.8.1 behaviour
4671 // check to see if we should transfer annotation colours
4672 propagateAnnColour = true;
4673 for (jalview.datamodel.SequenceGroup sg : al.getGroups())
4675 if (sg.cs instanceof AnnotationColourGradient)
4677 propagateAnnColour = false;
4681 // int find annotation
4682 if (annAlignment.getAlignmentAnnotation() != null)
4684 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
4686 if (annAlignment.getAlignmentAnnotation()[i].label
4687 .equals(viewAnnColour.getAnnotation()))
4689 if (annAlignment.getAlignmentAnnotation()[i].getThreshold() == null)
4691 annAlignment.getAlignmentAnnotation()[i]
4692 .setThreshold(new jalview.datamodel.GraphLine(
4693 viewAnnColour.getThreshold(), "Threshold",
4694 java.awt.Color.black)
4699 if (viewAnnColour.getColourScheme().equals("None"))
4701 cs = new AnnotationColourGradient(
4702 annAlignment.getAlignmentAnnotation()[i],
4703 new java.awt.Color(viewAnnColour.getMinColour()),
4704 new java.awt.Color(viewAnnColour.getMaxColour()),
4705 viewAnnColour.getAboveThreshold());
4707 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
4709 cs = new AnnotationColourGradient(
4710 annAlignment.getAlignmentAnnotation()[i],
4711 getUserColourScheme(jms,
4712 viewAnnColour.getColourScheme()),
4713 viewAnnColour.getAboveThreshold());
4717 cs = new AnnotationColourGradient(
4718 annAlignment.getAlignmentAnnotation()[i],
4719 ColourSchemeProperty.getColour(al,
4720 viewAnnColour.getColourScheme()),
4721 viewAnnColour.getAboveThreshold());
4723 if (viewAnnColour.hasPerSequence())
4725 ((AnnotationColourGradient) cs).setSeqAssociated(viewAnnColour
4728 if (viewAnnColour.hasPredefinedColours())
4730 ((AnnotationColourGradient) cs)
4731 .setPredefinedColours(viewAnnColour
4732 .isPredefinedColours());
4734 if (propagateAnnColour && al.getGroups() != null)
4736 // Also use these settings for all the groups
4737 for (int g = 0; g < al.getGroups().size(); g++)
4739 jalview.datamodel.SequenceGroup sg = al.getGroups().get(g);
4747 * if (viewAnnColour.getColourScheme().equals("None" )) { sg.cs =
4748 * new AnnotationColourGradient(
4749 * annAlignment.getAlignmentAnnotation()[i], new
4750 * java.awt.Color(viewAnnColour. getMinColour()), new
4751 * java.awt.Color(viewAnnColour. getMaxColour()),
4752 * viewAnnColour.getAboveThreshold()); } else
4755 sg.cs = new AnnotationColourGradient(
4756 annAlignment.getAlignmentAnnotation()[i], sg.cs,
4757 viewAnnColour.getAboveThreshold());
4758 if (cs instanceof AnnotationColourGradient)
4760 if (viewAnnColour.hasPerSequence())
4762 ((AnnotationColourGradient) cs)
4763 .setSeqAssociated(viewAnnColour.isPerSequence());
4765 if (viewAnnColour.hasPredefinedColours())
4767 ((AnnotationColourGradient) cs)
4768 .setPredefinedColours(viewAnnColour
4769 .isPredefinedColours());
4785 private void reorderAutoannotation(AlignFrame af, AlignmentI al,
4786 List<JvAnnotRow> autoAlan)
4788 // copy over visualization settings for autocalculated annotation in the
4790 if (al.getAlignmentAnnotation() != null)
4793 * Kludge for magic autoannotation names (see JAL-811)
4795 String[] magicNames = new String[] { "Consensus", "Quality",
4797 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
4798 Hashtable<String, JvAnnotRow> visan = new Hashtable<String, JvAnnotRow>();
4799 for (String nm : magicNames)
4801 visan.put(nm, nullAnnot);
4803 for (JvAnnotRow auan : autoAlan)
4805 visan.put(auan.template.label
4806 + (auan.template.getCalcId() == null ? "" : "\t"
4807 + auan.template.getCalcId()), auan);
4809 int hSize = al.getAlignmentAnnotation().length;
4810 List<JvAnnotRow> reorder = new ArrayList<JvAnnotRow>();
4811 // work through any autoCalculated annotation already on the view
4812 // removing it if it should be placed in a different location on the
4813 // annotation panel.
4814 List<String> remains = new ArrayList<String>(visan.keySet());
4815 for (int h = 0; h < hSize; h++)
4817 jalview.datamodel.AlignmentAnnotation jalan = al
4818 .getAlignmentAnnotation()[h];
4819 if (jalan.autoCalculated)
4822 JvAnnotRow valan = visan.get(k = jalan.label);
4823 if (jalan.getCalcId() != null)
4825 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
4830 // delete the auto calculated row from the alignment
4831 al.deleteAnnotation(jalan, false);
4835 if (valan != nullAnnot)
4837 if (jalan != valan.template)
4839 // newly created autoannotation row instance
4840 // so keep a reference to the visible annotation row
4841 // and copy over all relevant attributes
4842 if (valan.template.graphHeight >= 0)
4845 jalan.graphHeight = valan.template.graphHeight;
4847 jalan.visible = valan.template.visible;
4849 reorder.add(new JvAnnotRow(valan.order, jalan));
4854 // Add any (possibly stale) autocalculated rows that were not appended to
4855 // the view during construction
4856 for (String other : remains)
4858 JvAnnotRow othera = visan.get(other);
4859 if (othera != nullAnnot && othera.template.getCalcId() != null
4860 && othera.template.getCalcId().length() > 0)
4862 reorder.add(othera);
4865 // now put the automatic annotation in its correct place
4866 int s = 0, srt[] = new int[reorder.size()];
4867 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
4868 for (JvAnnotRow jvar : reorder)
4871 srt[s++] = jvar.order;
4874 jalview.util.QuickSort.sort(srt, rws);
4875 // and re-insert the annotation at its correct position
4876 for (JvAnnotRow jvar : rws)
4878 al.addAnnotation(jvar.template, jvar.order);
4880 af.alignPanel.adjustAnnotationHeight();
4884 Hashtable skipList = null;
4887 * TODO remove this method
4890 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
4891 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
4892 * throw new Error("Implementation Error. No skipList defined for this
4893 * Jalview2XML instance."); } return (AlignFrame)
4894 * skipList.get(view.getSequenceSetId()); }
4898 * Check if the Jalview view contained in object should be skipped or not.
4901 * @return true if view's sequenceSetId is a key in skipList
4903 private boolean skipViewport(JalviewModel object)
4905 if (skipList == null)
4910 if (skipList.containsKey(id = object.getJalviewModelSequence()
4911 .getViewport()[0].getSequenceSetId()))
4913 if (Cache.log != null && Cache.log.isDebugEnabled())
4915 Cache.log.debug("Skipping seuqence set id " + id);
4922 public void addToSkipList(AlignFrame af)
4924 if (skipList == null)
4926 skipList = new Hashtable();
4928 skipList.put(af.getViewport().getSequenceSetId(), af);
4931 public void clearSkipList()
4933 if (skipList != null)
4940 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
4941 boolean ignoreUnrefed)
4943 jalview.datamodel.AlignmentI ds = getDatasetFor(vamsasSet
4945 Vector dseqs = null;
4948 // create a list of new dataset sequences
4949 dseqs = new Vector();
4951 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
4953 Sequence vamsasSeq = vamsasSet.getSequence(i);
4954 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
4956 // create a new dataset
4959 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
4960 dseqs.copyInto(dsseqs);
4961 ds = new jalview.datamodel.Alignment(dsseqs);
4962 debug("Created new dataset " + vamsasSet.getDatasetId()
4963 + " for alignment " + System.identityHashCode(al));
4964 addDatasetRef(vamsasSet.getDatasetId(), ds);
4966 // set the dataset for the newly imported alignment.
4967 if (al.getDataset() == null && !ignoreUnrefed)
4976 * sequence definition to create/merge dataset sequence for
4980 * vector to add new dataset sequence to
4981 * @param ignoreUnrefed
4982 * - when true, don't create new sequences from vamsasSeq if it's id
4983 * doesn't already have an asssociated Jalview sequence.
4985 * - used to reorder the sequence in the alignment according to the
4986 * vamsasSeq array ordering, to preserve ordering of dataset
4988 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
4989 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed, int vseqpos)
4991 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
4993 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
4994 boolean reorder = false;
4995 SequenceI dsq = null;
4996 if (sq != null && sq.getDatasetSequence() != null)
4998 dsq = sq.getDatasetSequence();
5004 if (sq == null && ignoreUnrefed)
5008 String sqid = vamsasSeq.getDsseqid();
5011 // need to create or add a new dataset sequence reference to this sequence
5014 dsq = seqRefIds.get(sqid);
5019 // make a new dataset sequence
5020 dsq = sq.createDatasetSequence();
5023 // make up a new dataset reference for this sequence
5024 sqid = seqHash(dsq);
5026 dsq.setVamsasId(uniqueSetSuffix + sqid);
5027 seqRefIds.put(sqid, dsq);
5032 dseqs.addElement(dsq);
5037 ds.addSequence(dsq);
5043 { // make this dataset sequence sq's dataset sequence
5044 sq.setDatasetSequence(dsq);
5045 // and update the current dataset alignment
5050 if (!dseqs.contains(dsq))
5057 if (ds.findIndex(dsq) < 0)
5059 ds.addSequence(dsq);
5066 // TODO: refactor this as a merge dataset sequence function
5067 // now check that sq (the dataset sequence) sequence really is the union of
5068 // all references to it
5069 // boolean pre = sq.getStart() < dsq.getStart();
5070 // boolean post = sq.getEnd() > dsq.getEnd();
5074 // StringBuffer sb = new StringBuffer();
5075 String newres = jalview.analysis.AlignSeq.extractGaps(
5076 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
5077 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
5078 && newres.length() > dsq.getLength())
5080 // Update with the longer sequence.
5084 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
5085 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
5086 * sb.append(newres.substring(newres.length() - sq.getEnd() -
5087 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
5089 dsq.setSequence(newres);
5091 // TODO: merges will never happen if we 'know' we have the real dataset
5092 // sequence - this should be detected when id==dssid
5094 .println("DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
5095 // + (pre ? "prepended" : "") + " "
5096 // + (post ? "appended" : ""));
5101 // sequence refs are identical. We may need to update the existing dataset
5102 // alignment with this one, though.
5103 if (ds != null && dseqs == null)
5105 int opos = ds.findIndex(dsq);
5106 SequenceI tseq = null;
5107 if (opos != -1 && vseqpos != opos)
5109 // remove from old position
5110 ds.deleteSequence(dsq);
5112 if (vseqpos < ds.getHeight())
5114 if (vseqpos != opos)
5116 // save sequence at destination position
5117 tseq = ds.getSequenceAt(vseqpos);
5118 ds.replaceSequenceAt(vseqpos, dsq);
5119 ds.addSequence(tseq);
5124 ds.addSequence(dsq);
5131 * TODO use AlignmentI here and in related methods - needs
5132 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
5134 Hashtable<String, AlignmentI> datasetIds = null;
5136 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
5138 private AlignmentI getDatasetFor(String datasetId)
5140 if (datasetIds == null)
5142 datasetIds = new Hashtable<String, AlignmentI>();
5145 if (datasetIds.containsKey(datasetId))
5147 return datasetIds.get(datasetId);
5152 private void addDatasetRef(String datasetId, AlignmentI dataset)
5154 if (datasetIds == null)
5156 datasetIds = new Hashtable<String, AlignmentI>();
5158 datasetIds.put(datasetId, dataset);
5162 * make a new dataset ID for this jalview dataset alignment
5167 private String getDatasetIdRef(AlignmentI dataset)
5169 if (dataset.getDataset() != null)
5171 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
5173 String datasetId = makeHashCode(dataset, null);
5174 if (datasetId == null)
5176 // make a new datasetId and record it
5177 if (dataset2Ids == null)
5179 dataset2Ids = new IdentityHashMap<AlignmentI, String>();
5183 datasetId = dataset2Ids.get(dataset);
5185 if (datasetId == null)
5187 datasetId = "ds" + dataset2Ids.size() + 1;
5188 dataset2Ids.put(dataset, datasetId);
5194 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5196 for (int d = 0; d < sequence.getDBRefCount(); d++)
5198 DBRef dr = sequence.getDBRef(d);
5199 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
5200 sequence.getDBRef(d).getSource(), sequence.getDBRef(d)
5201 .getVersion(), sequence.getDBRef(d).getAccessionId());
5202 if (dr.getMapping() != null)
5204 entry.setMap(addMapping(dr.getMapping()));
5206 datasetSequence.addDBRef(entry);
5210 private jalview.datamodel.Mapping addMapping(Mapping m)
5212 SequenceI dsto = null;
5213 // Mapping m = dr.getMapping();
5214 int fr[] = new int[m.getMapListFromCount() * 2];
5215 Enumeration f = m.enumerateMapListFrom();
5216 for (int _i = 0; f.hasMoreElements(); _i += 2)
5218 MapListFrom mf = (MapListFrom) f.nextElement();
5219 fr[_i] = mf.getStart();
5220 fr[_i + 1] = mf.getEnd();
5222 int fto[] = new int[m.getMapListToCount() * 2];
5223 f = m.enumerateMapListTo();
5224 for (int _i = 0; f.hasMoreElements(); _i += 2)
5226 MapListTo mf = (MapListTo) f.nextElement();
5227 fto[_i] = mf.getStart();
5228 fto[_i + 1] = mf.getEnd();
5230 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto,
5231 fr, fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
5232 if (m.getMappingChoice() != null)
5234 MappingChoice mc = m.getMappingChoice();
5235 if (mc.getDseqFor() != null)
5237 String dsfor = "" + mc.getDseqFor();
5238 if (seqRefIds.containsKey(dsfor))
5243 jmap.setTo(seqRefIds.get(dsfor));
5247 frefedSequence.add(newMappingRef(dsfor, jmap));
5253 * local sequence definition
5255 Sequence ms = mc.getSequence();
5256 SequenceI djs = null;
5257 String sqid = ms.getDsseqid();
5258 if (sqid != null && sqid.length() > 0)
5261 * recover dataset sequence
5263 djs = seqRefIds.get(sqid);
5268 .println("Warning - making up dataset sequence id for DbRef sequence map reference");
5269 sqid = ((Object) ms).toString(); // make up a new hascode for
5270 // undefined dataset sequence hash
5271 // (unlikely to happen)
5277 * make a new dataset sequence and add it to refIds hash
5279 djs = new jalview.datamodel.Sequence(ms.getName(),
5281 djs.setStart(jmap.getMap().getToLowest());
5282 djs.setEnd(jmap.getMap().getToHighest());
5283 djs.setVamsasId(uniqueSetSuffix + sqid);
5285 incompleteSeqs.put(sqid, djs);
5286 seqRefIds.put(sqid, djs);
5289 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5298 public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
5299 boolean keepSeqRefs)
5302 JalviewModel jm = saveState(ap, null, null, null);
5307 jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
5311 uniqueSetSuffix = "";
5312 jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
5317 if (this.frefedSequence == null)
5319 frefedSequence = new Vector();
5322 viewportsAdded.clear();
5324 AlignFrame af = loadFromObject(jm, null, false, null);
5325 af.alignPanels.clear();
5326 af.closeMenuItem_actionPerformed(true);
5329 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5330 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5331 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5332 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5333 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5336 return af.alignPanel;
5340 * flag indicating if hashtables should be cleared on finalization TODO this
5341 * flag may not be necessary
5343 private final boolean _cleartables = true;
5345 private Hashtable jvids2vobj;
5350 * @see java.lang.Object#finalize()
5353 protected void finalize() throws Throwable
5355 // really make sure we have no buried refs left.
5360 this.seqRefIds = null;
5361 this.seqsToIds = null;
5365 private void warn(String msg)
5370 private void warn(String msg, Exception e)
5372 if (Cache.log != null)
5376 Cache.log.warn(msg, e);
5380 Cache.log.warn(msg);
5385 System.err.println("Warning: " + msg);
5388 e.printStackTrace();
5393 private void debug(String string)
5395 debug(string, null);
5398 private void debug(String msg, Exception e)
5400 if (Cache.log != null)
5404 Cache.log.debug(msg, e);
5408 Cache.log.debug(msg);
5413 System.err.println("Warning: " + msg);
5416 e.printStackTrace();
5422 * set the object to ID mapping tables used to write/recover objects and XML
5423 * ID strings for the jalview project. If external tables are provided then
5424 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
5425 * object goes out of scope. - also populates the datasetIds hashtable with
5426 * alignment objects containing dataset sequences
5429 * Map from ID strings to jalview datamodel
5431 * Map from jalview datamodel to ID strings
5435 public void setObjectMappingTables(Hashtable vobj2jv,
5436 IdentityHashMap jv2vobj)
5438 this.jv2vobj = jv2vobj;
5439 this.vobj2jv = vobj2jv;
5440 Iterator ds = jv2vobj.keySet().iterator();
5442 while (ds.hasNext())
5444 Object jvobj = ds.next();
5445 id = jv2vobj.get(jvobj).toString();
5446 if (jvobj instanceof jalview.datamodel.Alignment)
5448 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
5450 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
5453 else if (jvobj instanceof jalview.datamodel.Sequence)
5455 // register sequence object so the XML parser can recover it.
5456 if (seqRefIds == null)
5458 seqRefIds = new HashMap<String, SequenceI>();
5460 if (seqsToIds == null)
5462 seqsToIds = new IdentityHashMap<SequenceI, String>();
5464 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
5465 seqsToIds.put((SequenceI) jvobj, id);
5467 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
5470 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
5471 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
5472 if (jvann.annotationId == null)
5474 jvann.annotationId = anid;
5476 if (!jvann.annotationId.equals(anid))
5478 // TODO verify that this is the correct behaviour
5479 this.warn("Overriding Annotation ID for " + anid
5480 + " from different id : " + jvann.annotationId);
5481 jvann.annotationId = anid;
5484 else if (jvobj instanceof String)
5486 if (jvids2vobj == null)
5488 jvids2vobj = new Hashtable();
5489 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
5494 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
5500 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
5501 * objects created from the project archive. If string is null (default for
5502 * construction) then suffix will be set automatically.
5506 public void setUniqueSetSuffix(String string)
5508 uniqueSetSuffix = string;
5513 * uses skipList2 as the skipList for skipping views on sequence sets
5514 * associated with keys in the skipList
5518 public void setSkipList(Hashtable skipList2)
5520 skipList = skipList2;
5524 * Reads the jar entry of given name and returns its contents, or null if the
5525 * entry is not found.
5528 * @param jarEntryName
5531 protected String readJarEntry(jarInputStreamProvider jprovider,
5532 String jarEntryName)
5534 String result = null;
5535 BufferedReader in = null;
5540 * Reopen the jar input stream and traverse its entries to find a matching
5543 JarInputStream jin = jprovider.getJarInputStream();
5544 JarEntry entry = null;
5547 entry = jin.getNextJarEntry();
5548 } while (entry != null && !entry.getName().equals(jarEntryName));
5552 StringBuilder out = new StringBuilder(256);
5553 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
5556 while ((data = in.readLine()) != null)
5560 result = out.toString();
5564 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
5566 } catch (Exception ex)
5568 ex.printStackTrace();
5576 } catch (IOException e)
5587 * Returns an incrementing counter (0, 1, 2...)
5591 private synchronized int nextCounter()