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