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 // 2.9 JAL-1781 xref on sequence id rather than name
1515 an.setSequenceRef(seqsToIds.get(aa[i].sequenceRef));
1517 if (aa[i].groupRef != null)
1519 Object groupIdr = groupRefs.get(aa[i].groupRef);
1520 if (groupIdr == null)
1522 // make a locally unique String
1523 groupRefs.put(aa[i].groupRef,
1524 groupIdr = ("" + System.currentTimeMillis()
1525 + aa[i].groupRef.getName() + groupRefs.size()));
1527 an.setGroupRef(groupIdr.toString());
1530 // store all visualization attributes for annotation
1531 an.setGraphHeight(aa[i].graphHeight);
1532 an.setCentreColLabels(aa[i].centreColLabels);
1533 an.setScaleColLabels(aa[i].scaleColLabel);
1534 an.setShowAllColLabels(aa[i].showAllColLabels);
1535 an.setBelowAlignment(aa[i].belowAlignment);
1537 if (aa[i].graph > 0)
1540 an.setGraphType(aa[i].graph);
1541 an.setGraphGroup(aa[i].graphGroup);
1542 if (aa[i].getThreshold() != null)
1544 ThresholdLine line = new ThresholdLine();
1545 line.setLabel(aa[i].getThreshold().label);
1546 line.setValue(aa[i].getThreshold().value);
1547 line.setColour(aa[i].getThreshold().colour.getRGB());
1548 an.setThresholdLine(line);
1556 an.setLabel(aa[i].label);
1558 if (aa[i] == av.getAlignmentQualityAnnot()
1559 || aa[i] == av.getAlignmentConservationAnnotation()
1560 || aa[i] == av.getAlignmentConsensusAnnotation()
1561 || aa[i].autoCalculated)
1563 // new way of indicating autocalculated annotation -
1564 an.setAutoCalculated(aa[i].autoCalculated);
1566 if (aa[i].hasScore())
1568 an.setScore(aa[i].getScore());
1571 if (aa[i].getCalcId() != null)
1573 calcIdSet.add(aa[i].getCalcId());
1574 an.setCalcId(aa[i].getCalcId());
1576 if (aa[i].hasProperties())
1578 for (String pr : aa[i].getProperties())
1580 Property prop = new Property();
1582 prop.setValue(aa[i].getProperty(pr));
1583 an.addProperty(prop);
1587 AnnotationElement ae;
1588 if (aa[i].annotations != null)
1590 an.setScoreOnly(false);
1591 for (int a = 0; a < aa[i].annotations.length; a++)
1593 if ((aa[i] == null) || (aa[i].annotations[a] == null))
1598 ae = new AnnotationElement();
1599 if (aa[i].annotations[a].description != null)
1601 ae.setDescription(aa[i].annotations[a].description);
1603 if (aa[i].annotations[a].displayCharacter != null)
1605 ae.setDisplayCharacter(aa[i].annotations[a].displayCharacter);
1608 if (!Float.isNaN(aa[i].annotations[a].value))
1610 ae.setValue(aa[i].annotations[a].value);
1614 if (aa[i].annotations[a].secondaryStructure > ' ')
1616 ae.setSecondaryStructure(aa[i].annotations[a].secondaryStructure
1620 if (aa[i].annotations[a].colour != null
1621 && aa[i].annotations[a].colour != java.awt.Color.black)
1623 ae.setColour(aa[i].annotations[a].colour.getRGB());
1626 an.addAnnotationElement(ae);
1627 if (aa[i].autoCalculated)
1629 // only write one non-null entry into the annotation row -
1630 // sufficient to get the visualization attributes necessary to
1638 an.setScoreOnly(true);
1640 if (!storeDS || (storeDS && !aa[i].autoCalculated))
1642 // skip autocalculated annotation - these are only provided for
1644 vamsasSet.addAnnotation(an);
1650 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
1652 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
1653 if (settings != null)
1655 CalcIdParam vCalcIdParam = new CalcIdParam();
1656 vCalcIdParam.setCalcId(calcId);
1657 vCalcIdParam.addServiceURL(settings.getServiceURI());
1658 // generic URI allowing a third party to resolve another instance of the
1659 // service used for this calculation
1660 for (String urls : settings.getServiceURLs())
1662 vCalcIdParam.addServiceURL(urls);
1664 vCalcIdParam.setVersion("1.0");
1665 if (settings.getPreset() != null)
1667 WsParamSetI setting = settings.getPreset();
1668 vCalcIdParam.setName(setting.getName());
1669 vCalcIdParam.setDescription(setting.getDescription());
1673 vCalcIdParam.setName("");
1674 vCalcIdParam.setDescription("Last used parameters");
1676 // need to be able to recover 1) settings 2) user-defined presets or
1677 // recreate settings from preset 3) predefined settings provided by
1678 // service - or settings that can be transferred (or discarded)
1679 vCalcIdParam.setParameters(settings.getWsParamFile().replace("\n",
1681 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
1682 // todo - decide if updateImmediately is needed for any projects.
1684 return vCalcIdParam;
1689 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
1692 if (calcIdParam.getVersion().equals("1.0"))
1694 Jws2Instance service = Jws2Discoverer.getDiscoverer()
1695 .getPreferredServiceFor(calcIdParam.getServiceURL());
1696 if (service != null)
1698 WsParamSetI parmSet = null;
1701 parmSet = service.getParamStore().parseServiceParameterFile(
1702 calcIdParam.getName(), calcIdParam.getDescription(),
1703 calcIdParam.getServiceURL(),
1704 calcIdParam.getParameters().replace("|\\n|", "\n"));
1705 } catch (IOException x)
1707 warn("Couldn't parse parameter data for "
1708 + calcIdParam.getCalcId(), x);
1711 List<ArgumentI> argList = null;
1712 if (calcIdParam.getName().length() > 0)
1714 parmSet = service.getParamStore()
1715 .getPreset(calcIdParam.getName());
1716 if (parmSet != null)
1718 // TODO : check we have a good match with settings in AACon -
1719 // otherwise we'll need to create a new preset
1724 argList = parmSet.getArguments();
1727 AAConSettings settings = new AAConSettings(
1728 calcIdParam.isAutoUpdate(), service, parmSet, argList);
1729 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
1730 calcIdParam.isNeedsUpdate());
1735 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
1739 throw new Error(MessageManager.formatMessage(
1740 "error.unsupported_version_calcIdparam", new Object[]
1741 { calcIdParam.toString() }));
1745 * External mapping between jalview objects and objects yielding a valid and
1746 * unique object ID string. This is null for normal Jalview project IO, but
1747 * non-null when a jalview project is being read or written as part of a
1750 IdentityHashMap jv2vobj = null;
1753 * Construct a unique ID for jvobj using either existing bindings or if none
1754 * exist, the result of the hashcode call for the object.
1757 * jalview data object
1758 * @return unique ID for referring to jvobj
1760 private String makeHashCode(Object jvobj, String altCode)
1762 if (jv2vobj != null)
1764 Object id = jv2vobj.get(jvobj);
1767 return id.toString();
1769 // check string ID mappings
1770 if (jvids2vobj != null && jvobj instanceof String)
1772 id = jvids2vobj.get(jvobj);
1776 return id.toString();
1778 // give up and warn that something has gone wrong
1779 warn("Cannot find ID for object in external mapping : " + jvobj);
1785 * return local jalview object mapped to ID, if it exists
1789 * @return null or object bound to idcode
1791 private Object retrieveExistingObj(String idcode)
1793 if (idcode != null && vobj2jv != null)
1795 return vobj2jv.get(idcode);
1801 * binding from ID strings from external mapping table to jalview data model
1804 private Hashtable vobj2jv;
1806 private Sequence createVamsasSequence(String id, SequenceI jds)
1808 return createVamsasSequence(true, id, jds, null);
1811 private Sequence createVamsasSequence(boolean recurse, String id,
1812 SequenceI jds, SequenceI parentseq)
1814 Sequence vamsasSeq = new Sequence();
1815 vamsasSeq.setId(id);
1816 vamsasSeq.setName(jds.getName());
1817 vamsasSeq.setSequence(jds.getSequenceAsString());
1818 vamsasSeq.setDescription(jds.getDescription());
1819 jalview.datamodel.DBRefEntry[] dbrefs = null;
1820 if (jds.getDatasetSequence() != null)
1822 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
1823 if (jds.getDatasetSequence().getDBRef() != null)
1825 dbrefs = jds.getDatasetSequence().getDBRef();
1830 vamsasSeq.setDsseqid(id); // so we can tell which sequences really are
1831 // dataset sequences only
1832 dbrefs = jds.getDBRef();
1836 for (int d = 0; d < dbrefs.length; d++)
1838 DBRef dbref = new DBRef();
1839 dbref.setSource(dbrefs[d].getSource());
1840 dbref.setVersion(dbrefs[d].getVersion());
1841 dbref.setAccessionId(dbrefs[d].getAccessionId());
1842 if (dbrefs[d].hasMap())
1844 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
1846 dbref.setMapping(mp);
1848 vamsasSeq.addDBRef(dbref);
1854 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
1855 SequenceI parentseq, SequenceI jds, boolean recurse)
1858 if (jmp.getMap() != null)
1862 jalview.util.MapList mlst = jmp.getMap();
1863 List<int[]> r = mlst.getFromRanges();
1864 for (int[] range : r)
1866 MapListFrom mfrom = new MapListFrom();
1867 mfrom.setStart(range[0]);
1868 mfrom.setEnd(range[1]);
1869 mp.addMapListFrom(mfrom);
1871 r = mlst.getToRanges();
1872 for (int[] range : r)
1874 MapListTo mto = new MapListTo();
1875 mto.setStart(range[0]);
1876 mto.setEnd(range[1]);
1877 mp.addMapListTo(mto);
1879 mp.setMapFromUnit(mlst.getFromRatio());
1880 mp.setMapToUnit(mlst.getToRatio());
1881 if (jmp.getTo() != null)
1883 MappingChoice mpc = new MappingChoice();
1885 && (parentseq != jmp.getTo() || parentseq
1886 .getDatasetSequence() != jmp.getTo()))
1888 mpc.setSequence(createVamsasSequence(false, seqHash(jmp.getTo()),
1894 SequenceI ps = null;
1895 if (parentseq != jmp.getTo()
1896 && parentseq.getDatasetSequence() != jmp.getTo())
1898 // chaining dbref rather than a handshaking one
1899 jmpid = seqHash(ps = jmp.getTo());
1903 jmpid = seqHash(ps = parentseq);
1905 mpc.setDseqFor(jmpid);
1906 if (!seqRefIds.containsKey(mpc.getDseqFor()))
1908 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
1909 seqRefIds.put(mpc.getDseqFor(), ps);
1913 jalview.bin.Cache.log.debug("reusing DseqFor ID");
1916 mp.setMappingChoice(mpc);
1922 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
1923 List<UserColourScheme> userColours, JalviewModelSequence jms)
1926 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
1927 boolean newucs = false;
1928 if (!userColours.contains(ucs))
1930 userColours.add(ucs);
1933 id = "ucs" + userColours.indexOf(ucs);
1936 // actually create the scheme's entry in the XML model
1937 java.awt.Color[] colours = ucs.getColours();
1938 jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
1939 jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
1941 for (int i = 0; i < colours.length; i++)
1943 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
1944 col.setName(ResidueProperties.aa[i]);
1945 col.setRGB(jalview.util.Format.getHexString(colours[i]));
1946 jbucs.addColour(col);
1948 if (ucs.getLowerCaseColours() != null)
1950 colours = ucs.getLowerCaseColours();
1951 for (int i = 0; i < colours.length; i++)
1953 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
1954 col.setName(ResidueProperties.aa[i].toLowerCase());
1955 col.setRGB(jalview.util.Format.getHexString(colours[i]));
1956 jbucs.addColour(col);
1961 uc.setUserColourScheme(jbucs);
1962 jms.addUserColours(uc);
1968 jalview.schemes.UserColourScheme getUserColourScheme(
1969 JalviewModelSequence jms, String id)
1971 UserColours[] uc = jms.getUserColours();
1972 UserColours colours = null;
1974 for (int i = 0; i < uc.length; i++)
1976 if (uc[i].getId().equals(id))
1984 java.awt.Color[] newColours = new java.awt.Color[24];
1986 for (int i = 0; i < 24; i++)
1988 newColours[i] = new java.awt.Color(Integer.parseInt(colours
1989 .getUserColourScheme().getColour(i).getRGB(), 16));
1992 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
1995 if (colours.getUserColourScheme().getColourCount() > 24)
1997 newColours = new java.awt.Color[23];
1998 for (int i = 0; i < 23; i++)
2000 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2001 .getUserColourScheme().getColour(i + 24).getRGB(), 16));
2003 ucs.setLowerCaseColours(newColours);
2010 * contains last error message (if any) encountered by XML loader.
2012 String errorMessage = null;
2015 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2016 * exceptions are raised during project XML parsing
2018 public boolean attemptversion1parse = true;
2021 * Load a jalview project archive from a jar file
2024 * - HTTP URL or filename
2026 public AlignFrame loadJalviewAlign(final String file)
2029 jalview.gui.AlignFrame af = null;
2033 // create list to store references for any new Jmol viewers created
2034 newStructureViewers = new Vector<JalviewStructureDisplayI>();
2035 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2036 // Workaround is to make sure caller implements the JarInputStreamProvider
2038 // so we can re-open the jar input stream for each entry.
2040 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2041 af = loadJalviewAlign(jprovider);
2043 } catch (MalformedURLException e)
2045 errorMessage = "Invalid URL format for '" + file + "'";
2051 SwingUtilities.invokeAndWait(new Runnable()
2055 setLoadingFinishedForNewStructureViewers();
2058 } catch (Exception x)
2066 private jarInputStreamProvider createjarInputStreamProvider(
2067 final String file) throws MalformedURLException
2070 errorMessage = null;
2071 uniqueSetSuffix = null;
2073 viewportsAdded.clear();
2074 frefedSequence = null;
2076 if (file.startsWith("http://"))
2078 url = new URL(file);
2080 final URL _url = url;
2081 return new jarInputStreamProvider()
2085 public JarInputStream getJarInputStream() throws IOException
2089 return new JarInputStream(_url.openStream());
2093 return new JarInputStream(new FileInputStream(file));
2098 public String getFilename()
2106 * Recover jalview session from a jalview project archive. Caller may
2107 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2108 * themselves. Any null fields will be initialised with default values,
2109 * non-null fields are left alone.
2114 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2116 errorMessage = null;
2117 if (uniqueSetSuffix == null)
2119 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2121 if (seqRefIds == null)
2123 seqRefIds = new HashMap<String, SequenceI>();
2125 if (frefedSequence == null)
2127 frefedSequence = new Vector();
2130 AlignFrame af = null, _af = null;
2131 Map<String, AlignFrame> gatherToThisFrame = new HashMap<String, AlignFrame>();
2132 final String file = jprovider.getFilename();
2135 JarInputStream jin = null;
2136 JarEntry jarentry = null;
2141 jin = jprovider.getJarInputStream();
2142 for (int i = 0; i < entryCount; i++)
2144 jarentry = jin.getNextJarEntry();
2147 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2149 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2150 JalviewModel object = new JalviewModel();
2152 Unmarshaller unmar = new Unmarshaller(object);
2153 unmar.setValidation(false);
2154 object = (JalviewModel) unmar.unmarshal(in);
2155 if (true) // !skipViewport(object))
2157 _af = loadFromObject(object, file, true, jprovider);
2158 if (object.getJalviewModelSequence().getViewportCount() > 0)
2161 if (af.viewport.isGatherViewsHere())
2163 gatherToThisFrame.put(af.viewport.getSequenceSetId(), af);
2169 else if (jarentry != null)
2171 // Some other file here.
2174 } while (jarentry != null);
2175 resolveFrefedSequences();
2176 } catch (java.io.FileNotFoundException ex)
2178 ex.printStackTrace();
2179 errorMessage = "Couldn't locate Jalview XML file : " + file;
2180 System.err.println("Exception whilst loading jalview XML file : "
2182 } catch (java.net.UnknownHostException ex)
2184 ex.printStackTrace();
2185 errorMessage = "Couldn't locate Jalview XML file : " + file;
2186 System.err.println("Exception whilst loading jalview XML file : "
2188 } catch (Exception ex)
2190 System.err.println("Parsing as Jalview Version 2 file failed.");
2191 ex.printStackTrace(System.err);
2192 if (attemptversion1parse)
2194 // Is Version 1 Jar file?
2197 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
2198 } catch (Exception ex2)
2200 System.err.println("Exception whilst loading as jalviewXMLV1:");
2201 ex2.printStackTrace();
2205 if (Desktop.instance != null)
2207 Desktop.instance.stopLoading();
2211 System.out.println("Successfully loaded archive file");
2214 ex.printStackTrace();
2216 System.err.println("Exception whilst loading jalview XML file : "
2218 } catch (OutOfMemoryError e)
2220 // Don't use the OOM Window here
2221 errorMessage = "Out of memory loading jalview XML file";
2222 System.err.println("Out of memory whilst loading jalview XML file");
2223 e.printStackTrace();
2226 if (Desktop.instance != null)
2228 Desktop.instance.stopLoading();
2232 * Regather multiple views (with the same sequence set id) to the frame (if
2233 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2234 * views instead of separate frames. Note this doesn't restore a state where
2235 * some expanded views in turn have tabbed views - the last "first tab" read
2236 * in will play the role of gatherer for all.
2238 for (AlignFrame fr : gatherToThisFrame.values())
2240 Desktop.instance.gatherViews(fr);
2243 restoreSplitFrames();
2245 if (errorMessage != null)
2253 * Try to reconstruct and display SplitFrame windows, where each contains
2254 * complementary dna and protein alignments. Done by pairing up AlignFrame
2255 * objects (created earlier) which have complementary viewport ids associated.
2257 protected void restoreSplitFrames()
2259 List<SplitFrame> gatherTo = new ArrayList<SplitFrame>();
2260 List<AlignFrame> addedToSplitFrames = new ArrayList<AlignFrame>();
2261 Map<String, AlignFrame> dna = new HashMap<String, AlignFrame>();
2264 * Identify the DNA alignments
2266 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2269 AlignFrame af = candidate.getValue();
2270 if (af.getViewport().getAlignment().isNucleotide())
2272 dna.put(candidate.getKey().getId(), af);
2277 * Try to match up the protein complements
2279 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2282 AlignFrame af = candidate.getValue();
2283 if (!af.getViewport().getAlignment().isNucleotide())
2285 String complementId = candidate.getKey().getComplementId();
2286 // only non-null complements should be in the Map
2287 if (complementId != null && dna.containsKey(complementId))
2289 final AlignFrame dnaFrame = dna.get(complementId);
2290 SplitFrame sf = createSplitFrame(dnaFrame, af);
2291 addedToSplitFrames.add(dnaFrame);
2292 addedToSplitFrames.add(af);
2293 if (af.viewport.isGatherViewsHere())
2302 * Open any that we failed to pair up (which shouldn't happen!) as
2303 * standalone AlignFrame's.
2305 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2308 AlignFrame af = candidate.getValue();
2309 if (!addedToSplitFrames.contains(af)) {
2310 Viewport view = candidate.getKey();
2311 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
2313 System.err.println("Failed to restore view " + view.getTitle()
2314 + " to split frame");
2319 * Gather back into tabbed views as flagged.
2321 for (SplitFrame sf : gatherTo)
2323 Desktop.instance.gatherViews(sf);
2326 splitFrameCandidates.clear();
2330 * Construct and display one SplitFrame holding DNA and protein alignments.
2333 * @param proteinFrame
2336 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
2337 AlignFrame proteinFrame)
2339 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
2340 String title = MessageManager.getString("label.linked_view_title");
2341 int width = (int) dnaFrame.getBounds().getWidth();
2342 int height = (int) (dnaFrame.getBounds().getHeight()
2343 + proteinFrame.getBounds().getHeight() + 50);
2344 Desktop.addInternalFrame(splitFrame, title, width, height);
2347 * And compute cDNA consensus (couldn't do earlier with consensus as
2348 * mappings were not yet present)
2350 proteinFrame.viewport.alignmentChanged(proteinFrame.alignPanel);
2356 * check errorMessage for a valid error message and raise an error box in the
2357 * GUI or write the current errorMessage to stderr and then clear the error
2360 protected void reportErrors()
2362 reportErrors(false);
2365 protected void reportErrors(final boolean saving)
2367 if (errorMessage != null)
2369 final String finalErrorMessage = errorMessage;
2372 javax.swing.SwingUtilities.invokeLater(new Runnable()
2377 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2378 finalErrorMessage, "Error "
2379 + (saving ? "saving" : "loading")
2380 + " Jalview file", JOptionPane.WARNING_MESSAGE);
2386 System.err.println("Problem loading Jalview file: " + errorMessage);
2389 errorMessage = null;
2392 Map<String, String> alreadyLoadedPDB = new HashMap<String, String>();
2395 * when set, local views will be updated from view stored in JalviewXML
2396 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2397 * sync if this is set to true.
2399 private final boolean updateLocalViews = false;
2402 * Returns the path to a temporary file holding the PDB file for the given PDB
2403 * id. The first time of asking, searches for a file of that name in the
2404 * Jalview project jar, and copies it to a new temporary file. Any repeat
2405 * requests just return the path to the file previously created.
2411 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId)
2413 if (alreadyLoadedPDB.containsKey(pdbId))
2415 return alreadyLoadedPDB.get(pdbId).toString();
2418 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb");
2419 if (tempFile != null)
2421 alreadyLoadedPDB.put(pdbId, tempFile);
2427 * Copies the jar entry of given name to a new temporary file and returns the
2428 * path to the file, or null if the entry is not found.
2431 * @param jarEntryName
2433 * a prefix for the temporary file name, must be at least three
2437 protected String copyJarEntry(jarInputStreamProvider jprovider,
2438 String jarEntryName, String prefix)
2440 BufferedReader in = null;
2441 PrintWriter out = null;
2445 JarInputStream jin = jprovider.getJarInputStream();
2447 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2448 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2449 * FileInputStream(jprovider)); }
2452 JarEntry entry = null;
2455 entry = jin.getNextJarEntry();
2456 } while (entry != null && !entry.getName().equals(jarEntryName));
2459 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
2460 File outFile = File.createTempFile(prefix, ".tmp");
2461 outFile.deleteOnExit();
2462 out = new PrintWriter(new FileOutputStream(outFile));
2465 while ((data = in.readLine()) != null)
2470 String t = outFile.getAbsolutePath();
2475 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
2477 } catch (Exception ex)
2479 ex.printStackTrace();
2487 } catch (IOException e)
2501 private class JvAnnotRow
2503 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2510 * persisted version of annotation row from which to take vis properties
2512 public jalview.datamodel.AlignmentAnnotation template;
2515 * original position of the annotation row in the alignment
2521 * Load alignment frame from jalview XML DOM object
2526 * filename source string
2527 * @param loadTreesAndStructures
2528 * when false only create Viewport
2530 * data source provider
2531 * @return alignment frame created from view stored in DOM
2533 AlignFrame loadFromObject(JalviewModel object, String file,
2534 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
2536 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
2537 Sequence[] vamsasSeq = vamsasSet.getSequence();
2539 JalviewModelSequence jms = object.getJalviewModelSequence();
2541 Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
2544 // ////////////////////////////////
2547 List<SequenceI> hiddenSeqs = null;
2548 jalview.datamodel.Sequence jseq;
2550 List<SequenceI> tmpseqs = new ArrayList<SequenceI>();
2552 boolean multipleView = false;
2554 JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
2555 int vi = 0; // counter in vamsasSeq array
2556 for (int i = 0; i < jseqs.length; i++)
2558 String seqId = jseqs[i].getId();
2560 if (seqRefIds.get(seqId) != null)
2562 tmpseqs.add(seqRefIds.get(seqId));
2563 multipleView = true;
2567 jseq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
2568 vamsasSeq[vi].getSequence());
2569 jseq.setDescription(vamsasSeq[vi].getDescription());
2570 jseq.setStart(jseqs[i].getStart());
2571 jseq.setEnd(jseqs[i].getEnd());
2572 jseq.setVamsasId(uniqueSetSuffix + seqId);
2573 seqRefIds.put(vamsasSeq[vi].getId(), jseq);
2578 if (jseqs[i].getHidden())
2580 if (hiddenSeqs == null)
2582 hiddenSeqs = new ArrayList<SequenceI>();
2585 hiddenSeqs.add(seqRefIds.get(seqId));
2591 // Create the alignment object from the sequence set
2592 // ///////////////////////////////
2593 SequenceI[] orderedSeqs = tmpseqs
2594 .toArray(new SequenceI[tmpseqs.size()]);
2596 Alignment al = new Alignment(orderedSeqs);
2598 // / Add the alignment properties
2599 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
2601 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
2602 al.setProperty(ssp.getKey(), ssp.getValue());
2606 // SequenceFeatures are added to the DatasetSequence,
2607 // so we must create or recover the dataset before loading features
2608 // ///////////////////////////////
2609 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
2611 // older jalview projects do not have a dataset id.
2612 al.setDataset(null);
2616 // recover dataset - passing on flag indicating if this a 'viewless'
2617 // sequence set (a.k.a. a stored dataset for the project)
2618 recoverDatasetFor(vamsasSet, al, object.getJalviewModelSequence()
2619 .getViewportCount() == 0);
2621 // ///////////////////////////////
2623 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
2626 // load sequence features, database references and any associated PDB
2627 // structures for the alignment
2628 for (int i = 0; i < vamsasSeq.length; i++)
2630 if (jseqs[i].getFeaturesCount() > 0)
2632 Features[] features = jseqs[i].getFeatures();
2633 for (int f = 0; f < features.length; f++)
2635 jalview.datamodel.SequenceFeature sf = new jalview.datamodel.SequenceFeature(
2636 features[f].getType(), features[f].getDescription(),
2637 features[f].getStatus(), features[f].getBegin(),
2638 features[f].getEnd(), features[f].getFeatureGroup());
2640 sf.setScore(features[f].getScore());
2641 for (int od = 0; od < features[f].getOtherDataCount(); od++)
2643 OtherData keyValue = features[f].getOtherData(od);
2644 if (keyValue.getKey().startsWith("LINK"))
2646 sf.addLink(keyValue.getValue());
2650 sf.setValue(keyValue.getKey(), keyValue.getValue());
2655 al.getSequenceAt(i).getDatasetSequence().addSequenceFeature(sf);
2658 if (vamsasSeq[i].getDBRefCount() > 0)
2660 addDBRefs(al.getSequenceAt(i).getDatasetSequence(), vamsasSeq[i]);
2662 if (jseqs[i].getPdbidsCount() > 0)
2664 Pdbids[] ids = jseqs[i].getPdbids();
2665 for (int p = 0; p < ids.length; p++)
2667 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
2668 entry.setId(ids[p].getId());
2669 if (ids[p].getType() != null)
2671 if (ids[p].getType().equalsIgnoreCase("PDB"))
2673 entry.setType(PDBEntry.Type.PDB);
2677 entry.setType(PDBEntry.Type.FILE);
2680 if (ids[p].getFile() != null)
2682 if (!pdbloaded.containsKey(ids[p].getFile()))
2684 entry.setFile(loadPDBFile(jprovider, ids[p].getId()));
2688 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
2691 StructureSelectionManager.getStructureSelectionManager(
2692 Desktop.instance).registerPDBEntry(entry);
2693 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
2697 } // end !multipleview
2699 // ///////////////////////////////
2700 // LOAD SEQUENCE MAPPINGS
2702 if (vamsasSet.getAlcodonFrameCount() > 0)
2704 // TODO Potentially this should only be done once for all views of an
2706 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
2707 for (int i = 0; i < alc.length; i++)
2709 AlignedCodonFrame cf = new AlignedCodonFrame();
2710 if (alc[i].getAlcodMapCount() > 0)
2712 AlcodMap[] maps = alc[i].getAlcodMap();
2713 for (int m = 0; m < maps.length; m++)
2715 SequenceI dnaseq = seqRefIds.get(maps[m].getDnasq());
2717 jalview.datamodel.Mapping mapping = null;
2718 // attach to dna sequence reference.
2719 if (maps[m].getMapping() != null)
2721 mapping = addMapping(maps[m].getMapping());
2725 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
2730 frefedSequence.add(new Object[]
2731 { maps[m].getDnasq(), cf, mapping });
2735 al.addCodonFrame(cf);
2739 // ////////////////////////////////
2741 List<JvAnnotRow> autoAlan = new ArrayList<JvAnnotRow>();
2743 * store any annotations which forward reference a group's ID
2745 Hashtable<String, ArrayList<jalview.datamodel.AlignmentAnnotation>> groupAnnotRefs = new Hashtable<String, ArrayList<jalview.datamodel.AlignmentAnnotation>>();
2747 if (vamsasSet.getAnnotationCount() > 0)
2749 Annotation[] an = vamsasSet.getAnnotation();
2751 for (int i = 0; i < an.length; i++)
2754 * test if annotation is automatically calculated for this view only
2756 boolean autoForView = false;
2757 if (an[i].getLabel().equals("Quality")
2758 || an[i].getLabel().equals("Conservation")
2759 || an[i].getLabel().equals("Consensus"))
2761 // Kludge for pre 2.5 projects which lacked the autocalculated flag
2763 if (!an[i].hasAutoCalculated())
2765 an[i].setAutoCalculated(true);
2769 || (an[i].hasAutoCalculated() && an[i].isAutoCalculated()))
2771 // remove ID - we don't recover annotation from other views for
2772 // view-specific annotation
2776 // set visiblity for other annotation in this view
2777 if (an[i].getId() != null
2778 && annotationIds.containsKey(an[i].getId()))
2780 AlignmentAnnotation jda = annotationIds.get(an[i].getId());
2781 // in principle Visible should always be true for annotation displayed
2782 // in multiple views
2783 if (an[i].hasVisible())
2785 jda.visible = an[i].getVisible();
2788 al.addAnnotation(jda);
2792 // Construct new annotation from model.
2793 AnnotationElement[] ae = an[i].getAnnotationElement();
2794 jalview.datamodel.Annotation[] anot = null;
2795 java.awt.Color firstColour = null;
2797 if (!an[i].getScoreOnly())
2799 anot = new jalview.datamodel.Annotation[al.getWidth()];
2800 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
2802 anpos = ae[aa].getPosition();
2804 if (anpos >= anot.length)
2809 anot[anpos] = new jalview.datamodel.Annotation(
2811 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
2812 (ae[aa].getSecondaryStructure() == null || ae[aa]
2813 .getSecondaryStructure().length() == 0) ? ' '
2814 : ae[aa].getSecondaryStructure().charAt(0),
2818 // JBPNote: Consider verifying dataflow for IO of secondary
2819 // structure annotation read from Stockholm files
2820 // this was added to try to ensure that
2821 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
2823 // anot[ae[aa].getPosition()].displayCharacter = "";
2825 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
2826 if (firstColour == null)
2828 firstColour = anot[anpos].colour;
2832 jalview.datamodel.AlignmentAnnotation jaa = null;
2834 if (an[i].getGraph())
2836 float llim = 0, hlim = 0;
2837 // if (autoForView || an[i].isAutoCalculated()) {
2840 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
2841 an[i].getDescription(), anot, llim, hlim,
2842 an[i].getGraphType());
2844 jaa.graphGroup = an[i].getGraphGroup();
2845 jaa._linecolour = firstColour;
2846 if (an[i].getThresholdLine() != null)
2848 jaa.setThreshold(new jalview.datamodel.GraphLine(an[i]
2849 .getThresholdLine().getValue(), an[i]
2850 .getThresholdLine().getLabel(), new java.awt.Color(
2851 an[i].getThresholdLine().getColour())));
2854 if (autoForView || an[i].isAutoCalculated())
2856 // Hardwire the symbol display line to ensure that labels for
2857 // histograms are displayed
2863 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
2864 an[i].getDescription(), anot);
2865 jaa._linecolour = firstColour;
2867 // register new annotation
2868 if (an[i].getId() != null)
2870 annotationIds.put(an[i].getId(), jaa);
2871 jaa.annotationId = an[i].getId();
2873 // recover sequence association
2874 String sequenceRef = an[i].getSequenceRef();
2875 if (sequenceRef != null)
2877 // from 2.9 sequenceRef is to sequence id (JAL-1781)
2878 SequenceI sequence = seqRefIds.get(sequenceRef);
2879 if (sequence == null)
2881 // in pre-2.9 projects sequence ref is to sequence name
2882 sequence = al.findName(sequenceRef);
2884 if (sequence != null)
2886 jaa.createSequenceMapping(sequence, 1, true);
2887 sequence.addAlignmentAnnotation(jaa);
2890 // and make a note of any group association
2891 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
2893 ArrayList<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
2894 .get(an[i].getGroupRef());
2897 aal = new ArrayList<jalview.datamodel.AlignmentAnnotation>();
2898 groupAnnotRefs.put(an[i].getGroupRef(), aal);
2903 if (an[i].hasScore())
2905 jaa.setScore(an[i].getScore());
2907 if (an[i].hasVisible())
2909 jaa.visible = an[i].getVisible();
2912 if (an[i].hasCentreColLabels())
2914 jaa.centreColLabels = an[i].getCentreColLabels();
2917 if (an[i].hasScaleColLabels())
2919 jaa.scaleColLabel = an[i].getScaleColLabels();
2921 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
2923 // newer files have an 'autoCalculated' flag and store calculation
2924 // state in viewport properties
2925 jaa.autoCalculated = true; // means annotation will be marked for
2926 // update at end of load.
2928 if (an[i].hasGraphHeight())
2930 jaa.graphHeight = an[i].getGraphHeight();
2932 if (an[i].hasBelowAlignment())
2934 jaa.belowAlignment = an[i].isBelowAlignment();
2936 jaa.setCalcId(an[i].getCalcId());
2937 if (an[i].getPropertyCount() > 0)
2939 for (jalview.schemabinding.version2.Property prop : an[i]
2942 jaa.setProperty(prop.getName(), prop.getValue());
2945 if (jaa.autoCalculated)
2947 autoAlan.add(new JvAnnotRow(i, jaa));
2950 // if (!autoForView)
2952 // add autocalculated group annotation and any user created annotation
2954 al.addAnnotation(jaa);
2958 // ///////////////////////
2960 // Create alignment markup and styles for this view
2961 if (jms.getJGroupCount() > 0)
2963 JGroup[] groups = jms.getJGroup();
2964 boolean addAnnotSchemeGroup = false;
2965 for (int i = 0; i < groups.length; i++)
2967 ColourSchemeI cs = null;
2969 if (groups[i].getColour() != null)
2971 if (groups[i].getColour().startsWith("ucs"))
2973 cs = getUserColourScheme(jms, groups[i].getColour());
2975 else if (groups[i].getColour().equals("AnnotationColourGradient")
2976 && groups[i].getAnnotationColours() != null)
2978 addAnnotSchemeGroup = true;
2983 cs = ColourSchemeProperty.getColour(al, groups[i].getColour());
2988 cs.setThreshold(groups[i].getPidThreshold(), true);
2992 Vector seqs = new Vector();
2994 for (int s = 0; s < groups[i].getSeqCount(); s++)
2996 String seqId = groups[i].getSeq(s) + "";
2997 jalview.datamodel.SequenceI ts = seqRefIds.get(seqId);
3001 seqs.addElement(ts);
3005 if (seqs.size() < 1)
3010 jalview.datamodel.SequenceGroup sg = new jalview.datamodel.SequenceGroup(
3011 seqs, groups[i].getName(), cs, groups[i].getDisplayBoxes(),
3012 groups[i].getDisplayText(), groups[i].getColourText(),
3013 groups[i].getStart(), groups[i].getEnd());
3015 sg.setOutlineColour(new java.awt.Color(groups[i].getOutlineColour()));
3017 sg.textColour = new java.awt.Color(groups[i].getTextCol1());
3018 sg.textColour2 = new java.awt.Color(groups[i].getTextCol2());
3019 sg.setShowNonconserved(groups[i].hasShowUnconserved() ? groups[i]
3020 .isShowUnconserved() : false);
3021 sg.thresholdTextColour = groups[i].getTextColThreshold();
3022 if (groups[i].hasShowConsensusHistogram())
3024 sg.setShowConsensusHistogram(groups[i].isShowConsensusHistogram());
3027 if (groups[i].hasShowSequenceLogo())
3029 sg.setshowSequenceLogo(groups[i].isShowSequenceLogo());
3031 if (groups[i].hasNormaliseSequenceLogo())
3033 sg.setNormaliseSequenceLogo(groups[i].isNormaliseSequenceLogo());
3035 if (groups[i].hasIgnoreGapsinConsensus())
3037 sg.setIgnoreGapsConsensus(groups[i].getIgnoreGapsinConsensus());
3039 if (groups[i].getConsThreshold() != 0)
3041 jalview.analysis.Conservation c = new jalview.analysis.Conservation(
3042 "All", ResidueProperties.propHash, 3,
3043 sg.getSequences(null), 0, sg.getWidth() - 1);
3045 c.verdict(false, 25);
3046 sg.cs.setConservation(c);
3049 if (groups[i].getId() != null && groupAnnotRefs.size() > 0)
3051 // re-instate unique group/annotation row reference
3052 ArrayList<jalview.datamodel.AlignmentAnnotation> jaal = groupAnnotRefs
3053 .get(groups[i].getId());
3056 for (jalview.datamodel.AlignmentAnnotation jaa : jaal)
3059 if (jaa.autoCalculated)
3061 // match up and try to set group autocalc alignment row for this
3063 if (jaa.label.startsWith("Consensus for "))
3065 sg.setConsensus(jaa);
3067 // match up and try to set group autocalc alignment row for this
3069 if (jaa.label.startsWith("Conservation for "))
3071 sg.setConservationRow(jaa);
3078 if (addAnnotSchemeGroup)
3080 // reconstruct the annotation colourscheme
3081 sg.cs = constructAnnotationColour(
3082 groups[i].getAnnotationColours(), null, al, jms, false);
3088 // only dataset in this model, so just return.
3091 // ///////////////////////////////
3094 // If we just load in the same jar file again, the sequenceSetId
3095 // will be the same, and we end up with multiple references
3096 // to the same sequenceSet. We must modify this id on load
3097 // so that each load of the file gives a unique id
3098 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3099 String viewId = (view.getId() == null ? null : view.getId()
3101 AlignFrame af = null;
3102 AlignViewport av = null;
3103 // now check to see if we really need to create a new viewport.
3104 if (multipleView && viewportsAdded.size() == 0)
3106 // We recovered an alignment for which a viewport already exists.
3107 // TODO: fix up any settings necessary for overlaying stored state onto
3108 // state recovered from another document. (may not be necessary).
3109 // we may need a binding from a viewport in memory to one recovered from
3111 // and then recover its containing af to allow the settings to be applied.
3112 // TODO: fix for vamsas demo
3114 .println("About to recover a viewport for existing alignment: Sequence set ID is "
3116 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3117 if (seqsetobj != null)
3119 if (seqsetobj instanceof String)
3121 uniqueSeqSetId = (String) seqsetobj;
3123 .println("Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
3129 .println("Warning : Collision between sequence set ID string and existing jalview object mapping.");
3135 * indicate that annotation colours are applied across all groups (pre
3136 * Jalview 2.8.1 behaviour)
3138 boolean doGroupAnnColour = isVersionStringLaterThan("2.8.1",
3139 object.getVersion());
3141 AlignmentPanel ap = null;
3142 boolean isnewview = true;
3145 // Check to see if this alignment already has a view id == viewId
3146 jalview.gui.AlignmentPanel views[] = Desktop
3147 .getAlignmentPanels(uniqueSeqSetId);
3148 if (views != null && views.length > 0)
3150 for (int v = 0; v < views.length; v++)
3152 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
3154 // recover the existing alignpanel, alignframe, viewport
3155 af = views[v].alignFrame;
3158 // TODO: could even skip resetting view settings if we don't want to
3159 // change the local settings from other jalview processes
3168 af = loadViewport(file, jseqs, hiddenSeqs, al, jms, view,
3169 uniqueSeqSetId, viewId, autoAlan);
3174 // /////////////////////////////////////
3175 if (loadTreesAndStructures && jms.getTreeCount() > 0)
3179 for (int t = 0; t < jms.getTreeCount(); t++)
3182 Tree tree = jms.getTree(t);
3184 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
3187 tp = af.ShowNewickTree(
3188 new jalview.io.NewickFile(tree.getNewick()),
3189 tree.getTitle(), tree.getWidth(), tree.getHeight(),
3190 tree.getXpos(), tree.getYpos());
3191 if (tree.getId() != null)
3193 // perhaps bind the tree id to something ?
3198 // update local tree attributes ?
3199 // TODO: should check if tp has been manipulated by user - if so its
3200 // settings shouldn't be modified
3201 tp.setTitle(tree.getTitle());
3202 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(), tree
3203 .getWidth(), tree.getHeight()));
3204 tp.av = av; // af.viewport; // TODO: verify 'associate with all
3207 tp.treeCanvas.av = av; // af.viewport;
3208 tp.treeCanvas.ap = ap; // af.alignPanel;
3213 warn("There was a problem recovering stored Newick tree: \n"
3214 + tree.getNewick());
3218 tp.fitToWindow.setState(tree.getFitToWindow());
3219 tp.fitToWindow_actionPerformed(null);
3221 if (tree.getFontName() != null)
3223 tp.setTreeFont(new java.awt.Font(tree.getFontName(), tree
3224 .getFontStyle(), tree.getFontSize()));
3228 tp.setTreeFont(new java.awt.Font(view.getFontName(), view
3229 .getFontStyle(), tree.getFontSize()));
3232 tp.showPlaceholders(tree.getMarkUnlinked());
3233 tp.showBootstrap(tree.getShowBootstrap());
3234 tp.showDistances(tree.getShowDistances());
3236 tp.treeCanvas.threshold = tree.getThreshold();
3238 if (tree.getCurrentTree())
3240 af.viewport.setCurrentTree(tp.getTree());
3244 } catch (Exception ex)
3246 ex.printStackTrace();
3250 // //LOAD STRUCTURES
3251 if (loadTreesAndStructures)
3253 loadStructures(jprovider, jseqs, af, ap);
3255 // and finally return.
3260 * Load and link any saved structure viewers.
3267 protected void loadStructures(jarInputStreamProvider jprovider,
3268 JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
3271 * Run through all PDB ids on the alignment, and collect mappings between
3272 * distinct view ids and all sequences referring to that view.
3274 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<String, StructureViewerModel>();
3276 for (int i = 0; i < jseqs.length; i++)
3278 if (jseqs[i].getPdbidsCount() > 0)
3280 Pdbids[] ids = jseqs[i].getPdbids();
3281 for (int p = 0; p < ids.length; p++)
3283 final int structureStateCount = ids[p].getStructureStateCount();
3284 for (int s = 0; s < structureStateCount; s++)
3286 // check to see if we haven't already created this structure view
3287 final StructureState structureState = ids[p]
3288 .getStructureState(s);
3289 String sviewid = (structureState.getViewId() == null) ? null
3290 : structureState.getViewId() + uniqueSetSuffix;
3291 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
3292 // Originally : ids[p].getFile()
3293 // : TODO: verify external PDB file recovery still works in normal
3294 // jalview project load
3295 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId()));
3296 jpdb.setId(ids[p].getId());
3298 int x = structureState.getXpos();
3299 int y = structureState.getYpos();
3300 int width = structureState.getWidth();
3301 int height = structureState.getHeight();
3303 // Probably don't need to do this anymore...
3304 // Desktop.desktop.getComponentAt(x, y);
3305 // TODO: NOW: check that this recovers the PDB file correctly.
3306 String pdbFile = loadPDBFile(jprovider, ids[p].getId());
3307 jalview.datamodel.SequenceI seq = seqRefIds.get(jseqs[i]
3309 if (sviewid == null)
3311 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width
3314 if (!structureViewers.containsKey(sviewid))
3316 structureViewers.put(sviewid,
3317 new StructureViewerModel(x, y, width, height, false,
3318 false, true, structureState.getViewId(),
3319 structureState.getType()));
3320 // Legacy pre-2.7 conversion JAL-823 :
3321 // do not assume any view has to be linked for colour by
3325 // assemble String[] { pdb files }, String[] { id for each
3326 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3327 // seqs_file 2}, boolean[] {
3328 // linkAlignPanel,superposeWithAlignpanel}} from hash
3329 StructureViewerModel jmoldat = structureViewers.get(sviewid);
3330 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
3331 | (structureState.hasAlignwithAlignPanel() ? structureState
3332 .getAlignwithAlignPanel() : false));
3335 * Default colour by linked panel to false if not specified (e.g.
3336 * for pre-2.7 projects)
3338 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
3339 colourWithAlignPanel |= (structureState
3340 .hasColourwithAlignPanel() ? structureState
3341 .getColourwithAlignPanel() : false);
3342 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
3345 * Default colour by viewer to true if not specified (e.g. for
3348 boolean colourByViewer = jmoldat.isColourByViewer();
3349 colourByViewer &= structureState.hasColourByJmol() ? structureState
3350 .getColourByJmol() : true;
3351 jmoldat.setColourByViewer(colourByViewer);
3353 if (jmoldat.getStateData().length() < structureState
3354 .getContent().length())
3357 jmoldat.setStateData(structureState.getContent());
3360 if (ids[p].getFile() != null)
3362 File mapkey = new File(ids[p].getFile());
3363 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
3364 if (seqstrmaps == null)
3366 jmoldat.getFileData().put(
3368 seqstrmaps = jmoldat.new StructureData(pdbFile,
3371 if (!seqstrmaps.getSeqList().contains(seq))
3373 seqstrmaps.getSeqList().add(seq);
3379 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");
3386 // Instantiate the associated structure views
3387 for (Entry<String, StructureViewerModel> entry : structureViewers
3392 createOrLinkStructureViewer(entry, af, ap, jprovider);
3393 } catch (Exception e)
3395 System.err.println("Error loading structure viewer: "
3397 // failed - try the next one
3409 protected void createOrLinkStructureViewer(
3410 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3411 AlignmentPanel ap, jarInputStreamProvider jprovider)
3413 final StructureViewerModel stateData = viewerData.getValue();
3416 * Search for any viewer windows already open from other alignment views
3417 * that exactly match the stored structure state
3419 StructureViewerBase comp = findMatchingViewer(viewerData);
3423 linkStructureViewer(ap, comp, stateData);
3428 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
3429 * "viewer_"+stateData.viewId
3431 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
3433 createChimeraViewer(viewerData, af, jprovider);
3438 * else Jmol (if pre-2.9, stateData contains JMOL state string)
3440 createJmolViewer(viewerData, af, jprovider);
3445 * Create a new Chimera viewer.
3451 protected void createChimeraViewer(Entry<String, StructureViewerModel> viewerData,
3453 jarInputStreamProvider jprovider)
3455 StructureViewerModel data = viewerData.getValue();
3456 String chimeraSessionFile = data.getStateData();
3459 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
3461 * Note this is the 'saved' viewId as in the project file XML, _not_ the
3462 * 'uniquified' sviewid used to reconstruct the viewer here
3464 chimeraSessionFile = copyJarEntry(jprovider,
3465 getViewerJarEntryName(data.getViewId()), "chimera");
3467 Set<Entry<File, StructureData>> fileData = data.getFileData()
3469 List<PDBEntry> pdbs = new ArrayList<PDBEntry>();
3470 List<SequenceI[]> allseqs = new ArrayList<SequenceI[]>();
3471 for (Entry<File, StructureData> pdb : fileData)
3473 String filePath = pdb.getValue().getFilePath();
3474 String pdbId = pdb.getValue().getPdbId();
3475 // pdbs.add(new PDBEntry(filePath, pdbId));
3476 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
3477 final List<SequenceI> seqList = pdb.getValue().getSeqList();
3478 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
3482 boolean colourByChimera = data.isColourByViewer();
3483 boolean colourBySequence = data.isColourWithAlignPanel();
3485 // TODO use StructureViewer as a factory here, see JAL-1761
3486 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
3487 final SequenceI[][] seqsArray = allseqs.toArray(new SequenceI[allseqs
3489 String newViewId = viewerData.getKey();
3490 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
3491 af.alignPanel, pdbArray,
3492 seqsArray, colourByChimera, colourBySequence, newViewId);
3493 cvf.setSize(data.getWidth(), data.getHeight());
3494 cvf.setLocation(data.getX(), data.getY());
3498 * Create a new Jmol window. First parse the Jmol state to translate filenames
3499 * loaded into the view, and record the order in which files are shown in the
3500 * Jmol view, so we can add the sequence mappings in same order.
3506 protected void createJmolViewer(
3507 final Entry<String, StructureViewerModel> viewerData,
3508 AlignFrame af, jarInputStreamProvider jprovider)
3510 final StructureViewerModel svattrib = viewerData.getValue();
3511 String state = svattrib.getStateData();
3514 * Pre-2.9: state element value is the Jmol state string
3516 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
3519 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
3521 state = readJarEntry(jprovider,
3522 getViewerJarEntryName(svattrib.getViewId()));
3525 List<String> pdbfilenames = new ArrayList<String>();
3526 List<SequenceI[]> seqmaps = new ArrayList<SequenceI[]>();
3527 List<String> pdbids = new ArrayList<String>();
3528 StringBuilder newFileLoc = new StringBuilder(64);
3529 int cp = 0, ncp, ecp;
3530 Map<File, StructureData> oldFiles = svattrib.getFileData();
3531 while ((ncp = state.indexOf("load ", cp)) > -1)
3535 // look for next filename in load statement
3536 newFileLoc.append(state.substring(cp,
3537 ncp = (state.indexOf("\"", ncp + 1) + 1)));
3538 String oldfilenam = state.substring(ncp,
3539 ecp = state.indexOf("\"", ncp));
3540 // recover the new mapping data for this old filename
3541 // have to normalize filename - since Jmol and jalview do
3543 // translation differently.
3544 StructureData filedat = oldFiles.get(new File(oldfilenam));
3545 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
3546 pdbfilenames.add(filedat.getFilePath());
3547 pdbids.add(filedat.getPdbId());
3548 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
3549 newFileLoc.append("\"");
3550 cp = ecp + 1; // advance beyond last \" and set cursor so we can
3551 // look for next file statement.
3552 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
3556 // just append rest of state
3557 newFileLoc.append(state.substring(cp));
3561 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
3562 newFileLoc = new StringBuilder(state);
3563 newFileLoc.append("; load append ");
3564 for (File id : oldFiles.keySet())
3566 // add this and any other pdb files that should be present in
3568 StructureData filedat = oldFiles.get(id);
3569 newFileLoc.append(filedat.getFilePath());
3570 pdbfilenames.add(filedat.getFilePath());
3571 pdbids.add(filedat.getPdbId());
3572 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
3573 newFileLoc.append(" \"");
3574 newFileLoc.append(filedat.getFilePath());
3575 newFileLoc.append("\"");
3578 newFileLoc.append(";");
3581 if (newFileLoc.length() > 0)
3583 int histbug = newFileLoc.indexOf("history = ");
3585 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
3586 String val = (diff == -1) ? null : newFileLoc
3587 .substring(histbug, diff);
3588 if (val != null && val.length() >= 4)
3590 if (val.contains("e"))
3592 if (val.trim().equals("true"))
3600 newFileLoc.replace(histbug, diff, val);
3604 final String[] pdbf = pdbfilenames.toArray(new String[pdbfilenames
3606 final String[] id = pdbids.toArray(new String[pdbids.size()]);
3607 final SequenceI[][] sq = seqmaps
3608 .toArray(new SequenceI[seqmaps.size()][]);
3609 final String fileloc = newFileLoc.toString();
3610 final String sviewid = viewerData.getKey();
3611 final AlignFrame alf = af;
3612 final Rectangle rect = new Rectangle(svattrib.getX(),
3613 svattrib.getY(), svattrib.getWidth(), svattrib.getHeight());
3616 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
3621 JalviewStructureDisplayI sview = null;
3624 sview = new StructureViewer(alf.alignPanel
3625 .getStructureSelectionManager()).createView(
3626 StructureViewer.ViewerType.JMOL, pdbf, id, sq,
3627 alf.alignPanel, svattrib, fileloc, rect, sviewid);
3628 addNewStructureViewer(sview);
3629 } catch (OutOfMemoryError ex)
3631 new OOMWarning("restoring structure view for PDB id " + id,
3632 (OutOfMemoryError) ex.getCause());
3633 if (sview != null && sview.isVisible())
3635 sview.closeViewer(false);
3636 sview.setVisible(false);
3642 } catch (InvocationTargetException ex)
3644 warn("Unexpected error when opening Jmol view.", ex);
3646 } catch (InterruptedException e)
3648 // e.printStackTrace();
3654 * Generates a name for the entry in the project jar file to hold state
3655 * information for a structure viewer
3660 protected String getViewerJarEntryName(String viewId)
3662 return "viewer_" + viewId;
3666 * Returns any open frame that matches given structure viewer data. The match
3667 * is based on the unique viewId, or (for older project versions) the frame's
3673 protected StructureViewerBase findMatchingViewer(
3674 Entry<String, StructureViewerModel> viewerData)
3676 final String sviewid = viewerData.getKey();
3677 final StructureViewerModel svattrib = viewerData.getValue();
3678 StructureViewerBase comp = null;
3679 JInternalFrame[] frames = getAllFrames();
3680 for (JInternalFrame frame : frames)
3682 if (frame instanceof StructureViewerBase)
3685 * Post jalview 2.4 schema includes structure view id
3688 && ((StructureViewerBase) frame).getViewId()
3691 comp = (StructureViewerBase) frame;
3692 break; // break added in 2.9
3695 * Otherwise test for matching position and size of viewer frame
3697 else if (frame.getX() == svattrib.getX()
3698 && frame.getY() == svattrib.getY()
3699 && frame.getHeight() == svattrib.getHeight()
3700 && frame.getWidth() == svattrib.getWidth())
3702 comp = (StructureViewerBase) frame;
3703 // no break in faint hope of an exact match on viewId
3711 * Link an AlignmentPanel to an existing structure viewer.
3716 * @param useinViewerSuperpos
3717 * @param usetoColourbyseq
3718 * @param viewerColouring
3720 protected void linkStructureViewer(AlignmentPanel ap,
3721 StructureViewerBase viewer, StructureViewerModel stateData)
3723 // NOTE: if the jalview project is part of a shared session then
3724 // view synchronization should/could be done here.
3726 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
3727 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
3728 final boolean viewerColouring = stateData.isColourByViewer();
3729 Map<File, StructureData> oldFiles = stateData.getFileData();
3732 * Add mapping for sequences in this view to an already open viewer
3734 final AAStructureBindingModel binding = viewer.getBinding();
3735 for (File id : oldFiles.keySet())
3737 // add this and any other pdb files that should be present in the
3739 StructureData filedat = oldFiles.get(id);
3740 String pdbFile = filedat.getFilePath();
3741 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
3742 binding.getSsm().setMapping(seq, null, pdbFile,
3743 jalview.io.AppletFormatAdapter.FILE);
3744 binding.addSequenceForStructFile(pdbFile, seq);
3746 // and add the AlignmentPanel's reference to the view panel
3747 viewer.addAlignmentPanel(ap);
3748 if (useinViewerSuperpos)
3750 viewer.useAlignmentPanelForSuperposition(ap);
3754 viewer.excludeAlignmentPanelForSuperposition(ap);
3756 if (usetoColourbyseq)
3758 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
3762 viewer.excludeAlignmentPanelForColourbyseq(ap);
3767 * Get all frames within the Desktop.
3771 protected JInternalFrame[] getAllFrames()
3773 JInternalFrame[] frames = null;
3774 // TODO is this necessary - is it safe - risk of hanging?
3779 frames = Desktop.desktop.getAllFrames();
3780 } catch (ArrayIndexOutOfBoundsException e)
3782 // occasional No such child exceptions are thrown here...
3786 } catch (InterruptedException f)
3790 } while (frames == null);
3797 * - minimum version we are comparing against
3799 * - version of data being processsed.
3800 * @return true if version is development/null or evaluates to the same or
3801 * later X.Y.Z (where X,Y,Z are like [0-9]+b?[0-9]*)
3803 private boolean isVersionStringLaterThan(String supported, String version)
3805 if (version == null || version.equalsIgnoreCase("DEVELOPMENT BUILD")
3806 || version.equalsIgnoreCase("Test")
3807 || version.equalsIgnoreCase("AUTOMATED BUILD"))
3809 System.err.println("Assuming project file with "
3810 + (version == null ? "null" : version)
3811 + " is compatible with Jalview version " + supported);
3816 StringTokenizer currentV = new StringTokenizer(supported, "."), fileV = new StringTokenizer(
3818 while (currentV.hasMoreTokens() && fileV.hasMoreTokens())
3820 // convert b to decimal to catch bugfix releases within a series
3821 String curT = currentV.nextToken().toLowerCase().replace('b', '.');
3822 String fileT = fileV.nextToken().toLowerCase().replace('b', '.');
3825 if (Float.valueOf(curT) > Float.valueOf(fileT))
3827 // current version is newer than the version that wrote the file
3830 } catch (NumberFormatException nfe)
3833 .println("** WARNING: Version comparison failed for tokens ("
3837 + ")\n** Current: '"
3838 + supported + "' and Version: '" + version + "'");
3841 if (currentV.hasMoreElements())
3843 // fileV has no minor version but identical series to current
3850 Vector<JalviewStructureDisplayI> newStructureViewers = null;
3852 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
3854 if (newStructureViewers != null)
3856 sview.getBinding().setFinishedLoadingFromArchive(false);
3857 newStructureViewers.add(sview);
3861 protected void setLoadingFinishedForNewStructureViewers()
3863 if (newStructureViewers != null)
3865 for (JalviewStructureDisplayI sview : newStructureViewers)
3867 sview.getBinding().setFinishedLoadingFromArchive(true);
3869 newStructureViewers.clear();
3870 newStructureViewers = null;
3874 AlignFrame loadViewport(String file, JSeq[] JSEQ,
3875 List<SequenceI> hiddenSeqs, Alignment al,
3876 JalviewModelSequence jms, Viewport view, String uniqueSeqSetId,
3877 String viewId, List<JvAnnotRow> autoAlan)
3879 AlignFrame af = null;
3880 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
3881 uniqueSeqSetId, viewId);
3883 af.setFileName(file, "Jalview");
3885 for (int i = 0; i < JSEQ.length; i++)
3887 af.viewport.setSequenceColour(af.viewport.getAlignment()
3888 .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour()));
3891 af.viewport.setGatherViewsHere(view.getGatheredViews());
3893 if (view.getSequenceSetId() != null)
3895 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
3897 af.viewport.setSequenceSetId(uniqueSeqSetId);
3900 // propagate shared settings to this new view
3901 af.viewport.setHistoryList(av.getHistoryList());
3902 af.viewport.setRedoList(av.getRedoList());
3906 viewportsAdded.put(uniqueSeqSetId, af.viewport);
3908 // TODO: check if this method can be called repeatedly without
3909 // side-effects if alignpanel already registered.
3910 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
3912 // apply Hidden regions to view.
3913 if (hiddenSeqs != null)
3915 for (int s = 0; s < JSEQ.length; s++)
3917 jalview.datamodel.SequenceGroup hidden = new jalview.datamodel.SequenceGroup();
3919 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
3922 al.getSequenceAt(JSEQ[s].getHiddenSequences(r)), false);
3924 af.viewport.hideRepSequences(al.getSequenceAt(s), hidden);
3927 // jalview.datamodel.SequenceI[] hseqs = new
3928 // jalview.datamodel.SequenceI[hiddenSeqs
3931 // for (int s = 0; s < hiddenSeqs.size(); s++)
3933 // hseqs[s] = (jalview.datamodel.SequenceI) hiddenSeqs.elementAt(s);
3936 SequenceI[] hseqs = hiddenSeqs.toArray(new SequenceI[hiddenSeqs
3938 af.viewport.hideSequence(hseqs);
3941 // recover view properties and display parameters
3942 if (view.getViewName() != null)
3944 af.viewport.viewName = view.getViewName();
3945 af.setInitialTabVisible();
3947 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
3950 af.viewport.setShowAnnotation(view.getShowAnnotation());
3951 af.viewport.setAbovePIDThreshold(view.getPidSelected());
3953 af.viewport.setColourText(view.getShowColourText());
3955 af.viewport.setConservationSelected(view.getConservationSelected());
3956 af.viewport.setShowJVSuffix(view.getShowFullId());
3957 af.viewport.setRightAlignIds(view.getRightAlignIds());
3958 af.viewport.setFont(
3959 new java.awt.Font(view.getFontName(), view.getFontStyle(), view
3960 .getFontSize()), true);
3961 // TODO: allow custom charWidth/Heights to be restored by updating them
3962 // after setting font - which means set above to false
3963 af.viewport.setRenderGaps(view.getRenderGaps());
3964 af.viewport.setWrapAlignment(view.getWrapAlignment());
3965 af.viewport.setShowAnnotation(view.getShowAnnotation());
3967 af.viewport.setShowBoxes(view.getShowBoxes());
3969 af.viewport.setShowText(view.getShowText());
3971 af.viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
3972 af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
3973 af.viewport.setThresholdTextColour(view.getTextColThreshold());
3974 af.viewport.setShowUnconserved(view.hasShowUnconserved() ? view
3975 .isShowUnconserved() : false);
3976 af.viewport.setStartRes(view.getStartRes());
3977 af.viewport.setStartSeq(view.getStartSeq());
3978 af.alignPanel.updateLayout();
3979 ColourSchemeI cs = null;
3980 // apply colourschemes
3981 if (view.getBgColour() != null)
3983 if (view.getBgColour().startsWith("ucs"))
3985 cs = getUserColourScheme(jms, view.getBgColour());
3987 else if (view.getBgColour().startsWith("Annotation"))
3989 AnnotationColours viewAnnColour = view.getAnnotationColours();
3990 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
3997 cs = ColourSchemeProperty.getColour(al, view.getBgColour());
4002 cs.setThreshold(view.getPidThreshold(), true);
4003 cs.setConsensus(af.viewport.getSequenceConsensusHash());
4007 af.viewport.setGlobalColourScheme(cs);
4008 af.viewport.setColourAppliesToAllGroups(false);
4010 if (view.getConservationSelected() && cs != null)
4012 cs.setConservationInc(view.getConsThreshold());
4015 af.changeColour(cs);
4017 af.viewport.setColourAppliesToAllGroups(true);
4019 af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures());
4021 if (view.hasCentreColumnLabels())
4023 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
4025 if (view.hasIgnoreGapsinConsensus())
4027 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
4030 if (view.hasFollowHighlight())
4032 af.viewport.setFollowHighlight(view.getFollowHighlight());
4034 if (view.hasFollowSelection())
4036 af.viewport.followSelection = view.getFollowSelection();
4038 if (view.hasShowConsensusHistogram())
4040 af.viewport.setShowConsensusHistogram(view
4041 .getShowConsensusHistogram());
4045 af.viewport.setShowConsensusHistogram(true);
4047 if (view.hasShowSequenceLogo())
4049 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
4053 af.viewport.setShowSequenceLogo(false);
4055 if (view.hasNormaliseSequenceLogo())
4057 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
4059 if (view.hasShowDbRefTooltip())
4061 af.viewport.setShowDBRefs(view.getShowDbRefTooltip());
4063 if (view.hasShowNPfeatureTooltip())
4065 af.viewport.setShowNPFeats(view.hasShowNPfeatureTooltip());
4067 if (view.hasShowGroupConsensus())
4069 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
4073 af.viewport.setShowGroupConsensus(false);
4075 if (view.hasShowGroupConservation())
4077 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
4081 af.viewport.setShowGroupConservation(false);
4084 // recover featre settings
4085 if (jms.getFeatureSettings() != null)
4087 FeaturesDisplayed fdi;
4088 af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
4089 String[] renderOrder = new String[jms.getFeatureSettings()
4090 .getSettingCount()];
4091 Hashtable featureGroups = new Hashtable();
4092 Hashtable featureColours = new Hashtable();
4093 Hashtable featureOrder = new Hashtable();
4095 for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
4097 Setting setting = jms.getFeatureSettings().getSetting(fs);
4098 if (setting.hasMincolour())
4100 GraduatedColor gc = setting.hasMin() ? new GraduatedColor(
4101 new java.awt.Color(setting.getMincolour()),
4102 new java.awt.Color(setting.getColour()),
4103 setting.getMin(), setting.getMax()) : new GraduatedColor(
4104 new java.awt.Color(setting.getMincolour()),
4105 new java.awt.Color(setting.getColour()), 0, 1);
4106 if (setting.hasThreshold())
4108 gc.setThresh(setting.getThreshold());
4109 gc.setThreshType(setting.getThreshstate());
4111 gc.setAutoScaled(true); // default
4112 if (setting.hasAutoScale())
4114 gc.setAutoScaled(setting.getAutoScale());
4116 if (setting.hasColourByLabel())
4118 gc.setColourByLabel(setting.getColourByLabel());
4120 // and put in the feature colour table.
4121 featureColours.put(setting.getType(), gc);
4125 featureColours.put(setting.getType(),
4126 new java.awt.Color(setting.getColour()));
4128 renderOrder[fs] = setting.getType();
4129 if (setting.hasOrder())
4131 featureOrder.put(setting.getType(), setting.getOrder());
4135 featureOrder.put(setting.getType(), new Float(fs
4136 / jms.getFeatureSettings().getSettingCount()));
4138 if (setting.getDisplay())
4140 fdi.setVisible(setting.getType());
4143 Hashtable fgtable = new Hashtable();
4144 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
4146 Group grp = jms.getFeatureSettings().getGroup(gs);
4147 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
4149 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4150 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
4151 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
4152 FeatureRendererSettings frs = new FeatureRendererSettings(
4153 renderOrder, fgtable, featureColours, 1.0f, featureOrder);
4154 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
4155 .transferSettings(frs);
4159 if (view.getHiddenColumnsCount() > 0)
4161 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
4163 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(), view
4164 .getHiddenColumns(c).getEnd() // +1
4168 if (view.getCalcIdParam() != null)
4170 for (CalcIdParam calcIdParam : view.getCalcIdParam())
4172 if (calcIdParam != null)
4174 if (recoverCalcIdParam(calcIdParam, af.viewport))
4179 warn("Couldn't recover parameters for "
4180 + calcIdParam.getCalcId());
4185 af.setMenusFromViewport(af.viewport);
4187 // TODO: we don't need to do this if the viewport is aready visible.
4189 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
4190 * has a 'cdna/protein complement' view, in which case save it in order to
4191 * populate a SplitFrame once all views have been read in.
4193 String complementaryViewId = view.getComplementId();
4194 if (complementaryViewId == null)
4196 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
4198 // recompute any autoannotation
4199 af.alignPanel.updateAnnotation(false, true);
4200 reorderAutoannotation(af, al, autoAlan);
4201 af.alignPanel.alignmentChanged();
4205 splitFrameCandidates.put(view, af);
4210 private ColourSchemeI constructAnnotationColour(
4211 AnnotationColours viewAnnColour, AlignFrame af, Alignment al,
4212 JalviewModelSequence jms, boolean checkGroupAnnColour)
4214 boolean propagateAnnColour = false;
4215 ColourSchemeI cs = null;
4216 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
4217 if (checkGroupAnnColour && al.getGroups() != null
4218 && al.getGroups().size() > 0)
4220 // pre 2.8.1 behaviour
4221 // check to see if we should transfer annotation colours
4222 propagateAnnColour = true;
4223 for (jalview.datamodel.SequenceGroup sg : al.getGroups())
4225 if (sg.cs instanceof AnnotationColourGradient)
4227 propagateAnnColour = false;
4231 // int find annotation
4232 if (annAlignment.getAlignmentAnnotation() != null)
4234 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
4236 if (annAlignment.getAlignmentAnnotation()[i].label
4237 .equals(viewAnnColour.getAnnotation()))
4239 if (annAlignment.getAlignmentAnnotation()[i].getThreshold() == null)
4241 annAlignment.getAlignmentAnnotation()[i]
4242 .setThreshold(new jalview.datamodel.GraphLine(
4243 viewAnnColour.getThreshold(), "Threshold",
4244 java.awt.Color.black)
4249 if (viewAnnColour.getColourScheme().equals("None"))
4251 cs = new AnnotationColourGradient(
4252 annAlignment.getAlignmentAnnotation()[i],
4253 new java.awt.Color(viewAnnColour.getMinColour()),
4254 new java.awt.Color(viewAnnColour.getMaxColour()),
4255 viewAnnColour.getAboveThreshold());
4257 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
4259 cs = new AnnotationColourGradient(
4260 annAlignment.getAlignmentAnnotation()[i],
4261 getUserColourScheme(jms,
4262 viewAnnColour.getColourScheme()),
4263 viewAnnColour.getAboveThreshold());
4267 cs = new AnnotationColourGradient(
4268 annAlignment.getAlignmentAnnotation()[i],
4269 ColourSchemeProperty.getColour(al,
4270 viewAnnColour.getColourScheme()),
4271 viewAnnColour.getAboveThreshold());
4273 if (viewAnnColour.hasPerSequence())
4275 ((AnnotationColourGradient) cs).setSeqAssociated(viewAnnColour
4278 if (viewAnnColour.hasPredefinedColours())
4280 ((AnnotationColourGradient) cs)
4281 .setPredefinedColours(viewAnnColour
4282 .isPredefinedColours());
4284 if (propagateAnnColour && al.getGroups() != null)
4286 // Also use these settings for all the groups
4287 for (int g = 0; g < al.getGroups().size(); g++)
4289 jalview.datamodel.SequenceGroup sg = al.getGroups().get(g);
4297 * if (viewAnnColour.getColourScheme().equals("None" )) { sg.cs =
4298 * new AnnotationColourGradient(
4299 * annAlignment.getAlignmentAnnotation()[i], new
4300 * java.awt.Color(viewAnnColour. getMinColour()), new
4301 * java.awt.Color(viewAnnColour. getMaxColour()),
4302 * viewAnnColour.getAboveThreshold()); } else
4305 sg.cs = new AnnotationColourGradient(
4306 annAlignment.getAlignmentAnnotation()[i], sg.cs,
4307 viewAnnColour.getAboveThreshold());
4308 if (cs instanceof AnnotationColourGradient)
4310 if (viewAnnColour.hasPerSequence())
4312 ((AnnotationColourGradient) cs)
4313 .setSeqAssociated(viewAnnColour.isPerSequence());
4315 if (viewAnnColour.hasPredefinedColours())
4317 ((AnnotationColourGradient) cs)
4318 .setPredefinedColours(viewAnnColour
4319 .isPredefinedColours());
4335 private void reorderAutoannotation(AlignFrame af, Alignment al,
4336 List<JvAnnotRow> autoAlan)
4338 // copy over visualization settings for autocalculated annotation in the
4340 if (al.getAlignmentAnnotation() != null)
4343 * Kludge for magic autoannotation names (see JAL-811)
4345 String[] magicNames = new String[]
4346 { "Consensus", "Quality", "Conservation" };
4347 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
4348 Hashtable<String, JvAnnotRow> visan = new Hashtable<String, JvAnnotRow>();
4349 for (String nm : magicNames)
4351 visan.put(nm, nullAnnot);
4353 for (JvAnnotRow auan : autoAlan)
4355 visan.put(auan.template.label
4356 + (auan.template.getCalcId() == null ? "" : "\t"
4357 + auan.template.getCalcId()), auan);
4359 int hSize = al.getAlignmentAnnotation().length;
4360 List<JvAnnotRow> reorder = new ArrayList<JvAnnotRow>();
4361 // work through any autoCalculated annotation already on the view
4362 // removing it if it should be placed in a different location on the
4363 // annotation panel.
4364 List<String> remains = new ArrayList<String>(visan.keySet());
4365 for (int h = 0; h < hSize; h++)
4367 jalview.datamodel.AlignmentAnnotation jalan = al
4368 .getAlignmentAnnotation()[h];
4369 if (jalan.autoCalculated)
4372 JvAnnotRow valan = visan.get(k = jalan.label);
4373 if (jalan.getCalcId() != null)
4375 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
4380 // delete the auto calculated row from the alignment
4381 al.deleteAnnotation(jalan, false);
4385 if (valan != nullAnnot)
4387 if (jalan != valan.template)
4389 // newly created autoannotation row instance
4390 // so keep a reference to the visible annotation row
4391 // and copy over all relevant attributes
4392 if (valan.template.graphHeight >= 0)
4395 jalan.graphHeight = valan.template.graphHeight;
4397 jalan.visible = valan.template.visible;
4399 reorder.add(new JvAnnotRow(valan.order, jalan));
4404 // Add any (possibly stale) autocalculated rows that were not appended to
4405 // the view during construction
4406 for (String other : remains)
4408 JvAnnotRow othera = visan.get(other);
4409 if (othera != nullAnnot && othera.template.getCalcId() != null
4410 && othera.template.getCalcId().length() > 0)
4412 reorder.add(othera);
4415 // now put the automatic annotation in its correct place
4416 int s = 0, srt[] = new int[reorder.size()];
4417 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
4418 for (JvAnnotRow jvar : reorder)
4421 srt[s++] = jvar.order;
4424 jalview.util.QuickSort.sort(srt, rws);
4425 // and re-insert the annotation at its correct position
4426 for (JvAnnotRow jvar : rws)
4428 al.addAnnotation(jvar.template, jvar.order);
4430 af.alignPanel.adjustAnnotationHeight();
4434 Hashtable skipList = null;
4437 * TODO remove this method
4440 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
4441 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
4442 * throw new Error("Implementation Error. No skipList defined for this
4443 * Jalview2XML instance."); } return (AlignFrame)
4444 * skipList.get(view.getSequenceSetId()); }
4448 * Check if the Jalview view contained in object should be skipped or not.
4451 * @return true if view's sequenceSetId is a key in skipList
4453 private boolean skipViewport(JalviewModel object)
4455 if (skipList == null)
4460 if (skipList.containsKey(id = object.getJalviewModelSequence()
4461 .getViewport()[0].getSequenceSetId()))
4463 if (Cache.log != null && Cache.log.isDebugEnabled())
4465 Cache.log.debug("Skipping seuqence set id " + id);
4472 public void addToSkipList(AlignFrame af)
4474 if (skipList == null)
4476 skipList = new Hashtable();
4478 skipList.put(af.getViewport().getSequenceSetId(), af);
4481 public void clearSkipList()
4483 if (skipList != null)
4490 private void recoverDatasetFor(SequenceSet vamsasSet, Alignment al,
4491 boolean ignoreUnrefed)
4493 jalview.datamodel.Alignment ds = getDatasetFor(vamsasSet.getDatasetId());
4494 Vector dseqs = null;
4497 // create a list of new dataset sequences
4498 dseqs = new Vector();
4500 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
4502 Sequence vamsasSeq = vamsasSet.getSequence(i);
4503 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed);
4505 // create a new dataset
4508 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
4509 dseqs.copyInto(dsseqs);
4510 ds = new jalview.datamodel.Alignment(dsseqs);
4511 debug("Created new dataset " + vamsasSet.getDatasetId()
4512 + " for alignment " + System.identityHashCode(al));
4513 addDatasetRef(vamsasSet.getDatasetId(), ds);
4515 // set the dataset for the newly imported alignment.
4516 if (al.getDataset() == null && !ignoreUnrefed)
4525 * sequence definition to create/merge dataset sequence for
4529 * vector to add new dataset sequence to
4531 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
4532 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed)
4534 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
4536 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
4537 SequenceI dsq = null;
4538 if (sq != null && sq.getDatasetSequence() != null)
4540 dsq = sq.getDatasetSequence();
4542 if (sq == null && ignoreUnrefed)
4546 String sqid = vamsasSeq.getDsseqid();
4549 // need to create or add a new dataset sequence reference to this sequence
4552 dsq = seqRefIds.get(sqid);
4557 // make a new dataset sequence
4558 dsq = sq.createDatasetSequence();
4561 // make up a new dataset reference for this sequence
4562 sqid = seqHash(dsq);
4564 dsq.setVamsasId(uniqueSetSuffix + sqid);
4565 seqRefIds.put(sqid, dsq);
4570 dseqs.addElement(dsq);
4575 ds.addSequence(dsq);
4581 { // make this dataset sequence sq's dataset sequence
4582 sq.setDatasetSequence(dsq);
4583 // and update the current dataset alignment
4588 if (!dseqs.contains(dsq))
4595 if (ds.findIndex(dsq) < 0)
4597 ds.addSequence(dsq);
4604 // TODO: refactor this as a merge dataset sequence function
4605 // now check that sq (the dataset sequence) sequence really is the union of
4606 // all references to it
4607 // boolean pre = sq.getStart() < dsq.getStart();
4608 // boolean post = sq.getEnd() > dsq.getEnd();
4612 // StringBuffer sb = new StringBuffer();
4613 String newres = jalview.analysis.AlignSeq.extractGaps(
4614 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
4615 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
4616 && newres.length() > dsq.getLength())
4618 // Update with the longer sequence.
4622 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
4623 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
4624 * sb.append(newres.substring(newres.length() - sq.getEnd() -
4625 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
4627 dsq.setSequence(newres);
4629 // TODO: merges will never happen if we 'know' we have the real dataset
4630 // sequence - this should be detected when id==dssid
4632 .println("DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
4633 // + (pre ? "prepended" : "") + " "
4634 // + (post ? "appended" : ""));
4639 java.util.Hashtable datasetIds = null;
4641 java.util.IdentityHashMap dataset2Ids = null;
4643 private Alignment getDatasetFor(String datasetId)
4645 if (datasetIds == null)
4647 datasetIds = new Hashtable();
4650 if (datasetIds.containsKey(datasetId))
4652 return (Alignment) datasetIds.get(datasetId);
4657 private void addDatasetRef(String datasetId, Alignment dataset)
4659 if (datasetIds == null)
4661 datasetIds = new Hashtable();
4663 datasetIds.put(datasetId, dataset);
4667 * make a new dataset ID for this jalview dataset alignment
4672 private String getDatasetIdRef(jalview.datamodel.Alignment dataset)
4674 if (dataset.getDataset() != null)
4676 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
4678 String datasetId = makeHashCode(dataset, null);
4679 if (datasetId == null)
4681 // make a new datasetId and record it
4682 if (dataset2Ids == null)
4684 dataset2Ids = new IdentityHashMap();
4688 datasetId = (String) dataset2Ids.get(dataset);
4690 if (datasetId == null)
4692 datasetId = "ds" + dataset2Ids.size() + 1;
4693 dataset2Ids.put(dataset, datasetId);
4699 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
4701 for (int d = 0; d < sequence.getDBRefCount(); d++)
4703 DBRef dr = sequence.getDBRef(d);
4704 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
4705 sequence.getDBRef(d).getSource(), sequence.getDBRef(d)
4706 .getVersion(), sequence.getDBRef(d).getAccessionId());
4707 if (dr.getMapping() != null)
4709 entry.setMap(addMapping(dr.getMapping()));
4711 datasetSequence.addDBRef(entry);
4715 private jalview.datamodel.Mapping addMapping(Mapping m)
4717 SequenceI dsto = null;
4718 // Mapping m = dr.getMapping();
4719 int fr[] = new int[m.getMapListFromCount() * 2];
4720 Enumeration f = m.enumerateMapListFrom();
4721 for (int _i = 0; f.hasMoreElements(); _i += 2)
4723 MapListFrom mf = (MapListFrom) f.nextElement();
4724 fr[_i] = mf.getStart();
4725 fr[_i + 1] = mf.getEnd();
4727 int fto[] = new int[m.getMapListToCount() * 2];
4728 f = m.enumerateMapListTo();
4729 for (int _i = 0; f.hasMoreElements(); _i += 2)
4731 MapListTo mf = (MapListTo) f.nextElement();
4732 fto[_i] = mf.getStart();
4733 fto[_i + 1] = mf.getEnd();
4735 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto,
4736 fr, fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
4737 if (m.getMappingChoice() != null)
4739 MappingChoice mc = m.getMappingChoice();
4740 if (mc.getDseqFor() != null)
4742 String dsfor = "" + mc.getDseqFor();
4743 if (seqRefIds.containsKey(dsfor))
4748 jmap.setTo(seqRefIds.get(dsfor));
4752 frefedSequence.add(new Object[]
4759 * local sequence definition
4761 Sequence ms = mc.getSequence();
4762 SequenceI djs = null;
4763 String sqid = ms.getDsseqid();
4764 if (sqid != null && sqid.length() > 0)
4767 * recover dataset sequence
4769 djs = seqRefIds.get(sqid);
4774 .println("Warning - making up dataset sequence id for DbRef sequence map reference");
4775 sqid = ((Object) ms).toString(); // make up a new hascode for
4776 // undefined dataset sequence hash
4777 // (unlikely to happen)
4783 * make a new dataset sequence and add it to refIds hash
4785 djs = new jalview.datamodel.Sequence(ms.getName(),
4787 djs.setStart(jmap.getMap().getToLowest());
4788 djs.setEnd(jmap.getMap().getToHighest());
4789 djs.setVamsasId(uniqueSetSuffix + sqid);
4791 seqRefIds.put(sqid, djs);
4794 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
4803 public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
4804 boolean keepSeqRefs)
4807 jalview.schemabinding.version2.JalviewModel jm = saveState(ap, null,
4813 jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
4817 uniqueSetSuffix = "";
4818 jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
4823 if (this.frefedSequence == null)
4825 frefedSequence = new Vector();
4828 viewportsAdded.clear();
4830 AlignFrame af = loadFromObject(jm, null, false, null);
4831 af.alignPanels.clear();
4832 af.closeMenuItem_actionPerformed(true);
4835 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
4836 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
4837 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
4838 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
4839 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
4842 return af.alignPanel;
4846 * flag indicating if hashtables should be cleared on finalization TODO this
4847 * flag may not be necessary
4849 private final boolean _cleartables = true;
4851 private Hashtable jvids2vobj;
4856 * @see java.lang.Object#finalize()
4859 protected void finalize() throws Throwable
4861 // really make sure we have no buried refs left.
4866 this.seqRefIds = null;
4867 this.seqsToIds = null;
4871 private void warn(String msg)
4876 private void warn(String msg, Exception e)
4878 if (Cache.log != null)
4882 Cache.log.warn(msg, e);
4886 Cache.log.warn(msg);
4891 System.err.println("Warning: " + msg);
4894 e.printStackTrace();
4899 private void debug(String string)
4901 debug(string, null);
4904 private void debug(String msg, Exception e)
4906 if (Cache.log != null)
4910 Cache.log.debug(msg, e);
4914 Cache.log.debug(msg);
4919 System.err.println("Warning: " + msg);
4922 e.printStackTrace();
4928 * set the object to ID mapping tables used to write/recover objects and XML
4929 * ID strings for the jalview project. If external tables are provided then
4930 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
4931 * object goes out of scope. - also populates the datasetIds hashtable with
4932 * alignment objects containing dataset sequences
4935 * Map from ID strings to jalview datamodel
4937 * Map from jalview datamodel to ID strings
4941 public void setObjectMappingTables(Hashtable vobj2jv,
4942 IdentityHashMap jv2vobj)
4944 this.jv2vobj = jv2vobj;
4945 this.vobj2jv = vobj2jv;
4946 Iterator ds = jv2vobj.keySet().iterator();
4948 while (ds.hasNext())
4950 Object jvobj = ds.next();
4951 id = jv2vobj.get(jvobj).toString();
4952 if (jvobj instanceof jalview.datamodel.Alignment)
4954 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
4956 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
4959 else if (jvobj instanceof jalview.datamodel.Sequence)
4961 // register sequence object so the XML parser can recover it.
4962 if (seqRefIds == null)
4964 seqRefIds = new HashMap<String, SequenceI>();
4966 if (seqsToIds == null)
4968 seqsToIds = new IdentityHashMap<SequenceI, String>();
4970 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
4971 seqsToIds.put((SequenceI) jvobj, id);
4973 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
4976 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
4977 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
4978 if (jvann.annotationId == null)
4980 jvann.annotationId = anid;
4982 if (!jvann.annotationId.equals(anid))
4984 // TODO verify that this is the correct behaviour
4985 this.warn("Overriding Annotation ID for " + anid
4986 + " from different id : " + jvann.annotationId);
4987 jvann.annotationId = anid;
4990 else if (jvobj instanceof String)
4992 if (jvids2vobj == null)
4994 jvids2vobj = new Hashtable();
4995 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
5000 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
5006 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
5007 * objects created from the project archive. If string is null (default for
5008 * construction) then suffix will be set automatically.
5012 public void setUniqueSetSuffix(String string)
5014 uniqueSetSuffix = string;
5019 * uses skipList2 as the skipList for skipping views on sequence sets
5020 * associated with keys in the skipList
5024 public void setSkipList(Hashtable skipList2)
5026 skipList = skipList2;
5030 * Reads the jar entry of given name and returns its contents, or null if the
5031 * entry is not found.
5034 * @param jarEntryName
5037 protected String readJarEntry(jarInputStreamProvider jprovider,
5038 String jarEntryName)
5040 String result = null;
5041 BufferedReader in = null;
5046 * Reopen the jar input stream and traverse its entries to find a matching
5049 JarInputStream jin = jprovider.getJarInputStream();
5050 JarEntry entry = null;
5053 entry = jin.getNextJarEntry();
5054 } while (entry != null && !entry.getName().equals(jarEntryName));
5058 StringBuilder out = new StringBuilder(256);
5059 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
5062 while ((data = in.readLine()) != null)
5066 result = out.toString();
5070 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
5072 } catch (Exception ex)
5074 ex.printStackTrace();
5082 } catch (IOException e)