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.ViewStyleI;
24 import jalview.api.structures.JalviewStructureDisplayI;
25 import jalview.bin.Cache;
26 import jalview.datamodel.AlignedCodonFrame;
27 import jalview.datamodel.Alignment;
28 import jalview.datamodel.AlignmentAnnotation;
29 import jalview.datamodel.AlignmentI;
30 import jalview.datamodel.PDBEntry;
31 import jalview.datamodel.RnaViewerModel;
32 import jalview.datamodel.SequenceGroup;
33 import jalview.datamodel.SequenceI;
34 import jalview.datamodel.StructureViewerModel;
35 import jalview.datamodel.StructureViewerModel.StructureData;
36 import jalview.ext.varna.RnaModel;
37 import jalview.gui.StructureViewer.ViewerType;
38 import jalview.schemabinding.version2.AlcodMap;
39 import jalview.schemabinding.version2.AlcodonFrame;
40 import jalview.schemabinding.version2.Annotation;
41 import jalview.schemabinding.version2.AnnotationColours;
42 import jalview.schemabinding.version2.AnnotationElement;
43 import jalview.schemabinding.version2.CalcIdParam;
44 import jalview.schemabinding.version2.DBRef;
45 import jalview.schemabinding.version2.Features;
46 import jalview.schemabinding.version2.Group;
47 import jalview.schemabinding.version2.HiddenColumns;
48 import jalview.schemabinding.version2.JGroup;
49 import jalview.schemabinding.version2.JSeq;
50 import jalview.schemabinding.version2.JalviewModel;
51 import jalview.schemabinding.version2.JalviewModelSequence;
52 import jalview.schemabinding.version2.MapListFrom;
53 import jalview.schemabinding.version2.MapListTo;
54 import jalview.schemabinding.version2.Mapping;
55 import jalview.schemabinding.version2.MappingChoice;
56 import jalview.schemabinding.version2.OtherData;
57 import jalview.schemabinding.version2.PdbentryItem;
58 import jalview.schemabinding.version2.Pdbids;
59 import jalview.schemabinding.version2.Property;
60 import jalview.schemabinding.version2.RnaViewer;
61 import jalview.schemabinding.version2.SecondaryStructure;
62 import jalview.schemabinding.version2.Sequence;
63 import jalview.schemabinding.version2.SequenceSet;
64 import jalview.schemabinding.version2.SequenceSetProperties;
65 import jalview.schemabinding.version2.Setting;
66 import jalview.schemabinding.version2.StructureState;
67 import jalview.schemabinding.version2.ThresholdLine;
68 import jalview.schemabinding.version2.Tree;
69 import jalview.schemabinding.version2.UserColours;
70 import jalview.schemabinding.version2.Viewport;
71 import jalview.schemes.AnnotationColourGradient;
72 import jalview.schemes.ColourSchemeI;
73 import jalview.schemes.ColourSchemeProperty;
74 import jalview.schemes.GraduatedColor;
75 import jalview.schemes.ResidueColourScheme;
76 import jalview.schemes.ResidueProperties;
77 import jalview.schemes.UserColourScheme;
78 import jalview.structure.StructureSelectionManager;
79 import jalview.structures.models.AAStructureBindingModel;
80 import jalview.util.MessageManager;
81 import jalview.util.Platform;
82 import jalview.util.StringUtils;
83 import jalview.util.jarInputStreamProvider;
84 import jalview.viewmodel.AlignmentViewport;
85 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
86 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
87 import jalview.ws.jws2.Jws2Discoverer;
88 import jalview.ws.jws2.dm.AAConSettings;
89 import jalview.ws.jws2.jabaws2.Jws2Instance;
90 import jalview.ws.params.ArgumentI;
91 import jalview.ws.params.AutoCalcSetting;
92 import jalview.ws.params.WsParamSetI;
94 import java.awt.Color;
95 import java.awt.Rectangle;
96 import java.io.BufferedReader;
97 import java.io.DataInputStream;
98 import java.io.DataOutputStream;
100 import java.io.FileInputStream;
101 import java.io.FileOutputStream;
102 import java.io.IOException;
103 import java.io.InputStreamReader;
104 import java.io.OutputStreamWriter;
105 import java.io.PrintWriter;
106 import java.lang.reflect.InvocationTargetException;
107 import java.net.MalformedURLException;
109 import java.util.ArrayList;
110 import java.util.Enumeration;
111 import java.util.HashMap;
112 import java.util.HashSet;
113 import java.util.Hashtable;
114 import java.util.IdentityHashMap;
115 import java.util.Iterator;
116 import java.util.LinkedHashMap;
117 import java.util.List;
118 import java.util.Map;
119 import java.util.Map.Entry;
120 import java.util.Set;
121 import java.util.Vector;
122 import java.util.jar.JarEntry;
123 import java.util.jar.JarInputStream;
124 import java.util.jar.JarOutputStream;
126 import javax.swing.JInternalFrame;
127 import javax.swing.JOptionPane;
128 import javax.swing.SwingUtilities;
130 import org.exolab.castor.xml.Marshaller;
131 import org.exolab.castor.xml.Unmarshaller;
134 * Write out the current jalview desktop state as a Jalview XML stream.
136 * Note: the vamsas objects referred to here are primitive versions of the
137 * VAMSAS project schema elements - they are not the same and most likely never
141 * @version $Revision: 1.134 $
143 public class Jalview2XML
145 private static final String VIEWER_PREFIX = "viewer_";
147 private static final String RNA_PREFIX = "rna_";
149 private static final String UTF_8 = "UTF-8";
151 // use this with nextCounter() to make unique names for entities
152 private int counter = 0;
155 * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
156 * of sequence objects are created.
158 IdentityHashMap<SequenceI, String> seqsToIds = null;
161 * jalview XML Sequence ID to jalview sequence object reference (both dataset
162 * and alignment sequences. Populated as XML reps of sequence objects are
165 Map<String, SequenceI> seqRefIds = null;
167 Vector<Object[]> frefedSequence = null;
169 boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
172 * Map of reconstructed AlignFrame objects that appear to have come from
173 * SplitFrame objects (have a dna/protein complement view).
175 private Map<Viewport, AlignFrame> splitFrameCandidates = new HashMap<Viewport, AlignFrame>();
178 * Map from displayed rna structure models to their saved session state jar
181 private Map<RnaModel, String> rnaSessions = new HashMap<RnaModel, String>();
184 * create/return unique hash string for sq
187 * @return new or existing unique string for sq
189 String seqHash(SequenceI sq)
191 if (seqsToIds == null)
195 if (seqsToIds.containsKey(sq))
197 return seqsToIds.get(sq);
201 // create sequential key
202 String key = "sq" + (seqsToIds.size() + 1);
203 key = makeHashCode(sq, key); // check we don't have an external reference
205 seqsToIds.put(sq, key);
214 if (seqRefIds != null)
218 if (seqsToIds != null)
228 warn("clearSeqRefs called when _cleartables was not set. Doing nothing.");
229 // seqRefIds = new Hashtable();
230 // seqsToIds = new IdentityHashMap();
236 if (seqsToIds == null)
238 seqsToIds = new IdentityHashMap<SequenceI, String>();
240 if (seqRefIds == null)
242 seqRefIds = new HashMap<String, SequenceI>();
250 public Jalview2XML(boolean raiseGUI)
252 this.raiseGUI = raiseGUI;
255 public void resolveFrefedSequences()
257 if (frefedSequence.size() > 0)
259 int r = 0, rSize = frefedSequence.size();
262 Object[] ref = frefedSequence.elementAt(r);
265 String sref = (String) ref[0];
266 if (seqRefIds.containsKey(sref))
268 if (ref[1] instanceof jalview.datamodel.Mapping)
270 SequenceI seq = seqRefIds.get(sref);
271 while (seq.getDatasetSequence() != null)
273 seq = seq.getDatasetSequence();
275 ((jalview.datamodel.Mapping) ref[1]).setTo(seq);
279 if (ref[1] instanceof jalview.datamodel.AlignedCodonFrame)
281 SequenceI seq = seqRefIds.get(sref);
282 while (seq.getDatasetSequence() != null)
284 seq = seq.getDatasetSequence();
287 && ref[2] instanceof jalview.datamodel.Mapping)
289 jalview.datamodel.Mapping mp = (jalview.datamodel.Mapping) ref[2];
290 ((jalview.datamodel.AlignedCodonFrame) ref[1]).addMap(
291 seq, mp.getTo(), mp.getMap());
296 .println("IMPLEMENTATION ERROR: Unimplemented forward sequence references for AlcodonFrames involving "
297 + ref[2].getClass() + " type objects.");
303 .println("IMPLEMENTATION ERROR: Unimplemented forward sequence references for "
304 + ref[1].getClass() + " type objects.");
307 frefedSequence.remove(r);
313 .println("IMPLEMENTATION WARNING: Unresolved forward reference for hash string "
315 + " with objecttype "
316 + ref[1].getClass());
323 frefedSequence.remove(r);
331 * This maintains a map of viewports, the key being the seqSetId. Important to
332 * set historyItem and redoList for multiple views
334 Map<String, AlignViewport> viewportsAdded = new HashMap<String, AlignViewport>();
336 Map<String, AlignmentAnnotation> annotationIds = new HashMap<String, AlignmentAnnotation>();
338 String uniqueSetSuffix = "";
341 * List of pdbfiles added to Jar
343 List<String> pdbfiles = null;
345 // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
346 public void saveState(File statefile)
348 FileOutputStream fos = null;
351 fos = new FileOutputStream(statefile);
352 JarOutputStream jout = new JarOutputStream(fos);
355 } catch (Exception e)
357 // TODO: inform user of the problem - they need to know if their data was
359 if (errorMessage == null)
361 errorMessage = "Couldn't write Jalview Archive to output file '"
362 + statefile + "' - See console error log for details";
366 errorMessage += "(output file was '" + statefile + "')";
376 } catch (IOException e)
386 * Writes a jalview project archive to the given Jar output stream.
390 public void saveState(JarOutputStream jout)
392 AlignFrame[] frames = Desktop.getAlignFrames();
399 Hashtable<String, AlignFrame> dsses = new Hashtable<String, AlignFrame>();
402 * ensure cached data is clear before starting
404 // todo tidy up seqRefIds, seqsToIds initialisation / reset
406 splitFrameCandidates.clear();
411 // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
412 // //////////////////////////////////////////////////
414 List<String> shortNames = new ArrayList<String>();
415 List<String> viewIds = new ArrayList<String>();
418 for (int i = frames.length - 1; i > -1; i--)
420 AlignFrame af = frames[i];
424 .containsKey(af.getViewport().getSequenceSetId()))
429 String shortName = makeFilename(af, shortNames);
431 int ap, apSize = af.alignPanels.size();
433 for (ap = 0; ap < apSize; ap++)
435 AlignmentPanel apanel = af.alignPanels.get(ap);
436 String fileName = apSize == 1 ? shortName : ap + shortName;
437 if (!fileName.endsWith(".xml"))
439 fileName = fileName + ".xml";
442 saveState(apanel, fileName, jout, viewIds);
444 String dssid = getDatasetIdRef(af.getViewport().getAlignment()
446 if (!dsses.containsKey(dssid))
448 dsses.put(dssid, af);
453 writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix,
459 } catch (Exception foo)
464 } catch (Exception ex)
466 // TODO: inform user of the problem - they need to know if their data was
468 if (errorMessage == null)
470 errorMessage = "Couldn't write Jalview Archive - see error output for details";
472 ex.printStackTrace();
477 * Generates a distinct file name, based on the title of the AlignFrame, by
478 * appending _n for increasing n until an unused name is generated. The new
479 * name (without its extension) is added to the list.
483 * @return the generated name, with .xml extension
485 protected String makeFilename(AlignFrame af, List<String> namesUsed)
487 String shortName = af.getTitle();
489 if (shortName.indexOf(File.separatorChar) > -1)
491 shortName = shortName.substring(shortName
492 .lastIndexOf(File.separatorChar) + 1);
497 while (namesUsed.contains(shortName))
499 if (shortName.endsWith("_" + (count - 1)))
501 shortName = shortName.substring(0, shortName.lastIndexOf("_"));
504 shortName = shortName.concat("_" + count);
508 namesUsed.add(shortName);
510 if (!shortName.endsWith(".xml"))
512 shortName = shortName + ".xml";
517 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
518 public boolean saveAlignment(AlignFrame af, String jarFile,
524 int apSize = af.alignPanels.size();
525 FileOutputStream fos = new FileOutputStream(jarFile);
526 JarOutputStream jout = new JarOutputStream(fos);
527 Hashtable<String, AlignFrame> dsses = new Hashtable<String, AlignFrame>();
528 List<String> viewIds = new ArrayList<String>();
530 for (AlignmentPanel apanel : af.alignPanels)
532 String jfileName = apSize == 1 ? fileName : fileName + ap;
534 if (!jfileName.endsWith(".xml"))
536 jfileName = jfileName + ".xml";
538 saveState(apanel, jfileName, jout, viewIds);
539 String dssid = getDatasetIdRef(af.getViewport().getAlignment()
541 if (!dsses.containsKey(dssid))
543 dsses.put(dssid, af);
546 writeDatasetFor(dsses, fileName, jout);
550 } catch (Exception foo)
556 } catch (Exception ex)
558 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
559 ex.printStackTrace();
564 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
565 String fileName, JarOutputStream jout)
568 for (String dssids : dsses.keySet())
570 AlignFrame _af = dsses.get(dssids);
571 String jfileName = fileName + " Dataset for " + _af.getTitle();
572 if (!jfileName.endsWith(".xml"))
574 jfileName = jfileName + ".xml";
576 saveState(_af.alignPanel, jfileName, true, jout, null);
581 * create a JalviewModel from an alignment view and marshall it to a
585 * panel to create jalview model for
587 * name of alignment panel written to output stream
594 public JalviewModel saveState(AlignmentPanel ap, String fileName,
595 JarOutputStream jout, List<String> viewIds)
597 return saveState(ap, fileName, false, jout, viewIds);
601 * create a JalviewModel from an alignment view and marshall it to a
605 * panel to create jalview model for
607 * name of alignment panel written to output stream
609 * when true, only write the dataset for the alignment, not the data
610 * associated with the view.
616 public JalviewModel saveState(AlignmentPanel ap, String fileName,
617 boolean storeDS, JarOutputStream jout, List<String> viewIds)
621 viewIds = new ArrayList<String>();
626 List<UserColourScheme> userColours = new ArrayList<UserColourScheme>();
628 AlignViewport av = ap.av;
630 JalviewModel object = new JalviewModel();
631 object.setVamsasModel(new jalview.schemabinding.version2.VamsasModel());
633 object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
634 object.setVersion(jalview.bin.Cache.getDefault("VERSION",
635 "Development Build"));
638 * rjal is full height alignment, jal is actual alignment with full metadata
639 * but excludes hidden sequences.
641 jalview.datamodel.AlignmentI rjal = av.getAlignment(), jal = rjal;
643 if (av.hasHiddenRows())
645 rjal = jal.getHiddenSequences().getFullAlignment();
648 SequenceSet vamsasSet = new SequenceSet();
650 JalviewModelSequence jms = new JalviewModelSequence();
652 vamsasSet.setGapChar(jal.getGapCharacter() + "");
654 if (jal.getDataset() != null)
656 // dataset id is the dataset's hashcode
657 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
660 // switch jal and the dataset
661 jal = jal.getDataset();
665 if (jal.getProperties() != null)
667 Enumeration en = jal.getProperties().keys();
668 while (en.hasMoreElements())
670 String key = en.nextElement().toString();
671 SequenceSetProperties ssp = new SequenceSetProperties();
673 ssp.setValue(jal.getProperties().get(key).toString());
674 vamsasSet.addSequenceSetProperties(ssp);
679 Set<String> calcIdSet = new HashSet<String>();
682 for (int i = 0; i < rjal.getHeight(); i++)
684 final SequenceI jds = rjal.getSequenceAt(i);
685 final SequenceI jdatasq = jds.getDatasetSequence() == null ? jds
686 : jds.getDatasetSequence();
687 String id = seqHash(jds);
689 if (seqRefIds.get(id) != null)
691 // This happens for two reasons: 1. multiple views are being serialised.
692 // 2. the hashCode has collided with another sequence's code. This DOES
693 // HAPPEN! (PF00072.15.stk does this)
694 // JBPNote: Uncomment to debug writing out of files that do not read
695 // back in due to ArrayOutOfBoundExceptions.
696 // System.err.println("vamsasSeq backref: "+id+"");
697 // System.err.println(jds.getName()+"
698 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
699 // System.err.println("Hashcode: "+seqHash(jds));
700 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
701 // System.err.println(rsq.getName()+"
702 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
703 // System.err.println("Hashcode: "+seqHash(rsq));
707 vamsasSeq = createVamsasSequence(id, jds);
708 vamsasSet.addSequence(vamsasSeq);
709 seqRefIds.put(id, jds);
713 jseq.setStart(jds.getStart());
714 jseq.setEnd(jds.getEnd());
715 jseq.setColour(av.getSequenceColour(jds).getRGB());
717 jseq.setId(id); // jseq id should be a string not a number
720 // Store any sequences this sequence represents
721 if (av.hasHiddenRows())
723 // use rjal, contains the full height alignment
724 jseq.setHidden(av.getAlignment().getHiddenSequences()
727 if (av.isHiddenRepSequence(rjal.getSequenceAt(i)))
729 jalview.datamodel.SequenceI[] reps = av
730 .getRepresentedSequences(rjal.getSequenceAt(i))
731 .getSequencesInOrder(rjal);
733 for (int h = 0; h < reps.length; h++)
735 if (reps[h] != rjal.getSequenceAt(i))
737 jseq.addHiddenSequences(rjal.findIndex(reps[h]));
744 if (jds.getSequenceFeatures() != null)
746 jalview.datamodel.SequenceFeature[] sf = jds.getSequenceFeatures();
748 while (index < sf.length)
750 Features features = new Features();
752 features.setBegin(sf[index].getBegin());
753 features.setEnd(sf[index].getEnd());
754 features.setDescription(sf[index].getDescription());
755 features.setType(sf[index].getType());
756 features.setFeatureGroup(sf[index].getFeatureGroup());
757 features.setScore(sf[index].getScore());
758 if (sf[index].links != null)
760 for (int l = 0; l < sf[index].links.size(); l++)
762 OtherData keyValue = new OtherData();
763 keyValue.setKey("LINK_" + l);
764 keyValue.setValue(sf[index].links.elementAt(l).toString());
765 features.addOtherData(keyValue);
768 if (sf[index].otherDetails != null)
771 Iterator<String> keys = sf[index].otherDetails.keySet()
773 while (keys.hasNext())
776 OtherData keyValue = new OtherData();
777 keyValue.setKey(key);
778 keyValue.setValue(sf[index].otherDetails.get(key).toString());
779 features.addOtherData(keyValue);
783 jseq.addFeatures(features);
788 if (jdatasq.getAllPDBEntries() != null)
790 Enumeration en = jdatasq.getAllPDBEntries().elements();
791 while (en.hasMoreElements())
793 Pdbids pdb = new Pdbids();
794 jalview.datamodel.PDBEntry entry = (jalview.datamodel.PDBEntry) en
797 String pdbId = entry.getId();
799 pdb.setType(entry.getType());
802 * Store any structure views associated with this sequence. This
803 * section copes with duplicate entries in the project, so a dataset
804 * only view *should* be coped with sensibly.
806 // This must have been loaded, is it still visible?
807 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
808 String matchedFile = null;
809 for (int f = frames.length - 1; f > -1; f--)
811 if (frames[f] instanceof StructureViewerBase)
813 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
814 matchedFile = saveStructureState(ap, jds, pdb, entry,
815 viewIds, matchedFile, viewFrame);
817 * Only store each structure viewer's state once in the project
818 * jar. First time through only (storeDS==false)
820 String viewId = viewFrame.getViewId();
821 if (!storeDS && !viewIds.contains(viewId))
826 String viewerState = viewFrame.getStateInfo();
827 writeJarEntry(jout, getViewerJarEntryName(viewId),
828 viewerState.getBytes());
829 } catch (IOException e)
831 System.err.println("Error saving viewer state: "
838 if (matchedFile != null || entry.getFile() != null)
840 if (entry.getFile() != null)
843 matchedFile = entry.getFile();
845 pdb.setFile(matchedFile); // entry.getFile());
846 if (pdbfiles == null)
848 pdbfiles = new ArrayList<String>();
851 if (!pdbfiles.contains(pdbId))
854 copyFileToJar(jout, matchedFile, pdbId);
858 if (entry.getProperty() != null && !entry.getProperty().isEmpty())
860 PdbentryItem item = new PdbentryItem();
861 Hashtable properties = entry.getProperty();
862 Enumeration en2 = properties.keys();
863 while (en2.hasMoreElements())
865 Property prop = new Property();
866 String key = en2.nextElement().toString();
868 prop.setValue(properties.get(key).toString());
869 item.addProperty(prop);
871 pdb.addPdbentryItem(item);
878 saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
883 if (!storeDS && av.hasHiddenRows())
885 jal = av.getAlignment();
888 if (jal.getCodonFrames() != null)
890 List<AlignedCodonFrame> jac = jal.getCodonFrames();
891 for (AlignedCodonFrame acf : jac)
893 AlcodonFrame alc = new AlcodonFrame();
894 vamsasSet.addAlcodonFrame(alc);
895 if (acf.getProtMappings() != null
896 && acf.getProtMappings().length > 0)
898 SequenceI[] dnas = acf.getdnaSeqs();
899 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
900 for (int m = 0; m < pmaps.length; m++)
902 AlcodMap alcmap = new AlcodMap();
903 alcmap.setDnasq(seqHash(dnas[m]));
904 alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
906 alc.addAlcodMap(alcmap);
909 // TODO: delete this ? dead code from 2.8.3->2.9 ?
911 // AlcodonFrame alc = new AlcodonFrame();
912 // vamsasSet.addAlcodonFrame(alc);
913 // for (int p = 0; p < acf.aaWidth; p++)
915 // Alcodon cmap = new Alcodon();
916 // if (acf.codons[p] != null)
918 // // Null codons indicate a gapped column in the translated peptide
920 // cmap.setPos1(acf.codons[p][0]);
921 // cmap.setPos2(acf.codons[p][1]);
922 // cmap.setPos3(acf.codons[p][2]);
924 // alc.addAlcodon(cmap);
926 // if (acf.getProtMappings() != null
927 // && acf.getProtMappings().length > 0)
929 // SequenceI[] dnas = acf.getdnaSeqs();
930 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
931 // for (int m = 0; m < pmaps.length; m++)
933 // AlcodMap alcmap = new AlcodMap();
934 // alcmap.setDnasq(seqHash(dnas[m]));
935 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
937 // alc.addAlcodMap(alcmap);
944 // /////////////////////////////////
945 if (!storeDS && av.currentTree != null)
947 // FIND ANY ASSOCIATED TREES
948 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
949 if (Desktop.desktop != null)
951 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
953 for (int t = 0; t < frames.length; t++)
955 if (frames[t] instanceof TreePanel)
957 TreePanel tp = (TreePanel) frames[t];
959 if (tp.treeCanvas.av.getAlignment() == jal)
961 Tree tree = new Tree();
962 tree.setTitle(tp.getTitle());
963 tree.setCurrentTree((av.currentTree == tp.getTree()));
964 tree.setNewick(tp.getTree().toString());
965 tree.setThreshold(tp.treeCanvas.threshold);
967 tree.setFitToWindow(tp.fitToWindow.getState());
968 tree.setFontName(tp.getTreeFont().getName());
969 tree.setFontSize(tp.getTreeFont().getSize());
970 tree.setFontStyle(tp.getTreeFont().getStyle());
971 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
973 tree.setShowBootstrap(tp.bootstrapMenu.getState());
974 tree.setShowDistances(tp.distanceMenu.getState());
976 tree.setHeight(tp.getHeight());
977 tree.setWidth(tp.getWidth());
978 tree.setXpos(tp.getX());
979 tree.setYpos(tp.getY());
980 tree.setId(makeHashCode(tp, null));
990 * store forward refs from an annotationRow to any groups
992 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<SequenceGroup, String>();
995 for (SequenceI sq : jal.getSequences())
997 // Store annotation on dataset sequences only
998 AlignmentAnnotation[] aa = sq.getAnnotation();
999 if (aa != null && aa.length > 0)
1001 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1008 if (jal.getAlignmentAnnotation() != null)
1010 // Store the annotation shown on the alignment.
1011 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1012 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1017 if (jal.getGroups() != null)
1019 JGroup[] groups = new JGroup[jal.getGroups().size()];
1021 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1023 JGroup jGroup = new JGroup();
1024 groups[++i] = jGroup;
1026 jGroup.setStart(sg.getStartRes());
1027 jGroup.setEnd(sg.getEndRes());
1028 jGroup.setName(sg.getName());
1029 if (groupRefs.containsKey(sg))
1031 // group has references so set its ID field
1032 jGroup.setId(groupRefs.get(sg));
1036 if (sg.cs.conservationApplied())
1038 jGroup.setConsThreshold(sg.cs.getConservationInc());
1040 if (sg.cs instanceof jalview.schemes.UserColourScheme)
1042 jGroup.setColour(setUserColourScheme(sg.cs, userColours, jms));
1046 jGroup.setColour(ColourSchemeProperty.getColourName(sg.cs));
1049 else if (sg.cs instanceof jalview.schemes.AnnotationColourGradient)
1051 jGroup.setColour("AnnotationColourGradient");
1052 jGroup.setAnnotationColours(constructAnnotationColours(
1053 (jalview.schemes.AnnotationColourGradient) sg.cs,
1056 else if (sg.cs instanceof jalview.schemes.UserColourScheme)
1058 jGroup.setColour(setUserColourScheme(sg.cs, userColours, jms));
1062 jGroup.setColour(ColourSchemeProperty.getColourName(sg.cs));
1065 jGroup.setPidThreshold(sg.cs.getThreshold());
1068 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1069 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1070 jGroup.setDisplayText(sg.getDisplayText());
1071 jGroup.setColourText(sg.getColourText());
1072 jGroup.setTextCol1(sg.textColour.getRGB());
1073 jGroup.setTextCol2(sg.textColour2.getRGB());
1074 jGroup.setTextColThreshold(sg.thresholdTextColour);
1075 jGroup.setShowUnconserved(sg.getShowNonconserved());
1076 jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1077 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1078 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1079 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1080 for (SequenceI seq : sg.getSequences())
1082 jGroup.addSeq(seqHash(seq));
1086 jms.setJGroup(groups);
1090 // /////////SAVE VIEWPORT
1091 Viewport view = new Viewport();
1092 view.setTitle(ap.alignFrame.getTitle());
1093 view.setSequenceSetId(makeHashCode(av.getSequenceSetId(),
1094 av.getSequenceSetId()));
1095 view.setId(av.getViewId());
1096 if (av.getCodingComplement() != null)
1098 view.setComplementId(av.getCodingComplement().getViewId());
1100 view.setViewName(av.viewName);
1101 view.setGatheredViews(av.isGatherViewsHere());
1103 Rectangle size = ap.av.getExplodedGeometry();
1104 Rectangle position = size;
1107 size = ap.alignFrame.getBounds();
1108 if (av.getCodingComplement() != null)
1110 position = ((SplitFrame) ap.alignFrame.getSplitViewContainer())
1118 view.setXpos(position.x);
1119 view.setYpos(position.y);
1121 view.setWidth(size.width);
1122 view.setHeight(size.height);
1124 view.setStartRes(av.startRes);
1125 view.setStartSeq(av.startSeq);
1127 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1129 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1132 else if (av.getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1134 AnnotationColours ac = constructAnnotationColours(
1135 (jalview.schemes.AnnotationColourGradient) av
1136 .getGlobalColourScheme(),
1139 view.setAnnotationColours(ac);
1140 view.setBgColour("AnnotationColourGradient");
1144 view.setBgColour(ColourSchemeProperty.getColourName(av
1145 .getGlobalColourScheme()));
1148 ColourSchemeI cs = av.getGlobalColourScheme();
1152 if (cs.conservationApplied())
1154 view.setConsThreshold(cs.getConservationInc());
1155 if (cs instanceof jalview.schemes.UserColourScheme)
1157 view.setBgColour(setUserColourScheme(cs, userColours, jms));
1161 if (cs instanceof ResidueColourScheme)
1163 view.setPidThreshold(cs.getThreshold());
1167 view.setConservationSelected(av.getConservationSelected());
1168 view.setPidSelected(av.getAbovePIDThreshold());
1169 view.setFontName(av.font.getName());
1170 view.setFontSize(av.font.getSize());
1171 view.setFontStyle(av.font.getStyle());
1172 view.setScaleProteinAsCdna(av.getViewStyle().isScaleProteinAsCdna());
1173 view.setRenderGaps(av.isRenderGaps());
1174 view.setShowAnnotation(av.isShowAnnotation());
1175 view.setShowBoxes(av.getShowBoxes());
1176 view.setShowColourText(av.getColourText());
1177 view.setShowFullId(av.getShowJVSuffix());
1178 view.setRightAlignIds(av.isRightAlignIds());
1179 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1180 view.setShowText(av.getShowText());
1181 view.setShowUnconserved(av.getShowUnconserved());
1182 view.setWrapAlignment(av.getWrapAlignment());
1183 view.setTextCol1(av.getTextColour().getRGB());
1184 view.setTextCol2(av.getTextColour2().getRGB());
1185 view.setTextColThreshold(av.getThresholdTextColour());
1186 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1187 view.setShowSequenceLogo(av.isShowSequenceLogo());
1188 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1189 view.setShowGroupConsensus(av.isShowGroupConsensus());
1190 view.setShowGroupConservation(av.isShowGroupConservation());
1191 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1192 view.setShowDbRefTooltip(av.isShowDBRefs());
1193 view.setFollowHighlight(av.isFollowHighlight());
1194 view.setFollowSelection(av.followSelection);
1195 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1196 if (av.getFeaturesDisplayed() != null)
1198 jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
1200 String[] renderOrder = ap.getSeqPanel().seqCanvas
1201 .getFeatureRenderer().getRenderOrder()
1202 .toArray(new String[0]);
1204 Vector<String> settingsAdded = new Vector<String>();
1205 Object gstyle = null;
1206 GraduatedColor gcol = null;
1207 if (renderOrder != null)
1209 for (String featureType : renderOrder)
1211 gstyle = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1212 .getFeatureStyle(featureType);
1213 Setting setting = new Setting();
1214 setting.setType(featureType);
1215 if (gstyle instanceof GraduatedColor)
1217 gcol = (GraduatedColor) gstyle;
1218 setting.setColour(gcol.getMaxColor().getRGB());
1219 setting.setMincolour(gcol.getMinColor().getRGB());
1220 setting.setMin(gcol.getMin());
1221 setting.setMax(gcol.getMax());
1222 setting.setColourByLabel(gcol.isColourByLabel());
1223 setting.setAutoScale(gcol.isAutoScale());
1224 setting.setThreshold(gcol.getThresh());
1225 setting.setThreshstate(gcol.getThreshType());
1229 setting.setColour(((Color) gstyle).getRGB());
1232 setting.setDisplay(av.getFeaturesDisplayed().isVisible(
1234 float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1235 .getOrder(featureType);
1238 setting.setOrder(rorder);
1240 fs.addSetting(setting);
1241 settingsAdded.addElement(featureType);
1245 // is groups actually supposed to be a map here ?
1246 Iterator<String> en = ap.getSeqPanel().seqCanvas
1247 .getFeatureRenderer()
1248 .getFeatureGroups().iterator();
1249 Vector<String> groupsAdded = new Vector<String>();
1250 while (en.hasNext())
1252 String grp = en.next();
1253 if (groupsAdded.contains(grp))
1257 Group g = new Group();
1259 g.setDisplay(((Boolean) ap.getSeqPanel().seqCanvas
1260 .getFeatureRenderer().checkGroupVisibility(grp, false))
1263 groupsAdded.addElement(grp);
1265 jms.setFeatureSettings(fs);
1269 if (av.hasHiddenColumns())
1271 if (av.getColumnSelection() == null
1272 || av.getColumnSelection().getHiddenColumns() == null)
1274 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1278 for (int c = 0; c < av.getColumnSelection().getHiddenColumns()
1281 int[] region = av.getColumnSelection().getHiddenColumns()
1283 HiddenColumns hc = new HiddenColumns();
1284 hc.setStart(region[0]);
1285 hc.setEnd(region[1]);
1286 view.addHiddenColumns(hc);
1290 if (calcIdSet.size() > 0)
1292 for (String calcId : calcIdSet)
1294 if (calcId.trim().length() > 0)
1296 CalcIdParam cidp = createCalcIdParam(calcId, av);
1297 // Some calcIds have no parameters.
1300 view.addCalcIdParam(cidp);
1306 jms.addViewport(view);
1308 object.setJalviewModelSequence(jms);
1309 object.getVamsasModel().addSequenceSet(vamsasSet);
1311 if (jout != null && fileName != null)
1313 // We may not want to write the object to disk,
1314 // eg we can copy the alignViewport to a new view object
1315 // using save and then load
1318 System.out.println("Writing jar entry " + fileName);
1319 JarEntry entry = new JarEntry(fileName);
1320 jout.putNextEntry(entry);
1321 PrintWriter pout = new PrintWriter(new OutputStreamWriter(jout,
1323 Marshaller marshaller = new Marshaller(pout);
1324 marshaller.marshal(object);
1327 } catch (Exception ex)
1329 // TODO: raise error in GUI if marshalling failed.
1330 ex.printStackTrace();
1337 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1338 * for each viewer, with
1340 * <li>viewer geometry (position, size, split pane divider location)</li>
1341 * <li>index of the selected structure in the viewer (currently shows gapped
1343 * <li>the id of the annotation holding RNA secondary structure</li>
1344 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1346 * Varna viewer state is also written out (in native Varna XML) to separate
1347 * project jar entries. A separate entry is written for each RNA structure
1348 * displayed, with the naming convention
1350 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
1358 * @param storeDataset
1360 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
1361 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
1362 boolean storeDataset)
1364 if (Desktop.desktop == null)
1368 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1369 for (int f = frames.length - 1; f > -1; f--)
1371 if (frames[f] instanceof AppVarna)
1373 AppVarna varna = (AppVarna) frames[f];
1375 * link the sequence to every viewer that is showing it and is linked to
1376 * its alignment panel
1378 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1380 String viewId = varna.getViewId();
1381 RnaViewer rna = new RnaViewer();
1382 rna.setViewId(viewId);
1383 rna.setTitle(varna.getTitle());
1384 rna.setXpos(varna.getX());
1385 rna.setYpos(varna.getY());
1386 rna.setWidth(varna.getWidth());
1387 rna.setHeight(varna.getHeight());
1388 rna.setDividerLocation(varna.getDividerLocation());
1389 rna.setSelectedRna(varna.getSelectedIndex());
1390 jseq.addRnaViewer(rna);
1393 * Store each Varna panel's state once in the project per sequence.
1394 * First time through only (storeDataset==false)
1396 // boolean storeSessions = false;
1397 // String sequenceViewId = viewId + seqsToIds.get(jds);
1398 // if (!storeDataset && !viewIds.contains(sequenceViewId))
1400 // viewIds.add(sequenceViewId);
1401 // storeSessions = true;
1403 for (RnaModel model : varna.getModels())
1405 if (model.seq == jds)
1408 * VARNA saves each view (sequence or alignment secondary
1409 * structure, gapped or trimmed) as a separate XML file
1411 String jarEntryName = rnaSessions.get(model);
1412 if (jarEntryName == null)
1415 String varnaStateFile = varna.getStateInfo(model.rna);
1416 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
1417 copyFileToJar(jout, varnaStateFile, jarEntryName);
1418 rnaSessions.put(model, jarEntryName);
1420 SecondaryStructure ss = new SecondaryStructure();
1421 String annotationId = varna.getAnnotation(jds).annotationId;
1422 ss.setAnnotationId(annotationId);
1423 ss.setViewerState(jarEntryName);
1424 ss.setGapped(model.gapped);
1425 ss.setTitle(model.title);
1426 rna.addSecondaryStructure(ss);
1435 * Copy the contents of a file to a new entry added to the output jar
1439 * @param jarEntryName
1441 protected void copyFileToJar(JarOutputStream jout, String infilePath,
1442 String jarEntryName)
1444 DataInputStream dis = null;
1447 File file = new File(infilePath);
1448 if (file.exists() && jout != null)
1450 dis = new DataInputStream(new FileInputStream(file));
1451 byte[] data = new byte[(int) file.length()];
1452 dis.readFully(data);
1453 writeJarEntry(jout, jarEntryName, data);
1455 } catch (Exception ex)
1457 ex.printStackTrace();
1465 } catch (IOException e)
1474 * Write the data to a new entry of given name in the output jar file
1477 * @param jarEntryName
1479 * @throws IOException
1481 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
1482 byte[] data) throws IOException
1486 System.out.println("Writing jar entry " + jarEntryName);
1487 jout.putNextEntry(new JarEntry(jarEntryName));
1488 DataOutputStream dout = new DataOutputStream(jout);
1489 dout.write(data, 0, data.length);
1496 * Save the state of a structure viewer
1501 * the archive XML element under which to save the state
1504 * @param matchedFile
1508 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
1509 Pdbids pdb, PDBEntry entry, List<String> viewIds,
1510 String matchedFile, StructureViewerBase viewFrame)
1512 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
1515 * Look for any bindings for this viewer to the PDB file of interest
1516 * (including part matches excluding chain id)
1518 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
1520 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
1521 final String pdbId = pdbentry.getId();
1522 if (!pdbId.equals(entry.getId())
1523 && !(entry.getId().length() > 4 && entry.getId()
1524 .toLowerCase().startsWith(pdbId.toLowerCase())))
1527 * not interested in a binding to a different PDB entry here
1531 if (matchedFile == null)
1533 matchedFile = pdbentry.getFile();
1535 else if (!matchedFile.equals(pdbentry.getFile()))
1538 .warn("Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
1539 + pdbentry.getFile());
1543 // can get at it if the ID
1544 // match is ambiguous (e.g.
1547 for (int smap = 0; smap < viewFrame.getBinding().getSequence()[peid].length; smap++)
1549 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
1550 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
1552 StructureState state = new StructureState();
1553 state.setVisible(true);
1554 state.setXpos(viewFrame.getX());
1555 state.setYpos(viewFrame.getY());
1556 state.setWidth(viewFrame.getWidth());
1557 state.setHeight(viewFrame.getHeight());
1558 final String viewId = viewFrame.getViewId();
1559 state.setViewId(viewId);
1560 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
1561 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
1562 state.setColourByJmol(viewFrame.isColouredByViewer());
1563 state.setType(viewFrame.getViewerType().toString());
1564 pdb.addStructureState(state);
1571 private AnnotationColours constructAnnotationColours(
1572 AnnotationColourGradient acg, List<UserColourScheme> userColours,
1573 JalviewModelSequence jms)
1575 AnnotationColours ac = new AnnotationColours();
1576 ac.setAboveThreshold(acg.getAboveThreshold());
1577 ac.setThreshold(acg.getAnnotationThreshold());
1578 ac.setAnnotation(acg.getAnnotation());
1579 if (acg.getBaseColour() instanceof jalview.schemes.UserColourScheme)
1581 ac.setColourScheme(setUserColourScheme(acg.getBaseColour(),
1586 ac.setColourScheme(ColourSchemeProperty.getColourName(acg
1590 ac.setMaxColour(acg.getMaxColour().getRGB());
1591 ac.setMinColour(acg.getMinColour().getRGB());
1592 ac.setPerSequence(acg.isSeqAssociated());
1593 ac.setPredefinedColours(acg.isPredefinedColours());
1597 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
1598 IdentityHashMap<SequenceGroup, String> groupRefs,
1599 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
1600 SequenceSet vamsasSet)
1603 for (int i = 0; i < aa.length; i++)
1605 Annotation an = new Annotation();
1607 AlignmentAnnotation annotation = aa[i];
1608 if (annotation.annotationId != null)
1610 annotationIds.put(annotation.annotationId, annotation);
1613 an.setId(annotation.annotationId);
1615 an.setVisible(annotation.visible);
1617 an.setDescription(annotation.description);
1619 if (annotation.sequenceRef != null)
1621 // 2.9 JAL-1781 xref on sequence id rather than name
1622 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
1624 if (annotation.groupRef != null)
1626 String groupIdr = groupRefs.get(annotation.groupRef);
1627 if (groupIdr == null)
1629 // make a locally unique String
1631 annotation.groupRef,
1632 groupIdr = ("" + System.currentTimeMillis()
1633 + annotation.groupRef.getName() + groupRefs
1636 an.setGroupRef(groupIdr.toString());
1639 // store all visualization attributes for annotation
1640 an.setGraphHeight(annotation.graphHeight);
1641 an.setCentreColLabels(annotation.centreColLabels);
1642 an.setScaleColLabels(annotation.scaleColLabel);
1643 an.setShowAllColLabels(annotation.showAllColLabels);
1644 an.setBelowAlignment(annotation.belowAlignment);
1646 if (annotation.graph > 0)
1649 an.setGraphType(annotation.graph);
1650 an.setGraphGroup(annotation.graphGroup);
1651 if (annotation.getThreshold() != null)
1653 ThresholdLine line = new ThresholdLine();
1654 line.setLabel(annotation.getThreshold().label);
1655 line.setValue(annotation.getThreshold().value);
1656 line.setColour(annotation.getThreshold().colour.getRGB());
1657 an.setThresholdLine(line);
1665 an.setLabel(annotation.label);
1667 if (annotation == av.getAlignmentQualityAnnot()
1668 || annotation == av.getAlignmentConservationAnnotation()
1669 || annotation == av.getAlignmentConsensusAnnotation()
1670 || annotation.autoCalculated)
1672 // new way of indicating autocalculated annotation -
1673 an.setAutoCalculated(annotation.autoCalculated);
1675 if (annotation.hasScore())
1677 an.setScore(annotation.getScore());
1680 if (annotation.getCalcId() != null)
1682 calcIdSet.add(annotation.getCalcId());
1683 an.setCalcId(annotation.getCalcId());
1685 if (annotation.hasProperties())
1687 for (String pr : annotation.getProperties())
1689 Property prop = new Property();
1691 prop.setValue(annotation.getProperty(pr));
1692 an.addProperty(prop);
1696 AnnotationElement ae;
1697 if (annotation.annotations != null)
1699 an.setScoreOnly(false);
1700 for (int a = 0; a < annotation.annotations.length; a++)
1702 if ((annotation == null) || (annotation.annotations[a] == null))
1707 ae = new AnnotationElement();
1708 if (annotation.annotations[a].description != null)
1710 ae.setDescription(annotation.annotations[a].description);
1712 if (annotation.annotations[a].displayCharacter != null)
1714 ae.setDisplayCharacter(annotation.annotations[a].displayCharacter);
1717 if (!Float.isNaN(annotation.annotations[a].value))
1719 ae.setValue(annotation.annotations[a].value);
1723 if (annotation.annotations[a].secondaryStructure > ' ')
1725 ae.setSecondaryStructure(annotation.annotations[a].secondaryStructure
1729 if (annotation.annotations[a].colour != null
1730 && annotation.annotations[a].colour != java.awt.Color.black)
1732 ae.setColour(annotation.annotations[a].colour.getRGB());
1735 an.addAnnotationElement(ae);
1736 if (annotation.autoCalculated)
1738 // only write one non-null entry into the annotation row -
1739 // sufficient to get the visualization attributes necessary to
1747 an.setScoreOnly(true);
1749 if (!storeDS || (storeDS && !annotation.autoCalculated))
1751 // skip autocalculated annotation - these are only provided for
1753 vamsasSet.addAnnotation(an);
1759 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
1761 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
1762 if (settings != null)
1764 CalcIdParam vCalcIdParam = new CalcIdParam();
1765 vCalcIdParam.setCalcId(calcId);
1766 vCalcIdParam.addServiceURL(settings.getServiceURI());
1767 // generic URI allowing a third party to resolve another instance of the
1768 // service used for this calculation
1769 for (String urls : settings.getServiceURLs())
1771 vCalcIdParam.addServiceURL(urls);
1773 vCalcIdParam.setVersion("1.0");
1774 if (settings.getPreset() != null)
1776 WsParamSetI setting = settings.getPreset();
1777 vCalcIdParam.setName(setting.getName());
1778 vCalcIdParam.setDescription(setting.getDescription());
1782 vCalcIdParam.setName("");
1783 vCalcIdParam.setDescription("Last used parameters");
1785 // need to be able to recover 1) settings 2) user-defined presets or
1786 // recreate settings from preset 3) predefined settings provided by
1787 // service - or settings that can be transferred (or discarded)
1788 vCalcIdParam.setParameters(settings.getWsParamFile().replace("\n",
1790 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
1791 // todo - decide if updateImmediately is needed for any projects.
1793 return vCalcIdParam;
1798 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
1801 if (calcIdParam.getVersion().equals("1.0"))
1803 Jws2Instance service = Jws2Discoverer.getDiscoverer()
1804 .getPreferredServiceFor(calcIdParam.getServiceURL());
1805 if (service != null)
1807 WsParamSetI parmSet = null;
1810 parmSet = service.getParamStore().parseServiceParameterFile(
1811 calcIdParam.getName(), calcIdParam.getDescription(),
1812 calcIdParam.getServiceURL(),
1813 calcIdParam.getParameters().replace("|\\n|", "\n"));
1814 } catch (IOException x)
1816 warn("Couldn't parse parameter data for "
1817 + calcIdParam.getCalcId(), x);
1820 List<ArgumentI> argList = null;
1821 if (calcIdParam.getName().length() > 0)
1823 parmSet = service.getParamStore()
1824 .getPreset(calcIdParam.getName());
1825 if (parmSet != null)
1827 // TODO : check we have a good match with settings in AACon -
1828 // otherwise we'll need to create a new preset
1833 argList = parmSet.getArguments();
1836 AAConSettings settings = new AAConSettings(
1837 calcIdParam.isAutoUpdate(), service, parmSet, argList);
1838 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
1839 calcIdParam.isNeedsUpdate());
1844 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
1848 throw new Error(MessageManager.formatMessage(
1849 "error.unsupported_version_calcIdparam",
1850 new Object[] { calcIdParam.toString() }));
1854 * External mapping between jalview objects and objects yielding a valid and
1855 * unique object ID string. This is null for normal Jalview project IO, but
1856 * non-null when a jalview project is being read or written as part of a
1859 IdentityHashMap jv2vobj = null;
1862 * Construct a unique ID for jvobj using either existing bindings or if none
1863 * exist, the result of the hashcode call for the object.
1866 * jalview data object
1867 * @return unique ID for referring to jvobj
1869 private String makeHashCode(Object jvobj, String altCode)
1871 if (jv2vobj != null)
1873 Object id = jv2vobj.get(jvobj);
1876 return id.toString();
1878 // check string ID mappings
1879 if (jvids2vobj != null && jvobj instanceof String)
1881 id = jvids2vobj.get(jvobj);
1885 return id.toString();
1887 // give up and warn that something has gone wrong
1888 warn("Cannot find ID for object in external mapping : " + jvobj);
1894 * return local jalview object mapped to ID, if it exists
1898 * @return null or object bound to idcode
1900 private Object retrieveExistingObj(String idcode)
1902 if (idcode != null && vobj2jv != null)
1904 return vobj2jv.get(idcode);
1910 * binding from ID strings from external mapping table to jalview data model
1913 private Hashtable vobj2jv;
1915 private Sequence createVamsasSequence(String id, SequenceI jds)
1917 return createVamsasSequence(true, id, jds, null);
1920 private Sequence createVamsasSequence(boolean recurse, String id,
1921 SequenceI jds, SequenceI parentseq)
1923 Sequence vamsasSeq = new Sequence();
1924 vamsasSeq.setId(id);
1925 vamsasSeq.setName(jds.getName());
1926 vamsasSeq.setSequence(jds.getSequenceAsString());
1927 vamsasSeq.setDescription(jds.getDescription());
1928 jalview.datamodel.DBRefEntry[] dbrefs = null;
1929 if (jds.getDatasetSequence() != null)
1931 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
1932 if (jds.getDatasetSequence().getDBRefs() != null)
1934 dbrefs = jds.getDatasetSequence().getDBRefs();
1939 vamsasSeq.setDsseqid(id); // so we can tell which sequences really are
1940 // dataset sequences only
1941 dbrefs = jds.getDBRefs();
1945 for (int d = 0; d < dbrefs.length; d++)
1947 DBRef dbref = new DBRef();
1948 dbref.setSource(dbrefs[d].getSource());
1949 dbref.setVersion(dbrefs[d].getVersion());
1950 dbref.setAccessionId(dbrefs[d].getAccessionId());
1951 if (dbrefs[d].hasMap())
1953 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
1955 dbref.setMapping(mp);
1957 vamsasSeq.addDBRef(dbref);
1963 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
1964 SequenceI parentseq, SequenceI jds, boolean recurse)
1967 if (jmp.getMap() != null)
1971 jalview.util.MapList mlst = jmp.getMap();
1972 List<int[]> r = mlst.getFromRanges();
1973 for (int[] range : r)
1975 MapListFrom mfrom = new MapListFrom();
1976 mfrom.setStart(range[0]);
1977 mfrom.setEnd(range[1]);
1978 mp.addMapListFrom(mfrom);
1980 r = mlst.getToRanges();
1981 for (int[] range : r)
1983 MapListTo mto = new MapListTo();
1984 mto.setStart(range[0]);
1985 mto.setEnd(range[1]);
1986 mp.addMapListTo(mto);
1988 mp.setMapFromUnit(mlst.getFromRatio());
1989 mp.setMapToUnit(mlst.getToRatio());
1990 if (jmp.getTo() != null)
1992 MappingChoice mpc = new MappingChoice();
1994 && (parentseq != jmp.getTo() || parentseq
1995 .getDatasetSequence() != jmp.getTo()))
1997 mpc.setSequence(createVamsasSequence(false, seqHash(jmp.getTo()),
2003 SequenceI ps = null;
2004 if (parentseq != jmp.getTo()
2005 && parentseq.getDatasetSequence() != jmp.getTo())
2007 // chaining dbref rather than a handshaking one
2008 jmpid = seqHash(ps = jmp.getTo());
2012 jmpid = seqHash(ps = parentseq);
2014 mpc.setDseqFor(jmpid);
2015 if (!seqRefIds.containsKey(mpc.getDseqFor()))
2017 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2018 seqRefIds.put(mpc.getDseqFor(), ps);
2022 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2025 mp.setMappingChoice(mpc);
2031 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2032 List<UserColourScheme> userColours, JalviewModelSequence jms)
2035 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2036 boolean newucs = false;
2037 if (!userColours.contains(ucs))
2039 userColours.add(ucs);
2042 id = "ucs" + userColours.indexOf(ucs);
2045 // actually create the scheme's entry in the XML model
2046 java.awt.Color[] colours = ucs.getColours();
2047 jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
2048 jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
2050 for (int i = 0; i < colours.length; i++)
2052 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2053 col.setName(ResidueProperties.aa[i]);
2054 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2055 jbucs.addColour(col);
2057 if (ucs.getLowerCaseColours() != null)
2059 colours = ucs.getLowerCaseColours();
2060 for (int i = 0; i < colours.length; i++)
2062 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2063 col.setName(ResidueProperties.aa[i].toLowerCase());
2064 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2065 jbucs.addColour(col);
2070 uc.setUserColourScheme(jbucs);
2071 jms.addUserColours(uc);
2077 jalview.schemes.UserColourScheme getUserColourScheme(
2078 JalviewModelSequence jms, String id)
2080 UserColours[] uc = jms.getUserColours();
2081 UserColours colours = null;
2083 for (int i = 0; i < uc.length; i++)
2085 if (uc[i].getId().equals(id))
2093 java.awt.Color[] newColours = new java.awt.Color[24];
2095 for (int i = 0; i < 24; i++)
2097 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2098 .getUserColourScheme().getColour(i).getRGB(), 16));
2101 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2104 if (colours.getUserColourScheme().getColourCount() > 24)
2106 newColours = new java.awt.Color[23];
2107 for (int i = 0; i < 23; i++)
2109 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2110 .getUserColourScheme().getColour(i + 24).getRGB(), 16));
2112 ucs.setLowerCaseColours(newColours);
2119 * contains last error message (if any) encountered by XML loader.
2121 String errorMessage = null;
2124 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2125 * exceptions are raised during project XML parsing
2127 public boolean attemptversion1parse = true;
2130 * Load a jalview project archive from a jar file
2133 * - HTTP URL or filename
2135 public AlignFrame loadJalviewAlign(final String file)
2138 jalview.gui.AlignFrame af = null;
2142 // create list to store references for any new Jmol viewers created
2143 newStructureViewers = new Vector<JalviewStructureDisplayI>();
2144 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2145 // Workaround is to make sure caller implements the JarInputStreamProvider
2147 // so we can re-open the jar input stream for each entry.
2149 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2150 af = loadJalviewAlign(jprovider);
2152 } catch (MalformedURLException e)
2154 errorMessage = "Invalid URL format for '" + file + "'";
2160 SwingUtilities.invokeAndWait(new Runnable()
2165 setLoadingFinishedForNewStructureViewers();
2168 } catch (Exception x)
2170 System.err.println("Error loading alignment: " + x.getMessage());
2176 private jarInputStreamProvider createjarInputStreamProvider(
2177 final String file) throws MalformedURLException
2180 errorMessage = null;
2181 uniqueSetSuffix = null;
2183 viewportsAdded.clear();
2184 frefedSequence = null;
2186 if (file.startsWith("http://"))
2188 url = new URL(file);
2190 final URL _url = url;
2191 return new jarInputStreamProvider()
2195 public JarInputStream getJarInputStream() throws IOException
2199 return new JarInputStream(_url.openStream());
2203 return new JarInputStream(new FileInputStream(file));
2208 public String getFilename()
2216 * Recover jalview session from a jalview project archive. Caller may
2217 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2218 * themselves. Any null fields will be initialised with default values,
2219 * non-null fields are left alone.
2224 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2226 errorMessage = null;
2227 if (uniqueSetSuffix == null)
2229 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2231 if (seqRefIds == null)
2233 seqRefIds = new HashMap<String, SequenceI>();
2235 if (frefedSequence == null)
2237 frefedSequence = new Vector<Object[]>();
2240 AlignFrame af = null, _af = null;
2241 Map<String, AlignFrame> gatherToThisFrame = new HashMap<String, AlignFrame>();
2242 final String file = jprovider.getFilename();
2245 JarInputStream jin = null;
2246 JarEntry jarentry = null;
2251 jin = jprovider.getJarInputStream();
2252 for (int i = 0; i < entryCount; i++)
2254 jarentry = jin.getNextJarEntry();
2257 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2259 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2260 JalviewModel object = new JalviewModel();
2262 Unmarshaller unmar = new Unmarshaller(object);
2263 unmar.setValidation(false);
2264 object = (JalviewModel) unmar.unmarshal(in);
2265 if (true) // !skipViewport(object))
2267 _af = loadFromObject(object, file, true, jprovider);
2268 if (object.getJalviewModelSequence().getViewportCount() > 0)
2271 if (af.viewport.isGatherViewsHere())
2273 gatherToThisFrame.put(af.viewport.getSequenceSetId(), af);
2279 else if (jarentry != null)
2281 // Some other file here.
2284 } while (jarentry != null);
2285 resolveFrefedSequences();
2286 } catch (IOException ex)
2288 ex.printStackTrace();
2289 errorMessage = "Couldn't locate Jalview XML file : " + file;
2290 System.err.println("Exception whilst loading jalview XML file : "
2292 } catch (Exception ex)
2294 System.err.println("Parsing as Jalview Version 2 file failed.");
2295 ex.printStackTrace(System.err);
2296 if (attemptversion1parse)
2298 // Is Version 1 Jar file?
2301 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
2302 } catch (Exception ex2)
2304 System.err.println("Exception whilst loading as jalviewXMLV1:");
2305 ex2.printStackTrace();
2309 if (Desktop.instance != null)
2311 Desktop.instance.stopLoading();
2315 System.out.println("Successfully loaded archive file");
2318 ex.printStackTrace();
2320 System.err.println("Exception whilst loading jalview XML file : "
2322 } catch (OutOfMemoryError e)
2324 // Don't use the OOM Window here
2325 errorMessage = "Out of memory loading jalview XML file";
2326 System.err.println("Out of memory whilst loading jalview XML file");
2327 e.printStackTrace();
2330 if (Desktop.instance != null)
2332 Desktop.instance.stopLoading();
2336 * Regather multiple views (with the same sequence set id) to the frame (if
2337 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2338 * views instead of separate frames. Note this doesn't restore a state where
2339 * some expanded views in turn have tabbed views - the last "first tab" read
2340 * in will play the role of gatherer for all.
2342 for (AlignFrame fr : gatherToThisFrame.values())
2344 Desktop.instance.gatherViews(fr);
2347 restoreSplitFrames();
2349 if (errorMessage != null)
2357 * Try to reconstruct and display SplitFrame windows, where each contains
2358 * complementary dna and protein alignments. Done by pairing up AlignFrame
2359 * objects (created earlier) which have complementary viewport ids associated.
2361 protected void restoreSplitFrames()
2363 List<SplitFrame> gatherTo = new ArrayList<SplitFrame>();
2364 List<AlignFrame> addedToSplitFrames = new ArrayList<AlignFrame>();
2365 Map<String, AlignFrame> dna = new HashMap<String, AlignFrame>();
2368 * Identify the DNA alignments
2370 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2373 AlignFrame af = candidate.getValue();
2374 if (af.getViewport().getAlignment().isNucleotide())
2376 dna.put(candidate.getKey().getId(), af);
2381 * Try to match up the protein complements
2383 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2386 AlignFrame af = candidate.getValue();
2387 if (!af.getViewport().getAlignment().isNucleotide())
2389 String complementId = candidate.getKey().getComplementId();
2390 // only non-null complements should be in the Map
2391 if (complementId != null && dna.containsKey(complementId))
2393 final AlignFrame dnaFrame = dna.get(complementId);
2394 SplitFrame sf = createSplitFrame(dnaFrame, af);
2395 addedToSplitFrames.add(dnaFrame);
2396 addedToSplitFrames.add(af);
2397 if (af.viewport.isGatherViewsHere())
2406 * Open any that we failed to pair up (which shouldn't happen!) as
2407 * standalone AlignFrame's.
2409 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2412 AlignFrame af = candidate.getValue();
2413 if (!addedToSplitFrames.contains(af))
2415 Viewport view = candidate.getKey();
2416 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
2418 System.err.println("Failed to restore view " + view.getTitle()
2419 + " to split frame");
2424 * Gather back into tabbed views as flagged.
2426 for (SplitFrame sf : gatherTo)
2428 Desktop.instance.gatherViews(sf);
2431 splitFrameCandidates.clear();
2435 * Construct and display one SplitFrame holding DNA and protein alignments.
2438 * @param proteinFrame
2441 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
2442 AlignFrame proteinFrame)
2444 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
2445 String title = MessageManager.getString("label.linked_view_title");
2446 int width = (int) dnaFrame.getBounds().getWidth();
2447 int height = (int) (dnaFrame.getBounds().getHeight()
2448 + proteinFrame.getBounds().getHeight() + 50);
2451 * SplitFrame location is saved to both enclosed frames
2453 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
2454 Desktop.addInternalFrame(splitFrame, title, width, height);
2457 * And compute cDNA consensus (couldn't do earlier with consensus as
2458 * mappings were not yet present)
2460 proteinFrame.viewport.alignmentChanged(proteinFrame.alignPanel);
2466 * check errorMessage for a valid error message and raise an error box in the
2467 * GUI or write the current errorMessage to stderr and then clear the error
2470 protected void reportErrors()
2472 reportErrors(false);
2475 protected void reportErrors(final boolean saving)
2477 if (errorMessage != null)
2479 final String finalErrorMessage = errorMessage;
2482 javax.swing.SwingUtilities.invokeLater(new Runnable()
2487 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2488 finalErrorMessage, "Error "
2489 + (saving ? "saving" : "loading")
2490 + " Jalview file", JOptionPane.WARNING_MESSAGE);
2496 System.err.println("Problem loading Jalview file: " + errorMessage);
2499 errorMessage = null;
2502 Map<String, String> alreadyLoadedPDB = new HashMap<String, String>();
2505 * when set, local views will be updated from view stored in JalviewXML
2506 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2507 * sync if this is set to true.
2509 private final boolean updateLocalViews = false;
2512 * Returns the path to a temporary file holding the PDB file for the given PDB
2513 * id. The first time of asking, searches for a file of that name in the
2514 * Jalview project jar, and copies it to a new temporary file. Any repeat
2515 * requests just return the path to the file previously created.
2521 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId)
2523 if (alreadyLoadedPDB.containsKey(pdbId))
2525 return alreadyLoadedPDB.get(pdbId).toString();
2528 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb");
2529 if (tempFile != null)
2531 alreadyLoadedPDB.put(pdbId, tempFile);
2537 * Copies the jar entry of given name to a new temporary file and returns the
2538 * path to the file, or null if the entry is not found.
2541 * @param jarEntryName
2543 * a prefix for the temporary file name, must be at least three
2547 protected String copyJarEntry(jarInputStreamProvider jprovider,
2548 String jarEntryName, String prefix)
2550 BufferedReader in = null;
2551 PrintWriter out = null;
2555 JarInputStream jin = jprovider.getJarInputStream();
2557 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2558 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2559 * FileInputStream(jprovider)); }
2562 JarEntry entry = null;
2565 entry = jin.getNextJarEntry();
2566 } while (entry != null && !entry.getName().equals(jarEntryName));
2569 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
2570 File outFile = File.createTempFile(prefix, ".tmp");
2571 outFile.deleteOnExit();
2572 out = new PrintWriter(new FileOutputStream(outFile));
2575 while ((data = in.readLine()) != null)
2580 String t = outFile.getAbsolutePath();
2585 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
2587 } catch (Exception ex)
2589 ex.printStackTrace();
2597 } catch (IOException e)
2611 private class JvAnnotRow
2613 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2620 * persisted version of annotation row from which to take vis properties
2622 public jalview.datamodel.AlignmentAnnotation template;
2625 * original position of the annotation row in the alignment
2631 * Load alignment frame from jalview XML DOM object
2636 * filename source string
2637 * @param loadTreesAndStructures
2638 * when false only create Viewport
2640 * data source provider
2641 * @return alignment frame created from view stored in DOM
2643 AlignFrame loadFromObject(JalviewModel object, String file,
2644 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
2646 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
2647 Sequence[] vamsasSeq = vamsasSet.getSequence();
2649 JalviewModelSequence jms = object.getJalviewModelSequence();
2651 Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
2654 // ////////////////////////////////
2657 List<SequenceI> hiddenSeqs = null;
2658 jalview.datamodel.Sequence jseq;
2660 List<SequenceI> tmpseqs = new ArrayList<SequenceI>();
2662 boolean multipleView = false;
2664 JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
2665 int vi = 0; // counter in vamsasSeq array
2666 for (int i = 0; i < jseqs.length; i++)
2668 String seqId = jseqs[i].getId();
2670 if (seqRefIds.get(seqId) != null)
2672 tmpseqs.add(seqRefIds.get(seqId));
2673 multipleView = true;
2677 jseq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
2678 vamsasSeq[vi].getSequence());
2679 jseq.setDescription(vamsasSeq[vi].getDescription());
2680 jseq.setStart(jseqs[i].getStart());
2681 jseq.setEnd(jseqs[i].getEnd());
2682 jseq.setVamsasId(uniqueSetSuffix + seqId);
2683 seqRefIds.put(vamsasSeq[vi].getId(), jseq);
2688 if (jseqs[i].getHidden())
2690 if (hiddenSeqs == null)
2692 hiddenSeqs = new ArrayList<SequenceI>();
2695 hiddenSeqs.add(seqRefIds.get(seqId));
2701 // Create the alignment object from the sequence set
2702 // ///////////////////////////////
2703 SequenceI[] orderedSeqs = tmpseqs
2704 .toArray(new SequenceI[tmpseqs.size()]);
2706 Alignment al = new Alignment(orderedSeqs);
2708 // / Add the alignment properties
2709 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
2711 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
2712 al.setProperty(ssp.getKey(), ssp.getValue());
2716 // SequenceFeatures are added to the DatasetSequence,
2717 // so we must create or recover the dataset before loading features
2718 // ///////////////////////////////
2719 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
2721 // older jalview projects do not have a dataset id.
2722 al.setDataset(null);
2726 // recover dataset - passing on flag indicating if this a 'viewless'
2727 // sequence set (a.k.a. a stored dataset for the project)
2728 recoverDatasetFor(vamsasSet, al, object.getJalviewModelSequence()
2729 .getViewportCount() == 0);
2731 // ///////////////////////////////
2733 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
2736 // load sequence features, database references and any associated PDB
2737 // structures for the alignment
2738 for (int i = 0; i < vamsasSeq.length; i++)
2740 if (jseqs[i].getFeaturesCount() > 0)
2742 Features[] features = jseqs[i].getFeatures();
2743 for (int f = 0; f < features.length; f++)
2745 jalview.datamodel.SequenceFeature sf = new jalview.datamodel.SequenceFeature(
2746 features[f].getType(), features[f].getDescription(),
2747 features[f].getStatus(), features[f].getBegin(),
2748 features[f].getEnd(), features[f].getFeatureGroup());
2750 sf.setScore(features[f].getScore());
2751 for (int od = 0; od < features[f].getOtherDataCount(); od++)
2753 OtherData keyValue = features[f].getOtherData(od);
2754 if (keyValue.getKey().startsWith("LINK"))
2756 sf.addLink(keyValue.getValue());
2760 sf.setValue(keyValue.getKey(), keyValue.getValue());
2765 al.getSequenceAt(i).getDatasetSequence().addSequenceFeature(sf);
2768 if (vamsasSeq[i].getDBRefCount() > 0)
2770 addDBRefs(al.getSequenceAt(i).getDatasetSequence(), vamsasSeq[i]);
2772 if (jseqs[i].getPdbidsCount() > 0)
2774 Pdbids[] ids = jseqs[i].getPdbids();
2775 for (int p = 0; p < ids.length; p++)
2777 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
2778 entry.setId(ids[p].getId());
2779 if (ids[p].getType() != null)
2781 if (ids[p].getType().equalsIgnoreCase("PDB"))
2783 entry.setType(PDBEntry.Type.PDB);
2787 entry.setType(PDBEntry.Type.FILE);
2790 if (ids[p].getFile() != null)
2792 if (!pdbloaded.containsKey(ids[p].getFile()))
2794 entry.setFile(loadPDBFile(jprovider, ids[p].getId()));
2798 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
2801 StructureSelectionManager.getStructureSelectionManager(
2802 Desktop.instance).registerPDBEntry(entry);
2803 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
2807 } // end !multipleview
2809 // ///////////////////////////////
2810 // LOAD SEQUENCE MAPPINGS
2812 if (vamsasSet.getAlcodonFrameCount() > 0)
2814 // TODO Potentially this should only be done once for all views of an
2816 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
2817 for (int i = 0; i < alc.length; i++)
2819 AlignedCodonFrame cf = new AlignedCodonFrame();
2820 if (alc[i].getAlcodMapCount() > 0)
2822 AlcodMap[] maps = alc[i].getAlcodMap();
2823 for (int m = 0; m < maps.length; m++)
2825 SequenceI dnaseq = seqRefIds.get(maps[m].getDnasq());
2827 jalview.datamodel.Mapping mapping = null;
2828 // attach to dna sequence reference.
2829 if (maps[m].getMapping() != null)
2831 mapping = addMapping(maps[m].getMapping());
2833 if (dnaseq != null && mapping.getTo() != null)
2835 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
2840 frefedSequence.add(new Object[] { maps[m].getDnasq(), cf,
2845 al.addCodonFrame(cf);
2849 // ////////////////////////////////
2851 List<JvAnnotRow> autoAlan = new ArrayList<JvAnnotRow>();
2854 * store any annotations which forward reference a group's ID
2856 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<String, List<AlignmentAnnotation>>();
2858 if (vamsasSet.getAnnotationCount() > 0)
2860 Annotation[] an = vamsasSet.getAnnotation();
2862 for (int i = 0; i < an.length; i++)
2864 Annotation annotation = an[i];
2867 * test if annotation is automatically calculated for this view only
2869 boolean autoForView = false;
2870 if (annotation.getLabel().equals("Quality")
2871 || annotation.getLabel().equals("Conservation")
2872 || annotation.getLabel().equals("Consensus"))
2874 // Kludge for pre 2.5 projects which lacked the autocalculated flag
2876 if (!annotation.hasAutoCalculated())
2878 annotation.setAutoCalculated(true);
2882 || (annotation.hasAutoCalculated() && annotation
2883 .isAutoCalculated()))
2885 // remove ID - we don't recover annotation from other views for
2886 // view-specific annotation
2887 annotation.setId(null);
2890 // set visiblity for other annotation in this view
2891 String annotationId = annotation.getId();
2892 if (annotationId != null && annotationIds.containsKey(annotationId))
2894 AlignmentAnnotation jda = annotationIds.get(annotationId);
2895 // in principle Visible should always be true for annotation displayed
2896 // in multiple views
2897 if (annotation.hasVisible())
2899 jda.visible = annotation.getVisible();
2902 al.addAnnotation(jda);
2906 // Construct new annotation from model.
2907 AnnotationElement[] ae = annotation.getAnnotationElement();
2908 jalview.datamodel.Annotation[] anot = null;
2909 java.awt.Color firstColour = null;
2911 if (!annotation.getScoreOnly())
2913 anot = new jalview.datamodel.Annotation[al.getWidth()];
2914 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
2916 anpos = ae[aa].getPosition();
2918 if (anpos >= anot.length)
2923 anot[anpos] = new jalview.datamodel.Annotation(
2925 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
2926 (ae[aa].getSecondaryStructure() == null || ae[aa]
2927 .getSecondaryStructure().length() == 0) ? ' '
2928 : ae[aa].getSecondaryStructure().charAt(0),
2932 // JBPNote: Consider verifying dataflow for IO of secondary
2933 // structure annotation read from Stockholm files
2934 // this was added to try to ensure that
2935 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
2937 // anot[ae[aa].getPosition()].displayCharacter = "";
2939 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
2940 if (firstColour == null)
2942 firstColour = anot[anpos].colour;
2946 jalview.datamodel.AlignmentAnnotation jaa = null;
2948 if (annotation.getGraph())
2950 float llim = 0, hlim = 0;
2951 // if (autoForView || an[i].isAutoCalculated()) {
2954 jaa = new jalview.datamodel.AlignmentAnnotation(
2955 annotation.getLabel(), annotation.getDescription(), anot,
2956 llim, hlim, annotation.getGraphType());
2958 jaa.graphGroup = annotation.getGraphGroup();
2959 jaa._linecolour = firstColour;
2960 if (annotation.getThresholdLine() != null)
2962 jaa.setThreshold(new jalview.datamodel.GraphLine(annotation
2963 .getThresholdLine().getValue(), annotation
2964 .getThresholdLine().getLabel(), new java.awt.Color(
2965 annotation.getThresholdLine().getColour())));
2968 if (autoForView || annotation.isAutoCalculated())
2970 // Hardwire the symbol display line to ensure that labels for
2971 // histograms are displayed
2977 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
2978 an[i].getDescription(), anot);
2979 jaa._linecolour = firstColour;
2981 // register new annotation
2982 if (an[i].getId() != null)
2984 annotationIds.put(an[i].getId(), jaa);
2985 jaa.annotationId = an[i].getId();
2987 // recover sequence association
2988 String sequenceRef = an[i].getSequenceRef();
2989 if (sequenceRef != null)
2991 // from 2.9 sequenceRef is to sequence id (JAL-1781)
2992 SequenceI sequence = seqRefIds.get(sequenceRef);
2993 if (sequence == null)
2995 // in pre-2.9 projects sequence ref is to sequence name
2996 sequence = al.findName(sequenceRef);
2998 if (sequence != null)
3000 jaa.createSequenceMapping(sequence, 1, true);
3001 sequence.addAlignmentAnnotation(jaa);
3004 // and make a note of any group association
3005 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
3007 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3008 .get(an[i].getGroupRef());
3011 aal = new ArrayList<jalview.datamodel.AlignmentAnnotation>();
3012 groupAnnotRefs.put(an[i].getGroupRef(), aal);
3017 if (an[i].hasScore())
3019 jaa.setScore(an[i].getScore());
3021 if (an[i].hasVisible())
3023 jaa.visible = an[i].getVisible();
3026 if (an[i].hasCentreColLabels())
3028 jaa.centreColLabels = an[i].getCentreColLabels();
3031 if (an[i].hasScaleColLabels())
3033 jaa.scaleColLabel = an[i].getScaleColLabels();
3035 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
3037 // newer files have an 'autoCalculated' flag and store calculation
3038 // state in viewport properties
3039 jaa.autoCalculated = true; // means annotation will be marked for
3040 // update at end of load.
3042 if (an[i].hasGraphHeight())
3044 jaa.graphHeight = an[i].getGraphHeight();
3046 if (an[i].hasBelowAlignment())
3048 jaa.belowAlignment = an[i].isBelowAlignment();
3050 jaa.setCalcId(an[i].getCalcId());
3051 if (an[i].getPropertyCount() > 0)
3053 for (jalview.schemabinding.version2.Property prop : an[i]
3056 jaa.setProperty(prop.getName(), prop.getValue());
3059 if (jaa.autoCalculated)
3061 autoAlan.add(new JvAnnotRow(i, jaa));
3064 // if (!autoForView)
3066 // add autocalculated group annotation and any user created annotation
3068 al.addAnnotation(jaa);
3072 // ///////////////////////
3074 // Create alignment markup and styles for this view
3075 if (jms.getJGroupCount() > 0)
3077 JGroup[] groups = jms.getJGroup();
3078 boolean addAnnotSchemeGroup = false;
3079 for (int i = 0; i < groups.length; i++)
3081 JGroup jGroup = groups[i];
3082 ColourSchemeI cs = null;
3083 if (jGroup.getColour() != null)
3085 if (jGroup.getColour().startsWith("ucs"))
3087 cs = getUserColourScheme(jms, jGroup.getColour());
3089 else if (jGroup.getColour().equals("AnnotationColourGradient")
3090 && jGroup.getAnnotationColours() != null)
3092 addAnnotSchemeGroup = true;
3097 cs = ColourSchemeProperty.getColour(al, jGroup.getColour());
3102 cs.setThreshold(jGroup.getPidThreshold(), true);
3106 Vector<SequenceI> seqs = new Vector<SequenceI>();
3108 for (int s = 0; s < jGroup.getSeqCount(); s++)
3110 String seqId = jGroup.getSeq(s) + "";
3111 SequenceI ts = seqRefIds.get(seqId);
3115 seqs.addElement(ts);
3119 if (seqs.size() < 1)
3124 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3125 jGroup.getDisplayBoxes(), jGroup.getDisplayText(),
3126 jGroup.getColourText(), jGroup.getStart(), jGroup.getEnd());
3128 sg.setOutlineColour(new java.awt.Color(jGroup.getOutlineColour()));
3130 sg.textColour = new java.awt.Color(jGroup.getTextCol1());
3131 sg.textColour2 = new java.awt.Color(jGroup.getTextCol2());
3132 sg.setShowNonconserved(jGroup.hasShowUnconserved() ? jGroup
3133 .isShowUnconserved() : false);
3134 sg.thresholdTextColour = jGroup.getTextColThreshold();
3135 if (jGroup.hasShowConsensusHistogram())
3137 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3140 if (jGroup.hasShowSequenceLogo())
3142 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3144 if (jGroup.hasNormaliseSequenceLogo())
3146 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3148 if (jGroup.hasIgnoreGapsinConsensus())
3150 sg.setIgnoreGapsConsensus(jGroup.getIgnoreGapsinConsensus());
3152 if (jGroup.getConsThreshold() != 0)
3154 jalview.analysis.Conservation c = new jalview.analysis.Conservation(
3155 "All", ResidueProperties.propHash, 3,
3156 sg.getSequences(null), 0, sg.getWidth() - 1);
3158 c.verdict(false, 25);
3159 sg.cs.setConservation(c);
3162 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3164 // re-instate unique group/annotation row reference
3165 List<AlignmentAnnotation> jaal = groupAnnotRefs.get(jGroup
3169 for (AlignmentAnnotation jaa : jaal)
3172 if (jaa.autoCalculated)
3174 // match up and try to set group autocalc alignment row for this
3176 if (jaa.label.startsWith("Consensus for "))
3178 sg.setConsensus(jaa);
3180 // match up and try to set group autocalc alignment row for this
3182 if (jaa.label.startsWith("Conservation for "))
3184 sg.setConservationRow(jaa);
3191 if (addAnnotSchemeGroup)
3193 // reconstruct the annotation colourscheme
3194 sg.cs = constructAnnotationColour(jGroup.getAnnotationColours(),
3195 null, al, jms, false);
3201 // only dataset in this model, so just return.
3204 // ///////////////////////////////
3207 // If we just load in the same jar file again, the sequenceSetId
3208 // will be the same, and we end up with multiple references
3209 // to the same sequenceSet. We must modify this id on load
3210 // so that each load of the file gives a unique id
3211 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3212 String viewId = (view.getId() == null ? null : view.getId()
3214 AlignFrame af = null;
3215 AlignViewport av = null;
3216 // now check to see if we really need to create a new viewport.
3217 if (multipleView && viewportsAdded.size() == 0)
3219 // We recovered an alignment for which a viewport already exists.
3220 // TODO: fix up any settings necessary for overlaying stored state onto
3221 // state recovered from another document. (may not be necessary).
3222 // we may need a binding from a viewport in memory to one recovered from
3224 // and then recover its containing af to allow the settings to be applied.
3225 // TODO: fix for vamsas demo
3227 .println("About to recover a viewport for existing alignment: Sequence set ID is "
3229 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3230 if (seqsetobj != null)
3232 if (seqsetobj instanceof String)
3234 uniqueSeqSetId = (String) seqsetobj;
3236 .println("Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
3242 .println("Warning : Collision between sequence set ID string and existing jalview object mapping.");
3248 * indicate that annotation colours are applied across all groups (pre
3249 * Jalview 2.8.1 behaviour)
3251 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan(
3252 "2.8.1", object.getVersion());
3254 AlignmentPanel ap = null;
3255 boolean isnewview = true;
3258 // Check to see if this alignment already has a view id == viewId
3259 jalview.gui.AlignmentPanel views[] = Desktop
3260 .getAlignmentPanels(uniqueSeqSetId);
3261 if (views != null && views.length > 0)
3263 for (int v = 0; v < views.length; v++)
3265 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
3267 // recover the existing alignpanel, alignframe, viewport
3268 af = views[v].alignFrame;
3271 // TODO: could even skip resetting view settings if we don't want to
3272 // change the local settings from other jalview processes
3281 af = loadViewport(file, jseqs, hiddenSeqs, al, jms, view,
3282 uniqueSeqSetId, viewId, autoAlan);
3288 * Load any trees, PDB structures and viewers
3290 * Not done if flag is false (when this method is used for New View)
3292 if (loadTreesAndStructures)
3294 loadTrees(jms, view, af, av, ap);
3295 loadPDBStructures(jprovider, jseqs, af, ap);
3296 loadRnaViewers(jprovider, jseqs, ap);
3298 // and finally return.
3303 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
3304 * panel is restored from separate jar entries, two (gapped and trimmed) per
3305 * sequence and secondary structure.
3307 * Currently each viewer shows just one sequence and structure (gapped and
3308 * trimmed), however this method is designed to support multiple sequences or
3309 * structures in viewers if wanted in future.
3315 private void loadRnaViewers(jarInputStreamProvider jprovider,
3316 JSeq[] jseqs, AlignmentPanel ap)
3319 * scan the sequences for references to viewers; create each one the first
3320 * time it is referenced, add Rna models to existing viewers
3322 for (JSeq jseq : jseqs)
3324 for (int i = 0; i < jseq.getRnaViewerCount(); i++)
3326 RnaViewer viewer = jseq.getRnaViewer(i);
3327 AppVarna appVarna = findOrCreateVarnaViewer(viewer,
3328 uniqueSetSuffix, ap);
3330 for (int j = 0; j < viewer.getSecondaryStructureCount(); j++)
3332 SecondaryStructure ss = viewer.getSecondaryStructure(j);
3333 SequenceI seq = seqRefIds.get(jseq.getId());
3334 AlignmentAnnotation ann = this.annotationIds.get(ss
3335 .getAnnotationId());
3338 * add the structure to the Varna display (with session state copied
3339 * from the jar to a temporary file)
3341 boolean gapped = ss.isGapped();
3342 String rnaTitle = ss.getTitle();
3343 String sessionState = ss.getViewerState();
3344 String tempStateFile = copyJarEntry(jprovider, sessionState,
3346 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
3347 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
3349 appVarna.setInitialSelection(viewer.getSelectedRna());
3355 * Locate and return an already instantiated matching AppVarna, or create one
3359 * @param viewIdSuffix
3363 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
3364 String viewIdSuffix, AlignmentPanel ap)
3367 * on each load a suffix is appended to the saved viewId, to avoid conflicts
3368 * if load is repeated
3370 String postLoadId = viewer.getViewId() + viewIdSuffix;
3371 for (JInternalFrame frame : getAllFrames())
3373 if (frame instanceof AppVarna)
3375 AppVarna varna = (AppVarna) frame;
3376 if (postLoadId.equals(varna.getViewId()))
3378 // this viewer is already instantiated
3379 // could in future here add ap as another 'parent' of the
3380 // AppVarna window; currently just 1-to-many
3387 * viewer not found - make it
3389 RnaViewerModel model = new RnaViewerModel(postLoadId,
3390 viewer.getTitle(), viewer.getXpos(), viewer.getYpos(),
3391 viewer.getWidth(), viewer.getHeight(),
3392 viewer.getDividerLocation());
3393 AppVarna varna = new AppVarna(model, ap);
3399 * Load any saved trees
3407 protected void loadTrees(JalviewModelSequence jms, Viewport view,
3408 AlignFrame af, AlignViewport av, AlignmentPanel ap)
3410 // TODO result of automated refactoring - are all these parameters needed?
3413 for (int t = 0; t < jms.getTreeCount(); t++)
3416 Tree tree = jms.getTree(t);
3418 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
3421 tp = af.ShowNewickTree(
3422 new jalview.io.NewickFile(tree.getNewick()),
3423 tree.getTitle(), tree.getWidth(), tree.getHeight(),
3424 tree.getXpos(), tree.getYpos());
3425 if (tree.getId() != null)
3427 // perhaps bind the tree id to something ?
3432 // update local tree attributes ?
3433 // TODO: should check if tp has been manipulated by user - if so its
3434 // settings shouldn't be modified
3435 tp.setTitle(tree.getTitle());
3436 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(), tree
3437 .getWidth(), tree.getHeight()));
3438 tp.av = av; // af.viewport; // TODO: verify 'associate with all
3441 tp.treeCanvas.av = av; // af.viewport;
3442 tp.treeCanvas.ap = ap; // af.alignPanel;
3447 warn("There was a problem recovering stored Newick tree: \n"
3448 + tree.getNewick());
3452 tp.fitToWindow.setState(tree.getFitToWindow());
3453 tp.fitToWindow_actionPerformed(null);
3455 if (tree.getFontName() != null)
3457 tp.setTreeFont(new java.awt.Font(tree.getFontName(), tree
3458 .getFontStyle(), tree.getFontSize()));
3462 tp.setTreeFont(new java.awt.Font(view.getFontName(), view
3463 .getFontStyle(), tree.getFontSize()));
3466 tp.showPlaceholders(tree.getMarkUnlinked());
3467 tp.showBootstrap(tree.getShowBootstrap());
3468 tp.showDistances(tree.getShowDistances());
3470 tp.treeCanvas.threshold = tree.getThreshold();
3472 if (tree.getCurrentTree())
3474 af.viewport.setCurrentTree(tp.getTree());
3478 } catch (Exception ex)
3480 ex.printStackTrace();
3485 * Load and link any saved structure viewers.
3492 protected void loadPDBStructures(jarInputStreamProvider jprovider,
3493 JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
3496 * Run through all PDB ids on the alignment, and collect mappings between
3497 * distinct view ids and all sequences referring to that view.
3499 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<String, StructureViewerModel>();
3501 for (int i = 0; i < jseqs.length; i++)
3503 if (jseqs[i].getPdbidsCount() > 0)
3505 Pdbids[] ids = jseqs[i].getPdbids();
3506 for (int p = 0; p < ids.length; p++)
3508 final int structureStateCount = ids[p].getStructureStateCount();
3509 for (int s = 0; s < structureStateCount; s++)
3511 // check to see if we haven't already created this structure view
3512 final StructureState structureState = ids[p]
3513 .getStructureState(s);
3514 String sviewid = (structureState.getViewId() == null) ? null
3515 : structureState.getViewId() + uniqueSetSuffix;
3516 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
3517 // Originally : ids[p].getFile()
3518 // : TODO: verify external PDB file recovery still works in normal
3519 // jalview project load
3520 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId()));
3521 jpdb.setId(ids[p].getId());
3523 int x = structureState.getXpos();
3524 int y = structureState.getYpos();
3525 int width = structureState.getWidth();
3526 int height = structureState.getHeight();
3528 // Probably don't need to do this anymore...
3529 // Desktop.desktop.getComponentAt(x, y);
3530 // TODO: NOW: check that this recovers the PDB file correctly.
3531 String pdbFile = loadPDBFile(jprovider, ids[p].getId());
3532 jalview.datamodel.SequenceI seq = seqRefIds.get(jseqs[i]
3534 if (sviewid == null)
3536 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width
3539 if (!structureViewers.containsKey(sviewid))
3541 structureViewers.put(sviewid,
3542 new StructureViewerModel(x, y, width, height, false,
3543 false, true, structureState.getViewId(),
3544 structureState.getType()));
3545 // Legacy pre-2.7 conversion JAL-823 :
3546 // do not assume any view has to be linked for colour by
3550 // assemble String[] { pdb files }, String[] { id for each
3551 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3552 // seqs_file 2}, boolean[] {
3553 // linkAlignPanel,superposeWithAlignpanel}} from hash
3554 StructureViewerModel jmoldat = structureViewers.get(sviewid);
3555 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
3556 | (structureState.hasAlignwithAlignPanel() ? structureState
3557 .getAlignwithAlignPanel() : false));
3560 * Default colour by linked panel to false if not specified (e.g.
3561 * for pre-2.7 projects)
3563 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
3564 colourWithAlignPanel |= (structureState
3565 .hasColourwithAlignPanel() ? structureState
3566 .getColourwithAlignPanel() : false);
3567 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
3570 * Default colour by viewer to true if not specified (e.g. for
3573 boolean colourByViewer = jmoldat.isColourByViewer();
3574 colourByViewer &= structureState.hasColourByJmol() ? structureState
3575 .getColourByJmol() : true;
3576 jmoldat.setColourByViewer(colourByViewer);
3578 if (jmoldat.getStateData().length() < structureState
3579 .getContent().length())
3582 jmoldat.setStateData(structureState.getContent());
3585 if (ids[p].getFile() != null)
3587 File mapkey = new File(ids[p].getFile());
3588 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
3589 if (seqstrmaps == null)
3591 jmoldat.getFileData().put(
3593 seqstrmaps = jmoldat.new StructureData(pdbFile,
3596 if (!seqstrmaps.getSeqList().contains(seq))
3598 seqstrmaps.getSeqList().add(seq);
3604 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");
3611 // Instantiate the associated structure views
3612 for (Entry<String, StructureViewerModel> entry : structureViewers
3617 createOrLinkStructureViewer(entry, af, ap, jprovider);
3618 } catch (Exception e)
3620 System.err.println("Error loading structure viewer: "
3622 // failed - try the next one
3634 protected void createOrLinkStructureViewer(
3635 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3636 AlignmentPanel ap, jarInputStreamProvider jprovider)
3638 final StructureViewerModel stateData = viewerData.getValue();
3641 * Search for any viewer windows already open from other alignment views
3642 * that exactly match the stored structure state
3644 StructureViewerBase comp = findMatchingViewer(viewerData);
3648 linkStructureViewer(ap, comp, stateData);
3653 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
3654 * "viewer_"+stateData.viewId
3656 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
3658 createChimeraViewer(viewerData, af, jprovider);
3663 * else Jmol (if pre-2.9, stateData contains JMOL state string)
3665 createJmolViewer(viewerData, af, jprovider);
3670 * Create a new Chimera viewer.
3676 protected void createChimeraViewer(
3677 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3678 jarInputStreamProvider jprovider)
3680 StructureViewerModel data = viewerData.getValue();
3681 String chimeraSessionFile = data.getStateData();
3684 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
3686 * NB this is the 'saved' viewId as in the project file XML, _not_ the
3687 * 'uniquified' sviewid used to reconstruct the viewer here
3689 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
3690 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
3693 Set<Entry<File, StructureData>> fileData = data.getFileData()
3695 List<PDBEntry> pdbs = new ArrayList<PDBEntry>();
3696 List<SequenceI[]> allseqs = new ArrayList<SequenceI[]>();
3697 for (Entry<File, StructureData> pdb : fileData)
3699 String filePath = pdb.getValue().getFilePath();
3700 String pdbId = pdb.getValue().getPdbId();
3701 // pdbs.add(new PDBEntry(filePath, pdbId));
3702 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
3703 final List<SequenceI> seqList = pdb.getValue().getSeqList();
3704 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
3708 boolean colourByChimera = data.isColourByViewer();
3709 boolean colourBySequence = data.isColourWithAlignPanel();
3711 // TODO use StructureViewer as a factory here, see JAL-1761
3712 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
3713 final SequenceI[][] seqsArray = allseqs.toArray(new SequenceI[allseqs
3715 String newViewId = viewerData.getKey();
3717 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
3718 af.alignPanel, pdbArray, seqsArray, colourByChimera,
3719 colourBySequence, newViewId);
3720 cvf.setSize(data.getWidth(), data.getHeight());
3721 cvf.setLocation(data.getX(), data.getY());
3725 * Create a new Jmol window. First parse the Jmol state to translate filenames
3726 * loaded into the view, and record the order in which files are shown in the
3727 * Jmol view, so we can add the sequence mappings in same order.
3733 protected void createJmolViewer(
3734 final Entry<String, StructureViewerModel> viewerData,
3735 AlignFrame af, jarInputStreamProvider jprovider)
3737 final StructureViewerModel svattrib = viewerData.getValue();
3738 String state = svattrib.getStateData();
3741 * Pre-2.9: state element value is the Jmol state string
3743 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
3746 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
3748 state = readJarEntry(jprovider,
3749 getViewerJarEntryName(svattrib.getViewId()));
3752 List<String> pdbfilenames = new ArrayList<String>();
3753 List<SequenceI[]> seqmaps = new ArrayList<SequenceI[]>();
3754 List<String> pdbids = new ArrayList<String>();
3755 StringBuilder newFileLoc = new StringBuilder(64);
3756 int cp = 0, ncp, ecp;
3757 Map<File, StructureData> oldFiles = svattrib.getFileData();
3758 while ((ncp = state.indexOf("load ", cp)) > -1)
3762 // look for next filename in load statement
3763 newFileLoc.append(state.substring(cp,
3764 ncp = (state.indexOf("\"", ncp + 1) + 1)));
3765 String oldfilenam = state.substring(ncp,
3766 ecp = state.indexOf("\"", ncp));
3767 // recover the new mapping data for this old filename
3768 // have to normalize filename - since Jmol and jalview do
3770 // translation differently.
3771 StructureData filedat = oldFiles.get(new File(oldfilenam));
3772 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
3773 pdbfilenames.add(filedat.getFilePath());
3774 pdbids.add(filedat.getPdbId());
3775 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
3776 newFileLoc.append("\"");
3777 cp = ecp + 1; // advance beyond last \" and set cursor so we can
3778 // look for next file statement.
3779 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
3783 // just append rest of state
3784 newFileLoc.append(state.substring(cp));
3788 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
3789 newFileLoc = new StringBuilder(state);
3790 newFileLoc.append("; load append ");
3791 for (File id : oldFiles.keySet())
3793 // add this and any other pdb files that should be present in
3795 StructureData filedat = oldFiles.get(id);
3796 newFileLoc.append(filedat.getFilePath());
3797 pdbfilenames.add(filedat.getFilePath());
3798 pdbids.add(filedat.getPdbId());
3799 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
3800 newFileLoc.append(" \"");
3801 newFileLoc.append(filedat.getFilePath());
3802 newFileLoc.append("\"");
3805 newFileLoc.append(";");
3808 if (newFileLoc.length() == 0)
3812 int histbug = newFileLoc.indexOf("history = ");
3816 * change "history = [true|false];" to "history = [1|0];"
3819 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
3820 String val = (diff == -1) ? null : newFileLoc
3821 .substring(histbug, diff);
3822 if (val != null && val.length() >= 4)
3824 if (val.contains("e")) // eh? what can it be?
3826 if (val.trim().equals("true"))
3834 newFileLoc.replace(histbug, diff, val);
3839 final String[] pdbf = pdbfilenames.toArray(new String[pdbfilenames
3841 final String[] id = pdbids.toArray(new String[pdbids.size()]);
3842 final SequenceI[][] sq = seqmaps
3843 .toArray(new SequenceI[seqmaps.size()][]);
3844 final String fileloc = newFileLoc.toString();
3845 final String sviewid = viewerData.getKey();
3846 final AlignFrame alf = af;
3847 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
3848 svattrib.getWidth(), svattrib.getHeight());
3851 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
3856 JalviewStructureDisplayI sview = null;
3859 sview = new StructureViewer(alf.alignPanel
3860 .getStructureSelectionManager()).createView(
3861 StructureViewer.ViewerType.JMOL, pdbf, id, sq,
3862 alf.alignPanel, svattrib, fileloc, rect, sviewid);
3863 addNewStructureViewer(sview);
3864 } catch (OutOfMemoryError ex)
3866 new OOMWarning("restoring structure view for PDB id " + id,
3867 (OutOfMemoryError) ex.getCause());
3868 if (sview != null && sview.isVisible())
3870 sview.closeViewer(false);
3871 sview.setVisible(false);
3877 } catch (InvocationTargetException ex)
3879 warn("Unexpected error when opening Jmol view.", ex);
3881 } catch (InterruptedException e)
3883 // e.printStackTrace();
3889 * Generates a name for the entry in the project jar file to hold state
3890 * information for a structure viewer
3895 protected String getViewerJarEntryName(String viewId)
3897 return VIEWER_PREFIX + viewId;
3901 * Returns any open frame that matches given structure viewer data. The match
3902 * is based on the unique viewId, or (for older project versions) the frame's
3908 protected StructureViewerBase findMatchingViewer(
3909 Entry<String, StructureViewerModel> viewerData)
3911 final String sviewid = viewerData.getKey();
3912 final StructureViewerModel svattrib = viewerData.getValue();
3913 StructureViewerBase comp = null;
3914 JInternalFrame[] frames = getAllFrames();
3915 for (JInternalFrame frame : frames)
3917 if (frame instanceof StructureViewerBase)
3920 * Post jalview 2.4 schema includes structure view id
3923 && ((StructureViewerBase) frame).getViewId()
3926 comp = (StructureViewerBase) frame;
3927 break; // break added in 2.9
3930 * Otherwise test for matching position and size of viewer frame
3932 else if (frame.getX() == svattrib.getX()
3933 && frame.getY() == svattrib.getY()
3934 && frame.getHeight() == svattrib.getHeight()
3935 && frame.getWidth() == svattrib.getWidth())
3937 comp = (StructureViewerBase) frame;
3938 // no break in faint hope of an exact match on viewId
3946 * Link an AlignmentPanel to an existing structure viewer.
3951 * @param useinViewerSuperpos
3952 * @param usetoColourbyseq
3953 * @param viewerColouring
3955 protected void linkStructureViewer(AlignmentPanel ap,
3956 StructureViewerBase viewer, StructureViewerModel stateData)
3958 // NOTE: if the jalview project is part of a shared session then
3959 // view synchronization should/could be done here.
3961 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
3962 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
3963 final boolean viewerColouring = stateData.isColourByViewer();
3964 Map<File, StructureData> oldFiles = stateData.getFileData();
3967 * Add mapping for sequences in this view to an already open viewer
3969 final AAStructureBindingModel binding = viewer.getBinding();
3970 for (File id : oldFiles.keySet())
3972 // add this and any other pdb files that should be present in the
3974 StructureData filedat = oldFiles.get(id);
3975 String pdbFile = filedat.getFilePath();
3976 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
3977 binding.getSsm().setMapping(seq, null, pdbFile,
3978 jalview.io.AppletFormatAdapter.FILE);
3979 binding.addSequenceForStructFile(pdbFile, seq);
3981 // and add the AlignmentPanel's reference to the view panel
3982 viewer.addAlignmentPanel(ap);
3983 if (useinViewerSuperpos)
3985 viewer.useAlignmentPanelForSuperposition(ap);
3989 viewer.excludeAlignmentPanelForSuperposition(ap);
3991 if (usetoColourbyseq)
3993 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
3997 viewer.excludeAlignmentPanelForColourbyseq(ap);
4002 * Get all frames within the Desktop.
4006 protected JInternalFrame[] getAllFrames()
4008 JInternalFrame[] frames = null;
4009 // TODO is this necessary - is it safe - risk of hanging?
4014 frames = Desktop.desktop.getAllFrames();
4015 } catch (ArrayIndexOutOfBoundsException e)
4017 // occasional No such child exceptions are thrown here...
4021 } catch (InterruptedException f)
4025 } while (frames == null);
4030 * Answers true if 'version' is equal to or later than 'supported', where each
4031 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4032 * changes. Development and test values for 'version' are leniently treated
4036 * - minimum version we are comparing against
4038 * - version of data being processsed
4041 public static boolean isVersionStringLaterThan(String supported,
4044 if (supported == null || version == null
4045 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4046 || version.equalsIgnoreCase("Test")
4047 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4049 System.err.println("Assuming project file with "
4050 + (version == null ? "null" : version)
4051 + " is compatible with Jalview version " + supported);
4056 return StringUtils.compareVersions(version, supported, "b") >= 0;
4060 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4062 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4064 if (newStructureViewers != null)
4066 sview.getBinding().setFinishedLoadingFromArchive(false);
4067 newStructureViewers.add(sview);
4071 protected void setLoadingFinishedForNewStructureViewers()
4073 if (newStructureViewers != null)
4075 for (JalviewStructureDisplayI sview : newStructureViewers)
4077 sview.getBinding().setFinishedLoadingFromArchive(true);
4079 newStructureViewers.clear();
4080 newStructureViewers = null;
4084 AlignFrame loadViewport(String file, JSeq[] JSEQ,
4085 List<SequenceI> hiddenSeqs, Alignment al,
4086 JalviewModelSequence jms, Viewport view, String uniqueSeqSetId,
4087 String viewId, List<JvAnnotRow> autoAlan)
4089 AlignFrame af = null;
4090 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
4091 uniqueSeqSetId, viewId);
4093 af.setFileName(file, "Jalview");
4095 for (int i = 0; i < JSEQ.length; i++)
4097 af.viewport.setSequenceColour(af.viewport.getAlignment()
4098 .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour()));
4101 af.viewport.setGatherViewsHere(view.getGatheredViews());
4103 if (view.getSequenceSetId() != null)
4105 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4107 af.viewport.setSequenceSetId(uniqueSeqSetId);
4110 // propagate shared settings to this new view
4111 af.viewport.setHistoryList(av.getHistoryList());
4112 af.viewport.setRedoList(av.getRedoList());
4116 viewportsAdded.put(uniqueSeqSetId, af.viewport);
4118 // TODO: check if this method can be called repeatedly without
4119 // side-effects if alignpanel already registered.
4120 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4122 // apply Hidden regions to view.
4123 if (hiddenSeqs != null)
4125 for (int s = 0; s < JSEQ.length; s++)
4127 jalview.datamodel.SequenceGroup hidden = new jalview.datamodel.SequenceGroup();
4129 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
4132 al.getSequenceAt(JSEQ[s].getHiddenSequences(r)), false);
4134 af.viewport.hideRepSequences(al.getSequenceAt(s), hidden);
4137 // jalview.datamodel.SequenceI[] hseqs = new
4138 // jalview.datamodel.SequenceI[hiddenSeqs
4141 // for (int s = 0; s < hiddenSeqs.size(); s++)
4143 // hseqs[s] = (jalview.datamodel.SequenceI) hiddenSeqs.elementAt(s);
4146 SequenceI[] hseqs = hiddenSeqs.toArray(new SequenceI[hiddenSeqs
4148 af.viewport.hideSequence(hseqs);
4151 // recover view properties and display parameters
4152 if (view.getViewName() != null)
4154 af.viewport.viewName = view.getViewName();
4155 af.setInitialTabVisible();
4157 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
4160 af.viewport.setShowAnnotation(view.getShowAnnotation());
4161 af.viewport.setAbovePIDThreshold(view.getPidSelected());
4163 af.viewport.setColourText(view.getShowColourText());
4165 af.viewport.setConservationSelected(view.getConservationSelected());
4166 af.viewport.setShowJVSuffix(view.getShowFullId());
4167 af.viewport.setRightAlignIds(view.getRightAlignIds());
4168 af.viewport.setFont(
4169 new java.awt.Font(view.getFontName(), view.getFontStyle(), view
4170 .getFontSize()), true);
4171 ViewStyleI vs = af.viewport.getViewStyle();
4172 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
4173 af.viewport.setViewStyle(vs);
4174 // TODO: allow custom charWidth/Heights to be restored by updating them
4175 // after setting font - which means set above to false
4176 af.viewport.setRenderGaps(view.getRenderGaps());
4177 af.viewport.setWrapAlignment(view.getWrapAlignment());
4178 af.viewport.setShowAnnotation(view.getShowAnnotation());
4180 af.viewport.setShowBoxes(view.getShowBoxes());
4182 af.viewport.setShowText(view.getShowText());
4184 af.viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
4185 af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
4186 af.viewport.setThresholdTextColour(view.getTextColThreshold());
4187 af.viewport.setShowUnconserved(view.hasShowUnconserved() ? view
4188 .isShowUnconserved() : false);
4189 af.viewport.setStartRes(view.getStartRes());
4190 af.viewport.setStartSeq(view.getStartSeq());
4191 af.alignPanel.updateLayout();
4192 ColourSchemeI cs = null;
4193 // apply colourschemes
4194 if (view.getBgColour() != null)
4196 if (view.getBgColour().startsWith("ucs"))
4198 cs = getUserColourScheme(jms, view.getBgColour());
4200 else if (view.getBgColour().startsWith("Annotation"))
4202 AnnotationColours viewAnnColour = view.getAnnotationColours();
4203 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
4210 cs = ColourSchemeProperty.getColour(al, view.getBgColour());
4215 cs.setThreshold(view.getPidThreshold(), true);
4216 cs.setConsensus(af.viewport.getSequenceConsensusHash());
4220 af.viewport.setGlobalColourScheme(cs);
4221 af.viewport.setColourAppliesToAllGroups(false);
4223 if (view.getConservationSelected() && cs != null)
4225 cs.setConservationInc(view.getConsThreshold());
4228 af.changeColour(cs);
4230 af.viewport.setColourAppliesToAllGroups(true);
4232 af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures());
4234 if (view.hasCentreColumnLabels())
4236 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
4238 if (view.hasIgnoreGapsinConsensus())
4240 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
4243 if (view.hasFollowHighlight())
4245 af.viewport.setFollowHighlight(view.getFollowHighlight());
4247 if (view.hasFollowSelection())
4249 af.viewport.followSelection = view.getFollowSelection();
4251 if (view.hasShowConsensusHistogram())
4253 af.viewport.setShowConsensusHistogram(view
4254 .getShowConsensusHistogram());
4258 af.viewport.setShowConsensusHistogram(true);
4260 if (view.hasShowSequenceLogo())
4262 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
4266 af.viewport.setShowSequenceLogo(false);
4268 if (view.hasNormaliseSequenceLogo())
4270 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
4272 if (view.hasShowDbRefTooltip())
4274 af.viewport.setShowDBRefs(view.getShowDbRefTooltip());
4276 if (view.hasShowNPfeatureTooltip())
4278 af.viewport.setShowNPFeats(view.hasShowNPfeatureTooltip());
4280 if (view.hasShowGroupConsensus())
4282 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
4286 af.viewport.setShowGroupConsensus(false);
4288 if (view.hasShowGroupConservation())
4290 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
4294 af.viewport.setShowGroupConservation(false);
4297 // recover featre settings
4298 if (jms.getFeatureSettings() != null)
4300 FeaturesDisplayed fdi;
4301 af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
4302 String[] renderOrder = new String[jms.getFeatureSettings()
4303 .getSettingCount()];
4304 Hashtable featureGroups = new Hashtable();
4305 Hashtable featureColours = new Hashtable();
4306 Hashtable featureOrder = new Hashtable();
4308 for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
4310 Setting setting = jms.getFeatureSettings().getSetting(fs);
4311 if (setting.hasMincolour())
4313 GraduatedColor gc = setting.hasMin() ? new GraduatedColor(
4314 new java.awt.Color(setting.getMincolour()),
4315 new java.awt.Color(setting.getColour()),
4316 setting.getMin(), setting.getMax()) : new GraduatedColor(
4317 new java.awt.Color(setting.getMincolour()),
4318 new java.awt.Color(setting.getColour()), 0, 1);
4319 if (setting.hasThreshold())
4321 gc.setThresh(setting.getThreshold());
4322 gc.setThreshType(setting.getThreshstate());
4324 gc.setAutoScaled(true); // default
4325 if (setting.hasAutoScale())
4327 gc.setAutoScaled(setting.getAutoScale());
4329 if (setting.hasColourByLabel())
4331 gc.setColourByLabel(setting.getColourByLabel());
4333 // and put in the feature colour table.
4334 featureColours.put(setting.getType(), gc);
4338 featureColours.put(setting.getType(),
4339 new java.awt.Color(setting.getColour()));
4341 renderOrder[fs] = setting.getType();
4342 if (setting.hasOrder())
4344 featureOrder.put(setting.getType(), setting.getOrder());
4348 featureOrder.put(setting.getType(), new Float(fs
4349 / jms.getFeatureSettings().getSettingCount()));
4351 if (setting.getDisplay())
4353 fdi.setVisible(setting.getType());
4356 Hashtable fgtable = new Hashtable();
4357 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
4359 Group grp = jms.getFeatureSettings().getGroup(gs);
4360 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
4362 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4363 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
4364 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
4365 FeatureRendererSettings frs = new FeatureRendererSettings(
4366 renderOrder, fgtable, featureColours, 1.0f, featureOrder);
4367 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
4368 .transferSettings(frs);
4372 if (view.getHiddenColumnsCount() > 0)
4374 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
4376 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(), view
4377 .getHiddenColumns(c).getEnd() // +1
4381 if (view.getCalcIdParam() != null)
4383 for (CalcIdParam calcIdParam : view.getCalcIdParam())
4385 if (calcIdParam != null)
4387 if (recoverCalcIdParam(calcIdParam, af.viewport))
4392 warn("Couldn't recover parameters for "
4393 + calcIdParam.getCalcId());
4398 af.setMenusFromViewport(af.viewport);
4400 // TODO: we don't need to do this if the viewport is aready visible.
4402 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
4403 * has a 'cdna/protein complement' view, in which case save it in order to
4404 * populate a SplitFrame once all views have been read in.
4406 String complementaryViewId = view.getComplementId();
4407 if (complementaryViewId == null)
4409 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
4411 // recompute any autoannotation
4412 af.alignPanel.updateAnnotation(false, true);
4413 reorderAutoannotation(af, al, autoAlan);
4414 af.alignPanel.alignmentChanged();
4418 splitFrameCandidates.put(view, af);
4423 private ColourSchemeI constructAnnotationColour(
4424 AnnotationColours viewAnnColour, AlignFrame af, Alignment al,
4425 JalviewModelSequence jms, boolean checkGroupAnnColour)
4427 boolean propagateAnnColour = false;
4428 ColourSchemeI cs = null;
4429 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
4430 if (checkGroupAnnColour && al.getGroups() != null
4431 && al.getGroups().size() > 0)
4433 // pre 2.8.1 behaviour
4434 // check to see if we should transfer annotation colours
4435 propagateAnnColour = true;
4436 for (jalview.datamodel.SequenceGroup sg : al.getGroups())
4438 if (sg.cs instanceof AnnotationColourGradient)
4440 propagateAnnColour = false;
4444 // int find annotation
4445 if (annAlignment.getAlignmentAnnotation() != null)
4447 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
4449 if (annAlignment.getAlignmentAnnotation()[i].label
4450 .equals(viewAnnColour.getAnnotation()))
4452 if (annAlignment.getAlignmentAnnotation()[i].getThreshold() == null)
4454 annAlignment.getAlignmentAnnotation()[i]
4455 .setThreshold(new jalview.datamodel.GraphLine(
4456 viewAnnColour.getThreshold(), "Threshold",
4457 java.awt.Color.black)
4462 if (viewAnnColour.getColourScheme().equals("None"))
4464 cs = new AnnotationColourGradient(
4465 annAlignment.getAlignmentAnnotation()[i],
4466 new java.awt.Color(viewAnnColour.getMinColour()),
4467 new java.awt.Color(viewAnnColour.getMaxColour()),
4468 viewAnnColour.getAboveThreshold());
4470 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
4472 cs = new AnnotationColourGradient(
4473 annAlignment.getAlignmentAnnotation()[i],
4474 getUserColourScheme(jms,
4475 viewAnnColour.getColourScheme()),
4476 viewAnnColour.getAboveThreshold());
4480 cs = new AnnotationColourGradient(
4481 annAlignment.getAlignmentAnnotation()[i],
4482 ColourSchemeProperty.getColour(al,
4483 viewAnnColour.getColourScheme()),
4484 viewAnnColour.getAboveThreshold());
4486 if (viewAnnColour.hasPerSequence())
4488 ((AnnotationColourGradient) cs).setSeqAssociated(viewAnnColour
4491 if (viewAnnColour.hasPredefinedColours())
4493 ((AnnotationColourGradient) cs)
4494 .setPredefinedColours(viewAnnColour
4495 .isPredefinedColours());
4497 if (propagateAnnColour && al.getGroups() != null)
4499 // Also use these settings for all the groups
4500 for (int g = 0; g < al.getGroups().size(); g++)
4502 jalview.datamodel.SequenceGroup sg = al.getGroups().get(g);
4510 * if (viewAnnColour.getColourScheme().equals("None" )) { sg.cs =
4511 * new AnnotationColourGradient(
4512 * annAlignment.getAlignmentAnnotation()[i], new
4513 * java.awt.Color(viewAnnColour. getMinColour()), new
4514 * java.awt.Color(viewAnnColour. getMaxColour()),
4515 * viewAnnColour.getAboveThreshold()); } else
4518 sg.cs = new AnnotationColourGradient(
4519 annAlignment.getAlignmentAnnotation()[i], sg.cs,
4520 viewAnnColour.getAboveThreshold());
4521 if (cs instanceof AnnotationColourGradient)
4523 if (viewAnnColour.hasPerSequence())
4525 ((AnnotationColourGradient) cs)
4526 .setSeqAssociated(viewAnnColour.isPerSequence());
4528 if (viewAnnColour.hasPredefinedColours())
4530 ((AnnotationColourGradient) cs)
4531 .setPredefinedColours(viewAnnColour
4532 .isPredefinedColours());
4548 private void reorderAutoannotation(AlignFrame af, Alignment al,
4549 List<JvAnnotRow> autoAlan)
4551 // copy over visualization settings for autocalculated annotation in the
4553 if (al.getAlignmentAnnotation() != null)
4556 * Kludge for magic autoannotation names (see JAL-811)
4558 String[] magicNames = new String[] { "Consensus", "Quality",
4560 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
4561 Hashtable<String, JvAnnotRow> visan = new Hashtable<String, JvAnnotRow>();
4562 for (String nm : magicNames)
4564 visan.put(nm, nullAnnot);
4566 for (JvAnnotRow auan : autoAlan)
4568 visan.put(auan.template.label
4569 + (auan.template.getCalcId() == null ? "" : "\t"
4570 + auan.template.getCalcId()), auan);
4572 int hSize = al.getAlignmentAnnotation().length;
4573 List<JvAnnotRow> reorder = new ArrayList<JvAnnotRow>();
4574 // work through any autoCalculated annotation already on the view
4575 // removing it if it should be placed in a different location on the
4576 // annotation panel.
4577 List<String> remains = new ArrayList<String>(visan.keySet());
4578 for (int h = 0; h < hSize; h++)
4580 jalview.datamodel.AlignmentAnnotation jalan = al
4581 .getAlignmentAnnotation()[h];
4582 if (jalan.autoCalculated)
4585 JvAnnotRow valan = visan.get(k = jalan.label);
4586 if (jalan.getCalcId() != null)
4588 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
4593 // delete the auto calculated row from the alignment
4594 al.deleteAnnotation(jalan, false);
4598 if (valan != nullAnnot)
4600 if (jalan != valan.template)
4602 // newly created autoannotation row instance
4603 // so keep a reference to the visible annotation row
4604 // and copy over all relevant attributes
4605 if (valan.template.graphHeight >= 0)
4608 jalan.graphHeight = valan.template.graphHeight;
4610 jalan.visible = valan.template.visible;
4612 reorder.add(new JvAnnotRow(valan.order, jalan));
4617 // Add any (possibly stale) autocalculated rows that were not appended to
4618 // the view during construction
4619 for (String other : remains)
4621 JvAnnotRow othera = visan.get(other);
4622 if (othera != nullAnnot && othera.template.getCalcId() != null
4623 && othera.template.getCalcId().length() > 0)
4625 reorder.add(othera);
4628 // now put the automatic annotation in its correct place
4629 int s = 0, srt[] = new int[reorder.size()];
4630 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
4631 for (JvAnnotRow jvar : reorder)
4634 srt[s++] = jvar.order;
4637 jalview.util.QuickSort.sort(srt, rws);
4638 // and re-insert the annotation at its correct position
4639 for (JvAnnotRow jvar : rws)
4641 al.addAnnotation(jvar.template, jvar.order);
4643 af.alignPanel.adjustAnnotationHeight();
4647 Hashtable skipList = null;
4650 * TODO remove this method
4653 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
4654 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
4655 * throw new Error("Implementation Error. No skipList defined for this
4656 * Jalview2XML instance."); } return (AlignFrame)
4657 * skipList.get(view.getSequenceSetId()); }
4661 * Check if the Jalview view contained in object should be skipped or not.
4664 * @return true if view's sequenceSetId is a key in skipList
4666 private boolean skipViewport(JalviewModel object)
4668 if (skipList == null)
4673 if (skipList.containsKey(id = object.getJalviewModelSequence()
4674 .getViewport()[0].getSequenceSetId()))
4676 if (Cache.log != null && Cache.log.isDebugEnabled())
4678 Cache.log.debug("Skipping seuqence set id " + id);
4685 public void addToSkipList(AlignFrame af)
4687 if (skipList == null)
4689 skipList = new Hashtable();
4691 skipList.put(af.getViewport().getSequenceSetId(), af);
4694 public void clearSkipList()
4696 if (skipList != null)
4703 private void recoverDatasetFor(SequenceSet vamsasSet, Alignment al,
4704 boolean ignoreUnrefed)
4706 jalview.datamodel.Alignment ds = getDatasetFor(vamsasSet.getDatasetId());
4707 Vector dseqs = null;
4710 // create a list of new dataset sequences
4711 dseqs = new Vector();
4713 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
4715 Sequence vamsasSeq = vamsasSet.getSequence(i);
4716 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed);
4718 // create a new dataset
4721 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
4722 dseqs.copyInto(dsseqs);
4723 ds = new jalview.datamodel.Alignment(dsseqs);
4724 debug("Created new dataset " + vamsasSet.getDatasetId()
4725 + " for alignment " + System.identityHashCode(al));
4726 addDatasetRef(vamsasSet.getDatasetId(), ds);
4728 // set the dataset for the newly imported alignment.
4729 if (al.getDataset() == null && !ignoreUnrefed)
4738 * sequence definition to create/merge dataset sequence for
4742 * vector to add new dataset sequence to
4744 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
4745 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed)
4747 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
4749 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
4750 SequenceI dsq = null;
4751 if (sq != null && sq.getDatasetSequence() != null)
4753 dsq = sq.getDatasetSequence();
4755 if (sq == null && ignoreUnrefed)
4759 String sqid = vamsasSeq.getDsseqid();
4762 // need to create or add a new dataset sequence reference to this sequence
4765 dsq = seqRefIds.get(sqid);
4770 // make a new dataset sequence
4771 dsq = sq.createDatasetSequence();
4774 // make up a new dataset reference for this sequence
4775 sqid = seqHash(dsq);
4777 dsq.setVamsasId(uniqueSetSuffix + sqid);
4778 seqRefIds.put(sqid, dsq);
4783 dseqs.addElement(dsq);
4788 ds.addSequence(dsq);
4794 { // make this dataset sequence sq's dataset sequence
4795 sq.setDatasetSequence(dsq);
4796 // and update the current dataset alignment
4801 if (!dseqs.contains(dsq))
4808 if (ds.findIndex(dsq) < 0)
4810 ds.addSequence(dsq);
4817 // TODO: refactor this as a merge dataset sequence function
4818 // now check that sq (the dataset sequence) sequence really is the union of
4819 // all references to it
4820 // boolean pre = sq.getStart() < dsq.getStart();
4821 // boolean post = sq.getEnd() > dsq.getEnd();
4825 // StringBuffer sb = new StringBuffer();
4826 String newres = jalview.analysis.AlignSeq.extractGaps(
4827 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
4828 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
4829 && newres.length() > dsq.getLength())
4831 // Update with the longer sequence.
4835 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
4836 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
4837 * sb.append(newres.substring(newres.length() - sq.getEnd() -
4838 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
4840 dsq.setSequence(newres);
4842 // TODO: merges will never happen if we 'know' we have the real dataset
4843 // sequence - this should be detected when id==dssid
4845 .println("DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
4846 // + (pre ? "prepended" : "") + " "
4847 // + (post ? "appended" : ""));
4853 * TODO use AlignmentI here and in related methods - needs
4854 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
4856 Hashtable<String, Alignment> datasetIds = null;
4858 IdentityHashMap<Alignment, String> dataset2Ids = null;
4860 private Alignment getDatasetFor(String datasetId)
4862 if (datasetIds == null)
4864 datasetIds = new Hashtable<String, Alignment>();
4867 if (datasetIds.containsKey(datasetId))
4869 return datasetIds.get(datasetId);
4874 private void addDatasetRef(String datasetId, Alignment dataset)
4876 if (datasetIds == null)
4878 datasetIds = new Hashtable<String, Alignment>();
4880 datasetIds.put(datasetId, dataset);
4884 * make a new dataset ID for this jalview dataset alignment
4889 private String getDatasetIdRef(Alignment dataset)
4891 if (dataset.getDataset() != null)
4893 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
4895 String datasetId = makeHashCode(dataset, null);
4896 if (datasetId == null)
4898 // make a new datasetId and record it
4899 if (dataset2Ids == null)
4901 dataset2Ids = new IdentityHashMap<Alignment, String>();
4905 datasetId = dataset2Ids.get(dataset);
4907 if (datasetId == null)
4909 datasetId = "ds" + dataset2Ids.size() + 1;
4910 dataset2Ids.put(dataset, datasetId);
4916 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
4918 for (int d = 0; d < sequence.getDBRefCount(); d++)
4920 DBRef dr = sequence.getDBRef(d);
4921 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
4922 sequence.getDBRef(d).getSource(), sequence.getDBRef(d)
4923 .getVersion(), sequence.getDBRef(d).getAccessionId());
4924 if (dr.getMapping() != null)
4926 entry.setMap(addMapping(dr.getMapping()));
4928 datasetSequence.addDBRef(entry);
4932 private jalview.datamodel.Mapping addMapping(Mapping m)
4934 SequenceI dsto = null;
4935 // Mapping m = dr.getMapping();
4936 int fr[] = new int[m.getMapListFromCount() * 2];
4937 Enumeration f = m.enumerateMapListFrom();
4938 for (int _i = 0; f.hasMoreElements(); _i += 2)
4940 MapListFrom mf = (MapListFrom) f.nextElement();
4941 fr[_i] = mf.getStart();
4942 fr[_i + 1] = mf.getEnd();
4944 int fto[] = new int[m.getMapListToCount() * 2];
4945 f = m.enumerateMapListTo();
4946 for (int _i = 0; f.hasMoreElements(); _i += 2)
4948 MapListTo mf = (MapListTo) f.nextElement();
4949 fto[_i] = mf.getStart();
4950 fto[_i + 1] = mf.getEnd();
4952 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto,
4953 fr, fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
4954 if (m.getMappingChoice() != null)
4956 MappingChoice mc = m.getMappingChoice();
4957 if (mc.getDseqFor() != null)
4959 String dsfor = "" + mc.getDseqFor();
4960 if (seqRefIds.containsKey(dsfor))
4965 jmap.setTo(seqRefIds.get(dsfor));
4969 frefedSequence.add(new Object[] { dsfor, jmap });
4975 * local sequence definition
4977 Sequence ms = mc.getSequence();
4978 SequenceI djs = null;
4979 String sqid = ms.getDsseqid();
4980 if (sqid != null && sqid.length() > 0)
4983 * recover dataset sequence
4985 djs = seqRefIds.get(sqid);
4990 .println("Warning - making up dataset sequence id for DbRef sequence map reference");
4991 sqid = ((Object) ms).toString(); // make up a new hascode for
4992 // undefined dataset sequence hash
4993 // (unlikely to happen)
4999 * make a new dataset sequence and add it to refIds hash
5001 djs = new jalview.datamodel.Sequence(ms.getName(),
5003 djs.setStart(jmap.getMap().getToLowest());
5004 djs.setEnd(jmap.getMap().getToHighest());
5005 djs.setVamsasId(uniqueSetSuffix + sqid);
5007 seqRefIds.put(sqid, djs);
5010 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5019 public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
5020 boolean keepSeqRefs)
5023 JalviewModel jm = saveState(ap, null, null, null);
5028 jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
5032 uniqueSetSuffix = "";
5033 jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
5038 if (this.frefedSequence == null)
5040 frefedSequence = new Vector();
5043 viewportsAdded.clear();
5045 AlignFrame af = loadFromObject(jm, null, false, null);
5046 af.alignPanels.clear();
5047 af.closeMenuItem_actionPerformed(true);
5050 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5051 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5052 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5053 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5054 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5057 return af.alignPanel;
5061 * flag indicating if hashtables should be cleared on finalization TODO this
5062 * flag may not be necessary
5064 private final boolean _cleartables = true;
5066 private Hashtable jvids2vobj;
5071 * @see java.lang.Object#finalize()
5074 protected void finalize() throws Throwable
5076 // really make sure we have no buried refs left.
5081 this.seqRefIds = null;
5082 this.seqsToIds = null;
5086 private void warn(String msg)
5091 private void warn(String msg, Exception e)
5093 if (Cache.log != null)
5097 Cache.log.warn(msg, e);
5101 Cache.log.warn(msg);
5106 System.err.println("Warning: " + msg);
5109 e.printStackTrace();
5114 private void debug(String string)
5116 debug(string, null);
5119 private void debug(String msg, Exception e)
5121 if (Cache.log != null)
5125 Cache.log.debug(msg, e);
5129 Cache.log.debug(msg);
5134 System.err.println("Warning: " + msg);
5137 e.printStackTrace();
5143 * set the object to ID mapping tables used to write/recover objects and XML
5144 * ID strings for the jalview project. If external tables are provided then
5145 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
5146 * object goes out of scope. - also populates the datasetIds hashtable with
5147 * alignment objects containing dataset sequences
5150 * Map from ID strings to jalview datamodel
5152 * Map from jalview datamodel to ID strings
5156 public void setObjectMappingTables(Hashtable vobj2jv,
5157 IdentityHashMap jv2vobj)
5159 this.jv2vobj = jv2vobj;
5160 this.vobj2jv = vobj2jv;
5161 Iterator ds = jv2vobj.keySet().iterator();
5163 while (ds.hasNext())
5165 Object jvobj = ds.next();
5166 id = jv2vobj.get(jvobj).toString();
5167 if (jvobj instanceof jalview.datamodel.Alignment)
5169 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
5171 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
5174 else if (jvobj instanceof jalview.datamodel.Sequence)
5176 // register sequence object so the XML parser can recover it.
5177 if (seqRefIds == null)
5179 seqRefIds = new HashMap<String, SequenceI>();
5181 if (seqsToIds == null)
5183 seqsToIds = new IdentityHashMap<SequenceI, String>();
5185 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
5186 seqsToIds.put((SequenceI) jvobj, id);
5188 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
5191 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
5192 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
5193 if (jvann.annotationId == null)
5195 jvann.annotationId = anid;
5197 if (!jvann.annotationId.equals(anid))
5199 // TODO verify that this is the correct behaviour
5200 this.warn("Overriding Annotation ID for " + anid
5201 + " from different id : " + jvann.annotationId);
5202 jvann.annotationId = anid;
5205 else if (jvobj instanceof String)
5207 if (jvids2vobj == null)
5209 jvids2vobj = new Hashtable();
5210 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
5215 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
5221 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
5222 * objects created from the project archive. If string is null (default for
5223 * construction) then suffix will be set automatically.
5227 public void setUniqueSetSuffix(String string)
5229 uniqueSetSuffix = string;
5234 * uses skipList2 as the skipList for skipping views on sequence sets
5235 * associated with keys in the skipList
5239 public void setSkipList(Hashtable skipList2)
5241 skipList = skipList2;
5245 * Reads the jar entry of given name and returns its contents, or null if the
5246 * entry is not found.
5249 * @param jarEntryName
5252 protected String readJarEntry(jarInputStreamProvider jprovider,
5253 String jarEntryName)
5255 String result = null;
5256 BufferedReader in = null;
5261 * Reopen the jar input stream and traverse its entries to find a matching
5264 JarInputStream jin = jprovider.getJarInputStream();
5265 JarEntry entry = null;
5268 entry = jin.getNextJarEntry();
5269 } while (entry != null && !entry.getName().equals(jarEntryName));
5273 StringBuilder out = new StringBuilder(256);
5274 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
5277 while ((data = in.readLine()) != null)
5281 result = out.toString();
5285 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
5287 } catch (Exception ex)
5289 ex.printStackTrace();
5297 } catch (IOException e)
5308 * Returns an incrementing counter (0, 1, 2...)
5312 private synchronized int nextCounter()