2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
3 * Copyright (C) 2014 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.structures.JalviewStructureDisplayI;
24 import jalview.bin.Cache;
25 import jalview.datamodel.AlignedCodonFrame;
26 import jalview.datamodel.Alignment;
27 import jalview.datamodel.AlignmentAnnotation;
28 import jalview.datamodel.AlignmentI;
29 import jalview.datamodel.PDBEntry;
30 import jalview.datamodel.SequenceI;
31 import jalview.datamodel.StructureViewerModel;
32 import jalview.datamodel.StructureViewerModel.StructureData;
33 import jalview.schemabinding.version2.AlcodMap;
34 import jalview.schemabinding.version2.AlcodonFrame;
35 import jalview.schemabinding.version2.Annotation;
36 import jalview.schemabinding.version2.AnnotationColours;
37 import jalview.schemabinding.version2.AnnotationElement;
38 import jalview.schemabinding.version2.CalcIdParam;
39 import jalview.schemabinding.version2.DBRef;
40 import jalview.schemabinding.version2.Features;
41 import jalview.schemabinding.version2.Group;
42 import jalview.schemabinding.version2.HiddenColumns;
43 import jalview.schemabinding.version2.JGroup;
44 import jalview.schemabinding.version2.JSeq;
45 import jalview.schemabinding.version2.JalviewModel;
46 import jalview.schemabinding.version2.JalviewModelSequence;
47 import jalview.schemabinding.version2.MapListFrom;
48 import jalview.schemabinding.version2.MapListTo;
49 import jalview.schemabinding.version2.Mapping;
50 import jalview.schemabinding.version2.MappingChoice;
51 import jalview.schemabinding.version2.OtherData;
52 import jalview.schemabinding.version2.PdbentryItem;
53 import jalview.schemabinding.version2.Pdbids;
54 import jalview.schemabinding.version2.Property;
55 import jalview.schemabinding.version2.Sequence;
56 import jalview.schemabinding.version2.SequenceSet;
57 import jalview.schemabinding.version2.SequenceSetProperties;
58 import jalview.schemabinding.version2.Setting;
59 import jalview.schemabinding.version2.StructureState;
60 import jalview.schemabinding.version2.ThresholdLine;
61 import jalview.schemabinding.version2.Tree;
62 import jalview.schemabinding.version2.UserColours;
63 import jalview.schemabinding.version2.Viewport;
64 import jalview.schemes.AnnotationColourGradient;
65 import jalview.schemes.ColourSchemeI;
66 import jalview.schemes.ColourSchemeProperty;
67 import jalview.schemes.GraduatedColor;
68 import jalview.schemes.ResidueColourScheme;
69 import jalview.schemes.ResidueProperties;
70 import jalview.schemes.UserColourScheme;
71 import jalview.structure.StructureSelectionManager;
72 import jalview.structures.models.AAStructureBindingModel;
73 import jalview.util.MessageManager;
74 import jalview.util.Platform;
75 import jalview.util.jarInputStreamProvider;
76 import jalview.viewmodel.AlignmentViewport;
77 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
78 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
79 import jalview.ws.jws2.Jws2Discoverer;
80 import jalview.ws.jws2.dm.AAConSettings;
81 import jalview.ws.jws2.jabaws2.Jws2Instance;
82 import jalview.ws.params.ArgumentI;
83 import jalview.ws.params.AutoCalcSetting;
84 import jalview.ws.params.WsParamSetI;
86 import java.awt.Rectangle;
87 import java.io.BufferedReader;
88 import java.io.DataInputStream;
89 import java.io.DataOutputStream;
91 import java.io.FileInputStream;
92 import java.io.FileOutputStream;
93 import java.io.IOException;
94 import java.io.InputStreamReader;
95 import java.io.OutputStreamWriter;
96 import java.io.PrintWriter;
97 import java.lang.reflect.InvocationTargetException;
98 import java.net.MalformedURLException;
100 import java.util.ArrayList;
101 import java.util.Enumeration;
102 import java.util.HashMap;
103 import java.util.HashSet;
104 import java.util.Hashtable;
105 import java.util.IdentityHashMap;
106 import java.util.Iterator;
107 import java.util.LinkedHashMap;
108 import java.util.List;
109 import java.util.Map;
110 import java.util.Map.Entry;
111 import java.util.Set;
112 import java.util.StringTokenizer;
113 import java.util.Vector;
114 import java.util.jar.JarEntry;
115 import java.util.jar.JarInputStream;
116 import java.util.jar.JarOutputStream;
118 import javax.swing.JInternalFrame;
119 import javax.swing.JOptionPane;
120 import javax.swing.SwingUtilities;
122 import org.exolab.castor.xml.Unmarshaller;
125 * Write out the current jalview desktop state as a Jalview XML stream.
127 * Note: the vamsas objects referred to here are primitive versions of the
128 * VAMSAS project schema elements - they are not the same and most likely never
132 * @version $Revision: 1.134 $
134 public class Jalview2XML
137 * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
138 * of sequence objects are created.
140 IdentityHashMap<SequenceI, String> seqsToIds = null;
143 * jalview XML Sequence ID to jalview sequence object reference (both dataset
144 * and alignment sequences. Populated as XML reps of sequence objects are
147 Map<String, SequenceI> seqRefIds = null;
149 Vector frefedSequence = null;
151 boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
154 * Map of reconstructed AlignFrame objects that appear to have come from
155 * SplitFrame objects (have a dna/protein complement view).
157 private Map<Viewport, AlignFrame> splitFrameCandidates = new HashMap<Viewport, AlignFrame>();
160 * create/return unique hash string for sq
163 * @return new or existing unique string for sq
165 String seqHash(SequenceI sq)
167 if (seqsToIds == null)
171 if (seqsToIds.containsKey(sq))
173 return seqsToIds.get(sq);
177 // create sequential key
178 String key = "sq" + (seqsToIds.size() + 1);
179 key = makeHashCode(sq, key); // check we don't have an external reference
181 seqsToIds.put(sq, key);
190 if (seqRefIds != null)
194 if (seqsToIds != null)
204 warn("clearSeqRefs called when _cleartables was not set. Doing nothing.");
205 // seqRefIds = new Hashtable();
206 // seqsToIds = new IdentityHashMap();
212 if (seqsToIds == null)
214 seqsToIds = new IdentityHashMap<SequenceI, String>();
216 if (seqRefIds == null)
218 seqRefIds = new HashMap<String, SequenceI>();
226 public Jalview2XML(boolean raiseGUI)
228 this.raiseGUI = raiseGUI;
231 public void resolveFrefedSequences()
233 if (frefedSequence.size() > 0)
235 int r = 0, rSize = frefedSequence.size();
238 Object[] ref = (Object[]) frefedSequence.elementAt(r);
241 String sref = (String) ref[0];
242 if (seqRefIds.containsKey(sref))
244 if (ref[1] instanceof jalview.datamodel.Mapping)
246 SequenceI seq = seqRefIds.get(sref);
247 while (seq.getDatasetSequence() != null)
249 seq = seq.getDatasetSequence();
251 ((jalview.datamodel.Mapping) ref[1]).setTo(seq);
255 if (ref[1] instanceof jalview.datamodel.AlignedCodonFrame)
257 SequenceI seq = seqRefIds.get(sref);
258 while (seq.getDatasetSequence() != null)
260 seq = seq.getDatasetSequence();
263 && ref[2] instanceof jalview.datamodel.Mapping)
265 jalview.datamodel.Mapping mp = (jalview.datamodel.Mapping) ref[2];
266 ((jalview.datamodel.AlignedCodonFrame) ref[1]).addMap(
267 seq, mp.getTo(), mp.getMap());
272 .println("IMPLEMENTATION ERROR: Unimplemented forward sequence references for AlcodonFrames involving "
273 + ref[2].getClass() + " type objects.");
279 .println("IMPLEMENTATION ERROR: Unimplemented forward sequence references for "
280 + ref[1].getClass() + " type objects.");
283 frefedSequence.remove(r);
289 .println("IMPLEMENTATION WARNING: Unresolved forward reference for hash string "
291 + " with objecttype "
292 + ref[1].getClass());
299 frefedSequence.remove(r);
307 * This maintains a map of viewports, the key being the seqSetId. Important to
308 * set historyItem and redoList for multiple views
310 Map<String, AlignViewport> viewportsAdded = new HashMap<String, AlignViewport>();
312 Map<String, AlignmentAnnotation> annotationIds = new HashMap<String, AlignmentAnnotation>();
314 String uniqueSetSuffix = "";
317 * List of pdbfiles added to Jar
319 List<String> pdbfiles = null;
321 // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
322 public void saveState(File statefile)
324 FileOutputStream fos = null;
327 fos = new FileOutputStream(statefile);
328 JarOutputStream jout = new JarOutputStream(fos);
331 } catch (Exception e)
333 // TODO: inform user of the problem - they need to know if their data was
335 if (errorMessage == null)
337 errorMessage = "Couldn't write Jalview Archive to output file '"
338 + statefile + "' - See console error log for details";
342 errorMessage += "(output file was '" + statefile + "')";
352 } catch (IOException e)
362 * Writes a jalview project archive to the given Jar output stream.
366 public void saveState(JarOutputStream jout)
368 AlignFrame[] frames = Desktop.getAlignFrames(); // Desktop.desktop.getAllFrames();
375 Hashtable<String, AlignFrame> dsses = new Hashtable<String, AlignFrame>();
380 // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
381 // //////////////////////////////////////////////////
383 Vector shortNames = new Vector();
386 for (int i = frames.length - 1; i > -1; i--)
388 AlignFrame af = frames[i];
392 .containsKey(af.getViewport().getSequenceSetId()))
397 String shortName = af.getTitle();
399 if (shortName.indexOf(File.separatorChar) > -1)
401 shortName = shortName.substring(shortName
402 .lastIndexOf(File.separatorChar) + 1);
407 while (shortNames.contains(shortName))
409 if (shortName.endsWith("_" + (count - 1)))
411 shortName = shortName.substring(0, shortName.lastIndexOf("_"));
414 shortName = shortName.concat("_" + count);
418 shortNames.addElement(shortName);
420 if (!shortName.endsWith(".xml"))
422 shortName = shortName + ".xml";
425 int ap, apSize = af.alignPanels.size();
427 for (ap = 0; ap < apSize; ap++)
429 AlignmentPanel apanel = af.alignPanels.get(ap);
430 String fileName = apSize == 1 ? shortName : ap + shortName;
431 if (!fileName.endsWith(".xml"))
433 fileName = fileName + ".xml";
436 saveState(apanel, fileName, jout);
438 String dssid = getDatasetIdRef(af.getViewport().getAlignment()
440 if (!dsses.containsKey(dssid))
442 dsses.put(dssid, af);
447 writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix,
453 } catch (Exception foo)
458 } catch (Exception ex)
460 // TODO: inform user of the problem - they need to know if their data was
462 if (errorMessage == null)
464 errorMessage = "Couldn't write Jalview Archive - see error output for details";
466 ex.printStackTrace();
470 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
471 public boolean saveAlignment(AlignFrame af, String jarFile,
477 int apSize = af.alignPanels.size();
478 FileOutputStream fos = new FileOutputStream(jarFile);
479 JarOutputStream jout = new JarOutputStream(fos);
480 Hashtable<String, AlignFrame> dsses = new Hashtable<String, AlignFrame>();
481 for (AlignmentPanel apanel : af.alignPanels)
483 String jfileName = apSize == 1 ? fileName : fileName + ap;
485 if (!jfileName.endsWith(".xml"))
487 jfileName = jfileName + ".xml";
489 saveState(apanel, jfileName, jout);
490 String dssid = getDatasetIdRef(af.getViewport().getAlignment()
492 if (!dsses.containsKey(dssid))
494 dsses.put(dssid, af);
497 writeDatasetFor(dsses, fileName, jout);
501 } catch (Exception foo)
507 } catch (Exception ex)
509 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
510 ex.printStackTrace();
515 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
516 String fileName, JarOutputStream jout)
519 for (String dssids : dsses.keySet())
521 AlignFrame _af = dsses.get(dssids);
522 String jfileName = fileName + " Dataset for " + _af.getTitle();
523 if (!jfileName.endsWith(".xml"))
525 jfileName = jfileName + ".xml";
527 saveState(_af.alignPanel, jfileName, true, jout);
532 * create a JalviewModel from an alignment view and marshall it to a
536 * panel to create jalview model for
538 * name of alignment panel written to output stream
544 public JalviewModel saveState(AlignmentPanel ap, String fileName,
545 JarOutputStream jout)
547 return saveState(ap, fileName, false, jout);
551 * create a JalviewModel from an alignment view and marshall it to a
555 * panel to create jalview model for
557 * name of alignment panel written to output stream
559 * when true, only write the dataset for the alignment, not the data
560 * associated with the view.
566 public JalviewModel saveState(AlignmentPanel ap, String fileName,
567 boolean storeDS, JarOutputStream jout)
570 List<String> viewIds = new ArrayList<String>();
571 List<UserColourScheme> userColours = new ArrayList<UserColourScheme>();
573 AlignViewport av = ap.av;
575 JalviewModel object = new JalviewModel();
576 object.setVamsasModel(new jalview.schemabinding.version2.VamsasModel());
578 object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
579 object.setVersion(jalview.bin.Cache.getDefault("VERSION",
580 "Development Build"));
582 jalview.datamodel.AlignmentI jal = av.getAlignment();
584 if (av.hasHiddenRows())
586 jal = jal.getHiddenSequences().getFullAlignment();
589 SequenceSet vamsasSet = new SequenceSet();
591 JalviewModelSequence jms = new JalviewModelSequence();
593 vamsasSet.setGapChar(jal.getGapCharacter() + "");
595 if (jal.getDataset() != null)
597 // dataset id is the dataset's hashcode
598 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
601 // switch jal and the dataset
602 jal = jal.getDataset();
605 if (jal.getProperties() != null)
607 Enumeration en = jal.getProperties().keys();
608 while (en.hasMoreElements())
610 String key = en.nextElement().toString();
611 SequenceSetProperties ssp = new SequenceSetProperties();
613 ssp.setValue(jal.getProperties().get(key).toString());
614 vamsasSet.addSequenceSetProperties(ssp);
619 Set<String> calcIdSet = new HashSet<String>();
623 jalview.datamodel.SequenceI jds, jdatasq;
624 for (int i = 0; i < jal.getHeight(); i++)
626 jds = jal.getSequenceAt(i);
627 jdatasq = jds.getDatasetSequence() == null ? jds : jds
628 .getDatasetSequence();
631 if (seqRefIds.get(id) != null)
633 // This happens for two reasons: 1. multiple views are being serialised.
634 // 2. the hashCode has collided with another sequence's code. This DOES
635 // HAPPEN! (PF00072.15.stk does this)
636 // JBPNote: Uncomment to debug writing out of files that do not read
637 // back in due to ArrayOutOfBoundExceptions.
638 // System.err.println("vamsasSeq backref: "+id+"");
639 // System.err.println(jds.getName()+"
640 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
641 // System.err.println("Hashcode: "+seqHash(jds));
642 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
643 // System.err.println(rsq.getName()+"
644 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
645 // System.err.println("Hashcode: "+seqHash(rsq));
649 vamsasSeq = createVamsasSequence(id, jds);
650 vamsasSet.addSequence(vamsasSeq);
651 seqRefIds.put(id, jds);
655 jseq.setStart(jds.getStart());
656 jseq.setEnd(jds.getEnd());
657 jseq.setColour(av.getSequenceColour(jds).getRGB());
659 jseq.setId(id); // jseq id should be a string not a number
662 // Store any sequences this sequence represents
663 if (av.hasHiddenRows())
665 jseq.setHidden(av.getAlignment().getHiddenSequences()
668 if (av.isHiddenRepSequence(jal.getSequenceAt(i)))
670 jalview.datamodel.SequenceI[] reps = av
671 .getRepresentedSequences(jal.getSequenceAt(i))
672 .getSequencesInOrder(jal);
674 for (int h = 0; h < reps.length; h++)
676 if (reps[h] != jal.getSequenceAt(i))
678 jseq.addHiddenSequences(jal.findIndex(reps[h]));
685 if (jdatasq.getSequenceFeatures() != null)
687 jalview.datamodel.SequenceFeature[] sf = jdatasq
688 .getSequenceFeatures();
690 while (index < sf.length)
692 Features features = new Features();
694 features.setBegin(sf[index].getBegin());
695 features.setEnd(sf[index].getEnd());
696 features.setDescription(sf[index].getDescription());
697 features.setType(sf[index].getType());
698 features.setFeatureGroup(sf[index].getFeatureGroup());
699 features.setScore(sf[index].getScore());
700 if (sf[index].links != null)
702 for (int l = 0; l < sf[index].links.size(); l++)
704 OtherData keyValue = new OtherData();
705 keyValue.setKey("LINK_" + l);
706 keyValue.setValue(sf[index].links.elementAt(l).toString());
707 features.addOtherData(keyValue);
710 if (sf[index].otherDetails != null)
713 Enumeration keys = sf[index].otherDetails.keys();
714 while (keys.hasMoreElements())
716 key = keys.nextElement().toString();
717 OtherData keyValue = new OtherData();
718 keyValue.setKey(key);
719 keyValue.setValue(sf[index].otherDetails.get(key).toString());
720 features.addOtherData(keyValue);
724 jseq.addFeatures(features);
729 if (jdatasq.getPDBId() != null)
731 Enumeration en = jdatasq.getPDBId().elements();
732 while (en.hasMoreElements())
734 Pdbids pdb = new Pdbids();
735 jalview.datamodel.PDBEntry entry = (jalview.datamodel.PDBEntry) en
738 pdb.setId(entry.getId());
739 pdb.setType(entry.getType());
742 * Store any structure views associated with this sequence. This
743 * section copes with duplicate entries in the project, so a dataset
744 * only view *should* be coped with sensibly.
746 // This must have been loaded, is it still visible?
747 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
748 String matchedFile = null;
749 for (int f = frames.length - 1; f > -1; f--)
751 if (frames[f] instanceof StructureViewerBase)
753 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
754 matchedFile = saveStructureState(ap, jds, pdb, entry,
755 viewIds, matchedFile, viewFrame);
759 if (matchedFile != null || entry.getFile() != null)
761 if (entry.getFile() != null)
764 matchedFile = entry.getFile();
766 pdb.setFile(matchedFile); // entry.getFile());
767 if (pdbfiles == null)
769 pdbfiles = new ArrayList<String>();
772 if (!pdbfiles.contains(entry.getId()))
774 pdbfiles.add(entry.getId());
775 DataInputStream dis = null;
778 File file = new File(matchedFile);
779 if (file.exists() && jout != null)
781 byte[] data = new byte[(int) file.length()];
782 jout.putNextEntry(new JarEntry(entry.getId()));
783 dis = new DataInputStream(new FileInputStream(file));
786 DataOutputStream dout = new DataOutputStream(jout);
787 dout.write(data, 0, data.length);
791 } catch (Exception ex)
793 ex.printStackTrace();
801 } catch (IOException e)
811 if (entry.getProperty() != null)
813 PdbentryItem item = new PdbentryItem();
814 Hashtable properties = entry.getProperty();
815 Enumeration en2 = properties.keys();
816 while (en2.hasMoreElements())
818 Property prop = new Property();
819 String key = en2.nextElement().toString();
821 prop.setValue(properties.get(key).toString());
822 item.addProperty(prop);
824 pdb.addPdbentryItem(item);
834 if (!storeDS && av.hasHiddenRows())
836 jal = av.getAlignment();
839 if (jal.getCodonFrames() != null)
841 Set<AlignedCodonFrame> jac = jal.getCodonFrames();
842 for (AlignedCodonFrame acf : jac)
844 AlcodonFrame alc = new AlcodonFrame();
845 vamsasSet.addAlcodonFrame(alc);
846 if (acf.getProtMappings() != null
847 && acf.getProtMappings().length > 0)
849 SequenceI[] dnas = acf.getdnaSeqs();
850 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
851 for (int m = 0; m < pmaps.length; m++)
853 AlcodMap alcmap = new AlcodMap();
854 alcmap.setDnasq(seqHash(dnas[m]));
855 alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
857 alc.addAlcodMap(alcmap);
862 // AlcodonFrame alc = new AlcodonFrame();
863 // vamsasSet.addAlcodonFrame(alc);
864 // for (int p = 0; p < acf.aaWidth; p++)
866 // Alcodon cmap = new Alcodon();
867 // if (acf.codons[p] != null)
869 // // Null codons indicate a gapped column in the translated peptide
871 // cmap.setPos1(acf.codons[p][0]);
872 // cmap.setPos2(acf.codons[p][1]);
873 // cmap.setPos3(acf.codons[p][2]);
875 // alc.addAlcodon(cmap);
877 // if (acf.getProtMappings() != null
878 // && acf.getProtMappings().length > 0)
880 // SequenceI[] dnas = acf.getdnaSeqs();
881 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
882 // for (int m = 0; m < pmaps.length; m++)
884 // AlcodMap alcmap = new AlcodMap();
885 // alcmap.setDnasq(seqHash(dnas[m]));
886 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
888 // alc.addAlcodMap(alcmap);
895 // /////////////////////////////////
896 if (!storeDS && av.currentTree != null)
898 // FIND ANY ASSOCIATED TREES
899 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
900 if (Desktop.desktop != null)
902 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
904 for (int t = 0; t < frames.length; t++)
906 if (frames[t] instanceof TreePanel)
908 TreePanel tp = (TreePanel) frames[t];
910 if (tp.treeCanvas.av.getAlignment() == jal)
912 Tree tree = new Tree();
913 tree.setTitle(tp.getTitle());
914 tree.setCurrentTree((av.currentTree == tp.getTree()));
915 tree.setNewick(tp.getTree().toString());
916 tree.setThreshold(tp.treeCanvas.threshold);
918 tree.setFitToWindow(tp.fitToWindow.getState());
919 tree.setFontName(tp.getTreeFont().getName());
920 tree.setFontSize(tp.getTreeFont().getSize());
921 tree.setFontStyle(tp.getTreeFont().getStyle());
922 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
924 tree.setShowBootstrap(tp.bootstrapMenu.getState());
925 tree.setShowDistances(tp.distanceMenu.getState());
927 tree.setHeight(tp.getHeight());
928 tree.setWidth(tp.getWidth());
929 tree.setXpos(tp.getX());
930 tree.setYpos(tp.getY());
931 tree.setId(makeHashCode(tp, null));
940 * store forward refs from an annotationRow to any groups
942 IdentityHashMap groupRefs = new IdentityHashMap();
945 for (SequenceI sq : jal.getSequences())
947 // Store annotation on dataset sequences only
948 jalview.datamodel.AlignmentAnnotation[] aa = sq.getAnnotation();
949 if (aa != null && aa.length > 0)
951 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
958 if (jal.getAlignmentAnnotation() != null)
960 // Store the annotation shown on the alignment.
961 jalview.datamodel.AlignmentAnnotation[] aa = jal
962 .getAlignmentAnnotation();
963 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
968 if (jal.getGroups() != null)
970 JGroup[] groups = new JGroup[jal.getGroups().size()];
972 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
974 groups[++i] = new JGroup();
976 groups[i].setStart(sg.getStartRes());
977 groups[i].setEnd(sg.getEndRes());
978 groups[i].setName(sg.getName());
979 if (groupRefs.containsKey(sg))
981 // group has references so set it's ID field
982 groups[i].setId(groupRefs.get(sg).toString());
986 if (sg.cs.conservationApplied())
988 groups[i].setConsThreshold(sg.cs.getConservationInc());
990 if (sg.cs instanceof jalview.schemes.UserColourScheme)
992 groups[i].setColour(setUserColourScheme(sg.cs, userColours,
998 .setColour(ColourSchemeProperty.getColourName(sg.cs));
1001 else if (sg.cs instanceof jalview.schemes.AnnotationColourGradient)
1003 groups[i].setColour("AnnotationColourGradient");
1004 groups[i].setAnnotationColours(constructAnnotationColours(
1005 (jalview.schemes.AnnotationColourGradient) sg.cs,
1008 else if (sg.cs instanceof jalview.schemes.UserColourScheme)
1011 .setColour(setUserColourScheme(sg.cs, userColours, jms));
1015 groups[i].setColour(ColourSchemeProperty.getColourName(sg.cs));
1018 groups[i].setPidThreshold(sg.cs.getThreshold());
1021 groups[i].setOutlineColour(sg.getOutlineColour().getRGB());
1022 groups[i].setDisplayBoxes(sg.getDisplayBoxes());
1023 groups[i].setDisplayText(sg.getDisplayText());
1024 groups[i].setColourText(sg.getColourText());
1025 groups[i].setTextCol1(sg.textColour.getRGB());
1026 groups[i].setTextCol2(sg.textColour2.getRGB());
1027 groups[i].setTextColThreshold(sg.thresholdTextColour);
1028 groups[i].setShowUnconserved(sg.getShowNonconserved());
1029 groups[i].setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1030 groups[i].setShowConsensusHistogram(sg.isShowConsensusHistogram());
1031 groups[i].setShowSequenceLogo(sg.isShowSequenceLogo());
1032 groups[i].setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1033 for (int s = 0; s < sg.getSize(); s++)
1035 jalview.datamodel.Sequence seq = (jalview.datamodel.Sequence) sg
1037 groups[i].addSeq(seqHash(seq));
1041 jms.setJGroup(groups);
1045 // /////////SAVE VIEWPORT
1046 Viewport view = new Viewport();
1047 view.setTitle(ap.alignFrame.getTitle());
1048 view.setSequenceSetId(makeHashCode(av.getSequenceSetId(),
1049 av.getSequenceSetId()));
1050 view.setId(av.getViewId());
1051 if (av.getCodingComplement() != null)
1053 view.setComplementId(av.getCodingComplement().getViewId());
1055 view.setViewName(av.viewName);
1056 view.setGatheredViews(av.isGatherViewsHere());
1058 Rectangle position = ap.av.getExplodedGeometry();
1059 if (position != null)
1061 view.setXpos(position.x);
1062 view.setYpos(position.y);
1063 view.setWidth(position.width);
1064 view.setHeight(position.height);
1068 view.setXpos(ap.alignFrame.getBounds().x);
1069 view.setYpos(ap.alignFrame.getBounds().y);
1070 view.setWidth(ap.alignFrame.getBounds().width);
1071 view.setHeight(ap.alignFrame.getBounds().height);
1074 view.setStartRes(av.startRes);
1075 view.setStartSeq(av.startSeq);
1077 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1079 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1082 else if (av.getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1084 AnnotationColours ac = constructAnnotationColours(
1085 (jalview.schemes.AnnotationColourGradient) av
1086 .getGlobalColourScheme(),
1089 view.setAnnotationColours(ac);
1090 view.setBgColour("AnnotationColourGradient");
1094 view.setBgColour(ColourSchemeProperty.getColourName(av
1095 .getGlobalColourScheme()));
1098 ColourSchemeI cs = av.getGlobalColourScheme();
1102 if (cs.conservationApplied())
1104 view.setConsThreshold(cs.getConservationInc());
1105 if (cs instanceof jalview.schemes.UserColourScheme)
1107 view.setBgColour(setUserColourScheme(cs, userColours, jms));
1111 if (cs instanceof ResidueColourScheme)
1113 view.setPidThreshold(cs.getThreshold());
1117 view.setConservationSelected(av.getConservationSelected());
1118 view.setPidSelected(av.getAbovePIDThreshold());
1119 view.setFontName(av.font.getName());
1120 view.setFontSize(av.font.getSize());
1121 view.setFontStyle(av.font.getStyle());
1122 view.setRenderGaps(av.isRenderGaps());
1123 view.setShowAnnotation(av.isShowAnnotation());
1124 view.setShowBoxes(av.getShowBoxes());
1125 view.setShowColourText(av.getColourText());
1126 view.setShowFullId(av.getShowJVSuffix());
1127 view.setRightAlignIds(av.isRightAlignIds());
1128 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1129 view.setShowText(av.getShowText());
1130 view.setShowUnconserved(av.getShowUnconserved());
1131 view.setWrapAlignment(av.getWrapAlignment());
1132 view.setTextCol1(av.getTextColour().getRGB());
1133 view.setTextCol2(av.getTextColour2().getRGB());
1134 view.setTextColThreshold(av.getThresholdTextColour());
1135 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1136 view.setShowSequenceLogo(av.isShowSequenceLogo());
1137 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1138 view.setShowGroupConsensus(av.isShowGroupConsensus());
1139 view.setShowGroupConservation(av.isShowGroupConservation());
1140 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1141 view.setShowDbRefTooltip(av.isShowDBRefs());
1142 view.setFollowHighlight(av.followHighlight);
1143 view.setFollowSelection(av.followSelection);
1144 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1145 if (av.getFeaturesDisplayed() != null)
1147 jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
1149 String[] renderOrder = ap.getSeqPanel().seqCanvas
1150 .getFeatureRenderer().getRenderOrder()
1151 .toArray(new String[0]);
1153 Vector settingsAdded = new Vector();
1154 Object gstyle = null;
1155 GraduatedColor gcol = null;
1156 if (renderOrder != null)
1158 for (int ro = 0; ro < renderOrder.length; ro++)
1160 gstyle = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1161 .getFeatureStyle(renderOrder[ro]);
1162 Setting setting = new Setting();
1163 setting.setType(renderOrder[ro]);
1164 if (gstyle instanceof GraduatedColor)
1166 gcol = (GraduatedColor) gstyle;
1167 setting.setColour(gcol.getMaxColor().getRGB());
1168 setting.setMincolour(gcol.getMinColor().getRGB());
1169 setting.setMin(gcol.getMin());
1170 setting.setMax(gcol.getMax());
1171 setting.setColourByLabel(gcol.isColourByLabel());
1172 setting.setAutoScale(gcol.isAutoScale());
1173 setting.setThreshold(gcol.getThresh());
1174 setting.setThreshstate(gcol.getThreshType());
1178 setting.setColour(ap.getSeqPanel().seqCanvas
1179 .getFeatureRenderer()
1180 .getColour(renderOrder[ro]).getRGB());
1183 setting.setDisplay(av.getFeaturesDisplayed().isVisible(
1185 float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1186 .getOrder(renderOrder[ro]);
1189 setting.setOrder(rorder);
1191 fs.addSetting(setting);
1192 settingsAdded.addElement(renderOrder[ro]);
1196 // Make sure we save none displayed feature settings
1197 Iterator en = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1198 .getFeatureColours().keySet().iterator();
1199 while (en.hasNext())
1201 String key = en.next().toString();
1202 if (settingsAdded.contains(key))
1207 Setting setting = new Setting();
1208 setting.setType(key);
1209 setting.setColour(ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1210 .getColour(key).getRGB());
1212 setting.setDisplay(false);
1213 float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1217 setting.setOrder(rorder);
1219 fs.addSetting(setting);
1220 settingsAdded.addElement(key);
1222 // is groups actually supposed to be a map here ?
1223 en = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1224 .getFeatureGroups().iterator();
1225 Vector groupsAdded = new Vector();
1226 while (en.hasNext())
1228 String grp = en.next().toString();
1229 if (groupsAdded.contains(grp))
1233 Group g = new Group();
1235 g.setDisplay(((Boolean) ap.getSeqPanel().seqCanvas
1236 .getFeatureRenderer().checkGroupVisibility(grp, false))
1239 groupsAdded.addElement(grp);
1241 jms.setFeatureSettings(fs);
1245 if (av.hasHiddenColumns())
1247 if (av.getColumnSelection() == null
1248 || av.getColumnSelection().getHiddenColumns() == null)
1250 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1254 for (int c = 0; c < av.getColumnSelection().getHiddenColumns()
1257 int[] region = av.getColumnSelection().getHiddenColumns()
1259 HiddenColumns hc = new HiddenColumns();
1260 hc.setStart(region[0]);
1261 hc.setEnd(region[1]);
1262 view.addHiddenColumns(hc);
1266 if (calcIdSet.size() > 0)
1268 for (String calcId : calcIdSet)
1270 if (calcId.trim().length() > 0)
1272 CalcIdParam cidp = createCalcIdParam(calcId, av);
1273 // Some calcIds have no parameters.
1276 view.addCalcIdParam(cidp);
1282 jms.addViewport(view);
1284 object.setJalviewModelSequence(jms);
1285 object.getVamsasModel().addSequenceSet(vamsasSet);
1287 if (jout != null && fileName != null)
1289 // We may not want to write the object to disk,
1290 // eg we can copy the alignViewport to a new view object
1291 // using save and then load
1294 JarEntry entry = new JarEntry(fileName);
1295 jout.putNextEntry(entry);
1296 PrintWriter pout = new PrintWriter(new OutputStreamWriter(jout,
1298 org.exolab.castor.xml.Marshaller marshaller = new org.exolab.castor.xml.Marshaller(
1300 marshaller.marshal(object);
1303 } catch (Exception ex)
1305 // TODO: raise error in GUI if marshalling failed.
1306 ex.printStackTrace();
1313 * Save the state of a structure viewer
1318 * the archive XML element under which to save the state
1321 * @param matchedFile
1325 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
1326 Pdbids pdb, PDBEntry entry, List<String> viewIds,
1327 String matchedFile, StructureViewerBase viewFrame)
1329 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
1330 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
1332 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
1333 final String pdbId = pdbentry.getId();
1334 if (!pdbId.equals(entry.getId())
1335 && !(entry.getId().length() > 4 && entry.getId()
1336 .toLowerCase().startsWith(pdbId.toLowerCase())))
1340 if (matchedFile == null)
1342 matchedFile = pdbentry.getFile();
1344 else if (!matchedFile.equals(pdbentry.getFile()))
1347 .warn("Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
1348 + pdbentry.getFile());
1352 // can get at it if the ID
1353 // match is ambiguous (e.g.
1355 String statestring = viewFrame.getStateInfo();
1357 for (int smap = 0; smap < viewFrame.getBinding().getSequence()[peid].length; smap++)
1359 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
1360 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
1362 StructureState state = new StructureState();
1363 state.setVisible(true);
1364 state.setXpos(viewFrame.getX());
1365 state.setYpos(viewFrame.getY());
1366 state.setWidth(viewFrame.getWidth());
1367 state.setHeight(viewFrame.getHeight());
1368 final String viewId = viewFrame.getViewId();
1369 state.setViewId(viewId);
1370 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
1371 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
1372 state.setColourByJmol(viewFrame.isColouredByViewer());
1374 * Only store each structure viewer's state once in each XML document.
1376 if (!viewIds.contains(viewId))
1378 viewIds.add(viewId);
1379 state.setContent(statestring.replaceAll("\n", ""));
1383 state.setContent("# duplicate state");
1385 pdb.addStructureState(state);
1392 private AnnotationColours constructAnnotationColours(
1393 AnnotationColourGradient acg, List<UserColourScheme> userColours,
1394 JalviewModelSequence jms)
1396 AnnotationColours ac = new AnnotationColours();
1397 ac.setAboveThreshold(acg.getAboveThreshold());
1398 ac.setThreshold(acg.getAnnotationThreshold());
1399 ac.setAnnotation(acg.getAnnotation());
1400 if (acg.getBaseColour() instanceof jalview.schemes.UserColourScheme)
1402 ac.setColourScheme(setUserColourScheme(acg.getBaseColour(),
1407 ac.setColourScheme(ColourSchemeProperty.getColourName(acg
1411 ac.setMaxColour(acg.getMaxColour().getRGB());
1412 ac.setMinColour(acg.getMinColour().getRGB());
1413 ac.setPerSequence(acg.isSeqAssociated());
1414 ac.setPredefinedColours(acg.isPredefinedColours());
1418 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
1419 IdentityHashMap groupRefs, AlignmentViewport av,
1420 Set<String> calcIdSet, boolean storeDS, SequenceSet vamsasSet)
1423 for (int i = 0; i < aa.length; i++)
1425 Annotation an = new Annotation();
1427 if (aa[i].annotationId != null)
1429 annotationIds.put(aa[i].annotationId, aa[i]);
1432 an.setId(aa[i].annotationId);
1434 an.setVisible(aa[i].visible);
1436 an.setDescription(aa[i].description);
1438 if (aa[i].sequenceRef != null)
1440 // TODO later annotation sequenceRef should be the XML ID of the
1441 // sequence rather than its display name
1442 an.setSequenceRef(aa[i].sequenceRef.getName());
1444 if (aa[i].groupRef != null)
1446 Object groupIdr = groupRefs.get(aa[i].groupRef);
1447 if (groupIdr == null)
1449 // make a locally unique String
1450 groupRefs.put(aa[i].groupRef,
1451 groupIdr = ("" + System.currentTimeMillis()
1452 + aa[i].groupRef.getName() + groupRefs.size()));
1454 an.setGroupRef(groupIdr.toString());
1457 // store all visualization attributes for annotation
1458 an.setGraphHeight(aa[i].graphHeight);
1459 an.setCentreColLabels(aa[i].centreColLabels);
1460 an.setScaleColLabels(aa[i].scaleColLabel);
1461 an.setShowAllColLabels(aa[i].showAllColLabels);
1462 an.setBelowAlignment(aa[i].belowAlignment);
1464 if (aa[i].graph > 0)
1467 an.setGraphType(aa[i].graph);
1468 an.setGraphGroup(aa[i].graphGroup);
1469 if (aa[i].getThreshold() != null)
1471 ThresholdLine line = new ThresholdLine();
1472 line.setLabel(aa[i].getThreshold().label);
1473 line.setValue(aa[i].getThreshold().value);
1474 line.setColour(aa[i].getThreshold().colour.getRGB());
1475 an.setThresholdLine(line);
1483 an.setLabel(aa[i].label);
1485 if (aa[i] == av.getAlignmentQualityAnnot()
1486 || aa[i] == av.getAlignmentConservationAnnotation()
1487 || aa[i] == av.getAlignmentConsensusAnnotation()
1488 || aa[i].autoCalculated)
1490 // new way of indicating autocalculated annotation -
1491 an.setAutoCalculated(aa[i].autoCalculated);
1493 if (aa[i].hasScore())
1495 an.setScore(aa[i].getScore());
1498 if (aa[i].getCalcId() != null)
1500 calcIdSet.add(aa[i].getCalcId());
1501 an.setCalcId(aa[i].getCalcId());
1503 if (aa[i].hasProperties())
1505 for (String pr : aa[i].getProperties())
1507 Property prop = new Property();
1509 prop.setValue(aa[i].getProperty(pr));
1510 an.addProperty(prop);
1514 AnnotationElement ae;
1515 if (aa[i].annotations != null)
1517 an.setScoreOnly(false);
1518 for (int a = 0; a < aa[i].annotations.length; a++)
1520 if ((aa[i] == null) || (aa[i].annotations[a] == null))
1525 ae = new AnnotationElement();
1526 if (aa[i].annotations[a].description != null)
1528 ae.setDescription(aa[i].annotations[a].description);
1530 if (aa[i].annotations[a].displayCharacter != null)
1532 ae.setDisplayCharacter(aa[i].annotations[a].displayCharacter);
1535 if (!Float.isNaN(aa[i].annotations[a].value))
1537 ae.setValue(aa[i].annotations[a].value);
1541 if (aa[i].annotations[a].secondaryStructure > ' ')
1543 ae.setSecondaryStructure(aa[i].annotations[a].secondaryStructure
1547 if (aa[i].annotations[a].colour != null
1548 && aa[i].annotations[a].colour != java.awt.Color.black)
1550 ae.setColour(aa[i].annotations[a].colour.getRGB());
1553 an.addAnnotationElement(ae);
1554 if (aa[i].autoCalculated)
1556 // only write one non-null entry into the annotation row -
1557 // sufficient to get the visualization attributes necessary to
1565 an.setScoreOnly(true);
1567 if (!storeDS || (storeDS && !aa[i].autoCalculated))
1569 // skip autocalculated annotation - these are only provided for
1571 vamsasSet.addAnnotation(an);
1577 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
1579 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
1580 if (settings != null)
1582 CalcIdParam vCalcIdParam = new CalcIdParam();
1583 vCalcIdParam.setCalcId(calcId);
1584 vCalcIdParam.addServiceURL(settings.getServiceURI());
1585 // generic URI allowing a third party to resolve another instance of the
1586 // service used for this calculation
1587 for (String urls : settings.getServiceURLs())
1589 vCalcIdParam.addServiceURL(urls);
1591 vCalcIdParam.setVersion("1.0");
1592 if (settings.getPreset() != null)
1594 WsParamSetI setting = settings.getPreset();
1595 vCalcIdParam.setName(setting.getName());
1596 vCalcIdParam.setDescription(setting.getDescription());
1600 vCalcIdParam.setName("");
1601 vCalcIdParam.setDescription("Last used parameters");
1603 // need to be able to recover 1) settings 2) user-defined presets or
1604 // recreate settings from preset 3) predefined settings provided by
1605 // service - or settings that can be transferred (or discarded)
1606 vCalcIdParam.setParameters(settings.getWsParamFile().replace("\n",
1608 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
1609 // todo - decide if updateImmediately is needed for any projects.
1611 return vCalcIdParam;
1616 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
1619 if (calcIdParam.getVersion().equals("1.0"))
1621 Jws2Instance service = Jws2Discoverer.getDiscoverer()
1622 .getPreferredServiceFor(calcIdParam.getServiceURL());
1623 if (service != null)
1625 WsParamSetI parmSet = null;
1628 parmSet = service.getParamStore().parseServiceParameterFile(
1629 calcIdParam.getName(), calcIdParam.getDescription(),
1630 calcIdParam.getServiceURL(),
1631 calcIdParam.getParameters().replace("|\\n|", "\n"));
1632 } catch (IOException x)
1634 warn("Couldn't parse parameter data for "
1635 + calcIdParam.getCalcId(), x);
1638 List<ArgumentI> argList = null;
1639 if (calcIdParam.getName().length() > 0)
1641 parmSet = service.getParamStore()
1642 .getPreset(calcIdParam.getName());
1643 if (parmSet != null)
1645 // TODO : check we have a good match with settings in AACon -
1646 // otherwise we'll need to create a new preset
1651 argList = parmSet.getArguments();
1654 AAConSettings settings = new AAConSettings(
1655 calcIdParam.isAutoUpdate(), service, parmSet, argList);
1656 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
1657 calcIdParam.isNeedsUpdate());
1662 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
1666 throw new Error(MessageManager.formatMessage(
1667 "error.unsupported_version_calcIdparam", new Object[]
1668 { calcIdParam.toString() }));
1672 * External mapping between jalview objects and objects yielding a valid and
1673 * unique object ID string. This is null for normal Jalview project IO, but
1674 * non-null when a jalview project is being read or written as part of a
1677 IdentityHashMap jv2vobj = null;
1680 * Construct a unique ID for jvobj using either existing bindings or if none
1681 * exist, the result of the hashcode call for the object.
1684 * jalview data object
1685 * @return unique ID for referring to jvobj
1687 private String makeHashCode(Object jvobj, String altCode)
1689 if (jv2vobj != null)
1691 Object id = jv2vobj.get(jvobj);
1694 return id.toString();
1696 // check string ID mappings
1697 if (jvids2vobj != null && jvobj instanceof String)
1699 id = jvids2vobj.get(jvobj);
1703 return id.toString();
1705 // give up and warn that something has gone wrong
1706 warn("Cannot find ID for object in external mapping : " + jvobj);
1712 * return local jalview object mapped to ID, if it exists
1716 * @return null or object bound to idcode
1718 private Object retrieveExistingObj(String idcode)
1720 if (idcode != null && vobj2jv != null)
1722 return vobj2jv.get(idcode);
1728 * binding from ID strings from external mapping table to jalview data model
1731 private Hashtable vobj2jv;
1733 private Sequence createVamsasSequence(String id, SequenceI jds)
1735 return createVamsasSequence(true, id, jds, null);
1738 private Sequence createVamsasSequence(boolean recurse, String id,
1739 SequenceI jds, SequenceI parentseq)
1741 Sequence vamsasSeq = new Sequence();
1742 vamsasSeq.setId(id);
1743 vamsasSeq.setName(jds.getName());
1744 vamsasSeq.setSequence(jds.getSequenceAsString());
1745 vamsasSeq.setDescription(jds.getDescription());
1746 jalview.datamodel.DBRefEntry[] dbrefs = null;
1747 if (jds.getDatasetSequence() != null)
1749 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
1750 if (jds.getDatasetSequence().getDBRef() != null)
1752 dbrefs = jds.getDatasetSequence().getDBRef();
1757 vamsasSeq.setDsseqid(id); // so we can tell which sequences really are
1758 // dataset sequences only
1759 dbrefs = jds.getDBRef();
1763 for (int d = 0; d < dbrefs.length; d++)
1765 DBRef dbref = new DBRef();
1766 dbref.setSource(dbrefs[d].getSource());
1767 dbref.setVersion(dbrefs[d].getVersion());
1768 dbref.setAccessionId(dbrefs[d].getAccessionId());
1769 if (dbrefs[d].hasMap())
1771 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
1773 dbref.setMapping(mp);
1775 vamsasSeq.addDBRef(dbref);
1781 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
1782 SequenceI parentseq, SequenceI jds, boolean recurse)
1785 if (jmp.getMap() != null)
1789 jalview.util.MapList mlst = jmp.getMap();
1790 int r[] = mlst.getFromRanges();
1791 for (int s = 0; s < r.length; s += 2)
1793 MapListFrom mfrom = new MapListFrom();
1794 mfrom.setStart(r[s]);
1795 mfrom.setEnd(r[s + 1]);
1796 mp.addMapListFrom(mfrom);
1798 r = mlst.getToRanges();
1799 for (int s = 0; s < r.length; s += 2)
1801 MapListTo mto = new MapListTo();
1803 mto.setEnd(r[s + 1]);
1804 mp.addMapListTo(mto);
1806 mp.setMapFromUnit(mlst.getFromRatio());
1807 mp.setMapToUnit(mlst.getToRatio());
1808 if (jmp.getTo() != null)
1810 MappingChoice mpc = new MappingChoice();
1812 && (parentseq != jmp.getTo() || parentseq
1813 .getDatasetSequence() != jmp.getTo()))
1815 mpc.setSequence(createVamsasSequence(false, seqHash(jmp.getTo()),
1821 SequenceI ps = null;
1822 if (parentseq != jmp.getTo()
1823 && parentseq.getDatasetSequence() != jmp.getTo())
1825 // chaining dbref rather than a handshaking one
1826 jmpid = seqHash(ps = jmp.getTo());
1830 jmpid = seqHash(ps = parentseq);
1832 mpc.setDseqFor(jmpid);
1833 if (!seqRefIds.containsKey(mpc.getDseqFor()))
1835 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
1836 seqRefIds.put(mpc.getDseqFor(), ps);
1840 jalview.bin.Cache.log.debug("reusing DseqFor ID");
1843 mp.setMappingChoice(mpc);
1849 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
1850 List<UserColourScheme> userColours, JalviewModelSequence jms)
1853 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
1854 boolean newucs = false;
1855 if (!userColours.contains(ucs))
1857 userColours.add(ucs);
1860 id = "ucs" + userColours.indexOf(ucs);
1863 // actually create the scheme's entry in the XML model
1864 java.awt.Color[] colours = ucs.getColours();
1865 jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
1866 jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
1868 for (int i = 0; i < colours.length; i++)
1870 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
1871 col.setName(ResidueProperties.aa[i]);
1872 col.setRGB(jalview.util.Format.getHexString(colours[i]));
1873 jbucs.addColour(col);
1875 if (ucs.getLowerCaseColours() != null)
1877 colours = ucs.getLowerCaseColours();
1878 for (int i = 0; i < colours.length; i++)
1880 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
1881 col.setName(ResidueProperties.aa[i].toLowerCase());
1882 col.setRGB(jalview.util.Format.getHexString(colours[i]));
1883 jbucs.addColour(col);
1888 uc.setUserColourScheme(jbucs);
1889 jms.addUserColours(uc);
1895 jalview.schemes.UserColourScheme getUserColourScheme(
1896 JalviewModelSequence jms, String id)
1898 UserColours[] uc = jms.getUserColours();
1899 UserColours colours = null;
1901 for (int i = 0; i < uc.length; i++)
1903 if (uc[i].getId().equals(id))
1911 java.awt.Color[] newColours = new java.awt.Color[24];
1913 for (int i = 0; i < 24; i++)
1915 newColours[i] = new java.awt.Color(Integer.parseInt(colours
1916 .getUserColourScheme().getColour(i).getRGB(), 16));
1919 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
1922 if (colours.getUserColourScheme().getColourCount() > 24)
1924 newColours = new java.awt.Color[23];
1925 for (int i = 0; i < 23; i++)
1927 newColours[i] = new java.awt.Color(Integer.parseInt(colours
1928 .getUserColourScheme().getColour(i + 24).getRGB(), 16));
1930 ucs.setLowerCaseColours(newColours);
1937 * contains last error message (if any) encountered by XML loader.
1939 String errorMessage = null;
1942 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
1943 * exceptions are raised during project XML parsing
1945 public boolean attemptversion1parse = true;
1948 * Load a jalview project archive from a jar file
1951 * - HTTP URL or filename
1953 public AlignFrame loadJalviewAlign(final String file)
1956 jalview.gui.AlignFrame af = null;
1960 // create list to store references for any new Jmol viewers created
1961 newStructureViewers = new Vector<JalviewStructureDisplayI>();
1962 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
1963 // Workaround is to make sure caller implements the JarInputStreamProvider
1965 // so we can re-open the jar input stream for each entry.
1967 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
1968 af = loadJalviewAlign(jprovider);
1970 } catch (MalformedURLException e)
1972 errorMessage = "Invalid URL format for '" + file + "'";
1978 SwingUtilities.invokeAndWait(new Runnable()
1982 setLoadingFinishedForNewStructureViewers();
1985 } catch (Exception x)
1993 private jarInputStreamProvider createjarInputStreamProvider(
1994 final String file) throws MalformedURLException
1997 errorMessage = null;
1998 uniqueSetSuffix = null;
2000 viewportsAdded.clear();
2001 frefedSequence = null;
2003 if (file.startsWith("http://"))
2005 url = new URL(file);
2007 final URL _url = url;
2008 return new jarInputStreamProvider()
2012 public JarInputStream getJarInputStream() throws IOException
2016 return new JarInputStream(_url.openStream());
2020 return new JarInputStream(new FileInputStream(file));
2025 public String getFilename()
2033 * Recover jalview session from a jalview project archive. Caller may
2034 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2035 * themselves. Any null fields will be initialised with default values,
2036 * non-null fields are left alone.
2041 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2043 errorMessage = null;
2044 if (uniqueSetSuffix == null)
2046 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2048 if (seqRefIds == null)
2050 seqRefIds = new HashMap<String, SequenceI>();
2052 if (frefedSequence == null)
2054 frefedSequence = new Vector();
2057 AlignFrame af = null, _af = null;
2058 Map<String, AlignFrame> gatherToThisFrame = new HashMap<String, AlignFrame>();
2059 final String file = jprovider.getFilename();
2062 JarInputStream jin = null;
2063 JarEntry jarentry = null;
2068 jin = jprovider.getJarInputStream();
2069 for (int i = 0; i < entryCount; i++)
2071 jarentry = jin.getNextJarEntry();
2074 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2076 InputStreamReader in = new InputStreamReader(jin, "UTF-8");
2077 JalviewModel object = new JalviewModel();
2079 Unmarshaller unmar = new Unmarshaller(object);
2080 unmar.setValidation(false);
2081 object = (JalviewModel) unmar.unmarshal(in);
2082 if (true) // !skipViewport(object))
2084 _af = loadFromObject(object, file, true, jprovider);
2085 if (object.getJalviewModelSequence().getViewportCount() > 0)
2088 if (af.viewport.isGatherViewsHere())
2090 gatherToThisFrame.put(af.viewport.getSequenceSetId(), af);
2096 else if (jarentry != null)
2098 // Some other file here.
2101 } while (jarentry != null);
2102 resolveFrefedSequences();
2103 } catch (java.io.FileNotFoundException ex)
2105 ex.printStackTrace();
2106 errorMessage = "Couldn't locate Jalview XML file : " + file;
2107 System.err.println("Exception whilst loading jalview XML file : "
2109 } catch (java.net.UnknownHostException ex)
2111 ex.printStackTrace();
2112 errorMessage = "Couldn't locate Jalview XML file : " + file;
2113 System.err.println("Exception whilst loading jalview XML file : "
2115 } catch (Exception ex)
2117 System.err.println("Parsing as Jalview Version 2 file failed.");
2118 ex.printStackTrace(System.err);
2119 if (attemptversion1parse)
2121 // Is Version 1 Jar file?
2124 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
2125 } catch (Exception ex2)
2127 System.err.println("Exception whilst loading as jalviewXMLV1:");
2128 ex2.printStackTrace();
2132 if (Desktop.instance != null)
2134 Desktop.instance.stopLoading();
2138 System.out.println("Successfully loaded archive file");
2141 ex.printStackTrace();
2143 System.err.println("Exception whilst loading jalview XML file : "
2145 } catch (OutOfMemoryError e)
2147 // Don't use the OOM Window here
2148 errorMessage = "Out of memory loading jalview XML file";
2149 System.err.println("Out of memory whilst loading jalview XML file");
2150 e.printStackTrace();
2153 if (Desktop.instance != null)
2155 Desktop.instance.stopLoading();
2159 * Regather multiple views (with the same sequence set id) to the frame (if
2160 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2161 * views instead of separate frames. Note this doesn't restore a state where
2162 * some expanded views in turn have tabbed views - the last "first tab" read
2163 * in will play the role of gatherer for all.
2165 for (AlignFrame fr : gatherToThisFrame.values())
2167 Desktop.instance.gatherViews(fr);
2170 restoreSplitFrames();
2172 if (errorMessage != null)
2180 * Try to reconstruct and display SplitFrame windows, where each contains
2181 * complementary dna and protein alignments. Done by pairing up AlignFrame
2182 * objects (created earlier) which have complementary viewport ids associated.
2184 protected void restoreSplitFrames()
2186 List<SplitFrame> gatherTo = new ArrayList<SplitFrame>();
2187 List<AlignFrame> addedToSplitFrames = new ArrayList<AlignFrame>();
2188 Map<String, AlignFrame> dna = new HashMap<String, AlignFrame>();
2191 * Identify the DNA alignments
2193 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2196 AlignFrame af = candidate.getValue();
2197 if (af.getViewport().getAlignment().isNucleotide())
2199 dna.put(candidate.getKey().getId(), af);
2204 * Try to match up the protein complements
2206 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2209 AlignFrame af = candidate.getValue();
2210 if (!af.getViewport().getAlignment().isNucleotide())
2212 String complementId = candidate.getKey().getComplementId();
2213 // only non-null complements should be in the Map
2214 if (complementId != null && dna.containsKey(complementId))
2216 final AlignFrame dnaFrame = dna.get(complementId);
2217 SplitFrame sf = createSplitFrame(dnaFrame, af);
2218 addedToSplitFrames.add(dnaFrame);
2219 addedToSplitFrames.add(af);
2220 if (af.viewport.isGatherViewsHere())
2229 * Open any that we failed to pair up (which shouldn't happen!) as
2230 * standalone AlignFrame's.
2232 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2235 AlignFrame af = candidate.getValue();
2236 if (!addedToSplitFrames.contains(af)) {
2237 Viewport view = candidate.getKey();
2238 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
2240 System.err.println("Failed to restore view " + view.getTitle()
2241 + " to split frame");
2246 * Gather back into tabbed views as flagged.
2248 for (SplitFrame sf : gatherTo)
2250 Desktop.instance.gatherViews(sf);
2253 splitFrameCandidates.clear();
2257 * Construct and display one SplitFrame holding DNA and protein alignments.
2260 * @param proteinFrame
2263 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
2264 AlignFrame proteinFrame)
2266 dnaFrame.setVisible(true);
2267 proteinFrame.setVisible(true);
2268 proteinFrame.getViewport().setCodingComplement(dnaFrame.getViewport());
2269 final StructureSelectionManager ssm = StructureSelectionManager
2270 .getStructureSelectionManager(Desktop.instance);
2271 ssm.addCommandListener(proteinFrame.getViewport());
2272 ssm.addCommandListener(dnaFrame.getViewport());
2274 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
2275 String title = MessageManager.getString("label.linked_view_title");
2276 Desktop.addInternalFrame(splitFrame, title, -1, -1);
2281 * check errorMessage for a valid error message and raise an error box in the
2282 * GUI or write the current errorMessage to stderr and then clear the error
2285 protected void reportErrors()
2287 reportErrors(false);
2290 protected void reportErrors(final boolean saving)
2292 if (errorMessage != null)
2294 final String finalErrorMessage = errorMessage;
2297 javax.swing.SwingUtilities.invokeLater(new Runnable()
2302 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2303 finalErrorMessage, "Error "
2304 + (saving ? "saving" : "loading")
2305 + " Jalview file", JOptionPane.WARNING_MESSAGE);
2311 System.err.println("Problem loading Jalview file: " + errorMessage);
2314 errorMessage = null;
2317 Map<String, String> alreadyLoadedPDB = new HashMap<String, String>();
2320 * when set, local views will be updated from view stored in JalviewXML
2321 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2322 * sync if this is set to true.
2324 private final boolean updateLocalViews = false;
2326 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId)
2328 if (alreadyLoadedPDB.containsKey(pdbId))
2330 return alreadyLoadedPDB.get(pdbId).toString();
2335 JarInputStream jin = jprovider.getJarInputStream();
2337 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2338 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2339 * FileInputStream(jprovider)); }
2342 JarEntry entry = null;
2345 entry = jin.getNextJarEntry();
2346 } while (entry != null && !entry.getName().equals(pdbId));
2349 BufferedReader in = new BufferedReader(new InputStreamReader(jin));
2350 File outFile = File.createTempFile("jalview_pdb", ".txt");
2351 outFile.deleteOnExit();
2352 PrintWriter out = new PrintWriter(new FileOutputStream(outFile));
2355 while ((data = in.readLine()) != null)
2362 } catch (Exception foo)
2367 String t = outFile.getAbsolutePath();
2368 alreadyLoadedPDB.put(pdbId, t);
2373 warn("Couldn't find PDB file entry in Jalview Jar for " + pdbId);
2375 } catch (Exception ex)
2377 ex.printStackTrace();
2383 private class JvAnnotRow
2385 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2392 * persisted version of annotation row from which to take vis properties
2394 public jalview.datamodel.AlignmentAnnotation template;
2397 * original position of the annotation row in the alignment
2403 * Load alignment frame from jalview XML DOM object
2408 * filename source string
2409 * @param loadTreesAndStructures
2410 * when false only create Viewport
2412 * data source provider
2413 * @return alignment frame created from view stored in DOM
2415 AlignFrame loadFromObject(JalviewModel object, String file,
2416 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
2418 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
2419 Sequence[] vamsasSeq = vamsasSet.getSequence();
2421 JalviewModelSequence jms = object.getJalviewModelSequence();
2423 Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
2426 // ////////////////////////////////
2429 List<SequenceI> hiddenSeqs = null;
2430 jalview.datamodel.Sequence jseq;
2432 List<SequenceI> tmpseqs = new ArrayList<SequenceI>();
2434 boolean multipleView = false;
2436 JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
2437 int vi = 0; // counter in vamsasSeq array
2438 for (int i = 0; i < jseqs.length; i++)
2440 String seqId = jseqs[i].getId();
2442 if (seqRefIds.get(seqId) != null)
2444 tmpseqs.add(seqRefIds.get(seqId));
2445 multipleView = true;
2449 jseq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
2450 vamsasSeq[vi].getSequence());
2451 jseq.setDescription(vamsasSeq[vi].getDescription());
2452 jseq.setStart(jseqs[i].getStart());
2453 jseq.setEnd(jseqs[i].getEnd());
2454 jseq.setVamsasId(uniqueSetSuffix + seqId);
2455 seqRefIds.put(vamsasSeq[vi].getId(), jseq);
2460 if (jseqs[i].getHidden())
2462 if (hiddenSeqs == null)
2464 hiddenSeqs = new ArrayList<SequenceI>();
2467 hiddenSeqs.add(seqRefIds.get(seqId));
2473 // Create the alignment object from the sequence set
2474 // ///////////////////////////////
2475 SequenceI[] orderedSeqs = tmpseqs
2476 .toArray(new SequenceI[tmpseqs.size()]);
2478 Alignment al = new Alignment(orderedSeqs);
2480 // / Add the alignment properties
2481 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
2483 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
2484 al.setProperty(ssp.getKey(), ssp.getValue());
2488 // SequenceFeatures are added to the DatasetSequence,
2489 // so we must create or recover the dataset before loading features
2490 // ///////////////////////////////
2491 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
2493 // older jalview projects do not have a dataset id.
2494 al.setDataset(null);
2498 // recover dataset - passing on flag indicating if this a 'viewless'
2499 // sequence set (a.k.a. a stored dataset for the project)
2500 recoverDatasetFor(vamsasSet, al, object.getJalviewModelSequence()
2501 .getViewportCount() == 0);
2503 // ///////////////////////////////
2505 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
2508 // load sequence features, database references and any associated PDB
2509 // structures for the alignment
2510 for (int i = 0; i < vamsasSeq.length; i++)
2512 if (jseqs[i].getFeaturesCount() > 0)
2514 Features[] features = jseqs[i].getFeatures();
2515 for (int f = 0; f < features.length; f++)
2517 jalview.datamodel.SequenceFeature sf = new jalview.datamodel.SequenceFeature(
2518 features[f].getType(), features[f].getDescription(),
2519 features[f].getStatus(), features[f].getBegin(),
2520 features[f].getEnd(), features[f].getFeatureGroup());
2522 sf.setScore(features[f].getScore());
2523 for (int od = 0; od < features[f].getOtherDataCount(); od++)
2525 OtherData keyValue = features[f].getOtherData(od);
2526 if (keyValue.getKey().startsWith("LINK"))
2528 sf.addLink(keyValue.getValue());
2532 sf.setValue(keyValue.getKey(), keyValue.getValue());
2537 al.getSequenceAt(i).getDatasetSequence().addSequenceFeature(sf);
2540 if (vamsasSeq[i].getDBRefCount() > 0)
2542 addDBRefs(al.getSequenceAt(i).getDatasetSequence(), vamsasSeq[i]);
2544 if (jseqs[i].getPdbidsCount() > 0)
2546 Pdbids[] ids = jseqs[i].getPdbids();
2547 for (int p = 0; p < ids.length; p++)
2549 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
2550 entry.setId(ids[p].getId());
2551 entry.setType(ids[p].getType());
2552 if (ids[p].getFile() != null)
2554 if (!pdbloaded.containsKey(ids[p].getFile()))
2556 entry.setFile(loadPDBFile(jprovider, ids[p].getId()));
2560 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
2563 StructureSelectionManager.getStructureSelectionManager(
2564 Desktop.instance).registerPDBEntry(entry);
2565 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
2569 } // end !multipleview
2571 // ///////////////////////////////
2572 // LOAD SEQUENCE MAPPINGS
2574 if (vamsasSet.getAlcodonFrameCount() > 0)
2576 // TODO Potentially this should only be done once for all views of an
2578 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
2579 for (int i = 0; i < alc.length; i++)
2581 AlignedCodonFrame cf = new AlignedCodonFrame();
2582 if (alc[i].getAlcodMapCount() > 0)
2584 AlcodMap[] maps = alc[i].getAlcodMap();
2585 for (int m = 0; m < maps.length; m++)
2587 SequenceI dnaseq = seqRefIds.get(maps[m].getDnasq());
2589 jalview.datamodel.Mapping mapping = null;
2590 // attach to dna sequence reference.
2591 if (maps[m].getMapping() != null)
2593 mapping = addMapping(maps[m].getMapping());
2597 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
2602 frefedSequence.add(new Object[]
2603 { maps[m].getDnasq(), cf, mapping });
2607 al.addCodonFrame(cf);
2611 // ////////////////////////////////
2613 List<JvAnnotRow> autoAlan = new ArrayList<JvAnnotRow>();
2615 * store any annotations which forward reference a group's ID
2617 Hashtable<String, ArrayList<jalview.datamodel.AlignmentAnnotation>> groupAnnotRefs = new Hashtable<String, ArrayList<jalview.datamodel.AlignmentAnnotation>>();
2619 if (vamsasSet.getAnnotationCount() > 0)
2621 Annotation[] an = vamsasSet.getAnnotation();
2623 for (int i = 0; i < an.length; i++)
2626 * test if annotation is automatically calculated for this view only
2628 boolean autoForView = false;
2629 if (an[i].getLabel().equals("Quality")
2630 || an[i].getLabel().equals("Conservation")
2631 || an[i].getLabel().equals("Consensus"))
2633 // Kludge for pre 2.5 projects which lacked the autocalculated flag
2635 if (!an[i].hasAutoCalculated())
2637 an[i].setAutoCalculated(true);
2641 || (an[i].hasAutoCalculated() && an[i].isAutoCalculated()))
2643 // remove ID - we don't recover annotation from other views for
2644 // view-specific annotation
2648 // set visiblity for other annotation in this view
2649 if (an[i].getId() != null
2650 && annotationIds.containsKey(an[i].getId()))
2652 AlignmentAnnotation jda = annotationIds.get(an[i].getId());
2653 // in principle Visible should always be true for annotation displayed
2654 // in multiple views
2655 if (an[i].hasVisible())
2657 jda.visible = an[i].getVisible();
2660 al.addAnnotation(jda);
2664 // Construct new annotation from model.
2665 AnnotationElement[] ae = an[i].getAnnotationElement();
2666 jalview.datamodel.Annotation[] anot = null;
2667 java.awt.Color firstColour = null;
2669 if (!an[i].getScoreOnly())
2671 anot = new jalview.datamodel.Annotation[al.getWidth()];
2672 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
2674 anpos = ae[aa].getPosition();
2676 if (anpos >= anot.length)
2681 anot[anpos] = new jalview.datamodel.Annotation(
2683 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
2684 (ae[aa].getSecondaryStructure() == null || ae[aa]
2685 .getSecondaryStructure().length() == 0) ? ' '
2686 : ae[aa].getSecondaryStructure().charAt(0),
2690 // JBPNote: Consider verifying dataflow for IO of secondary
2691 // structure annotation read from Stockholm files
2692 // this was added to try to ensure that
2693 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
2695 // anot[ae[aa].getPosition()].displayCharacter = "";
2697 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
2698 if (firstColour == null)
2700 firstColour = anot[anpos].colour;
2704 jalview.datamodel.AlignmentAnnotation jaa = null;
2706 if (an[i].getGraph())
2708 float llim = 0, hlim = 0;
2709 // if (autoForView || an[i].isAutoCalculated()) {
2712 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
2713 an[i].getDescription(), anot, llim, hlim,
2714 an[i].getGraphType());
2716 jaa.graphGroup = an[i].getGraphGroup();
2717 jaa._linecolour = firstColour;
2718 if (an[i].getThresholdLine() != null)
2720 jaa.setThreshold(new jalview.datamodel.GraphLine(an[i]
2721 .getThresholdLine().getValue(), an[i]
2722 .getThresholdLine().getLabel(), new java.awt.Color(
2723 an[i].getThresholdLine().getColour())));
2726 if (autoForView || an[i].isAutoCalculated())
2728 // Hardwire the symbol display line to ensure that labels for
2729 // histograms are displayed
2735 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
2736 an[i].getDescription(), anot);
2737 jaa._linecolour = firstColour;
2739 // register new annotation
2740 if (an[i].getId() != null)
2742 annotationIds.put(an[i].getId(), jaa);
2743 jaa.annotationId = an[i].getId();
2745 // recover sequence association
2746 if (an[i].getSequenceRef() != null)
2748 if (al.findName(an[i].getSequenceRef()) != null)
2750 jaa.createSequenceMapping(al.findName(an[i].getSequenceRef()),
2752 al.findName(an[i].getSequenceRef()).addAlignmentAnnotation(jaa);
2755 // and make a note of any group association
2756 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
2758 ArrayList<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
2759 .get(an[i].getGroupRef());
2762 aal = new ArrayList<jalview.datamodel.AlignmentAnnotation>();
2763 groupAnnotRefs.put(an[i].getGroupRef(), aal);
2768 if (an[i].hasScore())
2770 jaa.setScore(an[i].getScore());
2772 if (an[i].hasVisible())
2774 jaa.visible = an[i].getVisible();
2777 if (an[i].hasCentreColLabels())
2779 jaa.centreColLabels = an[i].getCentreColLabels();
2782 if (an[i].hasScaleColLabels())
2784 jaa.scaleColLabel = an[i].getScaleColLabels();
2786 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
2788 // newer files have an 'autoCalculated' flag and store calculation
2789 // state in viewport properties
2790 jaa.autoCalculated = true; // means annotation will be marked for
2791 // update at end of load.
2793 if (an[i].hasGraphHeight())
2795 jaa.graphHeight = an[i].getGraphHeight();
2797 if (an[i].hasBelowAlignment())
2799 jaa.belowAlignment = an[i].isBelowAlignment();
2801 jaa.setCalcId(an[i].getCalcId());
2802 if (an[i].getPropertyCount() > 0)
2804 for (jalview.schemabinding.version2.Property prop : an[i]
2807 jaa.setProperty(prop.getName(), prop.getValue());
2810 if (jaa.autoCalculated)
2812 autoAlan.add(new JvAnnotRow(i, jaa));
2815 // if (!autoForView)
2817 // add autocalculated group annotation and any user created annotation
2819 al.addAnnotation(jaa);
2823 // ///////////////////////
2825 // Create alignment markup and styles for this view
2826 if (jms.getJGroupCount() > 0)
2828 JGroup[] groups = jms.getJGroup();
2829 boolean addAnnotSchemeGroup = false;
2830 for (int i = 0; i < groups.length; i++)
2832 ColourSchemeI cs = null;
2834 if (groups[i].getColour() != null)
2836 if (groups[i].getColour().startsWith("ucs"))
2838 cs = getUserColourScheme(jms, groups[i].getColour());
2840 else if (groups[i].getColour().equals("AnnotationColourGradient")
2841 && groups[i].getAnnotationColours() != null)
2843 addAnnotSchemeGroup = true;
2848 cs = ColourSchemeProperty.getColour(al, groups[i].getColour());
2853 cs.setThreshold(groups[i].getPidThreshold(), true);
2857 Vector seqs = new Vector();
2859 for (int s = 0; s < groups[i].getSeqCount(); s++)
2861 String seqId = groups[i].getSeq(s) + "";
2862 jalview.datamodel.SequenceI ts = seqRefIds.get(seqId);
2866 seqs.addElement(ts);
2870 if (seqs.size() < 1)
2875 jalview.datamodel.SequenceGroup sg = new jalview.datamodel.SequenceGroup(
2876 seqs, groups[i].getName(), cs, groups[i].getDisplayBoxes(),
2877 groups[i].getDisplayText(), groups[i].getColourText(),
2878 groups[i].getStart(), groups[i].getEnd());
2880 sg.setOutlineColour(new java.awt.Color(groups[i].getOutlineColour()));
2882 sg.textColour = new java.awt.Color(groups[i].getTextCol1());
2883 sg.textColour2 = new java.awt.Color(groups[i].getTextCol2());
2884 sg.setShowNonconserved(groups[i].hasShowUnconserved() ? groups[i]
2885 .isShowUnconserved() : false);
2886 sg.thresholdTextColour = groups[i].getTextColThreshold();
2887 if (groups[i].hasShowConsensusHistogram())
2889 sg.setShowConsensusHistogram(groups[i].isShowConsensusHistogram());
2892 if (groups[i].hasShowSequenceLogo())
2894 sg.setshowSequenceLogo(groups[i].isShowSequenceLogo());
2896 if (groups[i].hasNormaliseSequenceLogo())
2898 sg.setNormaliseSequenceLogo(groups[i].isNormaliseSequenceLogo());
2900 if (groups[i].hasIgnoreGapsinConsensus())
2902 sg.setIgnoreGapsConsensus(groups[i].getIgnoreGapsinConsensus());
2904 if (groups[i].getConsThreshold() != 0)
2906 jalview.analysis.Conservation c = new jalview.analysis.Conservation(
2907 "All", ResidueProperties.propHash, 3,
2908 sg.getSequences(null), 0, sg.getWidth() - 1);
2910 c.verdict(false, 25);
2911 sg.cs.setConservation(c);
2914 if (groups[i].getId() != null && groupAnnotRefs.size() > 0)
2916 // re-instate unique group/annotation row reference
2917 ArrayList<jalview.datamodel.AlignmentAnnotation> jaal = groupAnnotRefs
2918 .get(groups[i].getId());
2921 for (jalview.datamodel.AlignmentAnnotation jaa : jaal)
2924 if (jaa.autoCalculated)
2926 // match up and try to set group autocalc alignment row for this
2928 if (jaa.label.startsWith("Consensus for "))
2930 sg.setConsensus(jaa);
2932 // match up and try to set group autocalc alignment row for this
2934 if (jaa.label.startsWith("Conservation for "))
2936 sg.setConservationRow(jaa);
2943 if (addAnnotSchemeGroup)
2945 // reconstruct the annotation colourscheme
2946 sg.cs = constructAnnotationColour(
2947 groups[i].getAnnotationColours(), null, al, jms, false);
2953 // only dataset in this model, so just return.
2956 // ///////////////////////////////
2959 // If we just load in the same jar file again, the sequenceSetId
2960 // will be the same, and we end up with multiple references
2961 // to the same sequenceSet. We must modify this id on load
2962 // so that each load of the file gives a unique id
2963 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
2964 String viewId = (view.getId() == null ? null : view.getId()
2966 AlignFrame af = null;
2967 AlignViewport av = null;
2968 // now check to see if we really need to create a new viewport.
2969 if (multipleView && viewportsAdded.size() == 0)
2971 // We recovered an alignment for which a viewport already exists.
2972 // TODO: fix up any settings necessary for overlaying stored state onto
2973 // state recovered from another document. (may not be necessary).
2974 // we may need a binding from a viewport in memory to one recovered from
2976 // and then recover its containing af to allow the settings to be applied.
2977 // TODO: fix for vamsas demo
2979 .println("About to recover a viewport for existing alignment: Sequence set ID is "
2981 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
2982 if (seqsetobj != null)
2984 if (seqsetobj instanceof String)
2986 uniqueSeqSetId = (String) seqsetobj;
2988 .println("Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
2994 .println("Warning : Collision between sequence set ID string and existing jalview object mapping.");
3000 * indicate that annotation colours are applied across all groups (pre
3001 * Jalview 2.8.1 behaviour)
3003 boolean doGroupAnnColour = isVersionStringLaterThan("2.8.1",
3004 object.getVersion());
3006 AlignmentPanel ap = null;
3007 boolean isnewview = true;
3010 // Check to see if this alignment already has a view id == viewId
3011 jalview.gui.AlignmentPanel views[] = Desktop
3012 .getAlignmentPanels(uniqueSeqSetId);
3013 if (views != null && views.length > 0)
3015 for (int v = 0; v < views.length; v++)
3017 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
3019 // recover the existing alignpanel, alignframe, viewport
3020 af = views[v].alignFrame;
3023 // TODO: could even skip resetting view settings if we don't want to
3024 // change the local settings from other jalview processes
3033 af = loadViewport(file, jseqs, hiddenSeqs, al, jms, view,
3034 uniqueSeqSetId, viewId, autoAlan);
3039 // /////////////////////////////////////
3040 if (loadTreesAndStructures && jms.getTreeCount() > 0)
3044 for (int t = 0; t < jms.getTreeCount(); t++)
3047 Tree tree = jms.getTree(t);
3049 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
3052 tp = af.ShowNewickTree(
3053 new jalview.io.NewickFile(tree.getNewick()),
3054 tree.getTitle(), tree.getWidth(), tree.getHeight(),
3055 tree.getXpos(), tree.getYpos());
3056 if (tree.getId() != null)
3058 // perhaps bind the tree id to something ?
3063 // update local tree attributes ?
3064 // TODO: should check if tp has been manipulated by user - if so its
3065 // settings shouldn't be modified
3066 tp.setTitle(tree.getTitle());
3067 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(), tree
3068 .getWidth(), tree.getHeight()));
3069 tp.av = av; // af.viewport; // TODO: verify 'associate with all
3072 tp.treeCanvas.av = av; // af.viewport;
3073 tp.treeCanvas.ap = ap; // af.alignPanel;
3078 warn("There was a problem recovering stored Newick tree: \n"
3079 + tree.getNewick());
3083 tp.fitToWindow.setState(tree.getFitToWindow());
3084 tp.fitToWindow_actionPerformed(null);
3086 if (tree.getFontName() != null)
3088 tp.setTreeFont(new java.awt.Font(tree.getFontName(), tree
3089 .getFontStyle(), tree.getFontSize()));
3093 tp.setTreeFont(new java.awt.Font(view.getFontName(), view
3094 .getFontStyle(), tree.getFontSize()));
3097 tp.showPlaceholders(tree.getMarkUnlinked());
3098 tp.showBootstrap(tree.getShowBootstrap());
3099 tp.showDistances(tree.getShowDistances());
3101 tp.treeCanvas.threshold = tree.getThreshold();
3103 if (tree.getCurrentTree())
3105 af.viewport.setCurrentTree(tp.getTree());
3109 } catch (Exception ex)
3111 ex.printStackTrace();
3115 // //LOAD STRUCTURES
3116 if (loadTreesAndStructures)
3118 loadStructures(jprovider, jseqs, af, ap);
3120 // and finally return.
3125 * Load and link any saved structure viewers.
3132 protected void loadStructures(jarInputStreamProvider jprovider,
3133 JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
3136 * Run through all PDB ids on the alignment, and collect mappings between
3137 * distinct view ids and all sequences referring to that view.
3139 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<String, StructureViewerModel>();
3141 for (int i = 0; i < jseqs.length; i++)
3143 if (jseqs[i].getPdbidsCount() > 0)
3145 Pdbids[] ids = jseqs[i].getPdbids();
3146 for (int p = 0; p < ids.length; p++)
3148 final int structureStateCount = ids[p].getStructureStateCount();
3149 for (int s = 0; s < structureStateCount; s++)
3151 // check to see if we haven't already created this structure view
3152 final StructureState structureState = ids[p]
3153 .getStructureState(s);
3154 String sviewid = (structureState.getViewId() == null) ? null
3155 : structureState.getViewId() + uniqueSetSuffix;
3156 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
3157 // Originally : ids[p].getFile()
3158 // : TODO: verify external PDB file recovery still works in normal
3159 // jalview project load
3160 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId()));
3161 jpdb.setId(ids[p].getId());
3163 int x = structureState.getXpos();
3164 int y = structureState.getYpos();
3165 int width = structureState.getWidth();
3166 int height = structureState.getHeight();
3168 // Probably don't need to do this anymore...
3169 // Desktop.desktop.getComponentAt(x, y);
3170 // TODO: NOW: check that this recovers the PDB file correctly.
3171 String pdbFile = loadPDBFile(jprovider, ids[p].getId());
3172 jalview.datamodel.SequenceI seq = seqRefIds.get(jseqs[i]
3174 if (sviewid == null)
3176 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width
3179 if (!structureViewers.containsKey(sviewid))
3181 structureViewers.put(sviewid, new StructureViewerModel(x, y,
3182 width, height, false, false, true));
3183 // Legacy pre-2.7 conversion JAL-823 :
3184 // do not assume any view has to be linked for colour by
3188 // assemble String[] { pdb files }, String[] { id for each
3189 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3190 // seqs_file 2}, boolean[] {
3191 // linkAlignPanel,superposeWithAlignpanel}} from hash
3192 StructureViewerModel jmoldat = structureViewers.get(sviewid);
3193 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
3194 | (structureState.hasAlignwithAlignPanel() ? structureState
3195 .getAlignwithAlignPanel() : false));
3198 * Default colour by linked panel to false if not specified (e.g.
3199 * for pre-2.7 projects)
3201 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
3202 colourWithAlignPanel |= (structureState
3203 .hasColourwithAlignPanel() ? structureState
3204 .getColourwithAlignPanel() : false);
3205 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
3208 * Default colour by viewer to true if not specified (e.g. for
3211 boolean colourByViewer = jmoldat.isColourByViewer();
3212 colourByViewer &= structureState.hasColourByJmol() ? structureState
3213 .getColourByJmol() : true;
3214 jmoldat.setColourByViewer(colourByViewer);
3216 if (jmoldat.getStateData().length() < structureState
3217 .getContent().length())
3220 jmoldat.setStateData(structureState.getContent());
3223 if (ids[p].getFile() != null)
3225 File mapkey = new File(ids[p].getFile());
3226 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
3227 if (seqstrmaps == null)
3229 jmoldat.getFileData().put(
3231 seqstrmaps = jmoldat.new StructureData(pdbFile,
3234 if (!seqstrmaps.getSeqList().contains(seq))
3236 seqstrmaps.getSeqList().add(seq);
3242 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");
3249 // Instantiate the associated structure views
3250 for (Entry<String, StructureViewerModel> entry : structureViewers
3253 createOrLinkStructureViewer(entry, af, ap);
3263 protected void createOrLinkStructureViewer(
3264 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3267 final StructureViewerModel svattrib = viewerData.getValue();
3270 * Search for any viewer windows already open from other alignment views
3271 * that exactly match the stored structure state
3273 StructureViewerBase comp = findMatchingViewer(viewerData);
3277 linkStructureViewer(ap, comp, svattrib);
3282 * Pending an XML element for ViewerType, just check if stateData contains
3283 * "chimera" (part of the chimera session filename).
3285 if (svattrib.getStateData().indexOf("chimera") > -1)
3287 createChimeraViewer(viewerData, af);
3291 createJmolViewer(viewerData, af);
3296 * Create a new Chimera viewer.
3301 protected void createChimeraViewer(
3302 Entry<String, StructureViewerModel> viewerData, AlignFrame af)
3304 final StructureViewerModel data = viewerData.getValue();
3305 String chimeraSession = data.getStateData();
3307 if (new File(chimeraSession).exists())
3309 Set<Entry<File, StructureData>> fileData = data.getFileData()
3311 List<PDBEntry> pdbs = new ArrayList<PDBEntry>();
3312 List<SequenceI[]> allseqs = new ArrayList<SequenceI[]>();
3313 for (Entry<File, StructureData> pdb : fileData)
3315 String filePath = pdb.getValue().getFilePath();
3316 String pdbId = pdb.getValue().getPdbId();
3317 pdbs.add(new PDBEntry(filePath, pdbId));
3318 final List<SequenceI> seqList = pdb.getValue().getSeqList();
3319 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
3323 boolean colourByChimera = data.isColourByViewer();
3324 boolean colourBySequence = data.isColourWithAlignPanel();
3326 // TODO can/should this be done via StructureViewer (like Jmol)?
3327 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
3328 final SequenceI[][] seqsArray = allseqs.toArray(new SequenceI[allseqs
3330 new ChimeraViewFrame(chimeraSession, af.alignPanel, pdbArray,
3331 seqsArray, colourByChimera, colourBySequence);
3335 Cache.log.error("Chimera session file " + chimeraSession
3341 * Create a new Jmol window. First parse the Jmol state to translate filenames
3342 * loaded into the view, and record the order in which files are shown in the
3343 * Jmol view, so we can add the sequence mappings in same order.
3348 protected void createJmolViewer(
3349 final Entry<String, StructureViewerModel> viewerData,
3352 final StructureViewerModel svattrib = viewerData.getValue();
3353 String state = svattrib.getStateData();
3354 List<String> pdbfilenames = new ArrayList<String>();
3355 List<SequenceI[]> seqmaps = new ArrayList<SequenceI[]>();
3356 List<String> pdbids = new ArrayList<String>();
3357 StringBuilder newFileLoc = new StringBuilder(64);
3358 int cp = 0, ncp, ecp;
3359 Map<File, StructureData> oldFiles = svattrib.getFileData();
3360 while ((ncp = state.indexOf("load ", cp)) > -1)
3364 // look for next filename in load statement
3365 newFileLoc.append(state.substring(cp,
3366 ncp = (state.indexOf("\"", ncp + 1) + 1)));
3367 String oldfilenam = state.substring(ncp,
3368 ecp = state.indexOf("\"", ncp));
3369 // recover the new mapping data for this old filename
3370 // have to normalize filename - since Jmol and jalview do
3372 // translation differently.
3373 StructureData filedat = oldFiles.get(new File(oldfilenam));
3374 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
3375 pdbfilenames.add(filedat.getFilePath());
3376 pdbids.add(filedat.getPdbId());
3377 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
3378 newFileLoc.append("\"");
3379 cp = ecp + 1; // advance beyond last \" and set cursor so we can
3380 // look for next file statement.
3381 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
3385 // just append rest of state
3386 newFileLoc.append(state.substring(cp));
3390 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
3391 newFileLoc = new StringBuilder(state);
3392 newFileLoc.append("; load append ");
3393 for (File id : oldFiles.keySet())
3395 // add this and any other pdb files that should be present in
3397 StructureData filedat = oldFiles.get(id);
3398 newFileLoc.append(filedat.getFilePath());
3399 pdbfilenames.add(filedat.getFilePath());
3400 pdbids.add(filedat.getPdbId());
3401 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
3402 newFileLoc.append(" \"");
3403 newFileLoc.append(filedat.getFilePath());
3404 newFileLoc.append("\"");
3407 newFileLoc.append(";");
3410 if (newFileLoc.length() > 0)
3412 int histbug = newFileLoc.indexOf("history = ");
3414 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
3415 String val = (diff == -1) ? null : newFileLoc
3416 .substring(histbug, diff);
3417 if (val != null && val.length() >= 4)
3419 if (val.contains("e"))
3421 if (val.trim().equals("true"))
3429 newFileLoc.replace(histbug, diff, val);
3433 final String[] pdbf = pdbfilenames.toArray(new String[pdbfilenames
3435 final String[] id = pdbids.toArray(new String[pdbids.size()]);
3436 final SequenceI[][] sq = seqmaps
3437 .toArray(new SequenceI[seqmaps.size()][]);
3438 final String fileloc = newFileLoc.toString();
3439 final String sviewid = viewerData.getKey();
3440 final AlignFrame alf = af;
3441 final Rectangle rect = new Rectangle(svattrib.getX(),
3442 svattrib.getY(), svattrib.getWidth(), svattrib.getHeight());
3445 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
3450 JalviewStructureDisplayI sview = null;
3453 // JAL-1333 note - we probably can't migrate Jmol views to UCSF
3455 sview = new StructureViewer(alf.alignPanel
3456 .getStructureSelectionManager()).createView(
3457 StructureViewer.ViewerType.JMOL, pdbf, id, sq,
3458 alf.alignPanel, svattrib, fileloc, rect, sviewid);
3459 addNewStructureViewer(sview);
3460 } catch (OutOfMemoryError ex)
3462 new OOMWarning("restoring structure view for PDB id " + id,
3463 (OutOfMemoryError) ex.getCause());
3464 if (sview != null && sview.isVisible())
3466 sview.closeViewer();
3467 sview.setVisible(false);
3473 } catch (InvocationTargetException ex)
3475 warn("Unexpected error when opening Jmol view.", ex);
3477 } catch (InterruptedException e)
3479 // e.printStackTrace();
3485 * Returns any open frame that matches given structure viewer data. The match
3486 * is based on the unique viewId, or (for older project versions) the frame's
3492 protected StructureViewerBase findMatchingViewer(
3493 Entry<String, StructureViewerModel> viewerData)
3495 final String sviewid = viewerData.getKey();
3496 final StructureViewerModel svattrib = viewerData.getValue();
3497 StructureViewerBase comp = null;
3498 JInternalFrame[] frames = getAllFrames();
3499 for (JInternalFrame frame : frames)
3501 if (frame instanceof StructureViewerBase)
3504 * Post jalview 2.4 schema includes structure view id
3507 && ((StructureViewerBase) frame).getViewId()
3510 comp = (AppJmol) frame;
3514 * Otherwise test for matching position and size of viewer frame
3516 else if (frame.getX() == svattrib.getX()
3517 && frame.getY() == svattrib.getY()
3518 && frame.getHeight() == svattrib.getHeight()
3519 && frame.getWidth() == svattrib.getWidth())
3521 comp = (AppJmol) frame;
3530 * Link an AlignmentPanel to an existing structure viewer.
3535 * @param useinViewerSuperpos
3536 * @param usetoColourbyseq
3537 * @param viewerColouring
3539 protected void linkStructureViewer(AlignmentPanel ap,
3540 StructureViewerBase viewer, StructureViewerModel svattrib)
3542 // NOTE: if the jalview project is part of a shared session then
3543 // view synchronization should/could be done here.
3545 final boolean useinViewerSuperpos = svattrib.isAlignWithPanel();
3546 final boolean usetoColourbyseq = svattrib.isColourWithAlignPanel();
3547 final boolean viewerColouring = svattrib.isColourByViewer();
3548 Map<File, StructureData> oldFiles = svattrib.getFileData();
3551 * Add mapping for sequences in this view to an already open viewer
3553 final AAStructureBindingModel binding = viewer.getBinding();
3554 for (File id : oldFiles.keySet())
3556 // add this and any other pdb files that should be present in the
3558 StructureData filedat = oldFiles.get(id);
3559 String pdbFile = filedat.getFilePath();
3560 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
3561 binding.getSsm().setMapping(seq, null, pdbFile,
3562 jalview.io.AppletFormatAdapter.FILE);
3563 binding.addSequenceForStructFile(pdbFile, seq);
3565 // and add the AlignmentPanel's reference to the view panel
3566 viewer.addAlignmentPanel(ap);
3567 if (useinViewerSuperpos)
3569 viewer.useAlignmentPanelForSuperposition(ap);
3573 viewer.excludeAlignmentPanelForSuperposition(ap);
3575 if (usetoColourbyseq)
3577 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
3581 viewer.excludeAlignmentPanelForColourbyseq(ap);
3586 * Get all frames within the Desktop.
3590 protected JInternalFrame[] getAllFrames()
3592 JInternalFrame[] frames = null;
3593 // TODO is this necessary - is it safe - risk of hanging?
3598 frames = Desktop.desktop.getAllFrames();
3599 } catch (ArrayIndexOutOfBoundsException e)
3601 // occasional No such child exceptions are thrown here...
3605 } catch (InterruptedException f)
3609 } while (frames == null);
3616 * - minimum version we are comparing against
3618 * - version of data being processsed.
3619 * @return true if version is development/null or evaluates to the same or
3620 * later X.Y.Z (where X,Y,Z are like [0-9]+b?[0-9]*)
3622 private boolean isVersionStringLaterThan(String supported, String version)
3624 if (version == null || version.equalsIgnoreCase("DEVELOPMENT BUILD")
3625 || version.equalsIgnoreCase("Test")
3626 || version.equalsIgnoreCase("AUTOMATED BUILD"))
3628 System.err.println("Assuming project file with "
3629 + (version == null ? "null" : version)
3630 + " is compatible with Jalview version " + supported);
3635 StringTokenizer currentV = new StringTokenizer(supported, "."), fileV = new StringTokenizer(
3637 while (currentV.hasMoreTokens() && fileV.hasMoreTokens())
3639 // convert b to decimal to catch bugfix releases within a series
3640 String curT = currentV.nextToken().toLowerCase().replace('b', '.');
3641 String fileT = fileV.nextToken().toLowerCase().replace('b', '.');
3644 if (Float.valueOf(curT) > Float.valueOf(fileT))
3646 // current version is newer than the version that wrote the file
3649 } catch (NumberFormatException nfe)
3652 .println("** WARNING: Version comparison failed for tokens ("
3656 + ")\n** Current: '"
3657 + supported + "' and Version: '" + version + "'");
3660 if (currentV.hasMoreElements())
3662 // fileV has no minor version but identical series to current
3669 Vector<JalviewStructureDisplayI> newStructureViewers = null;
3671 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
3673 if (newStructureViewers != null)
3675 sview.getBinding().setFinishedLoadingFromArchive(false);
3676 newStructureViewers.add(sview);
3680 protected void setLoadingFinishedForNewStructureViewers()
3682 if (newStructureViewers != null)
3684 for (JalviewStructureDisplayI sview : newStructureViewers)
3686 sview.getBinding().setFinishedLoadingFromArchive(true);
3688 newStructureViewers.clear();
3689 newStructureViewers = null;
3693 AlignFrame loadViewport(String file, JSeq[] JSEQ,
3694 List<SequenceI> hiddenSeqs, Alignment al,
3695 JalviewModelSequence jms, Viewport view, String uniqueSeqSetId,
3696 String viewId, List<JvAnnotRow> autoAlan)
3698 AlignFrame af = null;
3699 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
3700 uniqueSeqSetId, viewId);
3702 af.setFileName(file, "Jalview");
3704 for (int i = 0; i < JSEQ.length; i++)
3706 af.viewport.setSequenceColour(af.viewport.getAlignment()
3707 .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour()));
3710 af.viewport.setGatherViewsHere(view.getGatheredViews());
3712 if (view.getSequenceSetId() != null)
3714 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
3716 af.viewport.setSequenceSetId(uniqueSeqSetId);
3719 // propagate shared settings to this new view
3720 af.viewport.setHistoryList(av.getHistoryList());
3721 af.viewport.setRedoList(av.getRedoList());
3725 viewportsAdded.put(uniqueSeqSetId, af.viewport);
3727 // TODO: check if this method can be called repeatedly without
3728 // side-effects if alignpanel already registered.
3729 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
3731 // apply Hidden regions to view.
3732 if (hiddenSeqs != null)
3734 for (int s = 0; s < JSEQ.length; s++)
3736 jalview.datamodel.SequenceGroup hidden = new jalview.datamodel.SequenceGroup();
3738 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
3741 al.getSequenceAt(JSEQ[s].getHiddenSequences(r)), false);
3743 af.viewport.hideRepSequences(al.getSequenceAt(s), hidden);
3746 // jalview.datamodel.SequenceI[] hseqs = new
3747 // jalview.datamodel.SequenceI[hiddenSeqs
3750 // for (int s = 0; s < hiddenSeqs.size(); s++)
3752 // hseqs[s] = (jalview.datamodel.SequenceI) hiddenSeqs.elementAt(s);
3755 SequenceI[] hseqs = hiddenSeqs.toArray(new SequenceI[hiddenSeqs
3757 af.viewport.hideSequence(hseqs);
3760 // recover view properties and display parameters
3761 if (view.getViewName() != null)
3763 af.viewport.viewName = view.getViewName();
3764 af.setInitialTabVisible();
3766 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
3769 af.viewport.setShowAnnotation(view.getShowAnnotation());
3770 af.viewport.setAbovePIDThreshold(view.getPidSelected());
3772 af.viewport.setColourText(view.getShowColourText());
3774 af.viewport.setConservationSelected(view.getConservationSelected());
3775 af.viewport.setShowJVSuffix(view.getShowFullId());
3776 af.viewport.setRightAlignIds(view.getRightAlignIds());
3777 af.viewport.setFont(
3778 new java.awt.Font(view.getFontName(), view.getFontStyle(), view
3779 .getFontSize()), true);
3780 // TODO: allow custom charWidth/Heights to be restored by updating them
3781 // after setting font - which means set above to false
3782 af.viewport.setRenderGaps(view.getRenderGaps());
3783 af.viewport.setWrapAlignment(view.getWrapAlignment());
3784 af.viewport.setShowAnnotation(view.getShowAnnotation());
3786 af.viewport.setShowBoxes(view.getShowBoxes());
3788 af.viewport.setShowText(view.getShowText());
3790 af.viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
3791 af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
3792 af.viewport.setThresholdTextColour(view.getTextColThreshold());
3793 af.viewport.setShowUnconserved(view.hasShowUnconserved() ? view
3794 .isShowUnconserved() : false);
3795 af.viewport.setStartRes(view.getStartRes());
3796 af.viewport.setStartSeq(view.getStartSeq());
3797 af.alignPanel.updateLayout();
3798 ColourSchemeI cs = null;
3799 // apply colourschemes
3800 if (view.getBgColour() != null)
3802 if (view.getBgColour().startsWith("ucs"))
3804 cs = getUserColourScheme(jms, view.getBgColour());
3806 else if (view.getBgColour().startsWith("Annotation"))
3808 AnnotationColours viewAnnColour = view.getAnnotationColours();
3809 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
3816 cs = ColourSchemeProperty.getColour(al, view.getBgColour());
3821 cs.setThreshold(view.getPidThreshold(), true);
3822 cs.setConsensus(af.viewport.getSequenceConsensusHash());
3826 af.viewport.setGlobalColourScheme(cs);
3827 af.viewport.setColourAppliesToAllGroups(false);
3829 if (view.getConservationSelected() && cs != null)
3831 cs.setConservationInc(view.getConsThreshold());
3834 af.changeColour(cs);
3836 af.viewport.setColourAppliesToAllGroups(true);
3838 af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures());
3840 if (view.hasCentreColumnLabels())
3842 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
3844 if (view.hasIgnoreGapsinConsensus())
3846 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
3849 if (view.hasFollowHighlight())
3851 af.viewport.followHighlight = view.getFollowHighlight();
3853 if (view.hasFollowSelection())
3855 af.viewport.followSelection = view.getFollowSelection();
3857 if (view.hasShowConsensusHistogram())
3859 af.viewport.setShowConsensusHistogram(view
3860 .getShowConsensusHistogram());
3864 af.viewport.setShowConsensusHistogram(true);
3866 if (view.hasShowSequenceLogo())
3868 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
3872 af.viewport.setShowSequenceLogo(false);
3874 if (view.hasNormaliseSequenceLogo())
3876 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
3878 if (view.hasShowDbRefTooltip())
3880 af.viewport.setShowDBRefs(view.getShowDbRefTooltip());
3882 if (view.hasShowNPfeatureTooltip())
3884 af.viewport.setShowNPFeats(view.hasShowNPfeatureTooltip());
3886 if (view.hasShowGroupConsensus())
3888 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
3892 af.viewport.setShowGroupConsensus(false);
3894 if (view.hasShowGroupConservation())
3896 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
3900 af.viewport.setShowGroupConservation(false);
3903 // recover featre settings
3904 if (jms.getFeatureSettings() != null)
3906 FeaturesDisplayed fdi;
3907 af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
3908 String[] renderOrder = new String[jms.getFeatureSettings()
3909 .getSettingCount()];
3910 Hashtable featureGroups = new Hashtable();
3911 Hashtable featureColours = new Hashtable();
3912 Hashtable featureOrder = new Hashtable();
3914 for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
3916 Setting setting = jms.getFeatureSettings().getSetting(fs);
3917 if (setting.hasMincolour())
3919 GraduatedColor gc = setting.hasMin() ? new GraduatedColor(
3920 new java.awt.Color(setting.getMincolour()),
3921 new java.awt.Color(setting.getColour()),
3922 setting.getMin(), setting.getMax()) : new GraduatedColor(
3923 new java.awt.Color(setting.getMincolour()),
3924 new java.awt.Color(setting.getColour()), 0, 1);
3925 if (setting.hasThreshold())
3927 gc.setThresh(setting.getThreshold());
3928 gc.setThreshType(setting.getThreshstate());
3930 gc.setAutoScaled(true); // default
3931 if (setting.hasAutoScale())
3933 gc.setAutoScaled(setting.getAutoScale());
3935 if (setting.hasColourByLabel())
3937 gc.setColourByLabel(setting.getColourByLabel());
3939 // and put in the feature colour table.
3940 featureColours.put(setting.getType(), gc);
3944 featureColours.put(setting.getType(),
3945 new java.awt.Color(setting.getColour()));
3947 renderOrder[fs] = setting.getType();
3948 if (setting.hasOrder())
3950 featureOrder.put(setting.getType(), setting.getOrder());
3954 featureOrder.put(setting.getType(), new Float(fs
3955 / jms.getFeatureSettings().getSettingCount()));
3957 if (setting.getDisplay())
3959 fdi.setVisible(setting.getType());
3962 Hashtable fgtable = new Hashtable();
3963 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
3965 Group grp = jms.getFeatureSettings().getGroup(gs);
3966 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
3968 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
3969 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
3970 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
3971 FeatureRendererSettings frs = new FeatureRendererSettings(
3972 renderOrder, fgtable, featureColours, 1.0f, featureOrder);
3973 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
3974 .transferSettings(frs);
3978 if (view.getHiddenColumnsCount() > 0)
3980 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
3982 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(), view
3983 .getHiddenColumns(c).getEnd() // +1
3987 if (view.getCalcIdParam() != null)
3989 for (CalcIdParam calcIdParam : view.getCalcIdParam())
3991 if (calcIdParam != null)
3993 if (recoverCalcIdParam(calcIdParam, af.viewport))
3998 warn("Couldn't recover parameters for "
3999 + calcIdParam.getCalcId());
4004 af.setMenusFromViewport(af.viewport);
4006 // TODO: we don't need to do this if the viewport is aready visible.
4008 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
4009 * has a 'cdna/protein complement' view, in which case save it in order to
4010 * populate a SplitFrame once all views have been read in.
4012 String complementaryViewId = view.getComplementId();
4013 if (complementaryViewId == null)
4015 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
4017 // recompute any autoannotation
4018 af.alignPanel.updateAnnotation(false, true);
4019 reorderAutoannotation(af, al, autoAlan);
4020 af.alignPanel.alignmentChanged();
4024 splitFrameCandidates.put(view, af);
4029 private ColourSchemeI constructAnnotationColour(
4030 AnnotationColours viewAnnColour, AlignFrame af, Alignment al,
4031 JalviewModelSequence jms, boolean checkGroupAnnColour)
4033 boolean propagateAnnColour = false;
4034 ColourSchemeI cs = null;
4035 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
4036 if (checkGroupAnnColour && al.getGroups() != null
4037 && al.getGroups().size() > 0)
4039 // pre 2.8.1 behaviour
4040 // check to see if we should transfer annotation colours
4041 propagateAnnColour = true;
4042 for (jalview.datamodel.SequenceGroup sg : al.getGroups())
4044 if (sg.cs instanceof AnnotationColourGradient)
4046 propagateAnnColour = false;
4050 // int find annotation
4051 if (annAlignment.getAlignmentAnnotation() != null)
4053 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
4055 if (annAlignment.getAlignmentAnnotation()[i].label
4056 .equals(viewAnnColour.getAnnotation()))
4058 if (annAlignment.getAlignmentAnnotation()[i].getThreshold() == null)
4060 annAlignment.getAlignmentAnnotation()[i]
4061 .setThreshold(new jalview.datamodel.GraphLine(
4062 viewAnnColour.getThreshold(), "Threshold",
4063 java.awt.Color.black)
4068 if (viewAnnColour.getColourScheme().equals("None"))
4070 cs = new AnnotationColourGradient(
4071 annAlignment.getAlignmentAnnotation()[i],
4072 new java.awt.Color(viewAnnColour.getMinColour()),
4073 new java.awt.Color(viewAnnColour.getMaxColour()),
4074 viewAnnColour.getAboveThreshold());
4076 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
4078 cs = new AnnotationColourGradient(
4079 annAlignment.getAlignmentAnnotation()[i],
4080 getUserColourScheme(jms,
4081 viewAnnColour.getColourScheme()),
4082 viewAnnColour.getAboveThreshold());
4086 cs = new AnnotationColourGradient(
4087 annAlignment.getAlignmentAnnotation()[i],
4088 ColourSchemeProperty.getColour(al,
4089 viewAnnColour.getColourScheme()),
4090 viewAnnColour.getAboveThreshold());
4092 if (viewAnnColour.hasPerSequence())
4094 ((AnnotationColourGradient) cs).setSeqAssociated(viewAnnColour
4097 if (viewAnnColour.hasPredefinedColours())
4099 ((AnnotationColourGradient) cs)
4100 .setPredefinedColours(viewAnnColour
4101 .isPredefinedColours());
4103 if (propagateAnnColour && al.getGroups() != null)
4105 // Also use these settings for all the groups
4106 for (int g = 0; g < al.getGroups().size(); g++)
4108 jalview.datamodel.SequenceGroup sg = al.getGroups().get(g);
4116 * if (viewAnnColour.getColourScheme().equals("None" )) { sg.cs =
4117 * new AnnotationColourGradient(
4118 * annAlignment.getAlignmentAnnotation()[i], new
4119 * java.awt.Color(viewAnnColour. getMinColour()), new
4120 * java.awt.Color(viewAnnColour. getMaxColour()),
4121 * viewAnnColour.getAboveThreshold()); } else
4124 sg.cs = new AnnotationColourGradient(
4125 annAlignment.getAlignmentAnnotation()[i], sg.cs,
4126 viewAnnColour.getAboveThreshold());
4127 if (cs instanceof AnnotationColourGradient)
4129 if (viewAnnColour.hasPerSequence())
4131 ((AnnotationColourGradient) cs)
4132 .setSeqAssociated(viewAnnColour.isPerSequence());
4134 if (viewAnnColour.hasPredefinedColours())
4136 ((AnnotationColourGradient) cs)
4137 .setPredefinedColours(viewAnnColour
4138 .isPredefinedColours());
4154 private void reorderAutoannotation(AlignFrame af, Alignment al,
4155 List<JvAnnotRow> autoAlan)
4157 // copy over visualization settings for autocalculated annotation in the
4159 if (al.getAlignmentAnnotation() != null)
4162 * Kludge for magic autoannotation names (see JAL-811)
4164 String[] magicNames = new String[]
4165 { "Consensus", "Quality", "Conservation" };
4166 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
4167 Hashtable<String, JvAnnotRow> visan = new Hashtable<String, JvAnnotRow>();
4168 for (String nm : magicNames)
4170 visan.put(nm, nullAnnot);
4172 for (JvAnnotRow auan : autoAlan)
4174 visan.put(auan.template.label
4175 + (auan.template.getCalcId() == null ? "" : "\t"
4176 + auan.template.getCalcId()), auan);
4178 int hSize = al.getAlignmentAnnotation().length;
4179 List<JvAnnotRow> reorder = new ArrayList<JvAnnotRow>();
4180 // work through any autoCalculated annotation already on the view
4181 // removing it if it should be placed in a different location on the
4182 // annotation panel.
4183 List<String> remains = new ArrayList<String>(visan.keySet());
4184 for (int h = 0; h < hSize; h++)
4186 jalview.datamodel.AlignmentAnnotation jalan = al
4187 .getAlignmentAnnotation()[h];
4188 if (jalan.autoCalculated)
4191 JvAnnotRow valan = visan.get(k = jalan.label);
4192 if (jalan.getCalcId() != null)
4194 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
4199 // delete the auto calculated row from the alignment
4200 al.deleteAnnotation(jalan, false);
4204 if (valan != nullAnnot)
4206 if (jalan != valan.template)
4208 // newly created autoannotation row instance
4209 // so keep a reference to the visible annotation row
4210 // and copy over all relevant attributes
4211 if (valan.template.graphHeight >= 0)
4214 jalan.graphHeight = valan.template.graphHeight;
4216 jalan.visible = valan.template.visible;
4218 reorder.add(new JvAnnotRow(valan.order, jalan));
4223 // Add any (possibly stale) autocalculated rows that were not appended to
4224 // the view during construction
4225 for (String other : remains)
4227 JvAnnotRow othera = visan.get(other);
4228 if (othera != nullAnnot && othera.template.getCalcId() != null
4229 && othera.template.getCalcId().length() > 0)
4231 reorder.add(othera);
4234 // now put the automatic annotation in its correct place
4235 int s = 0, srt[] = new int[reorder.size()];
4236 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
4237 for (JvAnnotRow jvar : reorder)
4240 srt[s++] = jvar.order;
4243 jalview.util.QuickSort.sort(srt, rws);
4244 // and re-insert the annotation at its correct position
4245 for (JvAnnotRow jvar : rws)
4247 al.addAnnotation(jvar.template, jvar.order);
4249 af.alignPanel.adjustAnnotationHeight();
4253 Hashtable skipList = null;
4256 * TODO remove this method
4259 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
4260 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
4261 * throw new Error("Implementation Error. No skipList defined for this
4262 * Jalview2XML instance."); } return (AlignFrame)
4263 * skipList.get(view.getSequenceSetId()); }
4267 * Check if the Jalview view contained in object should be skipped or not.
4270 * @return true if view's sequenceSetId is a key in skipList
4272 private boolean skipViewport(JalviewModel object)
4274 if (skipList == null)
4279 if (skipList.containsKey(id = object.getJalviewModelSequence()
4280 .getViewport()[0].getSequenceSetId()))
4282 if (Cache.log != null && Cache.log.isDebugEnabled())
4284 Cache.log.debug("Skipping seuqence set id " + id);
4291 public void addToSkipList(AlignFrame af)
4293 if (skipList == null)
4295 skipList = new Hashtable();
4297 skipList.put(af.getViewport().getSequenceSetId(), af);
4300 public void clearSkipList()
4302 if (skipList != null)
4309 private void recoverDatasetFor(SequenceSet vamsasSet, Alignment al,
4310 boolean ignoreUnrefed)
4312 jalview.datamodel.Alignment ds = getDatasetFor(vamsasSet.getDatasetId());
4313 Vector dseqs = null;
4316 // create a list of new dataset sequences
4317 dseqs = new Vector();
4319 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
4321 Sequence vamsasSeq = vamsasSet.getSequence(i);
4322 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed);
4324 // create a new dataset
4327 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
4328 dseqs.copyInto(dsseqs);
4329 ds = new jalview.datamodel.Alignment(dsseqs);
4330 debug("Created new dataset " + vamsasSet.getDatasetId()
4331 + " for alignment " + System.identityHashCode(al));
4332 addDatasetRef(vamsasSet.getDatasetId(), ds);
4334 // set the dataset for the newly imported alignment.
4335 if (al.getDataset() == null && !ignoreUnrefed)
4344 * sequence definition to create/merge dataset sequence for
4348 * vector to add new dataset sequence to
4350 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
4351 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed)
4353 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
4355 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
4356 SequenceI dsq = null;
4357 if (sq != null && sq.getDatasetSequence() != null)
4359 dsq = sq.getDatasetSequence();
4361 if (sq == null && ignoreUnrefed)
4365 String sqid = vamsasSeq.getDsseqid();
4368 // need to create or add a new dataset sequence reference to this sequence
4371 dsq = seqRefIds.get(sqid);
4376 // make a new dataset sequence
4377 dsq = sq.createDatasetSequence();
4380 // make up a new dataset reference for this sequence
4381 sqid = seqHash(dsq);
4383 dsq.setVamsasId(uniqueSetSuffix + sqid);
4384 seqRefIds.put(sqid, dsq);
4389 dseqs.addElement(dsq);
4394 ds.addSequence(dsq);
4400 { // make this dataset sequence sq's dataset sequence
4401 sq.setDatasetSequence(dsq);
4402 // and update the current dataset alignment
4407 if (!dseqs.contains(dsq))
4414 if (ds.findIndex(dsq) < 0)
4416 ds.addSequence(dsq);
4423 // TODO: refactor this as a merge dataset sequence function
4424 // now check that sq (the dataset sequence) sequence really is the union of
4425 // all references to it
4426 // boolean pre = sq.getStart() < dsq.getStart();
4427 // boolean post = sq.getEnd() > dsq.getEnd();
4431 // StringBuffer sb = new StringBuffer();
4432 String newres = jalview.analysis.AlignSeq.extractGaps(
4433 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
4434 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
4435 && newres.length() > dsq.getLength())
4437 // Update with the longer sequence.
4441 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
4442 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
4443 * sb.append(newres.substring(newres.length() - sq.getEnd() -
4444 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
4446 dsq.setSequence(newres);
4448 // TODO: merges will never happen if we 'know' we have the real dataset
4449 // sequence - this should be detected when id==dssid
4451 .println("DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
4452 // + (pre ? "prepended" : "") + " "
4453 // + (post ? "appended" : ""));
4458 java.util.Hashtable datasetIds = null;
4460 java.util.IdentityHashMap dataset2Ids = null;
4462 private Alignment getDatasetFor(String datasetId)
4464 if (datasetIds == null)
4466 datasetIds = new Hashtable();
4469 if (datasetIds.containsKey(datasetId))
4471 return (Alignment) datasetIds.get(datasetId);
4476 private void addDatasetRef(String datasetId, Alignment dataset)
4478 if (datasetIds == null)
4480 datasetIds = new Hashtable();
4482 datasetIds.put(datasetId, dataset);
4486 * make a new dataset ID for this jalview dataset alignment
4491 private String getDatasetIdRef(jalview.datamodel.Alignment dataset)
4493 if (dataset.getDataset() != null)
4495 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
4497 String datasetId = makeHashCode(dataset, null);
4498 if (datasetId == null)
4500 // make a new datasetId and record it
4501 if (dataset2Ids == null)
4503 dataset2Ids = new IdentityHashMap();
4507 datasetId = (String) dataset2Ids.get(dataset);
4509 if (datasetId == null)
4511 datasetId = "ds" + dataset2Ids.size() + 1;
4512 dataset2Ids.put(dataset, datasetId);
4518 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
4520 for (int d = 0; d < sequence.getDBRefCount(); d++)
4522 DBRef dr = sequence.getDBRef(d);
4523 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
4524 sequence.getDBRef(d).getSource(), sequence.getDBRef(d)
4525 .getVersion(), sequence.getDBRef(d).getAccessionId());
4526 if (dr.getMapping() != null)
4528 entry.setMap(addMapping(dr.getMapping()));
4530 datasetSequence.addDBRef(entry);
4534 private jalview.datamodel.Mapping addMapping(Mapping m)
4536 SequenceI dsto = null;
4537 // Mapping m = dr.getMapping();
4538 int fr[] = new int[m.getMapListFromCount() * 2];
4539 Enumeration f = m.enumerateMapListFrom();
4540 for (int _i = 0; f.hasMoreElements(); _i += 2)
4542 MapListFrom mf = (MapListFrom) f.nextElement();
4543 fr[_i] = mf.getStart();
4544 fr[_i + 1] = mf.getEnd();
4546 int fto[] = new int[m.getMapListToCount() * 2];
4547 f = m.enumerateMapListTo();
4548 for (int _i = 0; f.hasMoreElements(); _i += 2)
4550 MapListTo mf = (MapListTo) f.nextElement();
4551 fto[_i] = mf.getStart();
4552 fto[_i + 1] = mf.getEnd();
4554 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto,
4555 fr, fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
4556 if (m.getMappingChoice() != null)
4558 MappingChoice mc = m.getMappingChoice();
4559 if (mc.getDseqFor() != null)
4561 String dsfor = "" + mc.getDseqFor();
4562 if (seqRefIds.containsKey(dsfor))
4567 jmap.setTo(seqRefIds.get(dsfor));
4571 frefedSequence.add(new Object[]
4578 * local sequence definition
4580 Sequence ms = mc.getSequence();
4581 SequenceI djs = null;
4582 String sqid = ms.getDsseqid();
4583 if (sqid != null && sqid.length() > 0)
4586 * recover dataset sequence
4588 djs = seqRefIds.get(sqid);
4593 .println("Warning - making up dataset sequence id for DbRef sequence map reference");
4594 sqid = ((Object) ms).toString(); // make up a new hascode for
4595 // undefined dataset sequence hash
4596 // (unlikely to happen)
4602 * make a new dataset sequence and add it to refIds hash
4604 djs = new jalview.datamodel.Sequence(ms.getName(),
4606 djs.setStart(jmap.getMap().getToLowest());
4607 djs.setEnd(jmap.getMap().getToHighest());
4608 djs.setVamsasId(uniqueSetSuffix + sqid);
4610 seqRefIds.put(sqid, djs);
4613 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
4622 public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
4623 boolean keepSeqRefs)
4626 jalview.schemabinding.version2.JalviewModel jm = saveState(ap, null,
4632 jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
4636 uniqueSetSuffix = "";
4637 jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
4642 if (this.frefedSequence == null)
4644 frefedSequence = new Vector();
4647 viewportsAdded.clear();
4649 AlignFrame af = loadFromObject(jm, null, false, null);
4650 af.alignPanels.clear();
4651 af.closeMenuItem_actionPerformed(true);
4654 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
4655 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
4656 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
4657 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
4658 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
4661 return af.alignPanel;
4665 * flag indicating if hashtables should be cleared on finalization TODO this
4666 * flag may not be necessary
4668 private final boolean _cleartables = true;
4670 private Hashtable jvids2vobj;
4675 * @see java.lang.Object#finalize()
4678 protected void finalize() throws Throwable
4680 // really make sure we have no buried refs left.
4685 this.seqRefIds = null;
4686 this.seqsToIds = null;
4690 private void warn(String msg)
4695 private void warn(String msg, Exception e)
4697 if (Cache.log != null)
4701 Cache.log.warn(msg, e);
4705 Cache.log.warn(msg);
4710 System.err.println("Warning: " + msg);
4713 e.printStackTrace();
4718 private void debug(String string)
4720 debug(string, null);
4723 private void debug(String msg, Exception e)
4725 if (Cache.log != null)
4729 Cache.log.debug(msg, e);
4733 Cache.log.debug(msg);
4738 System.err.println("Warning: " + msg);
4741 e.printStackTrace();
4747 * set the object to ID mapping tables used to write/recover objects and XML
4748 * ID strings for the jalview project. If external tables are provided then
4749 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
4750 * object goes out of scope. - also populates the datasetIds hashtable with
4751 * alignment objects containing dataset sequences
4754 * Map from ID strings to jalview datamodel
4756 * Map from jalview datamodel to ID strings
4760 public void setObjectMappingTables(Hashtable vobj2jv,
4761 IdentityHashMap jv2vobj)
4763 this.jv2vobj = jv2vobj;
4764 this.vobj2jv = vobj2jv;
4765 Iterator ds = jv2vobj.keySet().iterator();
4767 while (ds.hasNext())
4769 Object jvobj = ds.next();
4770 id = jv2vobj.get(jvobj).toString();
4771 if (jvobj instanceof jalview.datamodel.Alignment)
4773 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
4775 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
4778 else if (jvobj instanceof jalview.datamodel.Sequence)
4780 // register sequence object so the XML parser can recover it.
4781 if (seqRefIds == null)
4783 seqRefIds = new HashMap<String, SequenceI>();
4785 if (seqsToIds == null)
4787 seqsToIds = new IdentityHashMap<SequenceI, String>();
4789 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
4790 seqsToIds.put((SequenceI) jvobj, id);
4792 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
4795 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
4796 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
4797 if (jvann.annotationId == null)
4799 jvann.annotationId = anid;
4801 if (!jvann.annotationId.equals(anid))
4803 // TODO verify that this is the correct behaviour
4804 this.warn("Overriding Annotation ID for " + anid
4805 + " from different id : " + jvann.annotationId);
4806 jvann.annotationId = anid;
4809 else if (jvobj instanceof String)
4811 if (jvids2vobj == null)
4813 jvids2vobj = new Hashtable();
4814 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
4819 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
4825 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
4826 * objects created from the project archive. If string is null (default for
4827 * construction) then suffix will be set automatically.
4831 public void setUniqueSetSuffix(String string)
4833 uniqueSetSuffix = string;
4838 * uses skipList2 as the skipList for skipping views on sequence sets
4839 * associated with keys in the skipList
4843 public void setSkipList(Hashtable skipList2)
4845 skipList = skipList2;