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, "viewer_" + 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 // FIXME add attribute to schema and enable next line
1459 // state.setType(viewFrame.getViewerType().toString());
1460 state.setContent(viewFrame.getViewerType().toString());
1461 pdb.addStructureState(state);
1468 private AnnotationColours constructAnnotationColours(
1469 AnnotationColourGradient acg, List<UserColourScheme> userColours,
1470 JalviewModelSequence jms)
1472 AnnotationColours ac = new AnnotationColours();
1473 ac.setAboveThreshold(acg.getAboveThreshold());
1474 ac.setThreshold(acg.getAnnotationThreshold());
1475 ac.setAnnotation(acg.getAnnotation());
1476 if (acg.getBaseColour() instanceof jalview.schemes.UserColourScheme)
1478 ac.setColourScheme(setUserColourScheme(acg.getBaseColour(),
1483 ac.setColourScheme(ColourSchemeProperty.getColourName(acg
1487 ac.setMaxColour(acg.getMaxColour().getRGB());
1488 ac.setMinColour(acg.getMinColour().getRGB());
1489 ac.setPerSequence(acg.isSeqAssociated());
1490 ac.setPredefinedColours(acg.isPredefinedColours());
1494 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
1495 IdentityHashMap groupRefs, AlignmentViewport av,
1496 Set<String> calcIdSet, boolean storeDS, SequenceSet vamsasSet)
1499 for (int i = 0; i < aa.length; i++)
1501 Annotation an = new Annotation();
1503 if (aa[i].annotationId != null)
1505 annotationIds.put(aa[i].annotationId, aa[i]);
1508 an.setId(aa[i].annotationId);
1510 an.setVisible(aa[i].visible);
1512 an.setDescription(aa[i].description);
1514 if (aa[i].sequenceRef != null)
1516 // TODO later annotation sequenceRef should be the XML ID of the
1517 // sequence rather than its display name
1518 an.setSequenceRef(aa[i].sequenceRef.getName());
1520 if (aa[i].groupRef != null)
1522 Object groupIdr = groupRefs.get(aa[i].groupRef);
1523 if (groupIdr == null)
1525 // make a locally unique String
1526 groupRefs.put(aa[i].groupRef,
1527 groupIdr = ("" + System.currentTimeMillis()
1528 + aa[i].groupRef.getName() + groupRefs.size()));
1530 an.setGroupRef(groupIdr.toString());
1533 // store all visualization attributes for annotation
1534 an.setGraphHeight(aa[i].graphHeight);
1535 an.setCentreColLabels(aa[i].centreColLabels);
1536 an.setScaleColLabels(aa[i].scaleColLabel);
1537 an.setShowAllColLabels(aa[i].showAllColLabels);
1538 an.setBelowAlignment(aa[i].belowAlignment);
1540 if (aa[i].graph > 0)
1543 an.setGraphType(aa[i].graph);
1544 an.setGraphGroup(aa[i].graphGroup);
1545 if (aa[i].getThreshold() != null)
1547 ThresholdLine line = new ThresholdLine();
1548 line.setLabel(aa[i].getThreshold().label);
1549 line.setValue(aa[i].getThreshold().value);
1550 line.setColour(aa[i].getThreshold().colour.getRGB());
1551 an.setThresholdLine(line);
1559 an.setLabel(aa[i].label);
1561 if (aa[i] == av.getAlignmentQualityAnnot()
1562 || aa[i] == av.getAlignmentConservationAnnotation()
1563 || aa[i] == av.getAlignmentConsensusAnnotation()
1564 || aa[i].autoCalculated)
1566 // new way of indicating autocalculated annotation -
1567 an.setAutoCalculated(aa[i].autoCalculated);
1569 if (aa[i].hasScore())
1571 an.setScore(aa[i].getScore());
1574 if (aa[i].getCalcId() != null)
1576 calcIdSet.add(aa[i].getCalcId());
1577 an.setCalcId(aa[i].getCalcId());
1579 if (aa[i].hasProperties())
1581 for (String pr : aa[i].getProperties())
1583 Property prop = new Property();
1585 prop.setValue(aa[i].getProperty(pr));
1586 an.addProperty(prop);
1590 AnnotationElement ae;
1591 if (aa[i].annotations != null)
1593 an.setScoreOnly(false);
1594 for (int a = 0; a < aa[i].annotations.length; a++)
1596 if ((aa[i] == null) || (aa[i].annotations[a] == null))
1601 ae = new AnnotationElement();
1602 if (aa[i].annotations[a].description != null)
1604 ae.setDescription(aa[i].annotations[a].description);
1606 if (aa[i].annotations[a].displayCharacter != null)
1608 ae.setDisplayCharacter(aa[i].annotations[a].displayCharacter);
1611 if (!Float.isNaN(aa[i].annotations[a].value))
1613 ae.setValue(aa[i].annotations[a].value);
1617 if (aa[i].annotations[a].secondaryStructure > ' ')
1619 ae.setSecondaryStructure(aa[i].annotations[a].secondaryStructure
1623 if (aa[i].annotations[a].colour != null
1624 && aa[i].annotations[a].colour != java.awt.Color.black)
1626 ae.setColour(aa[i].annotations[a].colour.getRGB());
1629 an.addAnnotationElement(ae);
1630 if (aa[i].autoCalculated)
1632 // only write one non-null entry into the annotation row -
1633 // sufficient to get the visualization attributes necessary to
1641 an.setScoreOnly(true);
1643 if (!storeDS || (storeDS && !aa[i].autoCalculated))
1645 // skip autocalculated annotation - these are only provided for
1647 vamsasSet.addAnnotation(an);
1653 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
1655 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
1656 if (settings != null)
1658 CalcIdParam vCalcIdParam = new CalcIdParam();
1659 vCalcIdParam.setCalcId(calcId);
1660 vCalcIdParam.addServiceURL(settings.getServiceURI());
1661 // generic URI allowing a third party to resolve another instance of the
1662 // service used for this calculation
1663 for (String urls : settings.getServiceURLs())
1665 vCalcIdParam.addServiceURL(urls);
1667 vCalcIdParam.setVersion("1.0");
1668 if (settings.getPreset() != null)
1670 WsParamSetI setting = settings.getPreset();
1671 vCalcIdParam.setName(setting.getName());
1672 vCalcIdParam.setDescription(setting.getDescription());
1676 vCalcIdParam.setName("");
1677 vCalcIdParam.setDescription("Last used parameters");
1679 // need to be able to recover 1) settings 2) user-defined presets or
1680 // recreate settings from preset 3) predefined settings provided by
1681 // service - or settings that can be transferred (or discarded)
1682 vCalcIdParam.setParameters(settings.getWsParamFile().replace("\n",
1684 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
1685 // todo - decide if updateImmediately is needed for any projects.
1687 return vCalcIdParam;
1692 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
1695 if (calcIdParam.getVersion().equals("1.0"))
1697 Jws2Instance service = Jws2Discoverer.getDiscoverer()
1698 .getPreferredServiceFor(calcIdParam.getServiceURL());
1699 if (service != null)
1701 WsParamSetI parmSet = null;
1704 parmSet = service.getParamStore().parseServiceParameterFile(
1705 calcIdParam.getName(), calcIdParam.getDescription(),
1706 calcIdParam.getServiceURL(),
1707 calcIdParam.getParameters().replace("|\\n|", "\n"));
1708 } catch (IOException x)
1710 warn("Couldn't parse parameter data for "
1711 + calcIdParam.getCalcId(), x);
1714 List<ArgumentI> argList = null;
1715 if (calcIdParam.getName().length() > 0)
1717 parmSet = service.getParamStore()
1718 .getPreset(calcIdParam.getName());
1719 if (parmSet != null)
1721 // TODO : check we have a good match with settings in AACon -
1722 // otherwise we'll need to create a new preset
1727 argList = parmSet.getArguments();
1730 AAConSettings settings = new AAConSettings(
1731 calcIdParam.isAutoUpdate(), service, parmSet, argList);
1732 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
1733 calcIdParam.isNeedsUpdate());
1738 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
1742 throw new Error(MessageManager.formatMessage(
1743 "error.unsupported_version_calcIdparam", new Object[]
1744 { calcIdParam.toString() }));
1748 * External mapping between jalview objects and objects yielding a valid and
1749 * unique object ID string. This is null for normal Jalview project IO, but
1750 * non-null when a jalview project is being read or written as part of a
1753 IdentityHashMap jv2vobj = null;
1756 * Construct a unique ID for jvobj using either existing bindings or if none
1757 * exist, the result of the hashcode call for the object.
1760 * jalview data object
1761 * @return unique ID for referring to jvobj
1763 private String makeHashCode(Object jvobj, String altCode)
1765 if (jv2vobj != null)
1767 Object id = jv2vobj.get(jvobj);
1770 return id.toString();
1772 // check string ID mappings
1773 if (jvids2vobj != null && jvobj instanceof String)
1775 id = jvids2vobj.get(jvobj);
1779 return id.toString();
1781 // give up and warn that something has gone wrong
1782 warn("Cannot find ID for object in external mapping : " + jvobj);
1788 * return local jalview object mapped to ID, if it exists
1792 * @return null or object bound to idcode
1794 private Object retrieveExistingObj(String idcode)
1796 if (idcode != null && vobj2jv != null)
1798 return vobj2jv.get(idcode);
1804 * binding from ID strings from external mapping table to jalview data model
1807 private Hashtable vobj2jv;
1809 private Sequence createVamsasSequence(String id, SequenceI jds)
1811 return createVamsasSequence(true, id, jds, null);
1814 private Sequence createVamsasSequence(boolean recurse, String id,
1815 SequenceI jds, SequenceI parentseq)
1817 Sequence vamsasSeq = new Sequence();
1818 vamsasSeq.setId(id);
1819 vamsasSeq.setName(jds.getName());
1820 vamsasSeq.setSequence(jds.getSequenceAsString());
1821 vamsasSeq.setDescription(jds.getDescription());
1822 jalview.datamodel.DBRefEntry[] dbrefs = null;
1823 if (jds.getDatasetSequence() != null)
1825 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
1826 if (jds.getDatasetSequence().getDBRef() != null)
1828 dbrefs = jds.getDatasetSequence().getDBRef();
1833 vamsasSeq.setDsseqid(id); // so we can tell which sequences really are
1834 // dataset sequences only
1835 dbrefs = jds.getDBRef();
1839 for (int d = 0; d < dbrefs.length; d++)
1841 DBRef dbref = new DBRef();
1842 dbref.setSource(dbrefs[d].getSource());
1843 dbref.setVersion(dbrefs[d].getVersion());
1844 dbref.setAccessionId(dbrefs[d].getAccessionId());
1845 if (dbrefs[d].hasMap())
1847 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
1849 dbref.setMapping(mp);
1851 vamsasSeq.addDBRef(dbref);
1857 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
1858 SequenceI parentseq, SequenceI jds, boolean recurse)
1861 if (jmp.getMap() != null)
1865 jalview.util.MapList mlst = jmp.getMap();
1866 List<int[]> r = mlst.getFromRanges();
1867 for (int[] range : r)
1869 MapListFrom mfrom = new MapListFrom();
1870 mfrom.setStart(range[0]);
1871 mfrom.setEnd(range[1]);
1872 mp.addMapListFrom(mfrom);
1874 r = mlst.getToRanges();
1875 for (int[] range : r)
1877 MapListTo mto = new MapListTo();
1878 mto.setStart(range[0]);
1879 mto.setEnd(range[1]);
1880 mp.addMapListTo(mto);
1882 mp.setMapFromUnit(mlst.getFromRatio());
1883 mp.setMapToUnit(mlst.getToRatio());
1884 if (jmp.getTo() != null)
1886 MappingChoice mpc = new MappingChoice();
1888 && (parentseq != jmp.getTo() || parentseq
1889 .getDatasetSequence() != jmp.getTo()))
1891 mpc.setSequence(createVamsasSequence(false, seqHash(jmp.getTo()),
1897 SequenceI ps = null;
1898 if (parentseq != jmp.getTo()
1899 && parentseq.getDatasetSequence() != jmp.getTo())
1901 // chaining dbref rather than a handshaking one
1902 jmpid = seqHash(ps = jmp.getTo());
1906 jmpid = seqHash(ps = parentseq);
1908 mpc.setDseqFor(jmpid);
1909 if (!seqRefIds.containsKey(mpc.getDseqFor()))
1911 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
1912 seqRefIds.put(mpc.getDseqFor(), ps);
1916 jalview.bin.Cache.log.debug("reusing DseqFor ID");
1919 mp.setMappingChoice(mpc);
1925 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
1926 List<UserColourScheme> userColours, JalviewModelSequence jms)
1929 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
1930 boolean newucs = false;
1931 if (!userColours.contains(ucs))
1933 userColours.add(ucs);
1936 id = "ucs" + userColours.indexOf(ucs);
1939 // actually create the scheme's entry in the XML model
1940 java.awt.Color[] colours = ucs.getColours();
1941 jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
1942 jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
1944 for (int i = 0; i < colours.length; i++)
1946 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
1947 col.setName(ResidueProperties.aa[i]);
1948 col.setRGB(jalview.util.Format.getHexString(colours[i]));
1949 jbucs.addColour(col);
1951 if (ucs.getLowerCaseColours() != null)
1953 colours = ucs.getLowerCaseColours();
1954 for (int i = 0; i < colours.length; i++)
1956 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
1957 col.setName(ResidueProperties.aa[i].toLowerCase());
1958 col.setRGB(jalview.util.Format.getHexString(colours[i]));
1959 jbucs.addColour(col);
1964 uc.setUserColourScheme(jbucs);
1965 jms.addUserColours(uc);
1971 jalview.schemes.UserColourScheme getUserColourScheme(
1972 JalviewModelSequence jms, String id)
1974 UserColours[] uc = jms.getUserColours();
1975 UserColours colours = null;
1977 for (int i = 0; i < uc.length; i++)
1979 if (uc[i].getId().equals(id))
1987 java.awt.Color[] newColours = new java.awt.Color[24];
1989 for (int i = 0; i < 24; i++)
1991 newColours[i] = new java.awt.Color(Integer.parseInt(colours
1992 .getUserColourScheme().getColour(i).getRGB(), 16));
1995 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
1998 if (colours.getUserColourScheme().getColourCount() > 24)
2000 newColours = new java.awt.Color[23];
2001 for (int i = 0; i < 23; i++)
2003 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2004 .getUserColourScheme().getColour(i + 24).getRGB(), 16));
2006 ucs.setLowerCaseColours(newColours);
2013 * contains last error message (if any) encountered by XML loader.
2015 String errorMessage = null;
2018 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2019 * exceptions are raised during project XML parsing
2021 public boolean attemptversion1parse = true;
2024 * Load a jalview project archive from a jar file
2027 * - HTTP URL or filename
2029 public AlignFrame loadJalviewAlign(final String file)
2032 jalview.gui.AlignFrame af = null;
2036 // create list to store references for any new Jmol viewers created
2037 newStructureViewers = new Vector<JalviewStructureDisplayI>();
2038 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2039 // Workaround is to make sure caller implements the JarInputStreamProvider
2041 // so we can re-open the jar input stream for each entry.
2043 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2044 af = loadJalviewAlign(jprovider);
2046 } catch (MalformedURLException e)
2048 errorMessage = "Invalid URL format for '" + file + "'";
2054 SwingUtilities.invokeAndWait(new Runnable()
2058 setLoadingFinishedForNewStructureViewers();
2061 } catch (Exception x)
2069 private jarInputStreamProvider createjarInputStreamProvider(
2070 final String file) throws MalformedURLException
2073 errorMessage = null;
2074 uniqueSetSuffix = null;
2076 viewportsAdded.clear();
2077 frefedSequence = null;
2079 if (file.startsWith("http://"))
2081 url = new URL(file);
2083 final URL _url = url;
2084 return new jarInputStreamProvider()
2088 public JarInputStream getJarInputStream() throws IOException
2092 return new JarInputStream(_url.openStream());
2096 return new JarInputStream(new FileInputStream(file));
2101 public String getFilename()
2109 * Recover jalview session from a jalview project archive. Caller may
2110 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2111 * themselves. Any null fields will be initialised with default values,
2112 * non-null fields are left alone.
2117 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2119 errorMessage = null;
2120 if (uniqueSetSuffix == null)
2122 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2124 if (seqRefIds == null)
2126 seqRefIds = new HashMap<String, SequenceI>();
2128 if (frefedSequence == null)
2130 frefedSequence = new Vector();
2133 AlignFrame af = null, _af = null;
2134 Map<String, AlignFrame> gatherToThisFrame = new HashMap<String, AlignFrame>();
2135 final String file = jprovider.getFilename();
2138 JarInputStream jin = null;
2139 JarEntry jarentry = null;
2144 jin = jprovider.getJarInputStream();
2145 for (int i = 0; i < entryCount; i++)
2147 jarentry = jin.getNextJarEntry();
2150 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2152 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2153 JalviewModel object = new JalviewModel();
2155 Unmarshaller unmar = new Unmarshaller(object);
2156 unmar.setValidation(false);
2157 object = (JalviewModel) unmar.unmarshal(in);
2158 if (true) // !skipViewport(object))
2160 _af = loadFromObject(object, file, true, jprovider);
2161 if (object.getJalviewModelSequence().getViewportCount() > 0)
2164 if (af.viewport.isGatherViewsHere())
2166 gatherToThisFrame.put(af.viewport.getSequenceSetId(), af);
2172 else if (jarentry != null)
2174 // Some other file here.
2177 } while (jarentry != null);
2178 resolveFrefedSequences();
2179 } catch (java.io.FileNotFoundException ex)
2181 ex.printStackTrace();
2182 errorMessage = "Couldn't locate Jalview XML file : " + file;
2183 System.err.println("Exception whilst loading jalview XML file : "
2185 } catch (java.net.UnknownHostException ex)
2187 ex.printStackTrace();
2188 errorMessage = "Couldn't locate Jalview XML file : " + file;
2189 System.err.println("Exception whilst loading jalview XML file : "
2191 } catch (Exception ex)
2193 System.err.println("Parsing as Jalview Version 2 file failed.");
2194 ex.printStackTrace(System.err);
2195 if (attemptversion1parse)
2197 // Is Version 1 Jar file?
2200 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
2201 } catch (Exception ex2)
2203 System.err.println("Exception whilst loading as jalviewXMLV1:");
2204 ex2.printStackTrace();
2208 if (Desktop.instance != null)
2210 Desktop.instance.stopLoading();
2214 System.out.println("Successfully loaded archive file");
2217 ex.printStackTrace();
2219 System.err.println("Exception whilst loading jalview XML file : "
2221 } catch (OutOfMemoryError e)
2223 // Don't use the OOM Window here
2224 errorMessage = "Out of memory loading jalview XML file";
2225 System.err.println("Out of memory whilst loading jalview XML file");
2226 e.printStackTrace();
2229 if (Desktop.instance != null)
2231 Desktop.instance.stopLoading();
2235 * Regather multiple views (with the same sequence set id) to the frame (if
2236 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2237 * views instead of separate frames. Note this doesn't restore a state where
2238 * some expanded views in turn have tabbed views - the last "first tab" read
2239 * in will play the role of gatherer for all.
2241 for (AlignFrame fr : gatherToThisFrame.values())
2243 Desktop.instance.gatherViews(fr);
2246 restoreSplitFrames();
2248 if (errorMessage != null)
2256 * Try to reconstruct and display SplitFrame windows, where each contains
2257 * complementary dna and protein alignments. Done by pairing up AlignFrame
2258 * objects (created earlier) which have complementary viewport ids associated.
2260 protected void restoreSplitFrames()
2262 List<SplitFrame> gatherTo = new ArrayList<SplitFrame>();
2263 List<AlignFrame> addedToSplitFrames = new ArrayList<AlignFrame>();
2264 Map<String, AlignFrame> dna = new HashMap<String, AlignFrame>();
2267 * Identify the DNA alignments
2269 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2272 AlignFrame af = candidate.getValue();
2273 if (af.getViewport().getAlignment().isNucleotide())
2275 dna.put(candidate.getKey().getId(), af);
2280 * Try to match up the protein complements
2282 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2285 AlignFrame af = candidate.getValue();
2286 if (!af.getViewport().getAlignment().isNucleotide())
2288 String complementId = candidate.getKey().getComplementId();
2289 // only non-null complements should be in the Map
2290 if (complementId != null && dna.containsKey(complementId))
2292 final AlignFrame dnaFrame = dna.get(complementId);
2293 SplitFrame sf = createSplitFrame(dnaFrame, af);
2294 addedToSplitFrames.add(dnaFrame);
2295 addedToSplitFrames.add(af);
2296 if (af.viewport.isGatherViewsHere())
2305 * Open any that we failed to pair up (which shouldn't happen!) as
2306 * standalone AlignFrame's.
2308 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2311 AlignFrame af = candidate.getValue();
2312 if (!addedToSplitFrames.contains(af)) {
2313 Viewport view = candidate.getKey();
2314 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
2316 System.err.println("Failed to restore view " + view.getTitle()
2317 + " to split frame");
2322 * Gather back into tabbed views as flagged.
2324 for (SplitFrame sf : gatherTo)
2326 Desktop.instance.gatherViews(sf);
2329 splitFrameCandidates.clear();
2333 * Construct and display one SplitFrame holding DNA and protein alignments.
2336 * @param proteinFrame
2339 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
2340 AlignFrame proteinFrame)
2342 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
2343 String title = MessageManager.getString("label.linked_view_title");
2344 int width = (int) dnaFrame.getBounds().getWidth();
2345 int height = (int) (dnaFrame.getBounds().getHeight()
2346 + proteinFrame.getBounds().getHeight() + 50);
2347 Desktop.addInternalFrame(splitFrame, title, width, height);
2350 * And compute cDNA consensus (couldn't do earlier with consensus as
2351 * mappings were not yet present)
2353 proteinFrame.viewport.alignmentChanged(proteinFrame.alignPanel);
2359 * check errorMessage for a valid error message and raise an error box in the
2360 * GUI or write the current errorMessage to stderr and then clear the error
2363 protected void reportErrors()
2365 reportErrors(false);
2368 protected void reportErrors(final boolean saving)
2370 if (errorMessage != null)
2372 final String finalErrorMessage = errorMessage;
2375 javax.swing.SwingUtilities.invokeLater(new Runnable()
2380 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2381 finalErrorMessage, "Error "
2382 + (saving ? "saving" : "loading")
2383 + " Jalview file", JOptionPane.WARNING_MESSAGE);
2389 System.err.println("Problem loading Jalview file: " + errorMessage);
2392 errorMessage = null;
2395 Map<String, String> alreadyLoadedPDB = new HashMap<String, String>();
2398 * when set, local views will be updated from view stored in JalviewXML
2399 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2400 * sync if this is set to true.
2402 private final boolean updateLocalViews = false;
2405 * Returns the path to a temporary file holding the PDB file for the given PDB
2406 * id. The first time of asking, searches for a file of that name in the
2407 * Jalview project jar, and copies it to a new temporary file. Any repeat
2408 * requests just return the path to the file previously created.
2414 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId)
2416 if (alreadyLoadedPDB.containsKey(pdbId))
2418 return alreadyLoadedPDB.get(pdbId).toString();
2421 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb");
2422 if (tempFile != null)
2424 alreadyLoadedPDB.put(pdbId, tempFile);
2430 * Copies the jar entry of given name to a new temporary file and returns the
2431 * path to the file, or null if the entry is not found.
2434 * @param jarEntryName
2436 * a prefix for the temporary file name, must be at least three
2440 protected String copyJarEntry(jarInputStreamProvider jprovider,
2441 String jarEntryName, String prefix)
2443 BufferedReader in = null;
2444 PrintWriter out = null;
2448 JarInputStream jin = jprovider.getJarInputStream();
2450 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2451 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2452 * FileInputStream(jprovider)); }
2455 JarEntry entry = null;
2458 entry = jin.getNextJarEntry();
2459 } while (entry != null && !entry.getName().equals(jarEntryName));
2462 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
2463 File outFile = File.createTempFile(prefix, ".tmp");
2464 outFile.deleteOnExit();
2465 out = new PrintWriter(new FileOutputStream(outFile));
2468 while ((data = in.readLine()) != null)
2473 String t = outFile.getAbsolutePath();
2478 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
2480 } catch (Exception ex)
2482 ex.printStackTrace();
2490 } catch (IOException e)
2504 private class JvAnnotRow
2506 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2513 * persisted version of annotation row from which to take vis properties
2515 public jalview.datamodel.AlignmentAnnotation template;
2518 * original position of the annotation row in the alignment
2524 * Load alignment frame from jalview XML DOM object
2529 * filename source string
2530 * @param loadTreesAndStructures
2531 * when false only create Viewport
2533 * data source provider
2534 * @return alignment frame created from view stored in DOM
2536 AlignFrame loadFromObject(JalviewModel object, String file,
2537 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
2539 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
2540 Sequence[] vamsasSeq = vamsasSet.getSequence();
2542 JalviewModelSequence jms = object.getJalviewModelSequence();
2544 Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
2547 // ////////////////////////////////
2550 List<SequenceI> hiddenSeqs = null;
2551 jalview.datamodel.Sequence jseq;
2553 List<SequenceI> tmpseqs = new ArrayList<SequenceI>();
2555 boolean multipleView = false;
2557 JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
2558 int vi = 0; // counter in vamsasSeq array
2559 for (int i = 0; i < jseqs.length; i++)
2561 String seqId = jseqs[i].getId();
2563 if (seqRefIds.get(seqId) != null)
2565 tmpseqs.add(seqRefIds.get(seqId));
2566 multipleView = true;
2570 jseq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
2571 vamsasSeq[vi].getSequence());
2572 jseq.setDescription(vamsasSeq[vi].getDescription());
2573 jseq.setStart(jseqs[i].getStart());
2574 jseq.setEnd(jseqs[i].getEnd());
2575 jseq.setVamsasId(uniqueSetSuffix + seqId);
2576 seqRefIds.put(vamsasSeq[vi].getId(), jseq);
2581 if (jseqs[i].getHidden())
2583 if (hiddenSeqs == null)
2585 hiddenSeqs = new ArrayList<SequenceI>();
2588 hiddenSeqs.add(seqRefIds.get(seqId));
2594 // Create the alignment object from the sequence set
2595 // ///////////////////////////////
2596 SequenceI[] orderedSeqs = tmpseqs
2597 .toArray(new SequenceI[tmpseqs.size()]);
2599 Alignment al = new Alignment(orderedSeqs);
2601 // / Add the alignment properties
2602 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
2604 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
2605 al.setProperty(ssp.getKey(), ssp.getValue());
2609 // SequenceFeatures are added to the DatasetSequence,
2610 // so we must create or recover the dataset before loading features
2611 // ///////////////////////////////
2612 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
2614 // older jalview projects do not have a dataset id.
2615 al.setDataset(null);
2619 // recover dataset - passing on flag indicating if this a 'viewless'
2620 // sequence set (a.k.a. a stored dataset for the project)
2621 recoverDatasetFor(vamsasSet, al, object.getJalviewModelSequence()
2622 .getViewportCount() == 0);
2624 // ///////////////////////////////
2626 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
2629 // load sequence features, database references and any associated PDB
2630 // structures for the alignment
2631 for (int i = 0; i < vamsasSeq.length; i++)
2633 if (jseqs[i].getFeaturesCount() > 0)
2635 Features[] features = jseqs[i].getFeatures();
2636 for (int f = 0; f < features.length; f++)
2638 jalview.datamodel.SequenceFeature sf = new jalview.datamodel.SequenceFeature(
2639 features[f].getType(), features[f].getDescription(),
2640 features[f].getStatus(), features[f].getBegin(),
2641 features[f].getEnd(), features[f].getFeatureGroup());
2643 sf.setScore(features[f].getScore());
2644 for (int od = 0; od < features[f].getOtherDataCount(); od++)
2646 OtherData keyValue = features[f].getOtherData(od);
2647 if (keyValue.getKey().startsWith("LINK"))
2649 sf.addLink(keyValue.getValue());
2653 sf.setValue(keyValue.getKey(), keyValue.getValue());
2658 al.getSequenceAt(i).getDatasetSequence().addSequenceFeature(sf);
2661 if (vamsasSeq[i].getDBRefCount() > 0)
2663 addDBRefs(al.getSequenceAt(i).getDatasetSequence(), vamsasSeq[i]);
2665 if (jseqs[i].getPdbidsCount() > 0)
2667 Pdbids[] ids = jseqs[i].getPdbids();
2668 for (int p = 0; p < ids.length; p++)
2670 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
2671 entry.setId(ids[p].getId());
2672 if (ids[p].getType() != null)
2674 if (ids[p].getType().equalsIgnoreCase("PDB"))
2676 entry.setType(PDBEntry.Type.PDB);
2680 entry.setType(PDBEntry.Type.FILE);
2683 if (ids[p].getFile() != null)
2685 if (!pdbloaded.containsKey(ids[p].getFile()))
2687 entry.setFile(loadPDBFile(jprovider, ids[p].getId()));
2691 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
2694 StructureSelectionManager.getStructureSelectionManager(
2695 Desktop.instance).registerPDBEntry(entry);
2696 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
2700 } // end !multipleview
2702 // ///////////////////////////////
2703 // LOAD SEQUENCE MAPPINGS
2705 if (vamsasSet.getAlcodonFrameCount() > 0)
2707 // TODO Potentially this should only be done once for all views of an
2709 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
2710 for (int i = 0; i < alc.length; i++)
2712 AlignedCodonFrame cf = new AlignedCodonFrame();
2713 if (alc[i].getAlcodMapCount() > 0)
2715 AlcodMap[] maps = alc[i].getAlcodMap();
2716 for (int m = 0; m < maps.length; m++)
2718 SequenceI dnaseq = seqRefIds.get(maps[m].getDnasq());
2720 jalview.datamodel.Mapping mapping = null;
2721 // attach to dna sequence reference.
2722 if (maps[m].getMapping() != null)
2724 mapping = addMapping(maps[m].getMapping());
2728 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
2733 frefedSequence.add(new Object[]
2734 { maps[m].getDnasq(), cf, mapping });
2738 al.addCodonFrame(cf);
2742 // ////////////////////////////////
2744 List<JvAnnotRow> autoAlan = new ArrayList<JvAnnotRow>();
2746 * store any annotations which forward reference a group's ID
2748 Hashtable<String, ArrayList<jalview.datamodel.AlignmentAnnotation>> groupAnnotRefs = new Hashtable<String, ArrayList<jalview.datamodel.AlignmentAnnotation>>();
2750 if (vamsasSet.getAnnotationCount() > 0)
2752 Annotation[] an = vamsasSet.getAnnotation();
2754 for (int i = 0; i < an.length; i++)
2757 * test if annotation is automatically calculated for this view only
2759 boolean autoForView = false;
2760 if (an[i].getLabel().equals("Quality")
2761 || an[i].getLabel().equals("Conservation")
2762 || an[i].getLabel().equals("Consensus"))
2764 // Kludge for pre 2.5 projects which lacked the autocalculated flag
2766 if (!an[i].hasAutoCalculated())
2768 an[i].setAutoCalculated(true);
2772 || (an[i].hasAutoCalculated() && an[i].isAutoCalculated()))
2774 // remove ID - we don't recover annotation from other views for
2775 // view-specific annotation
2779 // set visiblity for other annotation in this view
2780 if (an[i].getId() != null
2781 && annotationIds.containsKey(an[i].getId()))
2783 AlignmentAnnotation jda = annotationIds.get(an[i].getId());
2784 // in principle Visible should always be true for annotation displayed
2785 // in multiple views
2786 if (an[i].hasVisible())
2788 jda.visible = an[i].getVisible();
2791 al.addAnnotation(jda);
2795 // Construct new annotation from model.
2796 AnnotationElement[] ae = an[i].getAnnotationElement();
2797 jalview.datamodel.Annotation[] anot = null;
2798 java.awt.Color firstColour = null;
2800 if (!an[i].getScoreOnly())
2802 anot = new jalview.datamodel.Annotation[al.getWidth()];
2803 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
2805 anpos = ae[aa].getPosition();
2807 if (anpos >= anot.length)
2812 anot[anpos] = new jalview.datamodel.Annotation(
2814 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
2815 (ae[aa].getSecondaryStructure() == null || ae[aa]
2816 .getSecondaryStructure().length() == 0) ? ' '
2817 : ae[aa].getSecondaryStructure().charAt(0),
2821 // JBPNote: Consider verifying dataflow for IO of secondary
2822 // structure annotation read from Stockholm files
2823 // this was added to try to ensure that
2824 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
2826 // anot[ae[aa].getPosition()].displayCharacter = "";
2828 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
2829 if (firstColour == null)
2831 firstColour = anot[anpos].colour;
2835 jalview.datamodel.AlignmentAnnotation jaa = null;
2837 if (an[i].getGraph())
2839 float llim = 0, hlim = 0;
2840 // if (autoForView || an[i].isAutoCalculated()) {
2843 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
2844 an[i].getDescription(), anot, llim, hlim,
2845 an[i].getGraphType());
2847 jaa.graphGroup = an[i].getGraphGroup();
2848 jaa._linecolour = firstColour;
2849 if (an[i].getThresholdLine() != null)
2851 jaa.setThreshold(new jalview.datamodel.GraphLine(an[i]
2852 .getThresholdLine().getValue(), an[i]
2853 .getThresholdLine().getLabel(), new java.awt.Color(
2854 an[i].getThresholdLine().getColour())));
2857 if (autoForView || an[i].isAutoCalculated())
2859 // Hardwire the symbol display line to ensure that labels for
2860 // histograms are displayed
2866 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
2867 an[i].getDescription(), anot);
2868 jaa._linecolour = firstColour;
2870 // register new annotation
2871 if (an[i].getId() != null)
2873 annotationIds.put(an[i].getId(), jaa);
2874 jaa.annotationId = an[i].getId();
2876 // recover sequence association
2877 if (an[i].getSequenceRef() != null)
2879 if (al.findName(an[i].getSequenceRef()) != null)
2881 jaa.createSequenceMapping(al.findName(an[i].getSequenceRef()),
2883 al.findName(an[i].getSequenceRef()).addAlignmentAnnotation(jaa);
2886 // and make a note of any group association
2887 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
2889 ArrayList<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
2890 .get(an[i].getGroupRef());
2893 aal = new ArrayList<jalview.datamodel.AlignmentAnnotation>();
2894 groupAnnotRefs.put(an[i].getGroupRef(), aal);
2899 if (an[i].hasScore())
2901 jaa.setScore(an[i].getScore());
2903 if (an[i].hasVisible())
2905 jaa.visible = an[i].getVisible();
2908 if (an[i].hasCentreColLabels())
2910 jaa.centreColLabels = an[i].getCentreColLabels();
2913 if (an[i].hasScaleColLabels())
2915 jaa.scaleColLabel = an[i].getScaleColLabels();
2917 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
2919 // newer files have an 'autoCalculated' flag and store calculation
2920 // state in viewport properties
2921 jaa.autoCalculated = true; // means annotation will be marked for
2922 // update at end of load.
2924 if (an[i].hasGraphHeight())
2926 jaa.graphHeight = an[i].getGraphHeight();
2928 if (an[i].hasBelowAlignment())
2930 jaa.belowAlignment = an[i].isBelowAlignment();
2932 jaa.setCalcId(an[i].getCalcId());
2933 if (an[i].getPropertyCount() > 0)
2935 for (jalview.schemabinding.version2.Property prop : an[i]
2938 jaa.setProperty(prop.getName(), prop.getValue());
2941 if (jaa.autoCalculated)
2943 autoAlan.add(new JvAnnotRow(i, jaa));
2946 // if (!autoForView)
2948 // add autocalculated group annotation and any user created annotation
2950 al.addAnnotation(jaa);
2954 // ///////////////////////
2956 // Create alignment markup and styles for this view
2957 if (jms.getJGroupCount() > 0)
2959 JGroup[] groups = jms.getJGroup();
2960 boolean addAnnotSchemeGroup = false;
2961 for (int i = 0; i < groups.length; i++)
2963 ColourSchemeI cs = null;
2965 if (groups[i].getColour() != null)
2967 if (groups[i].getColour().startsWith("ucs"))
2969 cs = getUserColourScheme(jms, groups[i].getColour());
2971 else if (groups[i].getColour().equals("AnnotationColourGradient")
2972 && groups[i].getAnnotationColours() != null)
2974 addAnnotSchemeGroup = true;
2979 cs = ColourSchemeProperty.getColour(al, groups[i].getColour());
2984 cs.setThreshold(groups[i].getPidThreshold(), true);
2988 Vector seqs = new Vector();
2990 for (int s = 0; s < groups[i].getSeqCount(); s++)
2992 String seqId = groups[i].getSeq(s) + "";
2993 jalview.datamodel.SequenceI ts = seqRefIds.get(seqId);
2997 seqs.addElement(ts);
3001 if (seqs.size() < 1)
3006 jalview.datamodel.SequenceGroup sg = new jalview.datamodel.SequenceGroup(
3007 seqs, groups[i].getName(), cs, groups[i].getDisplayBoxes(),
3008 groups[i].getDisplayText(), groups[i].getColourText(),
3009 groups[i].getStart(), groups[i].getEnd());
3011 sg.setOutlineColour(new java.awt.Color(groups[i].getOutlineColour()));
3013 sg.textColour = new java.awt.Color(groups[i].getTextCol1());
3014 sg.textColour2 = new java.awt.Color(groups[i].getTextCol2());
3015 sg.setShowNonconserved(groups[i].hasShowUnconserved() ? groups[i]
3016 .isShowUnconserved() : false);
3017 sg.thresholdTextColour = groups[i].getTextColThreshold();
3018 if (groups[i].hasShowConsensusHistogram())
3020 sg.setShowConsensusHistogram(groups[i].isShowConsensusHistogram());
3023 if (groups[i].hasShowSequenceLogo())
3025 sg.setshowSequenceLogo(groups[i].isShowSequenceLogo());
3027 if (groups[i].hasNormaliseSequenceLogo())
3029 sg.setNormaliseSequenceLogo(groups[i].isNormaliseSequenceLogo());
3031 if (groups[i].hasIgnoreGapsinConsensus())
3033 sg.setIgnoreGapsConsensus(groups[i].getIgnoreGapsinConsensus());
3035 if (groups[i].getConsThreshold() != 0)
3037 jalview.analysis.Conservation c = new jalview.analysis.Conservation(
3038 "All", ResidueProperties.propHash, 3,
3039 sg.getSequences(null), 0, sg.getWidth() - 1);
3041 c.verdict(false, 25);
3042 sg.cs.setConservation(c);
3045 if (groups[i].getId() != null && groupAnnotRefs.size() > 0)
3047 // re-instate unique group/annotation row reference
3048 ArrayList<jalview.datamodel.AlignmentAnnotation> jaal = groupAnnotRefs
3049 .get(groups[i].getId());
3052 for (jalview.datamodel.AlignmentAnnotation jaa : jaal)
3055 if (jaa.autoCalculated)
3057 // match up and try to set group autocalc alignment row for this
3059 if (jaa.label.startsWith("Consensus for "))
3061 sg.setConsensus(jaa);
3063 // match up and try to set group autocalc alignment row for this
3065 if (jaa.label.startsWith("Conservation for "))
3067 sg.setConservationRow(jaa);
3074 if (addAnnotSchemeGroup)
3076 // reconstruct the annotation colourscheme
3077 sg.cs = constructAnnotationColour(
3078 groups[i].getAnnotationColours(), null, al, jms, false);
3084 // only dataset in this model, so just return.
3087 // ///////////////////////////////
3090 // If we just load in the same jar file again, the sequenceSetId
3091 // will be the same, and we end up with multiple references
3092 // to the same sequenceSet. We must modify this id on load
3093 // so that each load of the file gives a unique id
3094 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3095 String viewId = (view.getId() == null ? null : view.getId()
3097 AlignFrame af = null;
3098 AlignViewport av = null;
3099 // now check to see if we really need to create a new viewport.
3100 if (multipleView && viewportsAdded.size() == 0)
3102 // We recovered an alignment for which a viewport already exists.
3103 // TODO: fix up any settings necessary for overlaying stored state onto
3104 // state recovered from another document. (may not be necessary).
3105 // we may need a binding from a viewport in memory to one recovered from
3107 // and then recover its containing af to allow the settings to be applied.
3108 // TODO: fix for vamsas demo
3110 .println("About to recover a viewport for existing alignment: Sequence set ID is "
3112 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3113 if (seqsetobj != null)
3115 if (seqsetobj instanceof String)
3117 uniqueSeqSetId = (String) seqsetobj;
3119 .println("Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
3125 .println("Warning : Collision between sequence set ID string and existing jalview object mapping.");
3131 * indicate that annotation colours are applied across all groups (pre
3132 * Jalview 2.8.1 behaviour)
3134 boolean doGroupAnnColour = isVersionStringLaterThan("2.8.1",
3135 object.getVersion());
3137 AlignmentPanel ap = null;
3138 boolean isnewview = true;
3141 // Check to see if this alignment already has a view id == viewId
3142 jalview.gui.AlignmentPanel views[] = Desktop
3143 .getAlignmentPanels(uniqueSeqSetId);
3144 if (views != null && views.length > 0)
3146 for (int v = 0; v < views.length; v++)
3148 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
3150 // recover the existing alignpanel, alignframe, viewport
3151 af = views[v].alignFrame;
3154 // TODO: could even skip resetting view settings if we don't want to
3155 // change the local settings from other jalview processes
3164 af = loadViewport(file, jseqs, hiddenSeqs, al, jms, view,
3165 uniqueSeqSetId, viewId, autoAlan);
3170 // /////////////////////////////////////
3171 if (loadTreesAndStructures && jms.getTreeCount() > 0)
3175 for (int t = 0; t < jms.getTreeCount(); t++)
3178 Tree tree = jms.getTree(t);
3180 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
3183 tp = af.ShowNewickTree(
3184 new jalview.io.NewickFile(tree.getNewick()),
3185 tree.getTitle(), tree.getWidth(), tree.getHeight(),
3186 tree.getXpos(), tree.getYpos());
3187 if (tree.getId() != null)
3189 // perhaps bind the tree id to something ?
3194 // update local tree attributes ?
3195 // TODO: should check if tp has been manipulated by user - if so its
3196 // settings shouldn't be modified
3197 tp.setTitle(tree.getTitle());
3198 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(), tree
3199 .getWidth(), tree.getHeight()));
3200 tp.av = av; // af.viewport; // TODO: verify 'associate with all
3203 tp.treeCanvas.av = av; // af.viewport;
3204 tp.treeCanvas.ap = ap; // af.alignPanel;
3209 warn("There was a problem recovering stored Newick tree: \n"
3210 + tree.getNewick());
3214 tp.fitToWindow.setState(tree.getFitToWindow());
3215 tp.fitToWindow_actionPerformed(null);
3217 if (tree.getFontName() != null)
3219 tp.setTreeFont(new java.awt.Font(tree.getFontName(), tree
3220 .getFontStyle(), tree.getFontSize()));
3224 tp.setTreeFont(new java.awt.Font(view.getFontName(), view
3225 .getFontStyle(), tree.getFontSize()));
3228 tp.showPlaceholders(tree.getMarkUnlinked());
3229 tp.showBootstrap(tree.getShowBootstrap());
3230 tp.showDistances(tree.getShowDistances());
3232 tp.treeCanvas.threshold = tree.getThreshold();
3234 if (tree.getCurrentTree())
3236 af.viewport.setCurrentTree(tp.getTree());
3240 } catch (Exception ex)
3242 ex.printStackTrace();
3246 // //LOAD STRUCTURES
3247 if (loadTreesAndStructures)
3249 loadStructures(jprovider, jseqs, af, ap);
3251 // and finally return.
3256 * Load and link any saved structure viewers.
3263 protected void loadStructures(jarInputStreamProvider jprovider,
3264 JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
3267 * Run through all PDB ids on the alignment, and collect mappings between
3268 * distinct view ids and all sequences referring to that view.
3270 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<String, StructureViewerModel>();
3272 for (int i = 0; i < jseqs.length; i++)
3274 if (jseqs[i].getPdbidsCount() > 0)
3276 Pdbids[] ids = jseqs[i].getPdbids();
3277 for (int p = 0; p < ids.length; p++)
3279 final int structureStateCount = ids[p].getStructureStateCount();
3280 for (int s = 0; s < structureStateCount; s++)
3282 // check to see if we haven't already created this structure view
3283 final StructureState structureState = ids[p]
3284 .getStructureState(s);
3285 String sviewid = (structureState.getViewId() == null) ? null
3286 : structureState.getViewId() + uniqueSetSuffix;
3287 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
3288 // Originally : ids[p].getFile()
3289 // : TODO: verify external PDB file recovery still works in normal
3290 // jalview project load
3291 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId()));
3292 jpdb.setId(ids[p].getId());
3294 int x = structureState.getXpos();
3295 int y = structureState.getYpos();
3296 int width = structureState.getWidth();
3297 int height = structureState.getHeight();
3299 // Probably don't need to do this anymore...
3300 // Desktop.desktop.getComponentAt(x, y);
3301 // TODO: NOW: check that this recovers the PDB file correctly.
3302 String pdbFile = loadPDBFile(jprovider, ids[p].getId());
3303 jalview.datamodel.SequenceI seq = seqRefIds.get(jseqs[i]
3305 if (sviewid == null)
3307 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width
3310 if (!structureViewers.containsKey(sviewid))
3312 structureViewers.put(sviewid,
3313 new StructureViewerModel(x, y, width, height, false,
3314 false, true, structureState.getViewId()));
3315 // Legacy pre-2.7 conversion JAL-823 :
3316 // do not assume any view has to be linked for colour by
3320 // assemble String[] { pdb files }, String[] { id for each
3321 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3322 // seqs_file 2}, boolean[] {
3323 // linkAlignPanel,superposeWithAlignpanel}} from hash
3324 StructureViewerModel jmoldat = structureViewers.get(sviewid);
3325 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
3326 | (structureState.hasAlignwithAlignPanel() ? structureState
3327 .getAlignwithAlignPanel() : false));
3330 * Default colour by linked panel to false if not specified (e.g.
3331 * for pre-2.7 projects)
3333 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
3334 colourWithAlignPanel |= (structureState
3335 .hasColourwithAlignPanel() ? structureState
3336 .getColourwithAlignPanel() : false);
3337 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
3340 * Default colour by viewer to true if not specified (e.g. for
3343 boolean colourByViewer = jmoldat.isColourByViewer();
3344 colourByViewer &= structureState.hasColourByJmol() ? structureState
3345 .getColourByJmol() : true;
3346 jmoldat.setColourByViewer(colourByViewer);
3348 if (jmoldat.getStateData().length() < structureState
3349 .getContent().length())
3352 jmoldat.setStateData(structureState.getContent());
3355 if (ids[p].getFile() != null)
3357 File mapkey = new File(ids[p].getFile());
3358 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
3359 if (seqstrmaps == null)
3361 jmoldat.getFileData().put(
3363 seqstrmaps = jmoldat.new StructureData(pdbFile,
3366 if (!seqstrmaps.getSeqList().contains(seq))
3368 seqstrmaps.getSeqList().add(seq);
3374 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");
3381 // Instantiate the associated structure views
3382 for (Entry<String, StructureViewerModel> entry : structureViewers
3387 createOrLinkStructureViewer(entry, af, ap, jprovider);
3388 } catch (Exception e)
3390 System.err.println("Error loading structure viewer: "
3392 // failed - try the next one
3404 protected void createOrLinkStructureViewer(
3405 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3406 AlignmentPanel ap, jarInputStreamProvider jprovider)
3408 final StructureViewerModel stateData = viewerData.getValue();
3411 * Search for any viewer windows already open from other alignment views
3412 * that exactly match the stored structure state
3414 StructureViewerBase comp = findMatchingViewer(viewerData);
3418 linkStructureViewer(ap, comp, stateData);
3423 * 2.8.2: stateData contains "chimera..." (session file name), or JMOL state
3426 * 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
3427 * "viewer_"+stateData.viewId
3429 // FIXME use stateData.getType() instead once schema updated
3430 if (ViewerType.CHIMERA.toString().equals(stateData.getStateData())
3431 || stateData.getStateData().indexOf("chimera") > -1)
3433 createChimeraViewer(viewerData, af, jprovider);
3437 createJmolViewer(viewerData, af, jprovider);
3442 * Create a new Chimera viewer.
3448 protected void createChimeraViewer(Entry<String, StructureViewerModel> viewerData,
3450 jarInputStreamProvider jprovider)
3452 StructureViewerModel data = viewerData.getValue();
3453 String chimeraSessionFile = data.getStateData();
3456 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
3458 * Note this is the 'saved' viewId as in the project file XML, _not_ the
3459 * 'uniquified' sviewid used to reconstruct the viewer here
3461 chimeraSessionFile = copyJarEntry(jprovider,
3462 "viewer_" + data.getViewId(), "chimera");
3464 Set<Entry<File, StructureData>> fileData = data.getFileData()
3466 List<PDBEntry> pdbs = new ArrayList<PDBEntry>();
3467 List<SequenceI[]> allseqs = new ArrayList<SequenceI[]>();
3468 for (Entry<File, StructureData> pdb : fileData)
3470 String filePath = pdb.getValue().getFilePath();
3471 String pdbId = pdb.getValue().getPdbId();
3472 // pdbs.add(new PDBEntry(filePath, pdbId));
3473 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
3474 final List<SequenceI> seqList = pdb.getValue().getSeqList();
3475 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
3479 boolean colourByChimera = data.isColourByViewer();
3480 boolean colourBySequence = data.isColourWithAlignPanel();
3482 // TODO use StructureViewer as a factory here, see JAL-1761
3483 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
3484 final SequenceI[][] seqsArray = allseqs.toArray(new SequenceI[allseqs
3486 String newViewId = viewerData.getKey();
3487 new ChimeraViewFrame(chimeraSessionFile, af.alignPanel, pdbArray,
3488 seqsArray, colourByChimera, colourBySequence, newViewId);
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 // FIXME use getType once Castor regenerated for new attribute
3514 if (ViewerType.JMOL.toString().equals(state /* svattrib.getType() */))
3516 state = readJarEntry(jprovider, "viewer_" + 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 * Returns any open frame that matches given structure viewer data. The match
3649 * is based on the unique viewId, or (for older project versions) the frame's
3655 protected StructureViewerBase findMatchingViewer(
3656 Entry<String, StructureViewerModel> viewerData)
3658 final String sviewid = viewerData.getKey();
3659 final StructureViewerModel svattrib = viewerData.getValue();
3660 StructureViewerBase comp = null;
3661 JInternalFrame[] frames = getAllFrames();
3662 for (JInternalFrame frame : frames)
3664 if (frame instanceof StructureViewerBase)
3667 * Post jalview 2.4 schema includes structure view id
3670 && ((StructureViewerBase) frame).getViewId()
3673 comp = (StructureViewerBase) frame;
3674 break; // break added in 2.9
3677 * Otherwise test for matching position and size of viewer frame
3679 else if (frame.getX() == svattrib.getX()
3680 && frame.getY() == svattrib.getY()
3681 && frame.getHeight() == svattrib.getHeight()
3682 && frame.getWidth() == svattrib.getWidth())
3684 comp = (StructureViewerBase) frame;
3685 // no break in faint hope of an exact match on viewId
3693 * Link an AlignmentPanel to an existing structure viewer.
3698 * @param useinViewerSuperpos
3699 * @param usetoColourbyseq
3700 * @param viewerColouring
3702 protected void linkStructureViewer(AlignmentPanel ap,
3703 StructureViewerBase viewer, StructureViewerModel stateData)
3705 // NOTE: if the jalview project is part of a shared session then
3706 // view synchronization should/could be done here.
3708 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
3709 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
3710 final boolean viewerColouring = stateData.isColourByViewer();
3711 Map<File, StructureData> oldFiles = stateData.getFileData();
3714 * Add mapping for sequences in this view to an already open viewer
3716 final AAStructureBindingModel binding = viewer.getBinding();
3717 for (File id : oldFiles.keySet())
3719 // add this and any other pdb files that should be present in the
3721 StructureData filedat = oldFiles.get(id);
3722 String pdbFile = filedat.getFilePath();
3723 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
3724 binding.getSsm().setMapping(seq, null, pdbFile,
3725 jalview.io.AppletFormatAdapter.FILE);
3726 binding.addSequenceForStructFile(pdbFile, seq);
3728 // and add the AlignmentPanel's reference to the view panel
3729 viewer.addAlignmentPanel(ap);
3730 if (useinViewerSuperpos)
3732 viewer.useAlignmentPanelForSuperposition(ap);
3736 viewer.excludeAlignmentPanelForSuperposition(ap);
3738 if (usetoColourbyseq)
3740 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
3744 viewer.excludeAlignmentPanelForColourbyseq(ap);
3749 * Get all frames within the Desktop.
3753 protected JInternalFrame[] getAllFrames()
3755 JInternalFrame[] frames = null;
3756 // TODO is this necessary - is it safe - risk of hanging?
3761 frames = Desktop.desktop.getAllFrames();
3762 } catch (ArrayIndexOutOfBoundsException e)
3764 // occasional No such child exceptions are thrown here...
3768 } catch (InterruptedException f)
3772 } while (frames == null);
3779 * - minimum version we are comparing against
3781 * - version of data being processsed.
3782 * @return true if version is development/null or evaluates to the same or
3783 * later X.Y.Z (where X,Y,Z are like [0-9]+b?[0-9]*)
3785 private boolean isVersionStringLaterThan(String supported, String version)
3787 if (version == null || version.equalsIgnoreCase("DEVELOPMENT BUILD")
3788 || version.equalsIgnoreCase("Test")
3789 || version.equalsIgnoreCase("AUTOMATED BUILD"))
3791 System.err.println("Assuming project file with "
3792 + (version == null ? "null" : version)
3793 + " is compatible with Jalview version " + supported);
3798 StringTokenizer currentV = new StringTokenizer(supported, "."), fileV = new StringTokenizer(
3800 while (currentV.hasMoreTokens() && fileV.hasMoreTokens())
3802 // convert b to decimal to catch bugfix releases within a series
3803 String curT = currentV.nextToken().toLowerCase().replace('b', '.');
3804 String fileT = fileV.nextToken().toLowerCase().replace('b', '.');
3807 if (Float.valueOf(curT) > Float.valueOf(fileT))
3809 // current version is newer than the version that wrote the file
3812 } catch (NumberFormatException nfe)
3815 .println("** WARNING: Version comparison failed for tokens ("
3819 + ")\n** Current: '"
3820 + supported + "' and Version: '" + version + "'");
3823 if (currentV.hasMoreElements())
3825 // fileV has no minor version but identical series to current
3832 Vector<JalviewStructureDisplayI> newStructureViewers = null;
3834 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
3836 if (newStructureViewers != null)
3838 sview.getBinding().setFinishedLoadingFromArchive(false);
3839 newStructureViewers.add(sview);
3843 protected void setLoadingFinishedForNewStructureViewers()
3845 if (newStructureViewers != null)
3847 for (JalviewStructureDisplayI sview : newStructureViewers)
3849 sview.getBinding().setFinishedLoadingFromArchive(true);
3851 newStructureViewers.clear();
3852 newStructureViewers = null;
3856 AlignFrame loadViewport(String file, JSeq[] JSEQ,
3857 List<SequenceI> hiddenSeqs, Alignment al,
3858 JalviewModelSequence jms, Viewport view, String uniqueSeqSetId,
3859 String viewId, List<JvAnnotRow> autoAlan)
3861 AlignFrame af = null;
3862 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
3863 uniqueSeqSetId, viewId);
3865 af.setFileName(file, "Jalview");
3867 for (int i = 0; i < JSEQ.length; i++)
3869 af.viewport.setSequenceColour(af.viewport.getAlignment()
3870 .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour()));
3873 af.viewport.setGatherViewsHere(view.getGatheredViews());
3875 if (view.getSequenceSetId() != null)
3877 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
3879 af.viewport.setSequenceSetId(uniqueSeqSetId);
3882 // propagate shared settings to this new view
3883 af.viewport.setHistoryList(av.getHistoryList());
3884 af.viewport.setRedoList(av.getRedoList());
3888 viewportsAdded.put(uniqueSeqSetId, af.viewport);
3890 // TODO: check if this method can be called repeatedly without
3891 // side-effects if alignpanel already registered.
3892 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
3894 // apply Hidden regions to view.
3895 if (hiddenSeqs != null)
3897 for (int s = 0; s < JSEQ.length; s++)
3899 jalview.datamodel.SequenceGroup hidden = new jalview.datamodel.SequenceGroup();
3901 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
3904 al.getSequenceAt(JSEQ[s].getHiddenSequences(r)), false);
3906 af.viewport.hideRepSequences(al.getSequenceAt(s), hidden);
3909 // jalview.datamodel.SequenceI[] hseqs = new
3910 // jalview.datamodel.SequenceI[hiddenSeqs
3913 // for (int s = 0; s < hiddenSeqs.size(); s++)
3915 // hseqs[s] = (jalview.datamodel.SequenceI) hiddenSeqs.elementAt(s);
3918 SequenceI[] hseqs = hiddenSeqs.toArray(new SequenceI[hiddenSeqs
3920 af.viewport.hideSequence(hseqs);
3923 // recover view properties and display parameters
3924 if (view.getViewName() != null)
3926 af.viewport.viewName = view.getViewName();
3927 af.setInitialTabVisible();
3929 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
3932 af.viewport.setShowAnnotation(view.getShowAnnotation());
3933 af.viewport.setAbovePIDThreshold(view.getPidSelected());
3935 af.viewport.setColourText(view.getShowColourText());
3937 af.viewport.setConservationSelected(view.getConservationSelected());
3938 af.viewport.setShowJVSuffix(view.getShowFullId());
3939 af.viewport.setRightAlignIds(view.getRightAlignIds());
3940 af.viewport.setFont(
3941 new java.awt.Font(view.getFontName(), view.getFontStyle(), view
3942 .getFontSize()), true);
3943 // TODO: allow custom charWidth/Heights to be restored by updating them
3944 // after setting font - which means set above to false
3945 af.viewport.setRenderGaps(view.getRenderGaps());
3946 af.viewport.setWrapAlignment(view.getWrapAlignment());
3947 af.viewport.setShowAnnotation(view.getShowAnnotation());
3949 af.viewport.setShowBoxes(view.getShowBoxes());
3951 af.viewport.setShowText(view.getShowText());
3953 af.viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
3954 af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
3955 af.viewport.setThresholdTextColour(view.getTextColThreshold());
3956 af.viewport.setShowUnconserved(view.hasShowUnconserved() ? view
3957 .isShowUnconserved() : false);
3958 af.viewport.setStartRes(view.getStartRes());
3959 af.viewport.setStartSeq(view.getStartSeq());
3960 af.alignPanel.updateLayout();
3961 ColourSchemeI cs = null;
3962 // apply colourschemes
3963 if (view.getBgColour() != null)
3965 if (view.getBgColour().startsWith("ucs"))
3967 cs = getUserColourScheme(jms, view.getBgColour());
3969 else if (view.getBgColour().startsWith("Annotation"))
3971 AnnotationColours viewAnnColour = view.getAnnotationColours();
3972 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
3979 cs = ColourSchemeProperty.getColour(al, view.getBgColour());
3984 cs.setThreshold(view.getPidThreshold(), true);
3985 cs.setConsensus(af.viewport.getSequenceConsensusHash());
3989 af.viewport.setGlobalColourScheme(cs);
3990 af.viewport.setColourAppliesToAllGroups(false);
3992 if (view.getConservationSelected() && cs != null)
3994 cs.setConservationInc(view.getConsThreshold());
3997 af.changeColour(cs);
3999 af.viewport.setColourAppliesToAllGroups(true);
4001 af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures());
4003 if (view.hasCentreColumnLabels())
4005 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
4007 if (view.hasIgnoreGapsinConsensus())
4009 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
4012 if (view.hasFollowHighlight())
4014 af.viewport.setFollowHighlight(view.getFollowHighlight());
4016 if (view.hasFollowSelection())
4018 af.viewport.followSelection = view.getFollowSelection();
4020 if (view.hasShowConsensusHistogram())
4022 af.viewport.setShowConsensusHistogram(view
4023 .getShowConsensusHistogram());
4027 af.viewport.setShowConsensusHistogram(true);
4029 if (view.hasShowSequenceLogo())
4031 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
4035 af.viewport.setShowSequenceLogo(false);
4037 if (view.hasNormaliseSequenceLogo())
4039 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
4041 if (view.hasShowDbRefTooltip())
4043 af.viewport.setShowDBRefs(view.getShowDbRefTooltip());
4045 if (view.hasShowNPfeatureTooltip())
4047 af.viewport.setShowNPFeats(view.hasShowNPfeatureTooltip());
4049 if (view.hasShowGroupConsensus())
4051 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
4055 af.viewport.setShowGroupConsensus(false);
4057 if (view.hasShowGroupConservation())
4059 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
4063 af.viewport.setShowGroupConservation(false);
4066 // recover featre settings
4067 if (jms.getFeatureSettings() != null)
4069 FeaturesDisplayed fdi;
4070 af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
4071 String[] renderOrder = new String[jms.getFeatureSettings()
4072 .getSettingCount()];
4073 Hashtable featureGroups = new Hashtable();
4074 Hashtable featureColours = new Hashtable();
4075 Hashtable featureOrder = new Hashtable();
4077 for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
4079 Setting setting = jms.getFeatureSettings().getSetting(fs);
4080 if (setting.hasMincolour())
4082 GraduatedColor gc = setting.hasMin() ? new GraduatedColor(
4083 new java.awt.Color(setting.getMincolour()),
4084 new java.awt.Color(setting.getColour()),
4085 setting.getMin(), setting.getMax()) : new GraduatedColor(
4086 new java.awt.Color(setting.getMincolour()),
4087 new java.awt.Color(setting.getColour()), 0, 1);
4088 if (setting.hasThreshold())
4090 gc.setThresh(setting.getThreshold());
4091 gc.setThreshType(setting.getThreshstate());
4093 gc.setAutoScaled(true); // default
4094 if (setting.hasAutoScale())
4096 gc.setAutoScaled(setting.getAutoScale());
4098 if (setting.hasColourByLabel())
4100 gc.setColourByLabel(setting.getColourByLabel());
4102 // and put in the feature colour table.
4103 featureColours.put(setting.getType(), gc);
4107 featureColours.put(setting.getType(),
4108 new java.awt.Color(setting.getColour()));
4110 renderOrder[fs] = setting.getType();
4111 if (setting.hasOrder())
4113 featureOrder.put(setting.getType(), setting.getOrder());
4117 featureOrder.put(setting.getType(), new Float(fs
4118 / jms.getFeatureSettings().getSettingCount()));
4120 if (setting.getDisplay())
4122 fdi.setVisible(setting.getType());
4125 Hashtable fgtable = new Hashtable();
4126 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
4128 Group grp = jms.getFeatureSettings().getGroup(gs);
4129 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
4131 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4132 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
4133 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
4134 FeatureRendererSettings frs = new FeatureRendererSettings(
4135 renderOrder, fgtable, featureColours, 1.0f, featureOrder);
4136 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
4137 .transferSettings(frs);
4141 if (view.getHiddenColumnsCount() > 0)
4143 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
4145 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(), view
4146 .getHiddenColumns(c).getEnd() // +1
4150 if (view.getCalcIdParam() != null)
4152 for (CalcIdParam calcIdParam : view.getCalcIdParam())
4154 if (calcIdParam != null)
4156 if (recoverCalcIdParam(calcIdParam, af.viewport))
4161 warn("Couldn't recover parameters for "
4162 + calcIdParam.getCalcId());
4167 af.setMenusFromViewport(af.viewport);
4169 // TODO: we don't need to do this if the viewport is aready visible.
4171 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
4172 * has a 'cdna/protein complement' view, in which case save it in order to
4173 * populate a SplitFrame once all views have been read in.
4175 String complementaryViewId = view.getComplementId();
4176 if (complementaryViewId == null)
4178 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
4180 // recompute any autoannotation
4181 af.alignPanel.updateAnnotation(false, true);
4182 reorderAutoannotation(af, al, autoAlan);
4183 af.alignPanel.alignmentChanged();
4187 splitFrameCandidates.put(view, af);
4192 private ColourSchemeI constructAnnotationColour(
4193 AnnotationColours viewAnnColour, AlignFrame af, Alignment al,
4194 JalviewModelSequence jms, boolean checkGroupAnnColour)
4196 boolean propagateAnnColour = false;
4197 ColourSchemeI cs = null;
4198 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
4199 if (checkGroupAnnColour && al.getGroups() != null
4200 && al.getGroups().size() > 0)
4202 // pre 2.8.1 behaviour
4203 // check to see if we should transfer annotation colours
4204 propagateAnnColour = true;
4205 for (jalview.datamodel.SequenceGroup sg : al.getGroups())
4207 if (sg.cs instanceof AnnotationColourGradient)
4209 propagateAnnColour = false;
4213 // int find annotation
4214 if (annAlignment.getAlignmentAnnotation() != null)
4216 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
4218 if (annAlignment.getAlignmentAnnotation()[i].label
4219 .equals(viewAnnColour.getAnnotation()))
4221 if (annAlignment.getAlignmentAnnotation()[i].getThreshold() == null)
4223 annAlignment.getAlignmentAnnotation()[i]
4224 .setThreshold(new jalview.datamodel.GraphLine(
4225 viewAnnColour.getThreshold(), "Threshold",
4226 java.awt.Color.black)
4231 if (viewAnnColour.getColourScheme().equals("None"))
4233 cs = new AnnotationColourGradient(
4234 annAlignment.getAlignmentAnnotation()[i],
4235 new java.awt.Color(viewAnnColour.getMinColour()),
4236 new java.awt.Color(viewAnnColour.getMaxColour()),
4237 viewAnnColour.getAboveThreshold());
4239 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
4241 cs = new AnnotationColourGradient(
4242 annAlignment.getAlignmentAnnotation()[i],
4243 getUserColourScheme(jms,
4244 viewAnnColour.getColourScheme()),
4245 viewAnnColour.getAboveThreshold());
4249 cs = new AnnotationColourGradient(
4250 annAlignment.getAlignmentAnnotation()[i],
4251 ColourSchemeProperty.getColour(al,
4252 viewAnnColour.getColourScheme()),
4253 viewAnnColour.getAboveThreshold());
4255 if (viewAnnColour.hasPerSequence())
4257 ((AnnotationColourGradient) cs).setSeqAssociated(viewAnnColour
4260 if (viewAnnColour.hasPredefinedColours())
4262 ((AnnotationColourGradient) cs)
4263 .setPredefinedColours(viewAnnColour
4264 .isPredefinedColours());
4266 if (propagateAnnColour && al.getGroups() != null)
4268 // Also use these settings for all the groups
4269 for (int g = 0; g < al.getGroups().size(); g++)
4271 jalview.datamodel.SequenceGroup sg = al.getGroups().get(g);
4279 * if (viewAnnColour.getColourScheme().equals("None" )) { sg.cs =
4280 * new AnnotationColourGradient(
4281 * annAlignment.getAlignmentAnnotation()[i], new
4282 * java.awt.Color(viewAnnColour. getMinColour()), new
4283 * java.awt.Color(viewAnnColour. getMaxColour()),
4284 * viewAnnColour.getAboveThreshold()); } else
4287 sg.cs = new AnnotationColourGradient(
4288 annAlignment.getAlignmentAnnotation()[i], sg.cs,
4289 viewAnnColour.getAboveThreshold());
4290 if (cs instanceof AnnotationColourGradient)
4292 if (viewAnnColour.hasPerSequence())
4294 ((AnnotationColourGradient) cs)
4295 .setSeqAssociated(viewAnnColour.isPerSequence());
4297 if (viewAnnColour.hasPredefinedColours())
4299 ((AnnotationColourGradient) cs)
4300 .setPredefinedColours(viewAnnColour
4301 .isPredefinedColours());
4317 private void reorderAutoannotation(AlignFrame af, Alignment al,
4318 List<JvAnnotRow> autoAlan)
4320 // copy over visualization settings for autocalculated annotation in the
4322 if (al.getAlignmentAnnotation() != null)
4325 * Kludge for magic autoannotation names (see JAL-811)
4327 String[] magicNames = new String[]
4328 { "Consensus", "Quality", "Conservation" };
4329 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
4330 Hashtable<String, JvAnnotRow> visan = new Hashtable<String, JvAnnotRow>();
4331 for (String nm : magicNames)
4333 visan.put(nm, nullAnnot);
4335 for (JvAnnotRow auan : autoAlan)
4337 visan.put(auan.template.label
4338 + (auan.template.getCalcId() == null ? "" : "\t"
4339 + auan.template.getCalcId()), auan);
4341 int hSize = al.getAlignmentAnnotation().length;
4342 List<JvAnnotRow> reorder = new ArrayList<JvAnnotRow>();
4343 // work through any autoCalculated annotation already on the view
4344 // removing it if it should be placed in a different location on the
4345 // annotation panel.
4346 List<String> remains = new ArrayList<String>(visan.keySet());
4347 for (int h = 0; h < hSize; h++)
4349 jalview.datamodel.AlignmentAnnotation jalan = al
4350 .getAlignmentAnnotation()[h];
4351 if (jalan.autoCalculated)
4354 JvAnnotRow valan = visan.get(k = jalan.label);
4355 if (jalan.getCalcId() != null)
4357 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
4362 // delete the auto calculated row from the alignment
4363 al.deleteAnnotation(jalan, false);
4367 if (valan != nullAnnot)
4369 if (jalan != valan.template)
4371 // newly created autoannotation row instance
4372 // so keep a reference to the visible annotation row
4373 // and copy over all relevant attributes
4374 if (valan.template.graphHeight >= 0)
4377 jalan.graphHeight = valan.template.graphHeight;
4379 jalan.visible = valan.template.visible;
4381 reorder.add(new JvAnnotRow(valan.order, jalan));
4386 // Add any (possibly stale) autocalculated rows that were not appended to
4387 // the view during construction
4388 for (String other : remains)
4390 JvAnnotRow othera = visan.get(other);
4391 if (othera != nullAnnot && othera.template.getCalcId() != null
4392 && othera.template.getCalcId().length() > 0)
4394 reorder.add(othera);
4397 // now put the automatic annotation in its correct place
4398 int s = 0, srt[] = new int[reorder.size()];
4399 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
4400 for (JvAnnotRow jvar : reorder)
4403 srt[s++] = jvar.order;
4406 jalview.util.QuickSort.sort(srt, rws);
4407 // and re-insert the annotation at its correct position
4408 for (JvAnnotRow jvar : rws)
4410 al.addAnnotation(jvar.template, jvar.order);
4412 af.alignPanel.adjustAnnotationHeight();
4416 Hashtable skipList = null;
4419 * TODO remove this method
4422 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
4423 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
4424 * throw new Error("Implementation Error. No skipList defined for this
4425 * Jalview2XML instance."); } return (AlignFrame)
4426 * skipList.get(view.getSequenceSetId()); }
4430 * Check if the Jalview view contained in object should be skipped or not.
4433 * @return true if view's sequenceSetId is a key in skipList
4435 private boolean skipViewport(JalviewModel object)
4437 if (skipList == null)
4442 if (skipList.containsKey(id = object.getJalviewModelSequence()
4443 .getViewport()[0].getSequenceSetId()))
4445 if (Cache.log != null && Cache.log.isDebugEnabled())
4447 Cache.log.debug("Skipping seuqence set id " + id);
4454 public void addToSkipList(AlignFrame af)
4456 if (skipList == null)
4458 skipList = new Hashtable();
4460 skipList.put(af.getViewport().getSequenceSetId(), af);
4463 public void clearSkipList()
4465 if (skipList != null)
4472 private void recoverDatasetFor(SequenceSet vamsasSet, Alignment al,
4473 boolean ignoreUnrefed)
4475 jalview.datamodel.Alignment ds = getDatasetFor(vamsasSet.getDatasetId());
4476 Vector dseqs = null;
4479 // create a list of new dataset sequences
4480 dseqs = new Vector();
4482 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
4484 Sequence vamsasSeq = vamsasSet.getSequence(i);
4485 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed);
4487 // create a new dataset
4490 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
4491 dseqs.copyInto(dsseqs);
4492 ds = new jalview.datamodel.Alignment(dsseqs);
4493 debug("Created new dataset " + vamsasSet.getDatasetId()
4494 + " for alignment " + System.identityHashCode(al));
4495 addDatasetRef(vamsasSet.getDatasetId(), ds);
4497 // set the dataset for the newly imported alignment.
4498 if (al.getDataset() == null && !ignoreUnrefed)
4507 * sequence definition to create/merge dataset sequence for
4511 * vector to add new dataset sequence to
4513 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
4514 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed)
4516 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
4518 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
4519 SequenceI dsq = null;
4520 if (sq != null && sq.getDatasetSequence() != null)
4522 dsq = sq.getDatasetSequence();
4524 if (sq == null && ignoreUnrefed)
4528 String sqid = vamsasSeq.getDsseqid();
4531 // need to create or add a new dataset sequence reference to this sequence
4534 dsq = seqRefIds.get(sqid);
4539 // make a new dataset sequence
4540 dsq = sq.createDatasetSequence();
4543 // make up a new dataset reference for this sequence
4544 sqid = seqHash(dsq);
4546 dsq.setVamsasId(uniqueSetSuffix + sqid);
4547 seqRefIds.put(sqid, dsq);
4552 dseqs.addElement(dsq);
4557 ds.addSequence(dsq);
4563 { // make this dataset sequence sq's dataset sequence
4564 sq.setDatasetSequence(dsq);
4565 // and update the current dataset alignment
4570 if (!dseqs.contains(dsq))
4577 if (ds.findIndex(dsq) < 0)
4579 ds.addSequence(dsq);
4586 // TODO: refactor this as a merge dataset sequence function
4587 // now check that sq (the dataset sequence) sequence really is the union of
4588 // all references to it
4589 // boolean pre = sq.getStart() < dsq.getStart();
4590 // boolean post = sq.getEnd() > dsq.getEnd();
4594 // StringBuffer sb = new StringBuffer();
4595 String newres = jalview.analysis.AlignSeq.extractGaps(
4596 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
4597 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
4598 && newres.length() > dsq.getLength())
4600 // Update with the longer sequence.
4604 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
4605 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
4606 * sb.append(newres.substring(newres.length() - sq.getEnd() -
4607 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
4609 dsq.setSequence(newres);
4611 // TODO: merges will never happen if we 'know' we have the real dataset
4612 // sequence - this should be detected when id==dssid
4614 .println("DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
4615 // + (pre ? "prepended" : "") + " "
4616 // + (post ? "appended" : ""));
4621 java.util.Hashtable datasetIds = null;
4623 java.util.IdentityHashMap dataset2Ids = null;
4625 private Alignment getDatasetFor(String datasetId)
4627 if (datasetIds == null)
4629 datasetIds = new Hashtable();
4632 if (datasetIds.containsKey(datasetId))
4634 return (Alignment) datasetIds.get(datasetId);
4639 private void addDatasetRef(String datasetId, Alignment dataset)
4641 if (datasetIds == null)
4643 datasetIds = new Hashtable();
4645 datasetIds.put(datasetId, dataset);
4649 * make a new dataset ID for this jalview dataset alignment
4654 private String getDatasetIdRef(jalview.datamodel.Alignment dataset)
4656 if (dataset.getDataset() != null)
4658 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
4660 String datasetId = makeHashCode(dataset, null);
4661 if (datasetId == null)
4663 // make a new datasetId and record it
4664 if (dataset2Ids == null)
4666 dataset2Ids = new IdentityHashMap();
4670 datasetId = (String) dataset2Ids.get(dataset);
4672 if (datasetId == null)
4674 datasetId = "ds" + dataset2Ids.size() + 1;
4675 dataset2Ids.put(dataset, datasetId);
4681 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
4683 for (int d = 0; d < sequence.getDBRefCount(); d++)
4685 DBRef dr = sequence.getDBRef(d);
4686 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
4687 sequence.getDBRef(d).getSource(), sequence.getDBRef(d)
4688 .getVersion(), sequence.getDBRef(d).getAccessionId());
4689 if (dr.getMapping() != null)
4691 entry.setMap(addMapping(dr.getMapping()));
4693 datasetSequence.addDBRef(entry);
4697 private jalview.datamodel.Mapping addMapping(Mapping m)
4699 SequenceI dsto = null;
4700 // Mapping m = dr.getMapping();
4701 int fr[] = new int[m.getMapListFromCount() * 2];
4702 Enumeration f = m.enumerateMapListFrom();
4703 for (int _i = 0; f.hasMoreElements(); _i += 2)
4705 MapListFrom mf = (MapListFrom) f.nextElement();
4706 fr[_i] = mf.getStart();
4707 fr[_i + 1] = mf.getEnd();
4709 int fto[] = new int[m.getMapListToCount() * 2];
4710 f = m.enumerateMapListTo();
4711 for (int _i = 0; f.hasMoreElements(); _i += 2)
4713 MapListTo mf = (MapListTo) f.nextElement();
4714 fto[_i] = mf.getStart();
4715 fto[_i + 1] = mf.getEnd();
4717 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto,
4718 fr, fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
4719 if (m.getMappingChoice() != null)
4721 MappingChoice mc = m.getMappingChoice();
4722 if (mc.getDseqFor() != null)
4724 String dsfor = "" + mc.getDseqFor();
4725 if (seqRefIds.containsKey(dsfor))
4730 jmap.setTo(seqRefIds.get(dsfor));
4734 frefedSequence.add(new Object[]
4741 * local sequence definition
4743 Sequence ms = mc.getSequence();
4744 SequenceI djs = null;
4745 String sqid = ms.getDsseqid();
4746 if (sqid != null && sqid.length() > 0)
4749 * recover dataset sequence
4751 djs = seqRefIds.get(sqid);
4756 .println("Warning - making up dataset sequence id for DbRef sequence map reference");
4757 sqid = ((Object) ms).toString(); // make up a new hascode for
4758 // undefined dataset sequence hash
4759 // (unlikely to happen)
4765 * make a new dataset sequence and add it to refIds hash
4767 djs = new jalview.datamodel.Sequence(ms.getName(),
4769 djs.setStart(jmap.getMap().getToLowest());
4770 djs.setEnd(jmap.getMap().getToHighest());
4771 djs.setVamsasId(uniqueSetSuffix + sqid);
4773 seqRefIds.put(sqid, djs);
4776 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
4785 public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
4786 boolean keepSeqRefs)
4789 jalview.schemabinding.version2.JalviewModel jm = saveState(ap, null,
4795 jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
4799 uniqueSetSuffix = "";
4800 jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
4805 if (this.frefedSequence == null)
4807 frefedSequence = new Vector();
4810 viewportsAdded.clear();
4812 AlignFrame af = loadFromObject(jm, null, false, null);
4813 af.alignPanels.clear();
4814 af.closeMenuItem_actionPerformed(true);
4817 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
4818 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
4819 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
4820 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
4821 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
4824 return af.alignPanel;
4828 * flag indicating if hashtables should be cleared on finalization TODO this
4829 * flag may not be necessary
4831 private final boolean _cleartables = true;
4833 private Hashtable jvids2vobj;
4838 * @see java.lang.Object#finalize()
4841 protected void finalize() throws Throwable
4843 // really make sure we have no buried refs left.
4848 this.seqRefIds = null;
4849 this.seqsToIds = null;
4853 private void warn(String msg)
4858 private void warn(String msg, Exception e)
4860 if (Cache.log != null)
4864 Cache.log.warn(msg, e);
4868 Cache.log.warn(msg);
4873 System.err.println("Warning: " + msg);
4876 e.printStackTrace();
4881 private void debug(String string)
4883 debug(string, null);
4886 private void debug(String msg, Exception e)
4888 if (Cache.log != null)
4892 Cache.log.debug(msg, e);
4896 Cache.log.debug(msg);
4901 System.err.println("Warning: " + msg);
4904 e.printStackTrace();
4910 * set the object to ID mapping tables used to write/recover objects and XML
4911 * ID strings for the jalview project. If external tables are provided then
4912 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
4913 * object goes out of scope. - also populates the datasetIds hashtable with
4914 * alignment objects containing dataset sequences
4917 * Map from ID strings to jalview datamodel
4919 * Map from jalview datamodel to ID strings
4923 public void setObjectMappingTables(Hashtable vobj2jv,
4924 IdentityHashMap jv2vobj)
4926 this.jv2vobj = jv2vobj;
4927 this.vobj2jv = vobj2jv;
4928 Iterator ds = jv2vobj.keySet().iterator();
4930 while (ds.hasNext())
4932 Object jvobj = ds.next();
4933 id = jv2vobj.get(jvobj).toString();
4934 if (jvobj instanceof jalview.datamodel.Alignment)
4936 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
4938 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
4941 else if (jvobj instanceof jalview.datamodel.Sequence)
4943 // register sequence object so the XML parser can recover it.
4944 if (seqRefIds == null)
4946 seqRefIds = new HashMap<String, SequenceI>();
4948 if (seqsToIds == null)
4950 seqsToIds = new IdentityHashMap<SequenceI, String>();
4952 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
4953 seqsToIds.put((SequenceI) jvobj, id);
4955 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
4958 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
4959 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
4960 if (jvann.annotationId == null)
4962 jvann.annotationId = anid;
4964 if (!jvann.annotationId.equals(anid))
4966 // TODO verify that this is the correct behaviour
4967 this.warn("Overriding Annotation ID for " + anid
4968 + " from different id : " + jvann.annotationId);
4969 jvann.annotationId = anid;
4972 else if (jvobj instanceof String)
4974 if (jvids2vobj == null)
4976 jvids2vobj = new Hashtable();
4977 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
4982 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
4988 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
4989 * objects created from the project archive. If string is null (default for
4990 * construction) then suffix will be set automatically.
4994 public void setUniqueSetSuffix(String string)
4996 uniqueSetSuffix = string;
5001 * uses skipList2 as the skipList for skipping views on sequence sets
5002 * associated with keys in the skipList
5006 public void setSkipList(Hashtable skipList2)
5008 skipList = skipList2;
5012 * Reads the jar entry of given name and returns its contents, or null if the
5013 * entry is not found.
5016 * @param jarEntryName
5019 protected String readJarEntry(jarInputStreamProvider jprovider,
5020 String jarEntryName)
5022 String result = null;
5023 BufferedReader in = null;
5028 * Reopen the jar input stream and traverse its entries to find a matching
5031 JarInputStream jin = jprovider.getJarInputStream();
5032 JarEntry entry = null;
5035 entry = jin.getNextJarEntry();
5036 } while (entry != null && !entry.getName().equals(jarEntryName));
5040 StringBuilder out = new StringBuilder(256);
5041 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
5044 while ((data = in.readLine()) != null)
5048 result = out.toString();
5052 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
5054 } catch (Exception ex)
5056 ex.printStackTrace();
5064 } catch (IOException e)