2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import java.awt.Rectangle;
24 import java.io.BufferedReader;
25 import java.io.DataInputStream;
26 import java.io.DataOutputStream;
28 import java.io.FileInputStream;
29 import java.io.FileOutputStream;
30 import java.io.IOException;
31 import java.io.InputStreamReader;
32 import java.io.OutputStreamWriter;
33 import java.io.PrintWriter;
34 import java.lang.reflect.InvocationTargetException;
35 import java.net.MalformedURLException;
37 import java.util.ArrayList;
38 import java.util.Enumeration;
39 import java.util.HashMap;
40 import java.util.HashSet;
41 import java.util.Hashtable;
42 import java.util.IdentityHashMap;
43 import java.util.Iterator;
44 import java.util.LinkedHashMap;
45 import java.util.List;
47 import java.util.Map.Entry;
49 import java.util.StringTokenizer;
50 import java.util.Vector;
51 import java.util.jar.JarEntry;
52 import java.util.jar.JarInputStream;
53 import java.util.jar.JarOutputStream;
55 import javax.swing.JInternalFrame;
56 import javax.swing.JOptionPane;
57 import javax.swing.SwingUtilities;
59 import org.exolab.castor.xml.Marshaller;
60 import org.exolab.castor.xml.Unmarshaller;
62 import jalview.api.structures.JalviewStructureDisplayI;
63 import jalview.bin.Cache;
64 import jalview.datamodel.AlignedCodonFrame;
65 import jalview.datamodel.Alignment;
66 import jalview.datamodel.AlignmentAnnotation;
67 import jalview.datamodel.AlignmentI;
68 import jalview.datamodel.PDBEntry;
69 import jalview.datamodel.SequenceI;
70 import jalview.datamodel.StructureViewerModel;
71 import jalview.datamodel.StructureViewerModel.StructureData;
72 import jalview.gui.StructureViewer.ViewerType;
73 import jalview.schemabinding.version2.AlcodMap;
74 import jalview.schemabinding.version2.AlcodonFrame;
75 import jalview.schemabinding.version2.Annotation;
76 import jalview.schemabinding.version2.AnnotationColours;
77 import jalview.schemabinding.version2.AnnotationElement;
78 import jalview.schemabinding.version2.CalcIdParam;
79 import jalview.schemabinding.version2.DBRef;
80 import jalview.schemabinding.version2.Features;
81 import jalview.schemabinding.version2.Group;
82 import jalview.schemabinding.version2.HiddenColumns;
83 import jalview.schemabinding.version2.JGroup;
84 import jalview.schemabinding.version2.JSeq;
85 import jalview.schemabinding.version2.JalviewModel;
86 import jalview.schemabinding.version2.JalviewModelSequence;
87 import jalview.schemabinding.version2.MapListFrom;
88 import jalview.schemabinding.version2.MapListTo;
89 import jalview.schemabinding.version2.Mapping;
90 import jalview.schemabinding.version2.MappingChoice;
91 import jalview.schemabinding.version2.OtherData;
92 import jalview.schemabinding.version2.PdbentryItem;
93 import jalview.schemabinding.version2.Pdbids;
94 import jalview.schemabinding.version2.Property;
95 import jalview.schemabinding.version2.Sequence;
96 import jalview.schemabinding.version2.SequenceSet;
97 import jalview.schemabinding.version2.SequenceSetProperties;
98 import jalview.schemabinding.version2.Setting;
99 import jalview.schemabinding.version2.StructureState;
100 import jalview.schemabinding.version2.ThresholdLine;
101 import jalview.schemabinding.version2.Tree;
102 import jalview.schemabinding.version2.UserColours;
103 import jalview.schemabinding.version2.Viewport;
104 import jalview.schemes.AnnotationColourGradient;
105 import jalview.schemes.ColourSchemeI;
106 import jalview.schemes.ColourSchemeProperty;
107 import jalview.schemes.GraduatedColor;
108 import jalview.schemes.ResidueColourScheme;
109 import jalview.schemes.ResidueProperties;
110 import jalview.schemes.UserColourScheme;
111 import jalview.structure.StructureSelectionManager;
112 import jalview.structures.models.AAStructureBindingModel;
113 import jalview.util.MessageManager;
114 import jalview.util.Platform;
115 import jalview.util.jarInputStreamProvider;
116 import jalview.viewmodel.AlignmentViewport;
117 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
118 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
119 import jalview.ws.jws2.Jws2Discoverer;
120 import jalview.ws.jws2.dm.AAConSettings;
121 import jalview.ws.jws2.jabaws2.Jws2Instance;
122 import jalview.ws.params.ArgumentI;
123 import jalview.ws.params.AutoCalcSetting;
124 import jalview.ws.params.WsParamSetI;
127 * Write out the current jalview desktop state as a Jalview XML stream.
129 * Note: the vamsas objects referred to here are primitive versions of the
130 * VAMSAS project schema elements - they are not the same and most likely never
134 * @version $Revision: 1.134 $
136 public class Jalview2XML
138 private static final String UTF_8 = "UTF-8";
141 * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
142 * of sequence objects are created.
144 IdentityHashMap<SequenceI, String> seqsToIds = null;
147 * jalview XML Sequence ID to jalview sequence object reference (both dataset
148 * and alignment sequences. Populated as XML reps of sequence objects are
151 Map<String, SequenceI> seqRefIds = null;
153 Vector frefedSequence = null;
155 boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
158 * Map of reconstructed AlignFrame objects that appear to have come from
159 * SplitFrame objects (have a dna/protein complement view).
161 private Map<Viewport, AlignFrame> splitFrameCandidates = new HashMap<Viewport, AlignFrame>();
164 * create/return unique hash string for sq
167 * @return new or existing unique string for sq
169 String seqHash(SequenceI sq)
171 if (seqsToIds == null)
175 if (seqsToIds.containsKey(sq))
177 return seqsToIds.get(sq);
181 // create sequential key
182 String key = "sq" + (seqsToIds.size() + 1);
183 key = makeHashCode(sq, key); // check we don't have an external reference
185 seqsToIds.put(sq, key);
194 if (seqRefIds != null)
198 if (seqsToIds != null)
208 warn("clearSeqRefs called when _cleartables was not set. Doing nothing.");
209 // seqRefIds = new Hashtable();
210 // seqsToIds = new IdentityHashMap();
216 if (seqsToIds == null)
218 seqsToIds = new IdentityHashMap<SequenceI, String>();
220 if (seqRefIds == null)
222 seqRefIds = new HashMap<String, SequenceI>();
230 public Jalview2XML(boolean raiseGUI)
232 this.raiseGUI = raiseGUI;
235 public void resolveFrefedSequences()
237 if (frefedSequence.size() > 0)
239 int r = 0, rSize = frefedSequence.size();
242 Object[] ref = (Object[]) frefedSequence.elementAt(r);
245 String sref = (String) ref[0];
246 if (seqRefIds.containsKey(sref))
248 if (ref[1] instanceof jalview.datamodel.Mapping)
250 SequenceI seq = seqRefIds.get(sref);
251 while (seq.getDatasetSequence() != null)
253 seq = seq.getDatasetSequence();
255 ((jalview.datamodel.Mapping) ref[1]).setTo(seq);
259 if (ref[1] instanceof jalview.datamodel.AlignedCodonFrame)
261 SequenceI seq = seqRefIds.get(sref);
262 while (seq.getDatasetSequence() != null)
264 seq = seq.getDatasetSequence();
267 && ref[2] instanceof jalview.datamodel.Mapping)
269 jalview.datamodel.Mapping mp = (jalview.datamodel.Mapping) ref[2];
270 ((jalview.datamodel.AlignedCodonFrame) ref[1]).addMap(
271 seq, mp.getTo(), mp.getMap());
276 .println("IMPLEMENTATION ERROR: Unimplemented forward sequence references for AlcodonFrames involving "
277 + ref[2].getClass() + " type objects.");
283 .println("IMPLEMENTATION ERROR: Unimplemented forward sequence references for "
284 + ref[1].getClass() + " type objects.");
287 frefedSequence.remove(r);
293 .println("IMPLEMENTATION WARNING: Unresolved forward reference for hash string "
295 + " with objecttype "
296 + ref[1].getClass());
303 frefedSequence.remove(r);
311 * This maintains a map of viewports, the key being the seqSetId. Important to
312 * set historyItem and redoList for multiple views
314 Map<String, AlignViewport> viewportsAdded = new HashMap<String, AlignViewport>();
316 Map<String, AlignmentAnnotation> annotationIds = new HashMap<String, AlignmentAnnotation>();
318 String uniqueSetSuffix = "";
321 * List of pdbfiles added to Jar
323 List<String> pdbfiles = null;
325 // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
326 public void saveState(File statefile)
328 FileOutputStream fos = null;
331 fos = new FileOutputStream(statefile);
332 JarOutputStream jout = new JarOutputStream(fos);
335 } catch (Exception e)
337 // TODO: inform user of the problem - they need to know if their data was
339 if (errorMessage == null)
341 errorMessage = "Couldn't write Jalview Archive to output file '"
342 + statefile + "' - See console error log for details";
346 errorMessage += "(output file was '" + statefile + "')";
356 } catch (IOException e)
366 * Writes a jalview project archive to the given Jar output stream.
370 public void saveState(JarOutputStream jout)
372 AlignFrame[] frames = Desktop.getAlignFrames(); // Desktop.desktop.getAllFrames();
379 Hashtable<String, AlignFrame> dsses = new Hashtable<String, AlignFrame>();
384 // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
385 // //////////////////////////////////////////////////
387 List<String> shortNames = new ArrayList<String>();
390 for (int i = frames.length - 1; i > -1; i--)
392 AlignFrame af = frames[i];
396 .containsKey(af.getViewport().getSequenceSetId()))
401 String shortName = makeFilename(af, shortNames);
403 int ap, apSize = af.alignPanels.size();
405 for (ap = 0; ap < apSize; ap++)
407 AlignmentPanel apanel = af.alignPanels.get(ap);
408 String fileName = apSize == 1 ? shortName : ap + shortName;
409 if (!fileName.endsWith(".xml"))
411 fileName = fileName + ".xml";
414 saveState(apanel, fileName, jout);
416 String dssid = getDatasetIdRef(af.getViewport().getAlignment()
418 if (!dsses.containsKey(dssid))
420 dsses.put(dssid, af);
425 writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix,
431 } catch (Exception foo)
436 } catch (Exception ex)
438 // TODO: inform user of the problem - they need to know if their data was
440 if (errorMessage == null)
442 errorMessage = "Couldn't write Jalview Archive - see error output for details";
444 ex.printStackTrace();
449 * Generates a distinct file name, based on the title of the AlignFrame, by
450 * appending _n for increasing n until an unused name is generated. The new
451 * name (without its extension) is added to the list.
455 * @return the generated name, with .xml extension
457 protected String makeFilename(AlignFrame af, List<String> namesUsed)
459 String shortName = af.getTitle();
461 if (shortName.indexOf(File.separatorChar) > -1)
463 shortName = shortName.substring(shortName
464 .lastIndexOf(File.separatorChar) + 1);
469 while (namesUsed.contains(shortName))
471 if (shortName.endsWith("_" + (count - 1)))
473 shortName = shortName.substring(0, shortName.lastIndexOf("_"));
476 shortName = shortName.concat("_" + count);
480 namesUsed.add(shortName);
482 if (!shortName.endsWith(".xml"))
484 shortName = shortName + ".xml";
489 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
490 public boolean saveAlignment(AlignFrame af, String jarFile,
496 int apSize = af.alignPanels.size();
497 FileOutputStream fos = new FileOutputStream(jarFile);
498 JarOutputStream jout = new JarOutputStream(fos);
499 Hashtable<String, AlignFrame> dsses = new Hashtable<String, AlignFrame>();
500 for (AlignmentPanel apanel : af.alignPanels)
502 String jfileName = apSize == 1 ? fileName : fileName + ap;
504 if (!jfileName.endsWith(".xml"))
506 jfileName = jfileName + ".xml";
508 saveState(apanel, jfileName, jout);
509 String dssid = getDatasetIdRef(af.getViewport().getAlignment()
511 if (!dsses.containsKey(dssid))
513 dsses.put(dssid, af);
516 writeDatasetFor(dsses, fileName, jout);
520 } catch (Exception foo)
526 } catch (Exception ex)
528 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
529 ex.printStackTrace();
534 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
535 String fileName, JarOutputStream jout)
538 for (String dssids : dsses.keySet())
540 AlignFrame _af = dsses.get(dssids);
541 String jfileName = fileName + " Dataset for " + _af.getTitle();
542 if (!jfileName.endsWith(".xml"))
544 jfileName = jfileName + ".xml";
546 saveState(_af.alignPanel, jfileName, true, 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
563 public JalviewModel saveState(AlignmentPanel ap, String fileName,
564 JarOutputStream jout)
566 return saveState(ap, fileName, false, jout);
570 * create a JalviewModel from an alignment view and marshall it to a
574 * panel to create jalview model for
576 * name of alignment panel written to output stream
578 * when true, only write the dataset for the alignment, not the data
579 * associated with the view.
585 public JalviewModel saveState(AlignmentPanel ap, String fileName,
586 boolean storeDS, JarOutputStream jout)
589 List<String> viewIds = new ArrayList<String>();
590 List<UserColourScheme> userColours = new ArrayList<UserColourScheme>();
592 AlignViewport av = ap.av;
594 JalviewModel object = new JalviewModel();
595 object.setVamsasModel(new jalview.schemabinding.version2.VamsasModel());
597 object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
598 object.setVersion(jalview.bin.Cache.getDefault("VERSION",
599 "Development Build"));
601 jalview.datamodel.AlignmentI jal = av.getAlignment();
603 if (av.hasHiddenRows())
605 jal = jal.getHiddenSequences().getFullAlignment();
608 SequenceSet vamsasSet = new SequenceSet();
610 JalviewModelSequence jms = new JalviewModelSequence();
612 vamsasSet.setGapChar(jal.getGapCharacter() + "");
614 if (jal.getDataset() != null)
616 // dataset id is the dataset's hashcode
617 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
620 // switch jal and the dataset
621 jal = jal.getDataset();
624 if (jal.getProperties() != null)
626 Enumeration en = jal.getProperties().keys();
627 while (en.hasMoreElements())
629 String key = en.nextElement().toString();
630 SequenceSetProperties ssp = new SequenceSetProperties();
632 ssp.setValue(jal.getProperties().get(key).toString());
633 vamsasSet.addSequenceSetProperties(ssp);
638 Set<String> calcIdSet = new HashSet<String>();
642 jalview.datamodel.SequenceI jds, jdatasq;
643 for (int i = 0; i < jal.getHeight(); i++)
645 jds = jal.getSequenceAt(i);
646 jdatasq = jds.getDatasetSequence() == null ? jds : jds
647 .getDatasetSequence();
650 if (seqRefIds.get(id) != null)
652 // This happens for two reasons: 1. multiple views are being serialised.
653 // 2. the hashCode has collided with another sequence's code. This DOES
654 // HAPPEN! (PF00072.15.stk does this)
655 // JBPNote: Uncomment to debug writing out of files that do not read
656 // back in due to ArrayOutOfBoundExceptions.
657 // System.err.println("vamsasSeq backref: "+id+"");
658 // System.err.println(jds.getName()+"
659 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
660 // System.err.println("Hashcode: "+seqHash(jds));
661 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
662 // System.err.println(rsq.getName()+"
663 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
664 // System.err.println("Hashcode: "+seqHash(rsq));
668 vamsasSeq = createVamsasSequence(id, jds);
669 vamsasSet.addSequence(vamsasSeq);
670 seqRefIds.put(id, jds);
674 jseq.setStart(jds.getStart());
675 jseq.setEnd(jds.getEnd());
676 jseq.setColour(av.getSequenceColour(jds).getRGB());
678 jseq.setId(id); // jseq id should be a string not a number
681 // Store any sequences this sequence represents
682 if (av.hasHiddenRows())
684 jseq.setHidden(av.getAlignment().getHiddenSequences()
687 if (av.isHiddenRepSequence(jal.getSequenceAt(i)))
689 jalview.datamodel.SequenceI[] reps = av
690 .getRepresentedSequences(jal.getSequenceAt(i))
691 .getSequencesInOrder(jal);
693 for (int h = 0; h < reps.length; h++)
695 if (reps[h] != jal.getSequenceAt(i))
697 jseq.addHiddenSequences(jal.findIndex(reps[h]));
704 if (jds.getSequenceFeatures() != null)
706 jalview.datamodel.SequenceFeature[] sf = jds
707 .getSequenceFeatures();
709 while (index < sf.length)
711 Features features = new Features();
713 features.setBegin(sf[index].getBegin());
714 features.setEnd(sf[index].getEnd());
715 features.setDescription(sf[index].getDescription());
716 features.setType(sf[index].getType());
717 features.setFeatureGroup(sf[index].getFeatureGroup());
718 features.setScore(sf[index].getScore());
719 if (sf[index].links != null)
721 for (int l = 0; l < sf[index].links.size(); l++)
723 OtherData keyValue = new OtherData();
724 keyValue.setKey("LINK_" + l);
725 keyValue.setValue(sf[index].links.elementAt(l).toString());
726 features.addOtherData(keyValue);
729 if (sf[index].otherDetails != null)
732 Enumeration keys = sf[index].otherDetails.keys();
733 while (keys.hasMoreElements())
735 key = keys.nextElement().toString();
736 OtherData keyValue = new OtherData();
737 keyValue.setKey(key);
738 keyValue.setValue(sf[index].otherDetails.get(key).toString());
739 features.addOtherData(keyValue);
743 jseq.addFeatures(features);
748 if (jdatasq.getPDBId() != null)
750 Enumeration en = jdatasq.getPDBId().elements();
751 while (en.hasMoreElements())
753 Pdbids pdb = new Pdbids();
754 jalview.datamodel.PDBEntry entry = (jalview.datamodel.PDBEntry) en
757 String pdbId = entry.getId();
759 pdb.setType(entry.getType());
762 * Store any structure views associated with this sequence. This
763 * section copes with duplicate entries in the project, so a dataset
764 * only view *should* be coped with sensibly.
766 // This must have been loaded, is it still visible?
767 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
768 String matchedFile = null;
769 for (int f = frames.length - 1; f > -1; f--)
771 if (frames[f] instanceof StructureViewerBase)
773 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
774 matchedFile = saveStructureState(ap, jds, pdb, entry,
775 viewIds, matchedFile, viewFrame);
777 * Only store each structure viewer's state once in each XML
778 * document. First time through only (storeDS==false)
780 String viewId = viewFrame.getViewId();
781 if (!storeDS && !viewIds.contains(viewId))
786 writeJarEntry(jout, getViewerJarEntryName(viewId),
787 viewFrame.getStateInfo().getBytes());
788 } catch (IOException e)
790 System.err.println("Error saving viewer state: "
797 if (matchedFile != null || entry.getFile() != null)
799 if (entry.getFile() != null)
802 matchedFile = entry.getFile();
804 pdb.setFile(matchedFile); // entry.getFile());
805 if (pdbfiles == null)
807 pdbfiles = new ArrayList<String>();
810 if (!pdbfiles.contains(pdbId))
813 copyFileToJar(jout, matchedFile, pdbId);
817 if (entry.getProperty() != null && !entry.getProperty().isEmpty())
819 PdbentryItem item = new PdbentryItem();
820 Hashtable properties = entry.getProperty();
821 Enumeration en2 = properties.keys();
822 while (en2.hasMoreElements())
824 Property prop = new Property();
825 String key = en2.nextElement().toString();
827 prop.setValue(properties.get(key).toString());
828 item.addProperty(prop);
830 pdb.addPdbentryItem(item);
840 if (!storeDS && av.hasHiddenRows())
842 jal = av.getAlignment();
845 if (jal.getCodonFrames() != null)
847 Set<AlignedCodonFrame> jac = jal.getCodonFrames();
848 for (AlignedCodonFrame acf : jac)
850 AlcodonFrame alc = new AlcodonFrame();
851 vamsasSet.addAlcodonFrame(alc);
852 if (acf.getProtMappings() != null
853 && acf.getProtMappings().length > 0)
855 SequenceI[] dnas = acf.getdnaSeqs();
856 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
857 for (int m = 0; m < pmaps.length; m++)
859 AlcodMap alcmap = new AlcodMap();
860 alcmap.setDnasq(seqHash(dnas[m]));
861 alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
863 alc.addAlcodMap(alcmap);
868 // AlcodonFrame alc = new AlcodonFrame();
869 // vamsasSet.addAlcodonFrame(alc);
870 // for (int p = 0; p < acf.aaWidth; p++)
872 // Alcodon cmap = new Alcodon();
873 // if (acf.codons[p] != null)
875 // // Null codons indicate a gapped column in the translated peptide
877 // cmap.setPos1(acf.codons[p][0]);
878 // cmap.setPos2(acf.codons[p][1]);
879 // cmap.setPos3(acf.codons[p][2]);
881 // alc.addAlcodon(cmap);
883 // if (acf.getProtMappings() != null
884 // && acf.getProtMappings().length > 0)
886 // SequenceI[] dnas = acf.getdnaSeqs();
887 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
888 // for (int m = 0; m < pmaps.length; m++)
890 // AlcodMap alcmap = new AlcodMap();
891 // alcmap.setDnasq(seqHash(dnas[m]));
892 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
894 // alc.addAlcodMap(alcmap);
901 // /////////////////////////////////
902 if (!storeDS && av.currentTree != null)
904 // FIND ANY ASSOCIATED TREES
905 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
906 if (Desktop.desktop != null)
908 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
910 for (int t = 0; t < frames.length; t++)
912 if (frames[t] instanceof TreePanel)
914 TreePanel tp = (TreePanel) frames[t];
916 if (tp.treeCanvas.av.getAlignment() == jal)
918 Tree tree = new Tree();
919 tree.setTitle(tp.getTitle());
920 tree.setCurrentTree((av.currentTree == tp.getTree()));
921 tree.setNewick(tp.getTree().toString());
922 tree.setThreshold(tp.treeCanvas.threshold);
924 tree.setFitToWindow(tp.fitToWindow.getState());
925 tree.setFontName(tp.getTreeFont().getName());
926 tree.setFontSize(tp.getTreeFont().getSize());
927 tree.setFontStyle(tp.getTreeFont().getStyle());
928 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
930 tree.setShowBootstrap(tp.bootstrapMenu.getState());
931 tree.setShowDistances(tp.distanceMenu.getState());
933 tree.setHeight(tp.getHeight());
934 tree.setWidth(tp.getWidth());
935 tree.setXpos(tp.getX());
936 tree.setYpos(tp.getY());
937 tree.setId(makeHashCode(tp, null));
946 * Save associated Varna panels
948 if (Desktop.desktop != null)
950 for (JInternalFrame frame : Desktop.desktop.getAllFrames())
952 if (frame instanceof AppVarna)
954 AppVarna vp = (AppVarna) frame;
965 * store forward refs from an annotationRow to any groups
967 IdentityHashMap groupRefs = new IdentityHashMap();
970 for (SequenceI sq : jal.getSequences())
972 // Store annotation on dataset sequences only
973 jalview.datamodel.AlignmentAnnotation[] aa = sq.getAnnotation();
974 if (aa != null && aa.length > 0)
976 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
983 if (jal.getAlignmentAnnotation() != null)
985 // Store the annotation shown on the alignment.
986 jalview.datamodel.AlignmentAnnotation[] aa = jal
987 .getAlignmentAnnotation();
988 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
993 if (jal.getGroups() != null)
995 JGroup[] groups = new JGroup[jal.getGroups().size()];
997 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
999 groups[++i] = new JGroup();
1001 groups[i].setStart(sg.getStartRes());
1002 groups[i].setEnd(sg.getEndRes());
1003 groups[i].setName(sg.getName());
1004 if (groupRefs.containsKey(sg))
1006 // group has references so set it's ID field
1007 groups[i].setId(groupRefs.get(sg).toString());
1011 if (sg.cs.conservationApplied())
1013 groups[i].setConsThreshold(sg.cs.getConservationInc());
1015 if (sg.cs instanceof jalview.schemes.UserColourScheme)
1017 groups[i].setColour(setUserColourScheme(sg.cs, userColours,
1023 .setColour(ColourSchemeProperty.getColourName(sg.cs));
1026 else if (sg.cs instanceof jalview.schemes.AnnotationColourGradient)
1028 groups[i].setColour("AnnotationColourGradient");
1029 groups[i].setAnnotationColours(constructAnnotationColours(
1030 (jalview.schemes.AnnotationColourGradient) sg.cs,
1033 else if (sg.cs instanceof jalview.schemes.UserColourScheme)
1036 .setColour(setUserColourScheme(sg.cs, userColours, jms));
1040 groups[i].setColour(ColourSchemeProperty.getColourName(sg.cs));
1043 groups[i].setPidThreshold(sg.cs.getThreshold());
1046 groups[i].setOutlineColour(sg.getOutlineColour().getRGB());
1047 groups[i].setDisplayBoxes(sg.getDisplayBoxes());
1048 groups[i].setDisplayText(sg.getDisplayText());
1049 groups[i].setColourText(sg.getColourText());
1050 groups[i].setTextCol1(sg.textColour.getRGB());
1051 groups[i].setTextCol2(sg.textColour2.getRGB());
1052 groups[i].setTextColThreshold(sg.thresholdTextColour);
1053 groups[i].setShowUnconserved(sg.getShowNonconserved());
1054 groups[i].setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1055 groups[i].setShowConsensusHistogram(sg.isShowConsensusHistogram());
1056 groups[i].setShowSequenceLogo(sg.isShowSequenceLogo());
1057 groups[i].setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1058 for (int s = 0; s < sg.getSize(); s++)
1060 jalview.datamodel.Sequence seq = (jalview.datamodel.Sequence) sg
1062 groups[i].addSeq(seqHash(seq));
1066 jms.setJGroup(groups);
1070 // /////////SAVE VIEWPORT
1071 Viewport view = new Viewport();
1072 view.setTitle(ap.alignFrame.getTitle());
1073 view.setSequenceSetId(makeHashCode(av.getSequenceSetId(),
1074 av.getSequenceSetId()));
1075 view.setId(av.getViewId());
1076 if (av.getCodingComplement() != null)
1078 view.setComplementId(av.getCodingComplement().getViewId());
1080 view.setViewName(av.viewName);
1081 view.setGatheredViews(av.isGatherViewsHere());
1083 Rectangle position = ap.av.getExplodedGeometry();
1084 if (position == null)
1086 position = ap.alignFrame.getBounds();
1088 view.setXpos(position.x);
1089 view.setYpos(position.y);
1090 view.setWidth(position.width);
1091 view.setHeight(position.height);
1093 view.setStartRes(av.startRes);
1094 view.setStartSeq(av.startSeq);
1096 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1098 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1101 else if (av.getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1103 AnnotationColours ac = constructAnnotationColours(
1104 (jalview.schemes.AnnotationColourGradient) av
1105 .getGlobalColourScheme(),
1108 view.setAnnotationColours(ac);
1109 view.setBgColour("AnnotationColourGradient");
1113 view.setBgColour(ColourSchemeProperty.getColourName(av
1114 .getGlobalColourScheme()));
1117 ColourSchemeI cs = av.getGlobalColourScheme();
1121 if (cs.conservationApplied())
1123 view.setConsThreshold(cs.getConservationInc());
1124 if (cs instanceof jalview.schemes.UserColourScheme)
1126 view.setBgColour(setUserColourScheme(cs, userColours, jms));
1130 if (cs instanceof ResidueColourScheme)
1132 view.setPidThreshold(cs.getThreshold());
1136 view.setConservationSelected(av.getConservationSelected());
1137 view.setPidSelected(av.getAbovePIDThreshold());
1138 view.setFontName(av.font.getName());
1139 view.setFontSize(av.font.getSize());
1140 view.setFontStyle(av.font.getStyle());
1141 view.setRenderGaps(av.isRenderGaps());
1142 view.setShowAnnotation(av.isShowAnnotation());
1143 view.setShowBoxes(av.getShowBoxes());
1144 view.setShowColourText(av.getColourText());
1145 view.setShowFullId(av.getShowJVSuffix());
1146 view.setRightAlignIds(av.isRightAlignIds());
1147 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1148 view.setShowText(av.getShowText());
1149 view.setShowUnconserved(av.getShowUnconserved());
1150 view.setWrapAlignment(av.getWrapAlignment());
1151 view.setTextCol1(av.getTextColour().getRGB());
1152 view.setTextCol2(av.getTextColour2().getRGB());
1153 view.setTextColThreshold(av.getThresholdTextColour());
1154 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1155 view.setShowSequenceLogo(av.isShowSequenceLogo());
1156 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1157 view.setShowGroupConsensus(av.isShowGroupConsensus());
1158 view.setShowGroupConservation(av.isShowGroupConservation());
1159 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1160 view.setShowDbRefTooltip(av.isShowDBRefs());
1161 view.setFollowHighlight(av.isFollowHighlight());
1162 view.setFollowSelection(av.followSelection);
1163 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1164 if (av.getFeaturesDisplayed() != null)
1166 jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
1168 String[] renderOrder = ap.getSeqPanel().seqCanvas
1169 .getFeatureRenderer().getRenderOrder()
1170 .toArray(new String[0]);
1172 Vector settingsAdded = new Vector();
1173 Object gstyle = null;
1174 GraduatedColor gcol = null;
1175 if (renderOrder != null)
1177 for (int ro = 0; ro < renderOrder.length; ro++)
1179 gstyle = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1180 .getFeatureStyle(renderOrder[ro]);
1181 Setting setting = new Setting();
1182 setting.setType(renderOrder[ro]);
1183 if (gstyle instanceof GraduatedColor)
1185 gcol = (GraduatedColor) gstyle;
1186 setting.setColour(gcol.getMaxColor().getRGB());
1187 setting.setMincolour(gcol.getMinColor().getRGB());
1188 setting.setMin(gcol.getMin());
1189 setting.setMax(gcol.getMax());
1190 setting.setColourByLabel(gcol.isColourByLabel());
1191 setting.setAutoScale(gcol.isAutoScale());
1192 setting.setThreshold(gcol.getThresh());
1193 setting.setThreshstate(gcol.getThreshType());
1197 setting.setColour(ap.getSeqPanel().seqCanvas
1198 .getFeatureRenderer()
1199 .getColour(renderOrder[ro]).getRGB());
1202 setting.setDisplay(av.getFeaturesDisplayed().isVisible(
1204 float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1205 .getOrder(renderOrder[ro]);
1208 setting.setOrder(rorder);
1210 fs.addSetting(setting);
1211 settingsAdded.addElement(renderOrder[ro]);
1215 // Make sure we save none displayed feature settings
1216 Iterator en = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1217 .getFeatureColours().keySet().iterator();
1218 while (en.hasNext())
1220 String key = en.next().toString();
1221 if (settingsAdded.contains(key))
1226 Setting setting = new Setting();
1227 setting.setType(key);
1228 setting.setColour(ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1229 .getColour(key).getRGB());
1231 setting.setDisplay(false);
1232 float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1236 setting.setOrder(rorder);
1238 fs.addSetting(setting);
1239 settingsAdded.addElement(key);
1241 // is groups actually supposed to be a map here ?
1242 en = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1243 .getFeatureGroups().iterator();
1244 Vector groupsAdded = new Vector();
1245 while (en.hasNext())
1247 String grp = en.next().toString();
1248 if (groupsAdded.contains(grp))
1252 Group g = new Group();
1254 g.setDisplay(((Boolean) ap.getSeqPanel().seqCanvas
1255 .getFeatureRenderer().checkGroupVisibility(grp, false))
1258 groupsAdded.addElement(grp);
1260 jms.setFeatureSettings(fs);
1264 if (av.hasHiddenColumns())
1266 if (av.getColumnSelection() == null
1267 || av.getColumnSelection().getHiddenColumns() == null)
1269 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1273 for (int c = 0; c < av.getColumnSelection().getHiddenColumns()
1276 int[] region = av.getColumnSelection().getHiddenColumns()
1278 HiddenColumns hc = new HiddenColumns();
1279 hc.setStart(region[0]);
1280 hc.setEnd(region[1]);
1281 view.addHiddenColumns(hc);
1285 if (calcIdSet.size() > 0)
1287 for (String calcId : calcIdSet)
1289 if (calcId.trim().length() > 0)
1291 CalcIdParam cidp = createCalcIdParam(calcId, av);
1292 // Some calcIds have no parameters.
1295 view.addCalcIdParam(cidp);
1301 jms.addViewport(view);
1303 object.setJalviewModelSequence(jms);
1304 object.getVamsasModel().addSequenceSet(vamsasSet);
1306 if (jout != null && fileName != null)
1308 // We may not want to write the object to disk,
1309 // eg we can copy the alignViewport to a new view object
1310 // using save and then load
1313 JarEntry entry = new JarEntry(fileName);
1314 jout.putNextEntry(entry);
1315 PrintWriter pout = new PrintWriter(new OutputStreamWriter(jout,
1317 Marshaller marshaller = new Marshaller(pout);
1318 marshaller.marshal(object);
1321 } catch (Exception ex)
1323 // TODO: raise error in GUI if marshalling failed.
1324 ex.printStackTrace();
1331 * Copy the contents of a file to a new file added to the output jar
1335 * @param jarfileName
1337 protected void copyFileToJar(JarOutputStream jout, String infilePath,
1340 DataInputStream dis = null;
1343 File file = new File(infilePath);
1344 if (file.exists() && jout != null)
1346 dis = new DataInputStream(new FileInputStream(file));
1347 byte[] data = new byte[(int) file.length()];
1348 dis.readFully(data);
1349 writeJarEntry(jout, jarfileName, data);
1351 } catch (Exception ex)
1353 ex.printStackTrace();
1361 } catch (IOException e)
1370 * Write the data to a new entry of given name in the output jar file
1373 * @param jarfileName
1375 * @throws IOException
1377 protected void writeJarEntry(JarOutputStream jout, String jarfileName,
1378 byte[] data) throws IOException
1382 jout.putNextEntry(new JarEntry(jarfileName));
1383 DataOutputStream dout = new DataOutputStream(jout);
1384 dout.write(data, 0, data.length);
1391 * Save the state of a structure viewer
1396 * the archive XML element under which to save the state
1399 * @param matchedFile
1403 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
1404 Pdbids pdb, PDBEntry entry, List<String> viewIds,
1405 String matchedFile, StructureViewerBase viewFrame)
1407 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
1410 * Look for any bindings for this viewer to the PDB file of interest
1411 * (including part matches excluding chain id)
1413 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
1415 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
1416 final String pdbId = pdbentry.getId();
1417 if (!pdbId.equals(entry.getId())
1418 && !(entry.getId().length() > 4 && entry.getId()
1419 .toLowerCase().startsWith(pdbId.toLowerCase())))
1422 * not interested in a binding to a different PDB entry here
1426 if (matchedFile == null)
1428 matchedFile = pdbentry.getFile();
1430 else if (!matchedFile.equals(pdbentry.getFile()))
1433 .warn("Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
1434 + pdbentry.getFile());
1438 // can get at it if the ID
1439 // match is ambiguous (e.g.
1442 for (int smap = 0; smap < viewFrame.getBinding().getSequence()[peid].length; smap++)
1444 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
1445 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
1447 StructureState state = new StructureState();
1448 state.setVisible(true);
1449 state.setXpos(viewFrame.getX());
1450 state.setYpos(viewFrame.getY());
1451 state.setWidth(viewFrame.getWidth());
1452 state.setHeight(viewFrame.getHeight());
1453 final String viewId = viewFrame.getViewId();
1454 state.setViewId(viewId);
1455 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
1456 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
1457 state.setColourByJmol(viewFrame.isColouredByViewer());
1458 state.setType(viewFrame.getViewerType().toString());
1459 pdb.addStructureState(state);
1466 private AnnotationColours constructAnnotationColours(
1467 AnnotationColourGradient acg, List<UserColourScheme> userColours,
1468 JalviewModelSequence jms)
1470 AnnotationColours ac = new AnnotationColours();
1471 ac.setAboveThreshold(acg.getAboveThreshold());
1472 ac.setThreshold(acg.getAnnotationThreshold());
1473 ac.setAnnotation(acg.getAnnotation());
1474 if (acg.getBaseColour() instanceof jalview.schemes.UserColourScheme)
1476 ac.setColourScheme(setUserColourScheme(acg.getBaseColour(),
1481 ac.setColourScheme(ColourSchemeProperty.getColourName(acg
1485 ac.setMaxColour(acg.getMaxColour().getRGB());
1486 ac.setMinColour(acg.getMinColour().getRGB());
1487 ac.setPerSequence(acg.isSeqAssociated());
1488 ac.setPredefinedColours(acg.isPredefinedColours());
1492 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
1493 IdentityHashMap groupRefs, AlignmentViewport av,
1494 Set<String> calcIdSet, boolean storeDS, SequenceSet vamsasSet)
1497 for (int i = 0; i < aa.length; i++)
1499 Annotation an = new Annotation();
1501 if (aa[i].annotationId != null)
1503 annotationIds.put(aa[i].annotationId, aa[i]);
1506 an.setId(aa[i].annotationId);
1508 an.setVisible(aa[i].visible);
1510 an.setDescription(aa[i].description);
1512 if (aa[i].sequenceRef != null)
1514 // TODO later annotation sequenceRef should be the XML ID of the
1515 // sequence rather than its display name
1516 an.setSequenceRef(aa[i].sequenceRef.getName());
1518 if (aa[i].groupRef != null)
1520 Object groupIdr = groupRefs.get(aa[i].groupRef);
1521 if (groupIdr == null)
1523 // make a locally unique String
1524 groupRefs.put(aa[i].groupRef,
1525 groupIdr = ("" + System.currentTimeMillis()
1526 + aa[i].groupRef.getName() + groupRefs.size()));
1528 an.setGroupRef(groupIdr.toString());
1531 // store all visualization attributes for annotation
1532 an.setGraphHeight(aa[i].graphHeight);
1533 an.setCentreColLabels(aa[i].centreColLabels);
1534 an.setScaleColLabels(aa[i].scaleColLabel);
1535 an.setShowAllColLabels(aa[i].showAllColLabels);
1536 an.setBelowAlignment(aa[i].belowAlignment);
1538 if (aa[i].graph > 0)
1541 an.setGraphType(aa[i].graph);
1542 an.setGraphGroup(aa[i].graphGroup);
1543 if (aa[i].getThreshold() != null)
1545 ThresholdLine line = new ThresholdLine();
1546 line.setLabel(aa[i].getThreshold().label);
1547 line.setValue(aa[i].getThreshold().value);
1548 line.setColour(aa[i].getThreshold().colour.getRGB());
1549 an.setThresholdLine(line);
1557 an.setLabel(aa[i].label);
1559 if (aa[i] == av.getAlignmentQualityAnnot()
1560 || aa[i] == av.getAlignmentConservationAnnotation()
1561 || aa[i] == av.getAlignmentConsensusAnnotation()
1562 || aa[i].autoCalculated)
1564 // new way of indicating autocalculated annotation -
1565 an.setAutoCalculated(aa[i].autoCalculated);
1567 if (aa[i].hasScore())
1569 an.setScore(aa[i].getScore());
1572 if (aa[i].getCalcId() != null)
1574 calcIdSet.add(aa[i].getCalcId());
1575 an.setCalcId(aa[i].getCalcId());
1577 if (aa[i].hasProperties())
1579 for (String pr : aa[i].getProperties())
1581 Property prop = new Property();
1583 prop.setValue(aa[i].getProperty(pr));
1584 an.addProperty(prop);
1588 AnnotationElement ae;
1589 if (aa[i].annotations != null)
1591 an.setScoreOnly(false);
1592 for (int a = 0; a < aa[i].annotations.length; a++)
1594 if ((aa[i] == null) || (aa[i].annotations[a] == null))
1599 ae = new AnnotationElement();
1600 if (aa[i].annotations[a].description != null)
1602 ae.setDescription(aa[i].annotations[a].description);
1604 if (aa[i].annotations[a].displayCharacter != null)
1606 ae.setDisplayCharacter(aa[i].annotations[a].displayCharacter);
1609 if (!Float.isNaN(aa[i].annotations[a].value))
1611 ae.setValue(aa[i].annotations[a].value);
1615 if (aa[i].annotations[a].secondaryStructure > ' ')
1617 ae.setSecondaryStructure(aa[i].annotations[a].secondaryStructure
1621 if (aa[i].annotations[a].colour != null
1622 && aa[i].annotations[a].colour != java.awt.Color.black)
1624 ae.setColour(aa[i].annotations[a].colour.getRGB());
1627 an.addAnnotationElement(ae);
1628 if (aa[i].autoCalculated)
1630 // only write one non-null entry into the annotation row -
1631 // sufficient to get the visualization attributes necessary to
1639 an.setScoreOnly(true);
1641 if (!storeDS || (storeDS && !aa[i].autoCalculated))
1643 // skip autocalculated annotation - these are only provided for
1645 vamsasSet.addAnnotation(an);
1651 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
1653 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
1654 if (settings != null)
1656 CalcIdParam vCalcIdParam = new CalcIdParam();
1657 vCalcIdParam.setCalcId(calcId);
1658 vCalcIdParam.addServiceURL(settings.getServiceURI());
1659 // generic URI allowing a third party to resolve another instance of the
1660 // service used for this calculation
1661 for (String urls : settings.getServiceURLs())
1663 vCalcIdParam.addServiceURL(urls);
1665 vCalcIdParam.setVersion("1.0");
1666 if (settings.getPreset() != null)
1668 WsParamSetI setting = settings.getPreset();
1669 vCalcIdParam.setName(setting.getName());
1670 vCalcIdParam.setDescription(setting.getDescription());
1674 vCalcIdParam.setName("");
1675 vCalcIdParam.setDescription("Last used parameters");
1677 // need to be able to recover 1) settings 2) user-defined presets or
1678 // recreate settings from preset 3) predefined settings provided by
1679 // service - or settings that can be transferred (or discarded)
1680 vCalcIdParam.setParameters(settings.getWsParamFile().replace("\n",
1682 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
1683 // todo - decide if updateImmediately is needed for any projects.
1685 return vCalcIdParam;
1690 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
1693 if (calcIdParam.getVersion().equals("1.0"))
1695 Jws2Instance service = Jws2Discoverer.getDiscoverer()
1696 .getPreferredServiceFor(calcIdParam.getServiceURL());
1697 if (service != null)
1699 WsParamSetI parmSet = null;
1702 parmSet = service.getParamStore().parseServiceParameterFile(
1703 calcIdParam.getName(), calcIdParam.getDescription(),
1704 calcIdParam.getServiceURL(),
1705 calcIdParam.getParameters().replace("|\\n|", "\n"));
1706 } catch (IOException x)
1708 warn("Couldn't parse parameter data for "
1709 + calcIdParam.getCalcId(), x);
1712 List<ArgumentI> argList = null;
1713 if (calcIdParam.getName().length() > 0)
1715 parmSet = service.getParamStore()
1716 .getPreset(calcIdParam.getName());
1717 if (parmSet != null)
1719 // TODO : check we have a good match with settings in AACon -
1720 // otherwise we'll need to create a new preset
1725 argList = parmSet.getArguments();
1728 AAConSettings settings = new AAConSettings(
1729 calcIdParam.isAutoUpdate(), service, parmSet, argList);
1730 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
1731 calcIdParam.isNeedsUpdate());
1736 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
1740 throw new Error(MessageManager.formatMessage(
1741 "error.unsupported_version_calcIdparam", new Object[]
1742 { calcIdParam.toString() }));
1746 * External mapping between jalview objects and objects yielding a valid and
1747 * unique object ID string. This is null for normal Jalview project IO, but
1748 * non-null when a jalview project is being read or written as part of a
1751 IdentityHashMap jv2vobj = null;
1754 * Construct a unique ID for jvobj using either existing bindings or if none
1755 * exist, the result of the hashcode call for the object.
1758 * jalview data object
1759 * @return unique ID for referring to jvobj
1761 private String makeHashCode(Object jvobj, String altCode)
1763 if (jv2vobj != null)
1765 Object id = jv2vobj.get(jvobj);
1768 return id.toString();
1770 // check string ID mappings
1771 if (jvids2vobj != null && jvobj instanceof String)
1773 id = jvids2vobj.get(jvobj);
1777 return id.toString();
1779 // give up and warn that something has gone wrong
1780 warn("Cannot find ID for object in external mapping : " + jvobj);
1786 * return local jalview object mapped to ID, if it exists
1790 * @return null or object bound to idcode
1792 private Object retrieveExistingObj(String idcode)
1794 if (idcode != null && vobj2jv != null)
1796 return vobj2jv.get(idcode);
1802 * binding from ID strings from external mapping table to jalview data model
1805 private Hashtable vobj2jv;
1807 private Sequence createVamsasSequence(String id, SequenceI jds)
1809 return createVamsasSequence(true, id, jds, null);
1812 private Sequence createVamsasSequence(boolean recurse, String id,
1813 SequenceI jds, SequenceI parentseq)
1815 Sequence vamsasSeq = new Sequence();
1816 vamsasSeq.setId(id);
1817 vamsasSeq.setName(jds.getName());
1818 vamsasSeq.setSequence(jds.getSequenceAsString());
1819 vamsasSeq.setDescription(jds.getDescription());
1820 jalview.datamodel.DBRefEntry[] dbrefs = null;
1821 if (jds.getDatasetSequence() != null)
1823 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
1824 if (jds.getDatasetSequence().getDBRef() != null)
1826 dbrefs = jds.getDatasetSequence().getDBRef();
1831 vamsasSeq.setDsseqid(id); // so we can tell which sequences really are
1832 // dataset sequences only
1833 dbrefs = jds.getDBRef();
1837 for (int d = 0; d < dbrefs.length; d++)
1839 DBRef dbref = new DBRef();
1840 dbref.setSource(dbrefs[d].getSource());
1841 dbref.setVersion(dbrefs[d].getVersion());
1842 dbref.setAccessionId(dbrefs[d].getAccessionId());
1843 if (dbrefs[d].hasMap())
1845 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
1847 dbref.setMapping(mp);
1849 vamsasSeq.addDBRef(dbref);
1855 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
1856 SequenceI parentseq, SequenceI jds, boolean recurse)
1859 if (jmp.getMap() != null)
1863 jalview.util.MapList mlst = jmp.getMap();
1864 List<int[]> r = mlst.getFromRanges();
1865 for (int[] range : r)
1867 MapListFrom mfrom = new MapListFrom();
1868 mfrom.setStart(range[0]);
1869 mfrom.setEnd(range[1]);
1870 mp.addMapListFrom(mfrom);
1872 r = mlst.getToRanges();
1873 for (int[] range : r)
1875 MapListTo mto = new MapListTo();
1876 mto.setStart(range[0]);
1877 mto.setEnd(range[1]);
1878 mp.addMapListTo(mto);
1880 mp.setMapFromUnit(mlst.getFromRatio());
1881 mp.setMapToUnit(mlst.getToRatio());
1882 if (jmp.getTo() != null)
1884 MappingChoice mpc = new MappingChoice();
1886 && (parentseq != jmp.getTo() || parentseq
1887 .getDatasetSequence() != jmp.getTo()))
1889 mpc.setSequence(createVamsasSequence(false, seqHash(jmp.getTo()),
1895 SequenceI ps = null;
1896 if (parentseq != jmp.getTo()
1897 && parentseq.getDatasetSequence() != jmp.getTo())
1899 // chaining dbref rather than a handshaking one
1900 jmpid = seqHash(ps = jmp.getTo());
1904 jmpid = seqHash(ps = parentseq);
1906 mpc.setDseqFor(jmpid);
1907 if (!seqRefIds.containsKey(mpc.getDseqFor()))
1909 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
1910 seqRefIds.put(mpc.getDseqFor(), ps);
1914 jalview.bin.Cache.log.debug("reusing DseqFor ID");
1917 mp.setMappingChoice(mpc);
1923 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
1924 List<UserColourScheme> userColours, JalviewModelSequence jms)
1927 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
1928 boolean newucs = false;
1929 if (!userColours.contains(ucs))
1931 userColours.add(ucs);
1934 id = "ucs" + userColours.indexOf(ucs);
1937 // actually create the scheme's entry in the XML model
1938 java.awt.Color[] colours = ucs.getColours();
1939 jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
1940 jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
1942 for (int i = 0; i < colours.length; i++)
1944 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
1945 col.setName(ResidueProperties.aa[i]);
1946 col.setRGB(jalview.util.Format.getHexString(colours[i]));
1947 jbucs.addColour(col);
1949 if (ucs.getLowerCaseColours() != null)
1951 colours = ucs.getLowerCaseColours();
1952 for (int i = 0; i < colours.length; i++)
1954 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
1955 col.setName(ResidueProperties.aa[i].toLowerCase());
1956 col.setRGB(jalview.util.Format.getHexString(colours[i]));
1957 jbucs.addColour(col);
1962 uc.setUserColourScheme(jbucs);
1963 jms.addUserColours(uc);
1969 jalview.schemes.UserColourScheme getUserColourScheme(
1970 JalviewModelSequence jms, String id)
1972 UserColours[] uc = jms.getUserColours();
1973 UserColours colours = null;
1975 for (int i = 0; i < uc.length; i++)
1977 if (uc[i].getId().equals(id))
1985 java.awt.Color[] newColours = new java.awt.Color[24];
1987 for (int i = 0; i < 24; i++)
1989 newColours[i] = new java.awt.Color(Integer.parseInt(colours
1990 .getUserColourScheme().getColour(i).getRGB(), 16));
1993 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
1996 if (colours.getUserColourScheme().getColourCount() > 24)
1998 newColours = new java.awt.Color[23];
1999 for (int i = 0; i < 23; i++)
2001 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2002 .getUserColourScheme().getColour(i + 24).getRGB(), 16));
2004 ucs.setLowerCaseColours(newColours);
2011 * contains last error message (if any) encountered by XML loader.
2013 String errorMessage = null;
2016 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2017 * exceptions are raised during project XML parsing
2019 public boolean attemptversion1parse = true;
2022 * Load a jalview project archive from a jar file
2025 * - HTTP URL or filename
2027 public AlignFrame loadJalviewAlign(final String file)
2030 jalview.gui.AlignFrame af = null;
2034 // create list to store references for any new Jmol viewers created
2035 newStructureViewers = new Vector<JalviewStructureDisplayI>();
2036 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2037 // Workaround is to make sure caller implements the JarInputStreamProvider
2039 // so we can re-open the jar input stream for each entry.
2041 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2042 af = loadJalviewAlign(jprovider);
2044 } catch (MalformedURLException e)
2046 errorMessage = "Invalid URL format for '" + file + "'";
2052 SwingUtilities.invokeAndWait(new Runnable()
2056 setLoadingFinishedForNewStructureViewers();
2059 } catch (Exception x)
2067 private jarInputStreamProvider createjarInputStreamProvider(
2068 final String file) throws MalformedURLException
2071 errorMessage = null;
2072 uniqueSetSuffix = null;
2074 viewportsAdded.clear();
2075 frefedSequence = null;
2077 if (file.startsWith("http://"))
2079 url = new URL(file);
2081 final URL _url = url;
2082 return new jarInputStreamProvider()
2086 public JarInputStream getJarInputStream() throws IOException
2090 return new JarInputStream(_url.openStream());
2094 return new JarInputStream(new FileInputStream(file));
2099 public String getFilename()
2107 * Recover jalview session from a jalview project archive. Caller may
2108 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2109 * themselves. Any null fields will be initialised with default values,
2110 * non-null fields are left alone.
2115 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2117 errorMessage = null;
2118 if (uniqueSetSuffix == null)
2120 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2122 if (seqRefIds == null)
2124 seqRefIds = new HashMap<String, SequenceI>();
2126 if (frefedSequence == null)
2128 frefedSequence = new Vector();
2131 AlignFrame af = null, _af = null;
2132 Map<String, AlignFrame> gatherToThisFrame = new HashMap<String, AlignFrame>();
2133 final String file = jprovider.getFilename();
2136 JarInputStream jin = null;
2137 JarEntry jarentry = null;
2142 jin = jprovider.getJarInputStream();
2143 for (int i = 0; i < entryCount; i++)
2145 jarentry = jin.getNextJarEntry();
2148 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2150 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2151 JalviewModel object = new JalviewModel();
2153 Unmarshaller unmar = new Unmarshaller(object);
2154 unmar.setValidation(false);
2155 object = (JalviewModel) unmar.unmarshal(in);
2156 if (true) // !skipViewport(object))
2158 _af = loadFromObject(object, file, true, jprovider);
2159 if (object.getJalviewModelSequence().getViewportCount() > 0)
2162 if (af.viewport.isGatherViewsHere())
2164 gatherToThisFrame.put(af.viewport.getSequenceSetId(), af);
2170 else if (jarentry != null)
2172 // Some other file here.
2175 } while (jarentry != null);
2176 resolveFrefedSequences();
2177 } catch (java.io.FileNotFoundException ex)
2179 ex.printStackTrace();
2180 errorMessage = "Couldn't locate Jalview XML file : " + file;
2181 System.err.println("Exception whilst loading jalview XML file : "
2183 } catch (java.net.UnknownHostException ex)
2185 ex.printStackTrace();
2186 errorMessage = "Couldn't locate Jalview XML file : " + file;
2187 System.err.println("Exception whilst loading jalview XML file : "
2189 } catch (Exception ex)
2191 System.err.println("Parsing as Jalview Version 2 file failed.");
2192 ex.printStackTrace(System.err);
2193 if (attemptversion1parse)
2195 // Is Version 1 Jar file?
2198 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
2199 } catch (Exception ex2)
2201 System.err.println("Exception whilst loading as jalviewXMLV1:");
2202 ex2.printStackTrace();
2206 if (Desktop.instance != null)
2208 Desktop.instance.stopLoading();
2212 System.out.println("Successfully loaded archive file");
2215 ex.printStackTrace();
2217 System.err.println("Exception whilst loading jalview XML file : "
2219 } catch (OutOfMemoryError e)
2221 // Don't use the OOM Window here
2222 errorMessage = "Out of memory loading jalview XML file";
2223 System.err.println("Out of memory whilst loading jalview XML file");
2224 e.printStackTrace();
2227 if (Desktop.instance != null)
2229 Desktop.instance.stopLoading();
2233 * Regather multiple views (with the same sequence set id) to the frame (if
2234 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2235 * views instead of separate frames. Note this doesn't restore a state where
2236 * some expanded views in turn have tabbed views - the last "first tab" read
2237 * in will play the role of gatherer for all.
2239 for (AlignFrame fr : gatherToThisFrame.values())
2241 Desktop.instance.gatherViews(fr);
2244 restoreSplitFrames();
2246 if (errorMessage != null)
2254 * Try to reconstruct and display SplitFrame windows, where each contains
2255 * complementary dna and protein alignments. Done by pairing up AlignFrame
2256 * objects (created earlier) which have complementary viewport ids associated.
2258 protected void restoreSplitFrames()
2260 List<SplitFrame> gatherTo = new ArrayList<SplitFrame>();
2261 List<AlignFrame> addedToSplitFrames = new ArrayList<AlignFrame>();
2262 Map<String, AlignFrame> dna = new HashMap<String, AlignFrame>();
2265 * Identify the DNA alignments
2267 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2270 AlignFrame af = candidate.getValue();
2271 if (af.getViewport().getAlignment().isNucleotide())
2273 dna.put(candidate.getKey().getId(), af);
2278 * Try to match up the protein complements
2280 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2283 AlignFrame af = candidate.getValue();
2284 if (!af.getViewport().getAlignment().isNucleotide())
2286 String complementId = candidate.getKey().getComplementId();
2287 // only non-null complements should be in the Map
2288 if (complementId != null && dna.containsKey(complementId))
2290 final AlignFrame dnaFrame = dna.get(complementId);
2291 SplitFrame sf = createSplitFrame(dnaFrame, af);
2292 addedToSplitFrames.add(dnaFrame);
2293 addedToSplitFrames.add(af);
2294 if (af.viewport.isGatherViewsHere())
2303 * Open any that we failed to pair up (which shouldn't happen!) as
2304 * standalone AlignFrame's.
2306 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2309 AlignFrame af = candidate.getValue();
2310 if (!addedToSplitFrames.contains(af)) {
2311 Viewport view = candidate.getKey();
2312 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
2314 System.err.println("Failed to restore view " + view.getTitle()
2315 + " to split frame");
2320 * Gather back into tabbed views as flagged.
2322 for (SplitFrame sf : gatherTo)
2324 Desktop.instance.gatherViews(sf);
2327 splitFrameCandidates.clear();
2331 * Construct and display one SplitFrame holding DNA and protein alignments.
2334 * @param proteinFrame
2337 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
2338 AlignFrame proteinFrame)
2340 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
2341 String title = MessageManager.getString("label.linked_view_title");
2342 int width = (int) dnaFrame.getBounds().getWidth();
2343 int height = (int) (dnaFrame.getBounds().getHeight()
2344 + proteinFrame.getBounds().getHeight() + 50);
2345 Desktop.addInternalFrame(splitFrame, title, width, height);
2348 * And compute cDNA consensus (couldn't do earlier with consensus as
2349 * mappings were not yet present)
2351 proteinFrame.viewport.alignmentChanged(proteinFrame.alignPanel);
2357 * check errorMessage for a valid error message and raise an error box in the
2358 * GUI or write the current errorMessage to stderr and then clear the error
2361 protected void reportErrors()
2363 reportErrors(false);
2366 protected void reportErrors(final boolean saving)
2368 if (errorMessage != null)
2370 final String finalErrorMessage = errorMessage;
2373 javax.swing.SwingUtilities.invokeLater(new Runnable()
2378 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2379 finalErrorMessage, "Error "
2380 + (saving ? "saving" : "loading")
2381 + " Jalview file", JOptionPane.WARNING_MESSAGE);
2387 System.err.println("Problem loading Jalview file: " + errorMessage);
2390 errorMessage = null;
2393 Map<String, String> alreadyLoadedPDB = new HashMap<String, String>();
2396 * when set, local views will be updated from view stored in JalviewXML
2397 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2398 * sync if this is set to true.
2400 private final boolean updateLocalViews = false;
2403 * Returns the path to a temporary file holding the PDB file for the given PDB
2404 * id. The first time of asking, searches for a file of that name in the
2405 * Jalview project jar, and copies it to a new temporary file. Any repeat
2406 * requests just return the path to the file previously created.
2412 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId)
2414 if (alreadyLoadedPDB.containsKey(pdbId))
2416 return alreadyLoadedPDB.get(pdbId).toString();
2419 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb");
2420 if (tempFile != null)
2422 alreadyLoadedPDB.put(pdbId, tempFile);
2428 * Copies the jar entry of given name to a new temporary file and returns the
2429 * path to the file, or null if the entry is not found.
2432 * @param jarEntryName
2434 * a prefix for the temporary file name, must be at least three
2438 protected String copyJarEntry(jarInputStreamProvider jprovider,
2439 String jarEntryName, String prefix)
2441 BufferedReader in = null;
2442 PrintWriter out = null;
2446 JarInputStream jin = jprovider.getJarInputStream();
2448 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2449 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2450 * FileInputStream(jprovider)); }
2453 JarEntry entry = null;
2456 entry = jin.getNextJarEntry();
2457 } while (entry != null && !entry.getName().equals(jarEntryName));
2460 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
2461 File outFile = File.createTempFile(prefix, ".tmp");
2462 outFile.deleteOnExit();
2463 out = new PrintWriter(new FileOutputStream(outFile));
2466 while ((data = in.readLine()) != null)
2471 String t = outFile.getAbsolutePath();
2476 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
2478 } catch (Exception ex)
2480 ex.printStackTrace();
2488 } catch (IOException e)
2502 private class JvAnnotRow
2504 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2511 * persisted version of annotation row from which to take vis properties
2513 public jalview.datamodel.AlignmentAnnotation template;
2516 * original position of the annotation row in the alignment
2522 * Load alignment frame from jalview XML DOM object
2527 * filename source string
2528 * @param loadTreesAndStructures
2529 * when false only create Viewport
2531 * data source provider
2532 * @return alignment frame created from view stored in DOM
2534 AlignFrame loadFromObject(JalviewModel object, String file,
2535 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
2537 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
2538 Sequence[] vamsasSeq = vamsasSet.getSequence();
2540 JalviewModelSequence jms = object.getJalviewModelSequence();
2542 Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
2545 // ////////////////////////////////
2548 List<SequenceI> hiddenSeqs = null;
2549 jalview.datamodel.Sequence jseq;
2551 List<SequenceI> tmpseqs = new ArrayList<SequenceI>();
2553 boolean multipleView = false;
2555 JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
2556 int vi = 0; // counter in vamsasSeq array
2557 for (int i = 0; i < jseqs.length; i++)
2559 String seqId = jseqs[i].getId();
2561 if (seqRefIds.get(seqId) != null)
2563 tmpseqs.add(seqRefIds.get(seqId));
2564 multipleView = true;
2568 jseq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
2569 vamsasSeq[vi].getSequence());
2570 jseq.setDescription(vamsasSeq[vi].getDescription());
2571 jseq.setStart(jseqs[i].getStart());
2572 jseq.setEnd(jseqs[i].getEnd());
2573 jseq.setVamsasId(uniqueSetSuffix + seqId);
2574 seqRefIds.put(vamsasSeq[vi].getId(), jseq);
2579 if (jseqs[i].getHidden())
2581 if (hiddenSeqs == null)
2583 hiddenSeqs = new ArrayList<SequenceI>();
2586 hiddenSeqs.add(seqRefIds.get(seqId));
2592 // Create the alignment object from the sequence set
2593 // ///////////////////////////////
2594 SequenceI[] orderedSeqs = tmpseqs
2595 .toArray(new SequenceI[tmpseqs.size()]);
2597 Alignment al = new Alignment(orderedSeqs);
2599 // / Add the alignment properties
2600 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
2602 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
2603 al.setProperty(ssp.getKey(), ssp.getValue());
2607 // SequenceFeatures are added to the DatasetSequence,
2608 // so we must create or recover the dataset before loading features
2609 // ///////////////////////////////
2610 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
2612 // older jalview projects do not have a dataset id.
2613 al.setDataset(null);
2617 // recover dataset - passing on flag indicating if this a 'viewless'
2618 // sequence set (a.k.a. a stored dataset for the project)
2619 recoverDatasetFor(vamsasSet, al, object.getJalviewModelSequence()
2620 .getViewportCount() == 0);
2622 // ///////////////////////////////
2624 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
2627 // load sequence features, database references and any associated PDB
2628 // structures for the alignment
2629 for (int i = 0; i < vamsasSeq.length; i++)
2631 if (jseqs[i].getFeaturesCount() > 0)
2633 Features[] features = jseqs[i].getFeatures();
2634 for (int f = 0; f < features.length; f++)
2636 jalview.datamodel.SequenceFeature sf = new jalview.datamodel.SequenceFeature(
2637 features[f].getType(), features[f].getDescription(),
2638 features[f].getStatus(), features[f].getBegin(),
2639 features[f].getEnd(), features[f].getFeatureGroup());
2641 sf.setScore(features[f].getScore());
2642 for (int od = 0; od < features[f].getOtherDataCount(); od++)
2644 OtherData keyValue = features[f].getOtherData(od);
2645 if (keyValue.getKey().startsWith("LINK"))
2647 sf.addLink(keyValue.getValue());
2651 sf.setValue(keyValue.getKey(), keyValue.getValue());
2656 al.getSequenceAt(i).getDatasetSequence().addSequenceFeature(sf);
2659 if (vamsasSeq[i].getDBRefCount() > 0)
2661 addDBRefs(al.getSequenceAt(i).getDatasetSequence(), vamsasSeq[i]);
2663 if (jseqs[i].getPdbidsCount() > 0)
2665 Pdbids[] ids = jseqs[i].getPdbids();
2666 for (int p = 0; p < ids.length; p++)
2668 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
2669 entry.setId(ids[p].getId());
2670 if (ids[p].getType() != null)
2672 if (ids[p].getType().equalsIgnoreCase("PDB"))
2674 entry.setType(PDBEntry.Type.PDB);
2678 entry.setType(PDBEntry.Type.FILE);
2681 if (ids[p].getFile() != null)
2683 if (!pdbloaded.containsKey(ids[p].getFile()))
2685 entry.setFile(loadPDBFile(jprovider, ids[p].getId()));
2689 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
2692 StructureSelectionManager.getStructureSelectionManager(
2693 Desktop.instance).registerPDBEntry(entry);
2694 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
2698 } // end !multipleview
2700 // ///////////////////////////////
2701 // LOAD SEQUENCE MAPPINGS
2703 if (vamsasSet.getAlcodonFrameCount() > 0)
2705 // TODO Potentially this should only be done once for all views of an
2707 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
2708 for (int i = 0; i < alc.length; i++)
2710 AlignedCodonFrame cf = new AlignedCodonFrame();
2711 if (alc[i].getAlcodMapCount() > 0)
2713 AlcodMap[] maps = alc[i].getAlcodMap();
2714 for (int m = 0; m < maps.length; m++)
2716 SequenceI dnaseq = seqRefIds.get(maps[m].getDnasq());
2718 jalview.datamodel.Mapping mapping = null;
2719 // attach to dna sequence reference.
2720 if (maps[m].getMapping() != null)
2722 mapping = addMapping(maps[m].getMapping());
2726 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
2731 frefedSequence.add(new Object[]
2732 { maps[m].getDnasq(), cf, mapping });
2736 al.addCodonFrame(cf);
2740 // ////////////////////////////////
2742 List<JvAnnotRow> autoAlan = new ArrayList<JvAnnotRow>();
2744 * store any annotations which forward reference a group's ID
2746 Hashtable<String, ArrayList<jalview.datamodel.AlignmentAnnotation>> groupAnnotRefs = new Hashtable<String, ArrayList<jalview.datamodel.AlignmentAnnotation>>();
2748 if (vamsasSet.getAnnotationCount() > 0)
2750 Annotation[] an = vamsasSet.getAnnotation();
2752 for (int i = 0; i < an.length; i++)
2755 * test if annotation is automatically calculated for this view only
2757 boolean autoForView = false;
2758 if (an[i].getLabel().equals("Quality")
2759 || an[i].getLabel().equals("Conservation")
2760 || an[i].getLabel().equals("Consensus"))
2762 // Kludge for pre 2.5 projects which lacked the autocalculated flag
2764 if (!an[i].hasAutoCalculated())
2766 an[i].setAutoCalculated(true);
2770 || (an[i].hasAutoCalculated() && an[i].isAutoCalculated()))
2772 // remove ID - we don't recover annotation from other views for
2773 // view-specific annotation
2777 // set visiblity for other annotation in this view
2778 if (an[i].getId() != null
2779 && annotationIds.containsKey(an[i].getId()))
2781 AlignmentAnnotation jda = annotationIds.get(an[i].getId());
2782 // in principle Visible should always be true for annotation displayed
2783 // in multiple views
2784 if (an[i].hasVisible())
2786 jda.visible = an[i].getVisible();
2789 al.addAnnotation(jda);
2793 // Construct new annotation from model.
2794 AnnotationElement[] ae = an[i].getAnnotationElement();
2795 jalview.datamodel.Annotation[] anot = null;
2796 java.awt.Color firstColour = null;
2798 if (!an[i].getScoreOnly())
2800 anot = new jalview.datamodel.Annotation[al.getWidth()];
2801 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
2803 anpos = ae[aa].getPosition();
2805 if (anpos >= anot.length)
2810 anot[anpos] = new jalview.datamodel.Annotation(
2812 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
2813 (ae[aa].getSecondaryStructure() == null || ae[aa]
2814 .getSecondaryStructure().length() == 0) ? ' '
2815 : ae[aa].getSecondaryStructure().charAt(0),
2819 // JBPNote: Consider verifying dataflow for IO of secondary
2820 // structure annotation read from Stockholm files
2821 // this was added to try to ensure that
2822 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
2824 // anot[ae[aa].getPosition()].displayCharacter = "";
2826 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
2827 if (firstColour == null)
2829 firstColour = anot[anpos].colour;
2833 jalview.datamodel.AlignmentAnnotation jaa = null;
2835 if (an[i].getGraph())
2837 float llim = 0, hlim = 0;
2838 // if (autoForView || an[i].isAutoCalculated()) {
2841 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
2842 an[i].getDescription(), anot, llim, hlim,
2843 an[i].getGraphType());
2845 jaa.graphGroup = an[i].getGraphGroup();
2846 jaa._linecolour = firstColour;
2847 if (an[i].getThresholdLine() != null)
2849 jaa.setThreshold(new jalview.datamodel.GraphLine(an[i]
2850 .getThresholdLine().getValue(), an[i]
2851 .getThresholdLine().getLabel(), new java.awt.Color(
2852 an[i].getThresholdLine().getColour())));
2855 if (autoForView || an[i].isAutoCalculated())
2857 // Hardwire the symbol display line to ensure that labels for
2858 // histograms are displayed
2864 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
2865 an[i].getDescription(), anot);
2866 jaa._linecolour = firstColour;
2868 // register new annotation
2869 if (an[i].getId() != null)
2871 annotationIds.put(an[i].getId(), jaa);
2872 jaa.annotationId = an[i].getId();
2874 // recover sequence association
2875 if (an[i].getSequenceRef() != null)
2877 if (al.findName(an[i].getSequenceRef()) != null)
2879 jaa.createSequenceMapping(al.findName(an[i].getSequenceRef()),
2881 al.findName(an[i].getSequenceRef()).addAlignmentAnnotation(jaa);
2884 // and make a note of any group association
2885 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
2887 ArrayList<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
2888 .get(an[i].getGroupRef());
2891 aal = new ArrayList<jalview.datamodel.AlignmentAnnotation>();
2892 groupAnnotRefs.put(an[i].getGroupRef(), aal);
2897 if (an[i].hasScore())
2899 jaa.setScore(an[i].getScore());
2901 if (an[i].hasVisible())
2903 jaa.visible = an[i].getVisible();
2906 if (an[i].hasCentreColLabels())
2908 jaa.centreColLabels = an[i].getCentreColLabels();
2911 if (an[i].hasScaleColLabels())
2913 jaa.scaleColLabel = an[i].getScaleColLabels();
2915 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
2917 // newer files have an 'autoCalculated' flag and store calculation
2918 // state in viewport properties
2919 jaa.autoCalculated = true; // means annotation will be marked for
2920 // update at end of load.
2922 if (an[i].hasGraphHeight())
2924 jaa.graphHeight = an[i].getGraphHeight();
2926 if (an[i].hasBelowAlignment())
2928 jaa.belowAlignment = an[i].isBelowAlignment();
2930 jaa.setCalcId(an[i].getCalcId());
2931 if (an[i].getPropertyCount() > 0)
2933 for (jalview.schemabinding.version2.Property prop : an[i]
2936 jaa.setProperty(prop.getName(), prop.getValue());
2939 if (jaa.autoCalculated)
2941 autoAlan.add(new JvAnnotRow(i, jaa));
2944 // if (!autoForView)
2946 // add autocalculated group annotation and any user created annotation
2948 al.addAnnotation(jaa);
2952 // ///////////////////////
2954 // Create alignment markup and styles for this view
2955 if (jms.getJGroupCount() > 0)
2957 JGroup[] groups = jms.getJGroup();
2958 boolean addAnnotSchemeGroup = false;
2959 for (int i = 0; i < groups.length; i++)
2961 ColourSchemeI cs = null;
2963 if (groups[i].getColour() != null)
2965 if (groups[i].getColour().startsWith("ucs"))
2967 cs = getUserColourScheme(jms, groups[i].getColour());
2969 else if (groups[i].getColour().equals("AnnotationColourGradient")
2970 && groups[i].getAnnotationColours() != null)
2972 addAnnotSchemeGroup = true;
2977 cs = ColourSchemeProperty.getColour(al, groups[i].getColour());
2982 cs.setThreshold(groups[i].getPidThreshold(), true);
2986 Vector seqs = new Vector();
2988 for (int s = 0; s < groups[i].getSeqCount(); s++)
2990 String seqId = groups[i].getSeq(s) + "";
2991 jalview.datamodel.SequenceI ts = seqRefIds.get(seqId);
2995 seqs.addElement(ts);
2999 if (seqs.size() < 1)
3004 jalview.datamodel.SequenceGroup sg = new jalview.datamodel.SequenceGroup(
3005 seqs, groups[i].getName(), cs, groups[i].getDisplayBoxes(),
3006 groups[i].getDisplayText(), groups[i].getColourText(),
3007 groups[i].getStart(), groups[i].getEnd());
3009 sg.setOutlineColour(new java.awt.Color(groups[i].getOutlineColour()));
3011 sg.textColour = new java.awt.Color(groups[i].getTextCol1());
3012 sg.textColour2 = new java.awt.Color(groups[i].getTextCol2());
3013 sg.setShowNonconserved(groups[i].hasShowUnconserved() ? groups[i]
3014 .isShowUnconserved() : false);
3015 sg.thresholdTextColour = groups[i].getTextColThreshold();
3016 if (groups[i].hasShowConsensusHistogram())
3018 sg.setShowConsensusHistogram(groups[i].isShowConsensusHistogram());
3021 if (groups[i].hasShowSequenceLogo())
3023 sg.setshowSequenceLogo(groups[i].isShowSequenceLogo());
3025 if (groups[i].hasNormaliseSequenceLogo())
3027 sg.setNormaliseSequenceLogo(groups[i].isNormaliseSequenceLogo());
3029 if (groups[i].hasIgnoreGapsinConsensus())
3031 sg.setIgnoreGapsConsensus(groups[i].getIgnoreGapsinConsensus());
3033 if (groups[i].getConsThreshold() != 0)
3035 jalview.analysis.Conservation c = new jalview.analysis.Conservation(
3036 "All", ResidueProperties.propHash, 3,
3037 sg.getSequences(null), 0, sg.getWidth() - 1);
3039 c.verdict(false, 25);
3040 sg.cs.setConservation(c);
3043 if (groups[i].getId() != null && groupAnnotRefs.size() > 0)
3045 // re-instate unique group/annotation row reference
3046 ArrayList<jalview.datamodel.AlignmentAnnotation> jaal = groupAnnotRefs
3047 .get(groups[i].getId());
3050 for (jalview.datamodel.AlignmentAnnotation jaa : jaal)
3053 if (jaa.autoCalculated)
3055 // match up and try to set group autocalc alignment row for this
3057 if (jaa.label.startsWith("Consensus for "))
3059 sg.setConsensus(jaa);
3061 // match up and try to set group autocalc alignment row for this
3063 if (jaa.label.startsWith("Conservation for "))
3065 sg.setConservationRow(jaa);
3072 if (addAnnotSchemeGroup)
3074 // reconstruct the annotation colourscheme
3075 sg.cs = constructAnnotationColour(
3076 groups[i].getAnnotationColours(), null, al, jms, false);
3082 // only dataset in this model, so just return.
3085 // ///////////////////////////////
3088 // If we just load in the same jar file again, the sequenceSetId
3089 // will be the same, and we end up with multiple references
3090 // to the same sequenceSet. We must modify this id on load
3091 // so that each load of the file gives a unique id
3092 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3093 String viewId = (view.getId() == null ? null : view.getId()
3095 AlignFrame af = null;
3096 AlignViewport av = null;
3097 // now check to see if we really need to create a new viewport.
3098 if (multipleView && viewportsAdded.size() == 0)
3100 // We recovered an alignment for which a viewport already exists.
3101 // TODO: fix up any settings necessary for overlaying stored state onto
3102 // state recovered from another document. (may not be necessary).
3103 // we may need a binding from a viewport in memory to one recovered from
3105 // and then recover its containing af to allow the settings to be applied.
3106 // TODO: fix for vamsas demo
3108 .println("About to recover a viewport for existing alignment: Sequence set ID is "
3110 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3111 if (seqsetobj != null)
3113 if (seqsetobj instanceof String)
3115 uniqueSeqSetId = (String) seqsetobj;
3117 .println("Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
3123 .println("Warning : Collision between sequence set ID string and existing jalview object mapping.");
3129 * indicate that annotation colours are applied across all groups (pre
3130 * Jalview 2.8.1 behaviour)
3132 boolean doGroupAnnColour = isVersionStringLaterThan("2.8.1",
3133 object.getVersion());
3135 AlignmentPanel ap = null;
3136 boolean isnewview = true;
3139 // Check to see if this alignment already has a view id == viewId
3140 jalview.gui.AlignmentPanel views[] = Desktop
3141 .getAlignmentPanels(uniqueSeqSetId);
3142 if (views != null && views.length > 0)
3144 for (int v = 0; v < views.length; v++)
3146 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
3148 // recover the existing alignpanel, alignframe, viewport
3149 af = views[v].alignFrame;
3152 // TODO: could even skip resetting view settings if we don't want to
3153 // change the local settings from other jalview processes
3162 af = loadViewport(file, jseqs, hiddenSeqs, al, jms, view,
3163 uniqueSeqSetId, viewId, autoAlan);
3168 // /////////////////////////////////////
3169 if (loadTreesAndStructures && jms.getTreeCount() > 0)
3173 for (int t = 0; t < jms.getTreeCount(); t++)
3176 Tree tree = jms.getTree(t);
3178 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
3181 tp = af.ShowNewickTree(
3182 new jalview.io.NewickFile(tree.getNewick()),
3183 tree.getTitle(), tree.getWidth(), tree.getHeight(),
3184 tree.getXpos(), tree.getYpos());
3185 if (tree.getId() != null)
3187 // perhaps bind the tree id to something ?
3192 // update local tree attributes ?
3193 // TODO: should check if tp has been manipulated by user - if so its
3194 // settings shouldn't be modified
3195 tp.setTitle(tree.getTitle());
3196 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(), tree
3197 .getWidth(), tree.getHeight()));
3198 tp.av = av; // af.viewport; // TODO: verify 'associate with all
3201 tp.treeCanvas.av = av; // af.viewport;
3202 tp.treeCanvas.ap = ap; // af.alignPanel;
3207 warn("There was a problem recovering stored Newick tree: \n"
3208 + tree.getNewick());
3212 tp.fitToWindow.setState(tree.getFitToWindow());
3213 tp.fitToWindow_actionPerformed(null);
3215 if (tree.getFontName() != null)
3217 tp.setTreeFont(new java.awt.Font(tree.getFontName(), tree
3218 .getFontStyle(), tree.getFontSize()));
3222 tp.setTreeFont(new java.awt.Font(view.getFontName(), view
3223 .getFontStyle(), tree.getFontSize()));
3226 tp.showPlaceholders(tree.getMarkUnlinked());
3227 tp.showBootstrap(tree.getShowBootstrap());
3228 tp.showDistances(tree.getShowDistances());
3230 tp.treeCanvas.threshold = tree.getThreshold();
3232 if (tree.getCurrentTree())
3234 af.viewport.setCurrentTree(tp.getTree());
3238 } catch (Exception ex)
3240 ex.printStackTrace();
3244 // //LOAD STRUCTURES
3245 if (loadTreesAndStructures)
3247 loadStructures(jprovider, jseqs, af, ap);
3249 // and finally return.
3254 * Load and link any saved structure viewers.
3261 protected void loadStructures(jarInputStreamProvider jprovider,
3262 JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
3265 * Run through all PDB ids on the alignment, and collect mappings between
3266 * distinct view ids and all sequences referring to that view.
3268 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<String, StructureViewerModel>();
3270 for (int i = 0; i < jseqs.length; i++)
3272 if (jseqs[i].getPdbidsCount() > 0)
3274 Pdbids[] ids = jseqs[i].getPdbids();
3275 for (int p = 0; p < ids.length; p++)
3277 final int structureStateCount = ids[p].getStructureStateCount();
3278 for (int s = 0; s < structureStateCount; s++)
3280 // check to see if we haven't already created this structure view
3281 final StructureState structureState = ids[p]
3282 .getStructureState(s);
3283 String sviewid = (structureState.getViewId() == null) ? null
3284 : structureState.getViewId() + uniqueSetSuffix;
3285 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
3286 // Originally : ids[p].getFile()
3287 // : TODO: verify external PDB file recovery still works in normal
3288 // jalview project load
3289 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId()));
3290 jpdb.setId(ids[p].getId());
3292 int x = structureState.getXpos();
3293 int y = structureState.getYpos();
3294 int width = structureState.getWidth();
3295 int height = structureState.getHeight();
3297 // Probably don't need to do this anymore...
3298 // Desktop.desktop.getComponentAt(x, y);
3299 // TODO: NOW: check that this recovers the PDB file correctly.
3300 String pdbFile = loadPDBFile(jprovider, ids[p].getId());
3301 jalview.datamodel.SequenceI seq = seqRefIds.get(jseqs[i]
3303 if (sviewid == null)
3305 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width
3308 if (!structureViewers.containsKey(sviewid))
3310 structureViewers.put(sviewid,
3311 new StructureViewerModel(x, y, width, height, false,
3312 false, true, structureState.getViewId(),
3313 structureState.getType()));
3314 // Legacy pre-2.7 conversion JAL-823 :
3315 // do not assume any view has to be linked for colour by
3319 // assemble String[] { pdb files }, String[] { id for each
3320 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3321 // seqs_file 2}, boolean[] {
3322 // linkAlignPanel,superposeWithAlignpanel}} from hash
3323 StructureViewerModel jmoldat = structureViewers.get(sviewid);
3324 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
3325 | (structureState.hasAlignwithAlignPanel() ? structureState
3326 .getAlignwithAlignPanel() : false));
3329 * Default colour by linked panel to false if not specified (e.g.
3330 * for pre-2.7 projects)
3332 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
3333 colourWithAlignPanel |= (structureState
3334 .hasColourwithAlignPanel() ? structureState
3335 .getColourwithAlignPanel() : false);
3336 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
3339 * Default colour by viewer to true if not specified (e.g. for
3342 boolean colourByViewer = jmoldat.isColourByViewer();
3343 colourByViewer &= structureState.hasColourByJmol() ? structureState
3344 .getColourByJmol() : true;
3345 jmoldat.setColourByViewer(colourByViewer);
3347 if (jmoldat.getStateData().length() < structureState
3348 .getContent().length())
3351 jmoldat.setStateData(structureState.getContent());
3354 if (ids[p].getFile() != null)
3356 File mapkey = new File(ids[p].getFile());
3357 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
3358 if (seqstrmaps == null)
3360 jmoldat.getFileData().put(
3362 seqstrmaps = jmoldat.new StructureData(pdbFile,
3365 if (!seqstrmaps.getSeqList().contains(seq))
3367 seqstrmaps.getSeqList().add(seq);
3373 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");
3380 // Instantiate the associated structure views
3381 for (Entry<String, StructureViewerModel> entry : structureViewers
3386 createOrLinkStructureViewer(entry, af, ap, jprovider);
3387 } catch (Exception e)
3389 System.err.println("Error loading structure viewer: "
3391 // failed - try the next one
3403 protected void createOrLinkStructureViewer(
3404 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3405 AlignmentPanel ap, jarInputStreamProvider jprovider)
3407 final StructureViewerModel stateData = viewerData.getValue();
3410 * Search for any viewer windows already open from other alignment views
3411 * that exactly match the stored structure state
3413 StructureViewerBase comp = findMatchingViewer(viewerData);
3417 linkStructureViewer(ap, comp, stateData);
3422 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
3423 * "viewer_"+stateData.viewId
3425 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
3427 createChimeraViewer(viewerData, af, jprovider);
3432 * else Jmol (if pre-2.9, stateData contains JMOL state string)
3434 createJmolViewer(viewerData, af, jprovider);
3439 * Create a new Chimera viewer.
3445 protected void createChimeraViewer(Entry<String, StructureViewerModel> viewerData,
3447 jarInputStreamProvider jprovider)
3449 StructureViewerModel data = viewerData.getValue();
3450 String chimeraSessionFile = data.getStateData();
3453 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
3455 * Note this is the 'saved' viewId as in the project file XML, _not_ the
3456 * 'uniquified' sviewid used to reconstruct the viewer here
3458 chimeraSessionFile = copyJarEntry(jprovider,
3459 getViewerJarEntryName(data.getViewId()), "chimera");
3461 Set<Entry<File, StructureData>> fileData = data.getFileData()
3463 List<PDBEntry> pdbs = new ArrayList<PDBEntry>();
3464 List<SequenceI[]> allseqs = new ArrayList<SequenceI[]>();
3465 for (Entry<File, StructureData> pdb : fileData)
3467 String filePath = pdb.getValue().getFilePath();
3468 String pdbId = pdb.getValue().getPdbId();
3469 // pdbs.add(new PDBEntry(filePath, pdbId));
3470 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
3471 final List<SequenceI> seqList = pdb.getValue().getSeqList();
3472 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
3476 boolean colourByChimera = data.isColourByViewer();
3477 boolean colourBySequence = data.isColourWithAlignPanel();
3479 // TODO use StructureViewer as a factory here, see JAL-1761
3480 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
3481 final SequenceI[][] seqsArray = allseqs.toArray(new SequenceI[allseqs
3483 String newViewId = viewerData.getKey();
3484 new ChimeraViewFrame(chimeraSessionFile, af.alignPanel, pdbArray,
3485 seqsArray, colourByChimera, colourBySequence, newViewId);
3489 * Create a new Jmol window. First parse the Jmol state to translate filenames
3490 * loaded into the view, and record the order in which files are shown in the
3491 * Jmol view, so we can add the sequence mappings in same order.
3497 protected void createJmolViewer(
3498 final Entry<String, StructureViewerModel> viewerData,
3499 AlignFrame af, jarInputStreamProvider jprovider)
3501 final StructureViewerModel svattrib = viewerData.getValue();
3502 String state = svattrib.getStateData();
3505 * Pre-2.9: state element value is the Jmol state string
3507 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
3510 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
3512 state = readJarEntry(jprovider,
3513 getViewerJarEntryName(svattrib.getViewId()));
3516 List<String> pdbfilenames = new ArrayList<String>();
3517 List<SequenceI[]> seqmaps = new ArrayList<SequenceI[]>();
3518 List<String> pdbids = new ArrayList<String>();
3519 StringBuilder newFileLoc = new StringBuilder(64);
3520 int cp = 0, ncp, ecp;
3521 Map<File, StructureData> oldFiles = svattrib.getFileData();
3522 while ((ncp = state.indexOf("load ", cp)) > -1)
3526 // look for next filename in load statement
3527 newFileLoc.append(state.substring(cp,
3528 ncp = (state.indexOf("\"", ncp + 1) + 1)));
3529 String oldfilenam = state.substring(ncp,
3530 ecp = state.indexOf("\"", ncp));
3531 // recover the new mapping data for this old filename
3532 // have to normalize filename - since Jmol and jalview do
3534 // translation differently.
3535 StructureData filedat = oldFiles.get(new File(oldfilenam));
3536 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
3537 pdbfilenames.add(filedat.getFilePath());
3538 pdbids.add(filedat.getPdbId());
3539 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
3540 newFileLoc.append("\"");
3541 cp = ecp + 1; // advance beyond last \" and set cursor so we can
3542 // look for next file statement.
3543 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
3547 // just append rest of state
3548 newFileLoc.append(state.substring(cp));
3552 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
3553 newFileLoc = new StringBuilder(state);
3554 newFileLoc.append("; load append ");
3555 for (File id : oldFiles.keySet())
3557 // add this and any other pdb files that should be present in
3559 StructureData filedat = oldFiles.get(id);
3560 newFileLoc.append(filedat.getFilePath());
3561 pdbfilenames.add(filedat.getFilePath());
3562 pdbids.add(filedat.getPdbId());
3563 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
3564 newFileLoc.append(" \"");
3565 newFileLoc.append(filedat.getFilePath());
3566 newFileLoc.append("\"");
3569 newFileLoc.append(";");
3572 if (newFileLoc.length() > 0)
3574 int histbug = newFileLoc.indexOf("history = ");
3576 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
3577 String val = (diff == -1) ? null : newFileLoc
3578 .substring(histbug, diff);
3579 if (val != null && val.length() >= 4)
3581 if (val.contains("e"))
3583 if (val.trim().equals("true"))
3591 newFileLoc.replace(histbug, diff, val);
3595 final String[] pdbf = pdbfilenames.toArray(new String[pdbfilenames
3597 final String[] id = pdbids.toArray(new String[pdbids.size()]);
3598 final SequenceI[][] sq = seqmaps
3599 .toArray(new SequenceI[seqmaps.size()][]);
3600 final String fileloc = newFileLoc.toString();
3601 final String sviewid = viewerData.getKey();
3602 final AlignFrame alf = af;
3603 final Rectangle rect = new Rectangle(svattrib.getX(),
3604 svattrib.getY(), svattrib.getWidth(), svattrib.getHeight());
3607 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
3612 JalviewStructureDisplayI sview = null;
3615 sview = new StructureViewer(alf.alignPanel
3616 .getStructureSelectionManager()).createView(
3617 StructureViewer.ViewerType.JMOL, pdbf, id, sq,
3618 alf.alignPanel, svattrib, fileloc, rect, sviewid);
3619 addNewStructureViewer(sview);
3620 } catch (OutOfMemoryError ex)
3622 new OOMWarning("restoring structure view for PDB id " + id,
3623 (OutOfMemoryError) ex.getCause());
3624 if (sview != null && sview.isVisible())
3626 sview.closeViewer(false);
3627 sview.setVisible(false);
3633 } catch (InvocationTargetException ex)
3635 warn("Unexpected error when opening Jmol view.", ex);
3637 } catch (InterruptedException e)
3639 // e.printStackTrace();
3645 * Generates a name for the entry in the project jar file to hold state
3646 * information for a structure viewer
3651 protected String getViewerJarEntryName(String viewId)
3653 return "viewer_" + viewId;
3657 * Returns any open frame that matches given structure viewer data. The match
3658 * is based on the unique viewId, or (for older project versions) the frame's
3664 protected StructureViewerBase findMatchingViewer(
3665 Entry<String, StructureViewerModel> viewerData)
3667 final String sviewid = viewerData.getKey();
3668 final StructureViewerModel svattrib = viewerData.getValue();
3669 StructureViewerBase comp = null;
3670 JInternalFrame[] frames = getAllFrames();
3671 for (JInternalFrame frame : frames)
3673 if (frame instanceof StructureViewerBase)
3676 * Post jalview 2.4 schema includes structure view id
3679 && ((StructureViewerBase) frame).getViewId()
3682 comp = (StructureViewerBase) frame;
3683 break; // break added in 2.9
3686 * Otherwise test for matching position and size of viewer frame
3688 else if (frame.getX() == svattrib.getX()
3689 && frame.getY() == svattrib.getY()
3690 && frame.getHeight() == svattrib.getHeight()
3691 && frame.getWidth() == svattrib.getWidth())
3693 comp = (StructureViewerBase) frame;
3694 // no break in faint hope of an exact match on viewId
3702 * Link an AlignmentPanel to an existing structure viewer.
3707 * @param useinViewerSuperpos
3708 * @param usetoColourbyseq
3709 * @param viewerColouring
3711 protected void linkStructureViewer(AlignmentPanel ap,
3712 StructureViewerBase viewer, StructureViewerModel stateData)
3714 // NOTE: if the jalview project is part of a shared session then
3715 // view synchronization should/could be done here.
3717 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
3718 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
3719 final boolean viewerColouring = stateData.isColourByViewer();
3720 Map<File, StructureData> oldFiles = stateData.getFileData();
3723 * Add mapping for sequences in this view to an already open viewer
3725 final AAStructureBindingModel binding = viewer.getBinding();
3726 for (File id : oldFiles.keySet())
3728 // add this and any other pdb files that should be present in the
3730 StructureData filedat = oldFiles.get(id);
3731 String pdbFile = filedat.getFilePath();
3732 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
3733 binding.getSsm().setMapping(seq, null, pdbFile,
3734 jalview.io.AppletFormatAdapter.FILE);
3735 binding.addSequenceForStructFile(pdbFile, seq);
3737 // and add the AlignmentPanel's reference to the view panel
3738 viewer.addAlignmentPanel(ap);
3739 if (useinViewerSuperpos)
3741 viewer.useAlignmentPanelForSuperposition(ap);
3745 viewer.excludeAlignmentPanelForSuperposition(ap);
3747 if (usetoColourbyseq)
3749 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
3753 viewer.excludeAlignmentPanelForColourbyseq(ap);
3758 * Get all frames within the Desktop.
3762 protected JInternalFrame[] getAllFrames()
3764 JInternalFrame[] frames = null;
3765 // TODO is this necessary - is it safe - risk of hanging?
3770 frames = Desktop.desktop.getAllFrames();
3771 } catch (ArrayIndexOutOfBoundsException e)
3773 // occasional No such child exceptions are thrown here...
3777 } catch (InterruptedException f)
3781 } while (frames == null);
3788 * - minimum version we are comparing against
3790 * - version of data being processsed.
3791 * @return true if version is development/null or evaluates to the same or
3792 * later X.Y.Z (where X,Y,Z are like [0-9]+b?[0-9]*)
3794 private boolean isVersionStringLaterThan(String supported, String version)
3796 if (version == null || version.equalsIgnoreCase("DEVELOPMENT BUILD")
3797 || version.equalsIgnoreCase("Test")
3798 || version.equalsIgnoreCase("AUTOMATED BUILD"))
3800 System.err.println("Assuming project file with "
3801 + (version == null ? "null" : version)
3802 + " is compatible with Jalview version " + supported);
3807 StringTokenizer currentV = new StringTokenizer(supported, "."), fileV = new StringTokenizer(
3809 while (currentV.hasMoreTokens() && fileV.hasMoreTokens())
3811 // convert b to decimal to catch bugfix releases within a series
3812 String curT = currentV.nextToken().toLowerCase().replace('b', '.');
3813 String fileT = fileV.nextToken().toLowerCase().replace('b', '.');
3816 if (Float.valueOf(curT) > Float.valueOf(fileT))
3818 // current version is newer than the version that wrote the file
3821 } catch (NumberFormatException nfe)
3824 .println("** WARNING: Version comparison failed for tokens ("
3828 + ")\n** Current: '"
3829 + supported + "' and Version: '" + version + "'");
3832 if (currentV.hasMoreElements())
3834 // fileV has no minor version but identical series to current
3841 Vector<JalviewStructureDisplayI> newStructureViewers = null;
3843 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
3845 if (newStructureViewers != null)
3847 sview.getBinding().setFinishedLoadingFromArchive(false);
3848 newStructureViewers.add(sview);
3852 protected void setLoadingFinishedForNewStructureViewers()
3854 if (newStructureViewers != null)
3856 for (JalviewStructureDisplayI sview : newStructureViewers)
3858 sview.getBinding().setFinishedLoadingFromArchive(true);
3860 newStructureViewers.clear();
3861 newStructureViewers = null;
3865 AlignFrame loadViewport(String file, JSeq[] JSEQ,
3866 List<SequenceI> hiddenSeqs, Alignment al,
3867 JalviewModelSequence jms, Viewport view, String uniqueSeqSetId,
3868 String viewId, List<JvAnnotRow> autoAlan)
3870 AlignFrame af = null;
3871 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
3872 uniqueSeqSetId, viewId);
3874 af.setFileName(file, "Jalview");
3876 for (int i = 0; i < JSEQ.length; i++)
3878 af.viewport.setSequenceColour(af.viewport.getAlignment()
3879 .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour()));
3882 af.viewport.setGatherViewsHere(view.getGatheredViews());
3884 if (view.getSequenceSetId() != null)
3886 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
3888 af.viewport.setSequenceSetId(uniqueSeqSetId);
3891 // propagate shared settings to this new view
3892 af.viewport.setHistoryList(av.getHistoryList());
3893 af.viewport.setRedoList(av.getRedoList());
3897 viewportsAdded.put(uniqueSeqSetId, af.viewport);
3899 // TODO: check if this method can be called repeatedly without
3900 // side-effects if alignpanel already registered.
3901 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
3903 // apply Hidden regions to view.
3904 if (hiddenSeqs != null)
3906 for (int s = 0; s < JSEQ.length; s++)
3908 jalview.datamodel.SequenceGroup hidden = new jalview.datamodel.SequenceGroup();
3910 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
3913 al.getSequenceAt(JSEQ[s].getHiddenSequences(r)), false);
3915 af.viewport.hideRepSequences(al.getSequenceAt(s), hidden);
3918 // jalview.datamodel.SequenceI[] hseqs = new
3919 // jalview.datamodel.SequenceI[hiddenSeqs
3922 // for (int s = 0; s < hiddenSeqs.size(); s++)
3924 // hseqs[s] = (jalview.datamodel.SequenceI) hiddenSeqs.elementAt(s);
3927 SequenceI[] hseqs = hiddenSeqs.toArray(new SequenceI[hiddenSeqs
3929 af.viewport.hideSequence(hseqs);
3932 // recover view properties and display parameters
3933 if (view.getViewName() != null)
3935 af.viewport.viewName = view.getViewName();
3936 af.setInitialTabVisible();
3938 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
3941 af.viewport.setShowAnnotation(view.getShowAnnotation());
3942 af.viewport.setAbovePIDThreshold(view.getPidSelected());
3944 af.viewport.setColourText(view.getShowColourText());
3946 af.viewport.setConservationSelected(view.getConservationSelected());
3947 af.viewport.setShowJVSuffix(view.getShowFullId());
3948 af.viewport.setRightAlignIds(view.getRightAlignIds());
3949 af.viewport.setFont(
3950 new java.awt.Font(view.getFontName(), view.getFontStyle(), view
3951 .getFontSize()), true);
3952 // TODO: allow custom charWidth/Heights to be restored by updating them
3953 // after setting font - which means set above to false
3954 af.viewport.setRenderGaps(view.getRenderGaps());
3955 af.viewport.setWrapAlignment(view.getWrapAlignment());
3956 af.viewport.setShowAnnotation(view.getShowAnnotation());
3958 af.viewport.setShowBoxes(view.getShowBoxes());
3960 af.viewport.setShowText(view.getShowText());
3962 af.viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
3963 af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
3964 af.viewport.setThresholdTextColour(view.getTextColThreshold());
3965 af.viewport.setShowUnconserved(view.hasShowUnconserved() ? view
3966 .isShowUnconserved() : false);
3967 af.viewport.setStartRes(view.getStartRes());
3968 af.viewport.setStartSeq(view.getStartSeq());
3969 af.alignPanel.updateLayout();
3970 ColourSchemeI cs = null;
3971 // apply colourschemes
3972 if (view.getBgColour() != null)
3974 if (view.getBgColour().startsWith("ucs"))
3976 cs = getUserColourScheme(jms, view.getBgColour());
3978 else if (view.getBgColour().startsWith("Annotation"))
3980 AnnotationColours viewAnnColour = view.getAnnotationColours();
3981 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
3988 cs = ColourSchemeProperty.getColour(al, view.getBgColour());
3993 cs.setThreshold(view.getPidThreshold(), true);
3994 cs.setConsensus(af.viewport.getSequenceConsensusHash());
3998 af.viewport.setGlobalColourScheme(cs);
3999 af.viewport.setColourAppliesToAllGroups(false);
4001 if (view.getConservationSelected() && cs != null)
4003 cs.setConservationInc(view.getConsThreshold());
4006 af.changeColour(cs);
4008 af.viewport.setColourAppliesToAllGroups(true);
4010 af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures());
4012 if (view.hasCentreColumnLabels())
4014 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
4016 if (view.hasIgnoreGapsinConsensus())
4018 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
4021 if (view.hasFollowHighlight())
4023 af.viewport.setFollowHighlight(view.getFollowHighlight());
4025 if (view.hasFollowSelection())
4027 af.viewport.followSelection = view.getFollowSelection();
4029 if (view.hasShowConsensusHistogram())
4031 af.viewport.setShowConsensusHistogram(view
4032 .getShowConsensusHistogram());
4036 af.viewport.setShowConsensusHistogram(true);
4038 if (view.hasShowSequenceLogo())
4040 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
4044 af.viewport.setShowSequenceLogo(false);
4046 if (view.hasNormaliseSequenceLogo())
4048 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
4050 if (view.hasShowDbRefTooltip())
4052 af.viewport.setShowDBRefs(view.getShowDbRefTooltip());
4054 if (view.hasShowNPfeatureTooltip())
4056 af.viewport.setShowNPFeats(view.hasShowNPfeatureTooltip());
4058 if (view.hasShowGroupConsensus())
4060 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
4064 af.viewport.setShowGroupConsensus(false);
4066 if (view.hasShowGroupConservation())
4068 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
4072 af.viewport.setShowGroupConservation(false);
4075 // recover featre settings
4076 if (jms.getFeatureSettings() != null)
4078 FeaturesDisplayed fdi;
4079 af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
4080 String[] renderOrder = new String[jms.getFeatureSettings()
4081 .getSettingCount()];
4082 Hashtable featureGroups = new Hashtable();
4083 Hashtable featureColours = new Hashtable();
4084 Hashtable featureOrder = new Hashtable();
4086 for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
4088 Setting setting = jms.getFeatureSettings().getSetting(fs);
4089 if (setting.hasMincolour())
4091 GraduatedColor gc = setting.hasMin() ? new GraduatedColor(
4092 new java.awt.Color(setting.getMincolour()),
4093 new java.awt.Color(setting.getColour()),
4094 setting.getMin(), setting.getMax()) : new GraduatedColor(
4095 new java.awt.Color(setting.getMincolour()),
4096 new java.awt.Color(setting.getColour()), 0, 1);
4097 if (setting.hasThreshold())
4099 gc.setThresh(setting.getThreshold());
4100 gc.setThreshType(setting.getThreshstate());
4102 gc.setAutoScaled(true); // default
4103 if (setting.hasAutoScale())
4105 gc.setAutoScaled(setting.getAutoScale());
4107 if (setting.hasColourByLabel())
4109 gc.setColourByLabel(setting.getColourByLabel());
4111 // and put in the feature colour table.
4112 featureColours.put(setting.getType(), gc);
4116 featureColours.put(setting.getType(),
4117 new java.awt.Color(setting.getColour()));
4119 renderOrder[fs] = setting.getType();
4120 if (setting.hasOrder())
4122 featureOrder.put(setting.getType(), setting.getOrder());
4126 featureOrder.put(setting.getType(), new Float(fs
4127 / jms.getFeatureSettings().getSettingCount()));
4129 if (setting.getDisplay())
4131 fdi.setVisible(setting.getType());
4134 Hashtable fgtable = new Hashtable();
4135 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
4137 Group grp = jms.getFeatureSettings().getGroup(gs);
4138 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
4140 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4141 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
4142 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
4143 FeatureRendererSettings frs = new FeatureRendererSettings(
4144 renderOrder, fgtable, featureColours, 1.0f, featureOrder);
4145 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
4146 .transferSettings(frs);
4150 if (view.getHiddenColumnsCount() > 0)
4152 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
4154 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(), view
4155 .getHiddenColumns(c).getEnd() // +1
4159 if (view.getCalcIdParam() != null)
4161 for (CalcIdParam calcIdParam : view.getCalcIdParam())
4163 if (calcIdParam != null)
4165 if (recoverCalcIdParam(calcIdParam, af.viewport))
4170 warn("Couldn't recover parameters for "
4171 + calcIdParam.getCalcId());
4176 af.setMenusFromViewport(af.viewport);
4178 // TODO: we don't need to do this if the viewport is aready visible.
4180 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
4181 * has a 'cdna/protein complement' view, in which case save it in order to
4182 * populate a SplitFrame once all views have been read in.
4184 String complementaryViewId = view.getComplementId();
4185 if (complementaryViewId == null)
4187 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
4189 // recompute any autoannotation
4190 af.alignPanel.updateAnnotation(false, true);
4191 reorderAutoannotation(af, al, autoAlan);
4192 af.alignPanel.alignmentChanged();
4196 splitFrameCandidates.put(view, af);
4201 private ColourSchemeI constructAnnotationColour(
4202 AnnotationColours viewAnnColour, AlignFrame af, Alignment al,
4203 JalviewModelSequence jms, boolean checkGroupAnnColour)
4205 boolean propagateAnnColour = false;
4206 ColourSchemeI cs = null;
4207 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
4208 if (checkGroupAnnColour && al.getGroups() != null
4209 && al.getGroups().size() > 0)
4211 // pre 2.8.1 behaviour
4212 // check to see if we should transfer annotation colours
4213 propagateAnnColour = true;
4214 for (jalview.datamodel.SequenceGroup sg : al.getGroups())
4216 if (sg.cs instanceof AnnotationColourGradient)
4218 propagateAnnColour = false;
4222 // int find annotation
4223 if (annAlignment.getAlignmentAnnotation() != null)
4225 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
4227 if (annAlignment.getAlignmentAnnotation()[i].label
4228 .equals(viewAnnColour.getAnnotation()))
4230 if (annAlignment.getAlignmentAnnotation()[i].getThreshold() == null)
4232 annAlignment.getAlignmentAnnotation()[i]
4233 .setThreshold(new jalview.datamodel.GraphLine(
4234 viewAnnColour.getThreshold(), "Threshold",
4235 java.awt.Color.black)
4240 if (viewAnnColour.getColourScheme().equals("None"))
4242 cs = new AnnotationColourGradient(
4243 annAlignment.getAlignmentAnnotation()[i],
4244 new java.awt.Color(viewAnnColour.getMinColour()),
4245 new java.awt.Color(viewAnnColour.getMaxColour()),
4246 viewAnnColour.getAboveThreshold());
4248 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
4250 cs = new AnnotationColourGradient(
4251 annAlignment.getAlignmentAnnotation()[i],
4252 getUserColourScheme(jms,
4253 viewAnnColour.getColourScheme()),
4254 viewAnnColour.getAboveThreshold());
4258 cs = new AnnotationColourGradient(
4259 annAlignment.getAlignmentAnnotation()[i],
4260 ColourSchemeProperty.getColour(al,
4261 viewAnnColour.getColourScheme()),
4262 viewAnnColour.getAboveThreshold());
4264 if (viewAnnColour.hasPerSequence())
4266 ((AnnotationColourGradient) cs).setSeqAssociated(viewAnnColour
4269 if (viewAnnColour.hasPredefinedColours())
4271 ((AnnotationColourGradient) cs)
4272 .setPredefinedColours(viewAnnColour
4273 .isPredefinedColours());
4275 if (propagateAnnColour && al.getGroups() != null)
4277 // Also use these settings for all the groups
4278 for (int g = 0; g < al.getGroups().size(); g++)
4280 jalview.datamodel.SequenceGroup sg = al.getGroups().get(g);
4288 * if (viewAnnColour.getColourScheme().equals("None" )) { sg.cs =
4289 * new AnnotationColourGradient(
4290 * annAlignment.getAlignmentAnnotation()[i], new
4291 * java.awt.Color(viewAnnColour. getMinColour()), new
4292 * java.awt.Color(viewAnnColour. getMaxColour()),
4293 * viewAnnColour.getAboveThreshold()); } else
4296 sg.cs = new AnnotationColourGradient(
4297 annAlignment.getAlignmentAnnotation()[i], sg.cs,
4298 viewAnnColour.getAboveThreshold());
4299 if (cs instanceof AnnotationColourGradient)
4301 if (viewAnnColour.hasPerSequence())
4303 ((AnnotationColourGradient) cs)
4304 .setSeqAssociated(viewAnnColour.isPerSequence());
4306 if (viewAnnColour.hasPredefinedColours())
4308 ((AnnotationColourGradient) cs)
4309 .setPredefinedColours(viewAnnColour
4310 .isPredefinedColours());
4326 private void reorderAutoannotation(AlignFrame af, Alignment al,
4327 List<JvAnnotRow> autoAlan)
4329 // copy over visualization settings for autocalculated annotation in the
4331 if (al.getAlignmentAnnotation() != null)
4334 * Kludge for magic autoannotation names (see JAL-811)
4336 String[] magicNames = new String[]
4337 { "Consensus", "Quality", "Conservation" };
4338 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
4339 Hashtable<String, JvAnnotRow> visan = new Hashtable<String, JvAnnotRow>();
4340 for (String nm : magicNames)
4342 visan.put(nm, nullAnnot);
4344 for (JvAnnotRow auan : autoAlan)
4346 visan.put(auan.template.label
4347 + (auan.template.getCalcId() == null ? "" : "\t"
4348 + auan.template.getCalcId()), auan);
4350 int hSize = al.getAlignmentAnnotation().length;
4351 List<JvAnnotRow> reorder = new ArrayList<JvAnnotRow>();
4352 // work through any autoCalculated annotation already on the view
4353 // removing it if it should be placed in a different location on the
4354 // annotation panel.
4355 List<String> remains = new ArrayList<String>(visan.keySet());
4356 for (int h = 0; h < hSize; h++)
4358 jalview.datamodel.AlignmentAnnotation jalan = al
4359 .getAlignmentAnnotation()[h];
4360 if (jalan.autoCalculated)
4363 JvAnnotRow valan = visan.get(k = jalan.label);
4364 if (jalan.getCalcId() != null)
4366 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
4371 // delete the auto calculated row from the alignment
4372 al.deleteAnnotation(jalan, false);
4376 if (valan != nullAnnot)
4378 if (jalan != valan.template)
4380 // newly created autoannotation row instance
4381 // so keep a reference to the visible annotation row
4382 // and copy over all relevant attributes
4383 if (valan.template.graphHeight >= 0)
4386 jalan.graphHeight = valan.template.graphHeight;
4388 jalan.visible = valan.template.visible;
4390 reorder.add(new JvAnnotRow(valan.order, jalan));
4395 // Add any (possibly stale) autocalculated rows that were not appended to
4396 // the view during construction
4397 for (String other : remains)
4399 JvAnnotRow othera = visan.get(other);
4400 if (othera != nullAnnot && othera.template.getCalcId() != null
4401 && othera.template.getCalcId().length() > 0)
4403 reorder.add(othera);
4406 // now put the automatic annotation in its correct place
4407 int s = 0, srt[] = new int[reorder.size()];
4408 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
4409 for (JvAnnotRow jvar : reorder)
4412 srt[s++] = jvar.order;
4415 jalview.util.QuickSort.sort(srt, rws);
4416 // and re-insert the annotation at its correct position
4417 for (JvAnnotRow jvar : rws)
4419 al.addAnnotation(jvar.template, jvar.order);
4421 af.alignPanel.adjustAnnotationHeight();
4425 Hashtable skipList = null;
4428 * TODO remove this method
4431 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
4432 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
4433 * throw new Error("Implementation Error. No skipList defined for this
4434 * Jalview2XML instance."); } return (AlignFrame)
4435 * skipList.get(view.getSequenceSetId()); }
4439 * Check if the Jalview view contained in object should be skipped or not.
4442 * @return true if view's sequenceSetId is a key in skipList
4444 private boolean skipViewport(JalviewModel object)
4446 if (skipList == null)
4451 if (skipList.containsKey(id = object.getJalviewModelSequence()
4452 .getViewport()[0].getSequenceSetId()))
4454 if (Cache.log != null && Cache.log.isDebugEnabled())
4456 Cache.log.debug("Skipping seuqence set id " + id);
4463 public void addToSkipList(AlignFrame af)
4465 if (skipList == null)
4467 skipList = new Hashtable();
4469 skipList.put(af.getViewport().getSequenceSetId(), af);
4472 public void clearSkipList()
4474 if (skipList != null)
4481 private void recoverDatasetFor(SequenceSet vamsasSet, Alignment al,
4482 boolean ignoreUnrefed)
4484 jalview.datamodel.Alignment ds = getDatasetFor(vamsasSet.getDatasetId());
4485 Vector dseqs = null;
4488 // create a list of new dataset sequences
4489 dseqs = new Vector();
4491 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
4493 Sequence vamsasSeq = vamsasSet.getSequence(i);
4494 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed);
4496 // create a new dataset
4499 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
4500 dseqs.copyInto(dsseqs);
4501 ds = new jalview.datamodel.Alignment(dsseqs);
4502 debug("Created new dataset " + vamsasSet.getDatasetId()
4503 + " for alignment " + System.identityHashCode(al));
4504 addDatasetRef(vamsasSet.getDatasetId(), ds);
4506 // set the dataset for the newly imported alignment.
4507 if (al.getDataset() == null && !ignoreUnrefed)
4516 * sequence definition to create/merge dataset sequence for
4520 * vector to add new dataset sequence to
4522 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
4523 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed)
4525 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
4527 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
4528 SequenceI dsq = null;
4529 if (sq != null && sq.getDatasetSequence() != null)
4531 dsq = sq.getDatasetSequence();
4533 if (sq == null && ignoreUnrefed)
4537 String sqid = vamsasSeq.getDsseqid();
4540 // need to create or add a new dataset sequence reference to this sequence
4543 dsq = seqRefIds.get(sqid);
4548 // make a new dataset sequence
4549 dsq = sq.createDatasetSequence();
4552 // make up a new dataset reference for this sequence
4553 sqid = seqHash(dsq);
4555 dsq.setVamsasId(uniqueSetSuffix + sqid);
4556 seqRefIds.put(sqid, dsq);
4561 dseqs.addElement(dsq);
4566 ds.addSequence(dsq);
4572 { // make this dataset sequence sq's dataset sequence
4573 sq.setDatasetSequence(dsq);
4574 // and update the current dataset alignment
4579 if (!dseqs.contains(dsq))
4586 if (ds.findIndex(dsq) < 0)
4588 ds.addSequence(dsq);
4595 // TODO: refactor this as a merge dataset sequence function
4596 // now check that sq (the dataset sequence) sequence really is the union of
4597 // all references to it
4598 // boolean pre = sq.getStart() < dsq.getStart();
4599 // boolean post = sq.getEnd() > dsq.getEnd();
4603 // StringBuffer sb = new StringBuffer();
4604 String newres = jalview.analysis.AlignSeq.extractGaps(
4605 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
4606 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
4607 && newres.length() > dsq.getLength())
4609 // Update with the longer sequence.
4613 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
4614 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
4615 * sb.append(newres.substring(newres.length() - sq.getEnd() -
4616 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
4618 dsq.setSequence(newres);
4620 // TODO: merges will never happen if we 'know' we have the real dataset
4621 // sequence - this should be detected when id==dssid
4623 .println("DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
4624 // + (pre ? "prepended" : "") + " "
4625 // + (post ? "appended" : ""));
4630 java.util.Hashtable datasetIds = null;
4632 java.util.IdentityHashMap dataset2Ids = null;
4634 private Alignment getDatasetFor(String datasetId)
4636 if (datasetIds == null)
4638 datasetIds = new Hashtable();
4641 if (datasetIds.containsKey(datasetId))
4643 return (Alignment) datasetIds.get(datasetId);
4648 private void addDatasetRef(String datasetId, Alignment dataset)
4650 if (datasetIds == null)
4652 datasetIds = new Hashtable();
4654 datasetIds.put(datasetId, dataset);
4658 * make a new dataset ID for this jalview dataset alignment
4663 private String getDatasetIdRef(jalview.datamodel.Alignment dataset)
4665 if (dataset.getDataset() != null)
4667 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
4669 String datasetId = makeHashCode(dataset, null);
4670 if (datasetId == null)
4672 // make a new datasetId and record it
4673 if (dataset2Ids == null)
4675 dataset2Ids = new IdentityHashMap();
4679 datasetId = (String) dataset2Ids.get(dataset);
4681 if (datasetId == null)
4683 datasetId = "ds" + dataset2Ids.size() + 1;
4684 dataset2Ids.put(dataset, datasetId);
4690 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
4692 for (int d = 0; d < sequence.getDBRefCount(); d++)
4694 DBRef dr = sequence.getDBRef(d);
4695 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
4696 sequence.getDBRef(d).getSource(), sequence.getDBRef(d)
4697 .getVersion(), sequence.getDBRef(d).getAccessionId());
4698 if (dr.getMapping() != null)
4700 entry.setMap(addMapping(dr.getMapping()));
4702 datasetSequence.addDBRef(entry);
4706 private jalview.datamodel.Mapping addMapping(Mapping m)
4708 SequenceI dsto = null;
4709 // Mapping m = dr.getMapping();
4710 int fr[] = new int[m.getMapListFromCount() * 2];
4711 Enumeration f = m.enumerateMapListFrom();
4712 for (int _i = 0; f.hasMoreElements(); _i += 2)
4714 MapListFrom mf = (MapListFrom) f.nextElement();
4715 fr[_i] = mf.getStart();
4716 fr[_i + 1] = mf.getEnd();
4718 int fto[] = new int[m.getMapListToCount() * 2];
4719 f = m.enumerateMapListTo();
4720 for (int _i = 0; f.hasMoreElements(); _i += 2)
4722 MapListTo mf = (MapListTo) f.nextElement();
4723 fto[_i] = mf.getStart();
4724 fto[_i + 1] = mf.getEnd();
4726 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto,
4727 fr, fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
4728 if (m.getMappingChoice() != null)
4730 MappingChoice mc = m.getMappingChoice();
4731 if (mc.getDseqFor() != null)
4733 String dsfor = "" + mc.getDseqFor();
4734 if (seqRefIds.containsKey(dsfor))
4739 jmap.setTo(seqRefIds.get(dsfor));
4743 frefedSequence.add(new Object[]
4750 * local sequence definition
4752 Sequence ms = mc.getSequence();
4753 SequenceI djs = null;
4754 String sqid = ms.getDsseqid();
4755 if (sqid != null && sqid.length() > 0)
4758 * recover dataset sequence
4760 djs = seqRefIds.get(sqid);
4765 .println("Warning - making up dataset sequence id for DbRef sequence map reference");
4766 sqid = ((Object) ms).toString(); // make up a new hascode for
4767 // undefined dataset sequence hash
4768 // (unlikely to happen)
4774 * make a new dataset sequence and add it to refIds hash
4776 djs = new jalview.datamodel.Sequence(ms.getName(),
4778 djs.setStart(jmap.getMap().getToLowest());
4779 djs.setEnd(jmap.getMap().getToHighest());
4780 djs.setVamsasId(uniqueSetSuffix + sqid);
4782 seqRefIds.put(sqid, djs);
4785 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
4794 public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
4795 boolean keepSeqRefs)
4798 jalview.schemabinding.version2.JalviewModel jm = saveState(ap, null,
4804 jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
4808 uniqueSetSuffix = "";
4809 jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
4814 if (this.frefedSequence == null)
4816 frefedSequence = new Vector();
4819 viewportsAdded.clear();
4821 AlignFrame af = loadFromObject(jm, null, false, null);
4822 af.alignPanels.clear();
4823 af.closeMenuItem_actionPerformed(true);
4826 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
4827 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
4828 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
4829 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
4830 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
4833 return af.alignPanel;
4837 * flag indicating if hashtables should be cleared on finalization TODO this
4838 * flag may not be necessary
4840 private final boolean _cleartables = true;
4842 private Hashtable jvids2vobj;
4847 * @see java.lang.Object#finalize()
4850 protected void finalize() throws Throwable
4852 // really make sure we have no buried refs left.
4857 this.seqRefIds = null;
4858 this.seqsToIds = null;
4862 private void warn(String msg)
4867 private void warn(String msg, Exception e)
4869 if (Cache.log != null)
4873 Cache.log.warn(msg, e);
4877 Cache.log.warn(msg);
4882 System.err.println("Warning: " + msg);
4885 e.printStackTrace();
4890 private void debug(String string)
4892 debug(string, null);
4895 private void debug(String msg, Exception e)
4897 if (Cache.log != null)
4901 Cache.log.debug(msg, e);
4905 Cache.log.debug(msg);
4910 System.err.println("Warning: " + msg);
4913 e.printStackTrace();
4919 * set the object to ID mapping tables used to write/recover objects and XML
4920 * ID strings for the jalview project. If external tables are provided then
4921 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
4922 * object goes out of scope. - also populates the datasetIds hashtable with
4923 * alignment objects containing dataset sequences
4926 * Map from ID strings to jalview datamodel
4928 * Map from jalview datamodel to ID strings
4932 public void setObjectMappingTables(Hashtable vobj2jv,
4933 IdentityHashMap jv2vobj)
4935 this.jv2vobj = jv2vobj;
4936 this.vobj2jv = vobj2jv;
4937 Iterator ds = jv2vobj.keySet().iterator();
4939 while (ds.hasNext())
4941 Object jvobj = ds.next();
4942 id = jv2vobj.get(jvobj).toString();
4943 if (jvobj instanceof jalview.datamodel.Alignment)
4945 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
4947 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
4950 else if (jvobj instanceof jalview.datamodel.Sequence)
4952 // register sequence object so the XML parser can recover it.
4953 if (seqRefIds == null)
4955 seqRefIds = new HashMap<String, SequenceI>();
4957 if (seqsToIds == null)
4959 seqsToIds = new IdentityHashMap<SequenceI, String>();
4961 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
4962 seqsToIds.put((SequenceI) jvobj, id);
4964 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
4967 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
4968 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
4969 if (jvann.annotationId == null)
4971 jvann.annotationId = anid;
4973 if (!jvann.annotationId.equals(anid))
4975 // TODO verify that this is the correct behaviour
4976 this.warn("Overriding Annotation ID for " + anid
4977 + " from different id : " + jvann.annotationId);
4978 jvann.annotationId = anid;
4981 else if (jvobj instanceof String)
4983 if (jvids2vobj == null)
4985 jvids2vobj = new Hashtable();
4986 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
4991 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
4997 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
4998 * objects created from the project archive. If string is null (default for
4999 * construction) then suffix will be set automatically.
5003 public void setUniqueSetSuffix(String string)
5005 uniqueSetSuffix = string;
5010 * uses skipList2 as the skipList for skipping views on sequence sets
5011 * associated with keys in the skipList
5015 public void setSkipList(Hashtable skipList2)
5017 skipList = skipList2;
5021 * Reads the jar entry of given name and returns its contents, or null if the
5022 * entry is not found.
5025 * @param jarEntryName
5028 protected String readJarEntry(jarInputStreamProvider jprovider,
5029 String jarEntryName)
5031 String result = null;
5032 BufferedReader in = null;
5037 * Reopen the jar input stream and traverse its entries to find a matching
5040 JarInputStream jin = jprovider.getJarInputStream();
5041 JarEntry entry = null;
5044 entry = jin.getNextJarEntry();
5045 } while (entry != null && !entry.getName().equals(jarEntryName));
5049 StringBuilder out = new StringBuilder(256);
5050 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
5053 while ((data = in.readLine()) != null)
5057 result = out.toString();
5061 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
5063 } catch (Exception ex)
5065 ex.printStackTrace();
5073 } catch (IOException e)