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 jalview.api.ViewStyleI;
24 import jalview.api.structures.JalviewStructureDisplayI;
25 import jalview.bin.Cache;
26 import jalview.datamodel.AlignedCodonFrame;
27 import jalview.datamodel.Alignment;
28 import jalview.datamodel.AlignmentAnnotation;
29 import jalview.datamodel.AlignmentI;
30 import jalview.datamodel.PDBEntry;
31 import jalview.datamodel.RnaViewerModel;
32 import jalview.datamodel.SequenceGroup;
33 import jalview.datamodel.SequenceI;
34 import jalview.datamodel.StructureViewerModel;
35 import jalview.datamodel.StructureViewerModel.StructureData;
36 import jalview.ext.varna.RnaModel;
37 import jalview.gui.StructureViewer.ViewerType;
38 import jalview.schemabinding.version2.AlcodMap;
39 import jalview.schemabinding.version2.AlcodonFrame;
40 import jalview.schemabinding.version2.Annotation;
41 import jalview.schemabinding.version2.AnnotationColours;
42 import jalview.schemabinding.version2.AnnotationElement;
43 import jalview.schemabinding.version2.CalcIdParam;
44 import jalview.schemabinding.version2.DBRef;
45 import jalview.schemabinding.version2.Features;
46 import jalview.schemabinding.version2.Group;
47 import jalview.schemabinding.version2.HiddenColumns;
48 import jalview.schemabinding.version2.JGroup;
49 import jalview.schemabinding.version2.JSeq;
50 import jalview.schemabinding.version2.JalviewModel;
51 import jalview.schemabinding.version2.JalviewModelSequence;
52 import jalview.schemabinding.version2.MapListFrom;
53 import jalview.schemabinding.version2.MapListTo;
54 import jalview.schemabinding.version2.Mapping;
55 import jalview.schemabinding.version2.MappingChoice;
56 import jalview.schemabinding.version2.OtherData;
57 import jalview.schemabinding.version2.PdbentryItem;
58 import jalview.schemabinding.version2.Pdbids;
59 import jalview.schemabinding.version2.Property;
60 import jalview.schemabinding.version2.RnaViewer;
61 import jalview.schemabinding.version2.SecondaryStructure;
62 import jalview.schemabinding.version2.Sequence;
63 import jalview.schemabinding.version2.SequenceSet;
64 import jalview.schemabinding.version2.SequenceSetProperties;
65 import jalview.schemabinding.version2.Setting;
66 import jalview.schemabinding.version2.StructureState;
67 import jalview.schemabinding.version2.ThresholdLine;
68 import jalview.schemabinding.version2.Tree;
69 import jalview.schemabinding.version2.UserColours;
70 import jalview.schemabinding.version2.Viewport;
71 import jalview.schemes.AnnotationColourGradient;
72 import jalview.schemes.ColourSchemeI;
73 import jalview.schemes.ColourSchemeProperty;
74 import jalview.schemes.GraduatedColor;
75 import jalview.schemes.ResidueColourScheme;
76 import jalview.schemes.ResidueProperties;
77 import jalview.schemes.UserColourScheme;
78 import jalview.structure.StructureSelectionManager;
79 import jalview.structures.models.AAStructureBindingModel;
80 import jalview.util.MessageManager;
81 import jalview.util.Platform;
82 import jalview.util.StringUtils;
83 import jalview.util.jarInputStreamProvider;
84 import jalview.viewmodel.AlignmentViewport;
85 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
86 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
87 import jalview.ws.jws2.Jws2Discoverer;
88 import jalview.ws.jws2.dm.AAConSettings;
89 import jalview.ws.jws2.jabaws2.Jws2Instance;
90 import jalview.ws.params.ArgumentI;
91 import jalview.ws.params.AutoCalcSetting;
92 import jalview.ws.params.WsParamSetI;
94 import java.awt.Color;
95 import java.awt.Rectangle;
96 import java.io.BufferedReader;
97 import java.io.DataInputStream;
98 import java.io.DataOutputStream;
100 import java.io.FileInputStream;
101 import java.io.FileOutputStream;
102 import java.io.IOException;
103 import java.io.InputStreamReader;
104 import java.io.OutputStreamWriter;
105 import java.io.PrintWriter;
106 import java.lang.reflect.InvocationTargetException;
107 import java.net.MalformedURLException;
109 import java.util.ArrayList;
110 import java.util.Enumeration;
111 import java.util.HashMap;
112 import java.util.HashSet;
113 import java.util.Hashtable;
114 import java.util.IdentityHashMap;
115 import java.util.Iterator;
116 import java.util.LinkedHashMap;
117 import java.util.List;
118 import java.util.Map;
119 import java.util.Map.Entry;
120 import java.util.Set;
121 import java.util.Vector;
122 import java.util.jar.JarEntry;
123 import java.util.jar.JarInputStream;
124 import java.util.jar.JarOutputStream;
126 import javax.swing.JInternalFrame;
127 import javax.swing.JOptionPane;
128 import javax.swing.SwingUtilities;
130 import org.exolab.castor.xml.Marshaller;
131 import org.exolab.castor.xml.Unmarshaller;
134 * Write out the current jalview desktop state as a Jalview XML stream.
136 * Note: the vamsas objects referred to here are primitive versions of the
137 * VAMSAS project schema elements - they are not the same and most likely never
141 * @version $Revision: 1.134 $
143 public class Jalview2XML
145 private static final String VIEWER_PREFIX = "viewer_";
147 private static final String RNA_PREFIX = "rna_";
149 private static final String UTF_8 = "UTF-8";
151 // use this with nextCounter() to make unique names for entities
152 private int counter = 0;
155 * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
156 * of sequence objects are created.
158 IdentityHashMap<SequenceI, String> seqsToIds = null;
161 * jalview XML Sequence ID to jalview sequence object reference (both dataset
162 * and alignment sequences. Populated as XML reps of sequence objects are
165 Map<String, SequenceI> seqRefIds = null;
167 Vector<Object[]> frefedSequence = null;
169 boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
172 * Map of reconstructed AlignFrame objects that appear to have come from
173 * SplitFrame objects (have a dna/protein complement view).
175 private Map<Viewport, AlignFrame> splitFrameCandidates = new HashMap<Viewport, AlignFrame>();
178 * Map from displayed rna structure models to their saved session state jar
181 private Map<RnaModel, String> rnaSessions = new HashMap<RnaModel, String>();
184 * create/return unique hash string for sq
187 * @return new or existing unique string for sq
189 String seqHash(SequenceI sq)
191 if (seqsToIds == null)
195 if (seqsToIds.containsKey(sq))
197 return seqsToIds.get(sq);
201 // create sequential key
202 String key = "sq" + (seqsToIds.size() + 1);
203 key = makeHashCode(sq, key); // check we don't have an external reference
205 seqsToIds.put(sq, key);
214 if (seqRefIds != null)
218 if (seqsToIds != null)
228 warn("clearSeqRefs called when _cleartables was not set. Doing nothing.");
229 // seqRefIds = new Hashtable();
230 // seqsToIds = new IdentityHashMap();
236 if (seqsToIds == null)
238 seqsToIds = new IdentityHashMap<SequenceI, String>();
240 if (seqRefIds == null)
242 seqRefIds = new HashMap<String, SequenceI>();
250 public Jalview2XML(boolean raiseGUI)
252 this.raiseGUI = raiseGUI;
255 public void resolveFrefedSequences()
257 if (frefedSequence.size() > 0)
259 int r = 0, rSize = frefedSequence.size();
262 Object[] ref = frefedSequence.elementAt(r);
265 String sref = (String) ref[0];
266 if (seqRefIds.containsKey(sref))
268 if (ref[1] instanceof jalview.datamodel.Mapping)
270 SequenceI seq = seqRefIds.get(sref);
271 while (seq.getDatasetSequence() != null)
273 seq = seq.getDatasetSequence();
275 ((jalview.datamodel.Mapping) ref[1]).setTo(seq);
279 if (ref[1] instanceof jalview.datamodel.AlignedCodonFrame)
281 SequenceI seq = seqRefIds.get(sref);
282 while (seq.getDatasetSequence() != null)
284 seq = seq.getDatasetSequence();
287 && ref[2] instanceof jalview.datamodel.Mapping)
289 jalview.datamodel.Mapping mp = (jalview.datamodel.Mapping) ref[2];
290 ((jalview.datamodel.AlignedCodonFrame) ref[1]).addMap(
291 seq, mp.getTo(), mp.getMap());
296 .println("IMPLEMENTATION ERROR: Unimplemented forward sequence references for AlcodonFrames involving "
297 + ref[2].getClass() + " type objects.");
303 .println("IMPLEMENTATION ERROR: Unimplemented forward sequence references for "
304 + ref[1].getClass() + " type objects.");
307 frefedSequence.remove(r);
313 .println("IMPLEMENTATION WARNING: Unresolved forward reference for hash string "
315 + " with objecttype "
316 + ref[1].getClass());
323 frefedSequence.remove(r);
331 * This maintains a map of viewports, the key being the seqSetId. Important to
332 * set historyItem and redoList for multiple views
334 Map<String, AlignViewport> viewportsAdded = new HashMap<String, AlignViewport>();
336 Map<String, AlignmentAnnotation> annotationIds = new HashMap<String, AlignmentAnnotation>();
338 String uniqueSetSuffix = "";
341 * List of pdbfiles added to Jar
343 List<String> pdbfiles = null;
345 // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
346 public void saveState(File statefile)
348 FileOutputStream fos = null;
351 fos = new FileOutputStream(statefile);
352 JarOutputStream jout = new JarOutputStream(fos);
355 } catch (Exception e)
357 // TODO: inform user of the problem - they need to know if their data was
359 if (errorMessage == null)
361 errorMessage = "Couldn't write Jalview Archive to output file '"
362 + statefile + "' - See console error log for details";
366 errorMessage += "(output file was '" + statefile + "')";
376 } catch (IOException e)
386 * Writes a jalview project archive to the given Jar output stream.
390 public void saveState(JarOutputStream jout)
392 AlignFrame[] frames = Desktop.getAlignFrames();
399 Hashtable<String, AlignFrame> dsses = new Hashtable<String, AlignFrame>();
402 * ensure cached data is clear before starting
404 // todo tidy up seqRefIds, seqsToIds initialisation / reset
406 splitFrameCandidates.clear();
411 // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
412 // //////////////////////////////////////////////////
414 List<String> shortNames = new ArrayList<String>();
415 List<String> viewIds = new ArrayList<String>();
418 for (int i = frames.length - 1; i > -1; i--)
420 AlignFrame af = frames[i];
424 .containsKey(af.getViewport().getSequenceSetId()))
429 String shortName = makeFilename(af, shortNames);
431 int ap, apSize = af.alignPanels.size();
433 for (ap = 0; ap < apSize; ap++)
435 AlignmentPanel apanel = af.alignPanels.get(ap);
436 String fileName = apSize == 1 ? shortName : ap + shortName;
437 if (!fileName.endsWith(".xml"))
439 fileName = fileName + ".xml";
442 saveState(apanel, fileName, jout, viewIds);
444 String dssid = getDatasetIdRef(af.getViewport().getAlignment()
446 if (!dsses.containsKey(dssid))
448 dsses.put(dssid, af);
453 writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix,
459 } catch (Exception foo)
464 } catch (Exception ex)
466 // TODO: inform user of the problem - they need to know if their data was
468 if (errorMessage == null)
470 errorMessage = "Couldn't write Jalview Archive - see error output for details";
472 ex.printStackTrace();
477 * Generates a distinct file name, based on the title of the AlignFrame, by
478 * appending _n for increasing n until an unused name is generated. The new
479 * name (without its extension) is added to the list.
483 * @return the generated name, with .xml extension
485 protected String makeFilename(AlignFrame af, List<String> namesUsed)
487 String shortName = af.getTitle();
489 if (shortName.indexOf(File.separatorChar) > -1)
491 shortName = shortName.substring(shortName
492 .lastIndexOf(File.separatorChar) + 1);
497 while (namesUsed.contains(shortName))
499 if (shortName.endsWith("_" + (count - 1)))
501 shortName = shortName.substring(0, shortName.lastIndexOf("_"));
504 shortName = shortName.concat("_" + count);
508 namesUsed.add(shortName);
510 if (!shortName.endsWith(".xml"))
512 shortName = shortName + ".xml";
517 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
518 public boolean saveAlignment(AlignFrame af, String jarFile,
524 int apSize = af.alignPanels.size();
525 FileOutputStream fos = new FileOutputStream(jarFile);
526 JarOutputStream jout = new JarOutputStream(fos);
527 Hashtable<String, AlignFrame> dsses = new Hashtable<String, AlignFrame>();
528 List<String> viewIds = new ArrayList<String>();
530 for (AlignmentPanel apanel : af.alignPanels)
532 String jfileName = apSize == 1 ? fileName : fileName + ap;
534 if (!jfileName.endsWith(".xml"))
536 jfileName = jfileName + ".xml";
538 saveState(apanel, jfileName, jout, viewIds);
539 String dssid = getDatasetIdRef(af.getViewport().getAlignment()
541 if (!dsses.containsKey(dssid))
543 dsses.put(dssid, af);
546 writeDatasetFor(dsses, fileName, jout);
550 } catch (Exception foo)
556 } catch (Exception ex)
558 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
559 ex.printStackTrace();
564 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
565 String fileName, JarOutputStream jout)
568 for (String dssids : dsses.keySet())
570 AlignFrame _af = dsses.get(dssids);
571 String jfileName = fileName + " Dataset for " + _af.getTitle();
572 if (!jfileName.endsWith(".xml"))
574 jfileName = jfileName + ".xml";
576 saveState(_af.alignPanel, jfileName, true, jout, null);
581 * create a JalviewModel from an alignment view and marshall it to a
585 * panel to create jalview model for
587 * name of alignment panel written to output stream
594 public JalviewModel saveState(AlignmentPanel ap, String fileName,
595 JarOutputStream jout, List<String> viewIds)
597 return saveState(ap, fileName, false, jout, viewIds);
601 * create a JalviewModel from an alignment view and marshall it to a
605 * panel to create jalview model for
607 * name of alignment panel written to output stream
609 * when true, only write the dataset for the alignment, not the data
610 * associated with the view.
616 public JalviewModel saveState(AlignmentPanel ap, String fileName,
617 boolean storeDS, JarOutputStream jout, List<String> viewIds)
621 viewIds = new ArrayList<String>();
626 List<UserColourScheme> userColours = new ArrayList<UserColourScheme>();
628 AlignViewport av = ap.av;
630 JalviewModel object = new JalviewModel();
631 object.setVamsasModel(new jalview.schemabinding.version2.VamsasModel());
633 object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
634 object.setVersion(jalview.bin.Cache.getDefault("VERSION",
635 "Development Build"));
638 * rjal is full height alignment, jal is actual alignment with full metadata
639 * but excludes hidden sequences.
641 jalview.datamodel.AlignmentI rjal = av.getAlignment(), jal = rjal;
643 if (av.hasHiddenRows())
645 rjal = jal.getHiddenSequences().getFullAlignment();
648 SequenceSet vamsasSet = new SequenceSet();
650 JalviewModelSequence jms = new JalviewModelSequence();
652 vamsasSet.setGapChar(jal.getGapCharacter() + "");
654 if (jal.getDataset() != null)
656 // dataset id is the dataset's hashcode
657 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
660 // switch jal and the dataset
661 jal = jal.getDataset();
665 if (jal.getProperties() != null)
667 Enumeration en = jal.getProperties().keys();
668 while (en.hasMoreElements())
670 String key = en.nextElement().toString();
671 SequenceSetProperties ssp = new SequenceSetProperties();
673 ssp.setValue(jal.getProperties().get(key).toString());
674 vamsasSet.addSequenceSetProperties(ssp);
679 Set<String> calcIdSet = new HashSet<String>();
682 for (int i = 0; i < rjal.getHeight(); i++)
684 final SequenceI jds = rjal.getSequenceAt(i);
685 final SequenceI jdatasq = jds.getDatasetSequence() == null ? jds
686 : jds.getDatasetSequence();
687 String id = seqHash(jds);
689 if (seqRefIds.get(id) != null)
691 // This happens for two reasons: 1. multiple views are being serialised.
692 // 2. the hashCode has collided with another sequence's code. This DOES
693 // HAPPEN! (PF00072.15.stk does this)
694 // JBPNote: Uncomment to debug writing out of files that do not read
695 // back in due to ArrayOutOfBoundExceptions.
696 // System.err.println("vamsasSeq backref: "+id+"");
697 // System.err.println(jds.getName()+"
698 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
699 // System.err.println("Hashcode: "+seqHash(jds));
700 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
701 // System.err.println(rsq.getName()+"
702 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
703 // System.err.println("Hashcode: "+seqHash(rsq));
707 vamsasSeq = createVamsasSequence(id, jds);
708 vamsasSet.addSequence(vamsasSeq);
709 seqRefIds.put(id, jds);
713 jseq.setStart(jds.getStart());
714 jseq.setEnd(jds.getEnd());
715 jseq.setColour(av.getSequenceColour(jds).getRGB());
717 jseq.setId(id); // jseq id should be a string not a number
720 // Store any sequences this sequence represents
721 if (av.hasHiddenRows())
723 // use rjal, contains the full height alignment
724 jseq.setHidden(av.getAlignment().getHiddenSequences()
727 if (av.isHiddenRepSequence(rjal.getSequenceAt(i)))
729 jalview.datamodel.SequenceI[] reps = av
730 .getRepresentedSequences(rjal.getSequenceAt(i))
731 .getSequencesInOrder(rjal);
733 for (int h = 0; h < reps.length; h++)
735 if (reps[h] != rjal.getSequenceAt(i))
737 jseq.addHiddenSequences(rjal.findIndex(reps[h]));
744 // TODO: omit sequence features from each alignment view's XML dump if we
745 // are storing dataset
746 if (jds.getSequenceFeatures() != null)
748 jalview.datamodel.SequenceFeature[] sf = jds.getSequenceFeatures();
750 while (index < sf.length)
752 Features features = new Features();
754 features.setBegin(sf[index].getBegin());
755 features.setEnd(sf[index].getEnd());
756 features.setDescription(sf[index].getDescription());
757 features.setType(sf[index].getType());
758 features.setFeatureGroup(sf[index].getFeatureGroup());
759 features.setScore(sf[index].getScore());
760 if (sf[index].links != null)
762 for (int l = 0; l < sf[index].links.size(); l++)
764 OtherData keyValue = new OtherData();
765 keyValue.setKey("LINK_" + l);
766 keyValue.setValue(sf[index].links.elementAt(l).toString());
767 features.addOtherData(keyValue);
770 if (sf[index].otherDetails != null)
773 Iterator<String> keys = sf[index].otherDetails.keySet()
775 while (keys.hasNext())
778 OtherData keyValue = new OtherData();
779 keyValue.setKey(key);
780 keyValue.setValue(sf[index].otherDetails.get(key).toString());
781 features.addOtherData(keyValue);
785 jseq.addFeatures(features);
790 if (jdatasq.getAllPDBEntries() != null)
792 Enumeration en = jdatasq.getAllPDBEntries().elements();
793 while (en.hasMoreElements())
795 Pdbids pdb = new Pdbids();
796 jalview.datamodel.PDBEntry entry = (jalview.datamodel.PDBEntry) en
799 String pdbId = entry.getId();
801 pdb.setType(entry.getType());
804 * Store any structure views associated with this sequence. This
805 * section copes with duplicate entries in the project, so a dataset
806 * only view *should* be coped with sensibly.
808 // This must have been loaded, is it still visible?
809 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
810 String matchedFile = null;
811 for (int f = frames.length - 1; f > -1; f--)
813 if (frames[f] instanceof StructureViewerBase)
815 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
816 matchedFile = saveStructureState(ap, jds, pdb, entry,
817 viewIds, matchedFile, viewFrame);
819 * Only store each structure viewer's state once in the project
820 * jar. First time through only (storeDS==false)
822 String viewId = viewFrame.getViewId();
823 if (!storeDS && !viewIds.contains(viewId))
828 String viewerState = viewFrame.getStateInfo();
829 writeJarEntry(jout, getViewerJarEntryName(viewId),
830 viewerState.getBytes());
831 } catch (IOException e)
833 System.err.println("Error saving viewer state: "
840 if (matchedFile != null || entry.getFile() != null)
842 if (entry.getFile() != null)
845 matchedFile = entry.getFile();
847 pdb.setFile(matchedFile); // entry.getFile());
848 if (pdbfiles == null)
850 pdbfiles = new ArrayList<String>();
853 if (!pdbfiles.contains(pdbId))
856 copyFileToJar(jout, matchedFile, pdbId);
860 if (entry.getProperty() != null && !entry.getProperty().isEmpty())
862 PdbentryItem item = new PdbentryItem();
863 Hashtable properties = entry.getProperty();
864 Enumeration en2 = properties.keys();
865 while (en2.hasMoreElements())
867 Property prop = new Property();
868 String key = en2.nextElement().toString();
870 prop.setValue(properties.get(key).toString());
871 item.addProperty(prop);
873 pdb.addPdbentryItem(item);
880 saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
885 if (!storeDS && av.hasHiddenRows())
887 jal = av.getAlignment();
890 if (jal.getCodonFrames() != null)
892 List<AlignedCodonFrame> jac = jal.getCodonFrames();
893 for (AlignedCodonFrame acf : jac)
895 AlcodonFrame alc = new AlcodonFrame();
896 vamsasSet.addAlcodonFrame(alc);
897 if (acf.getProtMappings() != null
898 && acf.getProtMappings().length > 0)
900 SequenceI[] dnas = acf.getdnaSeqs();
901 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
902 for (int m = 0; m < pmaps.length; m++)
904 AlcodMap alcmap = new AlcodMap();
905 alcmap.setDnasq(seqHash(dnas[m]));
906 alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
908 alc.addAlcodMap(alcmap);
911 // TODO: delete this ? dead code from 2.8.3->2.9 ?
913 // AlcodonFrame alc = new AlcodonFrame();
914 // vamsasSet.addAlcodonFrame(alc);
915 // for (int p = 0; p < acf.aaWidth; p++)
917 // Alcodon cmap = new Alcodon();
918 // if (acf.codons[p] != null)
920 // // Null codons indicate a gapped column in the translated peptide
922 // cmap.setPos1(acf.codons[p][0]);
923 // cmap.setPos2(acf.codons[p][1]);
924 // cmap.setPos3(acf.codons[p][2]);
926 // alc.addAlcodon(cmap);
928 // if (acf.getProtMappings() != null
929 // && acf.getProtMappings().length > 0)
931 // SequenceI[] dnas = acf.getdnaSeqs();
932 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
933 // for (int m = 0; m < pmaps.length; m++)
935 // AlcodMap alcmap = new AlcodMap();
936 // alcmap.setDnasq(seqHash(dnas[m]));
937 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
939 // alc.addAlcodMap(alcmap);
946 // /////////////////////////////////
947 if (!storeDS && av.currentTree != null)
949 // FIND ANY ASSOCIATED TREES
950 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
951 if (Desktop.desktop != null)
953 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
955 for (int t = 0; t < frames.length; t++)
957 if (frames[t] instanceof TreePanel)
959 TreePanel tp = (TreePanel) frames[t];
961 if (tp.treeCanvas.av.getAlignment() == jal)
963 Tree tree = new Tree();
964 tree.setTitle(tp.getTitle());
965 tree.setCurrentTree((av.currentTree == tp.getTree()));
966 tree.setNewick(tp.getTree().toString());
967 tree.setThreshold(tp.treeCanvas.threshold);
969 tree.setFitToWindow(tp.fitToWindow.getState());
970 tree.setFontName(tp.getTreeFont().getName());
971 tree.setFontSize(tp.getTreeFont().getSize());
972 tree.setFontStyle(tp.getTreeFont().getStyle());
973 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
975 tree.setShowBootstrap(tp.bootstrapMenu.getState());
976 tree.setShowDistances(tp.distanceMenu.getState());
978 tree.setHeight(tp.getHeight());
979 tree.setWidth(tp.getWidth());
980 tree.setXpos(tp.getX());
981 tree.setYpos(tp.getY());
982 tree.setId(makeHashCode(tp, null));
992 * store forward refs from an annotationRow to any groups
994 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<SequenceGroup, String>();
997 for (SequenceI sq : jal.getSequences())
999 // Store annotation on dataset sequences only
1000 AlignmentAnnotation[] aa = sq.getAnnotation();
1001 if (aa != null && aa.length > 0)
1003 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1010 if (jal.getAlignmentAnnotation() != null)
1012 // Store the annotation shown on the alignment.
1013 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1014 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1019 if (jal.getGroups() != null)
1021 JGroup[] groups = new JGroup[jal.getGroups().size()];
1023 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1025 JGroup jGroup = new JGroup();
1026 groups[++i] = jGroup;
1028 jGroup.setStart(sg.getStartRes());
1029 jGroup.setEnd(sg.getEndRes());
1030 jGroup.setName(sg.getName());
1031 if (groupRefs.containsKey(sg))
1033 // group has references so set its ID field
1034 jGroup.setId(groupRefs.get(sg));
1038 if (sg.cs.conservationApplied())
1040 jGroup.setConsThreshold(sg.cs.getConservationInc());
1042 if (sg.cs instanceof jalview.schemes.UserColourScheme)
1044 jGroup.setColour(setUserColourScheme(sg.cs, userColours, jms));
1048 jGroup.setColour(ColourSchemeProperty.getColourName(sg.cs));
1051 else if (sg.cs instanceof jalview.schemes.AnnotationColourGradient)
1053 jGroup.setColour("AnnotationColourGradient");
1054 jGroup.setAnnotationColours(constructAnnotationColours(
1055 (jalview.schemes.AnnotationColourGradient) sg.cs,
1058 else if (sg.cs instanceof jalview.schemes.UserColourScheme)
1060 jGroup.setColour(setUserColourScheme(sg.cs, userColours, jms));
1064 jGroup.setColour(ColourSchemeProperty.getColourName(sg.cs));
1067 jGroup.setPidThreshold(sg.cs.getThreshold());
1070 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1071 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1072 jGroup.setDisplayText(sg.getDisplayText());
1073 jGroup.setColourText(sg.getColourText());
1074 jGroup.setTextCol1(sg.textColour.getRGB());
1075 jGroup.setTextCol2(sg.textColour2.getRGB());
1076 jGroup.setTextColThreshold(sg.thresholdTextColour);
1077 jGroup.setShowUnconserved(sg.getShowNonconserved());
1078 jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1079 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1080 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1081 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1082 for (SequenceI seq : sg.getSequences())
1084 jGroup.addSeq(seqHash(seq));
1088 jms.setJGroup(groups);
1092 // /////////SAVE VIEWPORT
1093 Viewport view = new Viewport();
1094 view.setTitle(ap.alignFrame.getTitle());
1095 view.setSequenceSetId(makeHashCode(av.getSequenceSetId(),
1096 av.getSequenceSetId()));
1097 view.setId(av.getViewId());
1098 if (av.getCodingComplement() != null)
1100 view.setComplementId(av.getCodingComplement().getViewId());
1102 view.setViewName(av.viewName);
1103 view.setGatheredViews(av.isGatherViewsHere());
1105 Rectangle size = ap.av.getExplodedGeometry();
1106 Rectangle position = size;
1109 size = ap.alignFrame.getBounds();
1110 if (av.getCodingComplement() != null)
1112 position = ((SplitFrame) ap.alignFrame.getSplitViewContainer())
1120 view.setXpos(position.x);
1121 view.setYpos(position.y);
1123 view.setWidth(size.width);
1124 view.setHeight(size.height);
1126 view.setStartRes(av.startRes);
1127 view.setStartSeq(av.startSeq);
1129 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1131 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1134 else if (av.getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1136 AnnotationColours ac = constructAnnotationColours(
1137 (jalview.schemes.AnnotationColourGradient) av
1138 .getGlobalColourScheme(),
1141 view.setAnnotationColours(ac);
1142 view.setBgColour("AnnotationColourGradient");
1146 view.setBgColour(ColourSchemeProperty.getColourName(av
1147 .getGlobalColourScheme()));
1150 ColourSchemeI cs = av.getGlobalColourScheme();
1154 if (cs.conservationApplied())
1156 view.setConsThreshold(cs.getConservationInc());
1157 if (cs instanceof jalview.schemes.UserColourScheme)
1159 view.setBgColour(setUserColourScheme(cs, userColours, jms));
1163 if (cs instanceof ResidueColourScheme)
1165 view.setPidThreshold(cs.getThreshold());
1169 view.setConservationSelected(av.getConservationSelected());
1170 view.setPidSelected(av.getAbovePIDThreshold());
1171 view.setFontName(av.font.getName());
1172 view.setFontSize(av.font.getSize());
1173 view.setFontStyle(av.font.getStyle());
1174 view.setScaleProteinAsCdna(av.getViewStyle().isScaleProteinAsCdna());
1175 view.setRenderGaps(av.isRenderGaps());
1176 view.setShowAnnotation(av.isShowAnnotation());
1177 view.setShowBoxes(av.getShowBoxes());
1178 view.setShowColourText(av.getColourText());
1179 view.setShowFullId(av.getShowJVSuffix());
1180 view.setRightAlignIds(av.isRightAlignIds());
1181 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1182 view.setShowText(av.getShowText());
1183 view.setShowUnconserved(av.getShowUnconserved());
1184 view.setWrapAlignment(av.getWrapAlignment());
1185 view.setTextCol1(av.getTextColour().getRGB());
1186 view.setTextCol2(av.getTextColour2().getRGB());
1187 view.setTextColThreshold(av.getThresholdTextColour());
1188 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1189 view.setShowSequenceLogo(av.isShowSequenceLogo());
1190 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1191 view.setShowGroupConsensus(av.isShowGroupConsensus());
1192 view.setShowGroupConservation(av.isShowGroupConservation());
1193 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1194 view.setShowDbRefTooltip(av.isShowDBRefs());
1195 view.setFollowHighlight(av.isFollowHighlight());
1196 view.setFollowSelection(av.followSelection);
1197 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1198 if (av.getFeaturesDisplayed() != null)
1200 jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
1202 String[] renderOrder = ap.getSeqPanel().seqCanvas
1203 .getFeatureRenderer().getRenderOrder()
1204 .toArray(new String[0]);
1206 Vector<String> settingsAdded = new Vector<String>();
1207 Object gstyle = null;
1208 GraduatedColor gcol = null;
1209 if (renderOrder != null)
1211 for (String featureType : renderOrder)
1213 gstyle = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1214 .getFeatureStyle(featureType);
1215 Setting setting = new Setting();
1216 setting.setType(featureType);
1217 if (gstyle instanceof GraduatedColor)
1219 gcol = (GraduatedColor) gstyle;
1220 setting.setColour(gcol.getMaxColor().getRGB());
1221 setting.setMincolour(gcol.getMinColor().getRGB());
1222 setting.setMin(gcol.getMin());
1223 setting.setMax(gcol.getMax());
1224 setting.setColourByLabel(gcol.isColourByLabel());
1225 setting.setAutoScale(gcol.isAutoScale());
1226 setting.setThreshold(gcol.getThresh());
1227 setting.setThreshstate(gcol.getThreshType());
1231 setting.setColour(((Color) gstyle).getRGB());
1234 setting.setDisplay(av.getFeaturesDisplayed().isVisible(
1236 float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1237 .getOrder(featureType);
1240 setting.setOrder(rorder);
1242 fs.addSetting(setting);
1243 settingsAdded.addElement(featureType);
1247 // is groups actually supposed to be a map here ?
1248 Iterator<String> en = ap.getSeqPanel().seqCanvas
1249 .getFeatureRenderer()
1250 .getFeatureGroups().iterator();
1251 Vector<String> groupsAdded = new Vector<String>();
1252 while (en.hasNext())
1254 String grp = en.next();
1255 if (groupsAdded.contains(grp))
1259 Group g = new Group();
1261 g.setDisplay(((Boolean) ap.getSeqPanel().seqCanvas
1262 .getFeatureRenderer().checkGroupVisibility(grp, false))
1265 groupsAdded.addElement(grp);
1267 jms.setFeatureSettings(fs);
1271 if (av.hasHiddenColumns())
1273 if (av.getColumnSelection() == null
1274 || av.getColumnSelection().getHiddenColumns() == null)
1276 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1280 for (int c = 0; c < av.getColumnSelection().getHiddenColumns()
1283 int[] region = av.getColumnSelection().getHiddenColumns()
1285 HiddenColumns hc = new HiddenColumns();
1286 hc.setStart(region[0]);
1287 hc.setEnd(region[1]);
1288 view.addHiddenColumns(hc);
1292 if (calcIdSet.size() > 0)
1294 for (String calcId : calcIdSet)
1296 if (calcId.trim().length() > 0)
1298 CalcIdParam cidp = createCalcIdParam(calcId, av);
1299 // Some calcIds have no parameters.
1302 view.addCalcIdParam(cidp);
1308 jms.addViewport(view);
1310 object.setJalviewModelSequence(jms);
1311 object.getVamsasModel().addSequenceSet(vamsasSet);
1313 if (jout != null && fileName != null)
1315 // We may not want to write the object to disk,
1316 // eg we can copy the alignViewport to a new view object
1317 // using save and then load
1320 System.out.println("Writing jar entry " + fileName);
1321 JarEntry entry = new JarEntry(fileName);
1322 jout.putNextEntry(entry);
1323 PrintWriter pout = new PrintWriter(new OutputStreamWriter(jout,
1325 Marshaller marshaller = new Marshaller(pout);
1326 marshaller.marshal(object);
1329 } catch (Exception ex)
1331 // TODO: raise error in GUI if marshalling failed.
1332 ex.printStackTrace();
1339 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1340 * for each viewer, with
1342 * <li>viewer geometry (position, size, split pane divider location)</li>
1343 * <li>index of the selected structure in the viewer (currently shows gapped
1345 * <li>the id of the annotation holding RNA secondary structure</li>
1346 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1348 * Varna viewer state is also written out (in native Varna XML) to separate
1349 * project jar entries. A separate entry is written for each RNA structure
1350 * displayed, with the naming convention
1352 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
1360 * @param storeDataset
1362 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
1363 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
1364 boolean storeDataset)
1366 if (Desktop.desktop == null)
1370 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1371 for (int f = frames.length - 1; f > -1; f--)
1373 if (frames[f] instanceof AppVarna)
1375 AppVarna varna = (AppVarna) frames[f];
1377 * link the sequence to every viewer that is showing it and is linked to
1378 * its alignment panel
1380 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1382 String viewId = varna.getViewId();
1383 RnaViewer rna = new RnaViewer();
1384 rna.setViewId(viewId);
1385 rna.setTitle(varna.getTitle());
1386 rna.setXpos(varna.getX());
1387 rna.setYpos(varna.getY());
1388 rna.setWidth(varna.getWidth());
1389 rna.setHeight(varna.getHeight());
1390 rna.setDividerLocation(varna.getDividerLocation());
1391 rna.setSelectedRna(varna.getSelectedIndex());
1392 jseq.addRnaViewer(rna);
1395 * Store each Varna panel's state once in the project per sequence.
1396 * First time through only (storeDataset==false)
1398 // boolean storeSessions = false;
1399 // String sequenceViewId = viewId + seqsToIds.get(jds);
1400 // if (!storeDataset && !viewIds.contains(sequenceViewId))
1402 // viewIds.add(sequenceViewId);
1403 // storeSessions = true;
1405 for (RnaModel model : varna.getModels())
1407 if (model.seq == jds)
1410 * VARNA saves each view (sequence or alignment secondary
1411 * structure, gapped or trimmed) as a separate XML file
1413 String jarEntryName = rnaSessions.get(model);
1414 if (jarEntryName == null)
1417 String varnaStateFile = varna.getStateInfo(model.rna);
1418 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
1419 copyFileToJar(jout, varnaStateFile, jarEntryName);
1420 rnaSessions.put(model, jarEntryName);
1422 SecondaryStructure ss = new SecondaryStructure();
1423 String annotationId = varna.getAnnotation(jds).annotationId;
1424 ss.setAnnotationId(annotationId);
1425 ss.setViewerState(jarEntryName);
1426 ss.setGapped(model.gapped);
1427 ss.setTitle(model.title);
1428 rna.addSecondaryStructure(ss);
1437 * Copy the contents of a file to a new entry added to the output jar
1441 * @param jarEntryName
1443 protected void copyFileToJar(JarOutputStream jout, String infilePath,
1444 String jarEntryName)
1446 DataInputStream dis = null;
1449 File file = new File(infilePath);
1450 if (file.exists() && jout != null)
1452 dis = new DataInputStream(new FileInputStream(file));
1453 byte[] data = new byte[(int) file.length()];
1454 dis.readFully(data);
1455 writeJarEntry(jout, jarEntryName, data);
1457 } catch (Exception ex)
1459 ex.printStackTrace();
1467 } catch (IOException e)
1476 * Write the data to a new entry of given name in the output jar file
1479 * @param jarEntryName
1481 * @throws IOException
1483 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
1484 byte[] data) throws IOException
1488 System.out.println("Writing jar entry " + jarEntryName);
1489 jout.putNextEntry(new JarEntry(jarEntryName));
1490 DataOutputStream dout = new DataOutputStream(jout);
1491 dout.write(data, 0, data.length);
1498 * Save the state of a structure viewer
1503 * the archive XML element under which to save the state
1506 * @param matchedFile
1510 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
1511 Pdbids pdb, PDBEntry entry, List<String> viewIds,
1512 String matchedFile, StructureViewerBase viewFrame)
1514 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
1517 * Look for any bindings for this viewer to the PDB file of interest
1518 * (including part matches excluding chain id)
1520 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
1522 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
1523 final String pdbId = pdbentry.getId();
1524 if (!pdbId.equals(entry.getId())
1525 && !(entry.getId().length() > 4 && entry.getId()
1526 .toLowerCase().startsWith(pdbId.toLowerCase())))
1529 * not interested in a binding to a different PDB entry here
1533 if (matchedFile == null)
1535 matchedFile = pdbentry.getFile();
1537 else if (!matchedFile.equals(pdbentry.getFile()))
1540 .warn("Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
1541 + pdbentry.getFile());
1545 // can get at it if the ID
1546 // match is ambiguous (e.g.
1549 for (int smap = 0; smap < viewFrame.getBinding().getSequence()[peid].length; smap++)
1551 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
1552 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
1554 StructureState state = new StructureState();
1555 state.setVisible(true);
1556 state.setXpos(viewFrame.getX());
1557 state.setYpos(viewFrame.getY());
1558 state.setWidth(viewFrame.getWidth());
1559 state.setHeight(viewFrame.getHeight());
1560 final String viewId = viewFrame.getViewId();
1561 state.setViewId(viewId);
1562 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
1563 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
1564 state.setColourByJmol(viewFrame.isColouredByViewer());
1565 state.setType(viewFrame.getViewerType().toString());
1566 pdb.addStructureState(state);
1573 private AnnotationColours constructAnnotationColours(
1574 AnnotationColourGradient acg, List<UserColourScheme> userColours,
1575 JalviewModelSequence jms)
1577 AnnotationColours ac = new AnnotationColours();
1578 ac.setAboveThreshold(acg.getAboveThreshold());
1579 ac.setThreshold(acg.getAnnotationThreshold());
1580 ac.setAnnotation(acg.getAnnotation());
1581 if (acg.getBaseColour() instanceof jalview.schemes.UserColourScheme)
1583 ac.setColourScheme(setUserColourScheme(acg.getBaseColour(),
1588 ac.setColourScheme(ColourSchemeProperty.getColourName(acg
1592 ac.setMaxColour(acg.getMaxColour().getRGB());
1593 ac.setMinColour(acg.getMinColour().getRGB());
1594 ac.setPerSequence(acg.isSeqAssociated());
1595 ac.setPredefinedColours(acg.isPredefinedColours());
1599 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
1600 IdentityHashMap<SequenceGroup, String> groupRefs,
1601 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
1602 SequenceSet vamsasSet)
1605 for (int i = 0; i < aa.length; i++)
1607 Annotation an = new Annotation();
1609 AlignmentAnnotation annotation = aa[i];
1610 if (annotation.annotationId != null)
1612 annotationIds.put(annotation.annotationId, annotation);
1615 an.setId(annotation.annotationId);
1617 an.setVisible(annotation.visible);
1619 an.setDescription(annotation.description);
1621 if (annotation.sequenceRef != null)
1623 // 2.9 JAL-1781 xref on sequence id rather than name
1624 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
1626 if (annotation.groupRef != null)
1628 String groupIdr = groupRefs.get(annotation.groupRef);
1629 if (groupIdr == null)
1631 // make a locally unique String
1633 annotation.groupRef,
1634 groupIdr = ("" + System.currentTimeMillis()
1635 + annotation.groupRef.getName() + groupRefs
1638 an.setGroupRef(groupIdr.toString());
1641 // store all visualization attributes for annotation
1642 an.setGraphHeight(annotation.graphHeight);
1643 an.setCentreColLabels(annotation.centreColLabels);
1644 an.setScaleColLabels(annotation.scaleColLabel);
1645 an.setShowAllColLabels(annotation.showAllColLabels);
1646 an.setBelowAlignment(annotation.belowAlignment);
1648 if (annotation.graph > 0)
1651 an.setGraphType(annotation.graph);
1652 an.setGraphGroup(annotation.graphGroup);
1653 if (annotation.getThreshold() != null)
1655 ThresholdLine line = new ThresholdLine();
1656 line.setLabel(annotation.getThreshold().label);
1657 line.setValue(annotation.getThreshold().value);
1658 line.setColour(annotation.getThreshold().colour.getRGB());
1659 an.setThresholdLine(line);
1667 an.setLabel(annotation.label);
1669 if (annotation == av.getAlignmentQualityAnnot()
1670 || annotation == av.getAlignmentConservationAnnotation()
1671 || annotation == av.getAlignmentConsensusAnnotation()
1672 || annotation.autoCalculated)
1674 // new way of indicating autocalculated annotation -
1675 an.setAutoCalculated(annotation.autoCalculated);
1677 if (annotation.hasScore())
1679 an.setScore(annotation.getScore());
1682 if (annotation.getCalcId() != null)
1684 calcIdSet.add(annotation.getCalcId());
1685 an.setCalcId(annotation.getCalcId());
1687 if (annotation.hasProperties())
1689 for (String pr : annotation.getProperties())
1691 Property prop = new Property();
1693 prop.setValue(annotation.getProperty(pr));
1694 an.addProperty(prop);
1698 AnnotationElement ae;
1699 if (annotation.annotations != null)
1701 an.setScoreOnly(false);
1702 for (int a = 0; a < annotation.annotations.length; a++)
1704 if ((annotation == null) || (annotation.annotations[a] == null))
1709 ae = new AnnotationElement();
1710 if (annotation.annotations[a].description != null)
1712 ae.setDescription(annotation.annotations[a].description);
1714 if (annotation.annotations[a].displayCharacter != null)
1716 ae.setDisplayCharacter(annotation.annotations[a].displayCharacter);
1719 if (!Float.isNaN(annotation.annotations[a].value))
1721 ae.setValue(annotation.annotations[a].value);
1725 if (annotation.annotations[a].secondaryStructure > ' ')
1727 ae.setSecondaryStructure(annotation.annotations[a].secondaryStructure
1731 if (annotation.annotations[a].colour != null
1732 && annotation.annotations[a].colour != java.awt.Color.black)
1734 ae.setColour(annotation.annotations[a].colour.getRGB());
1737 an.addAnnotationElement(ae);
1738 if (annotation.autoCalculated)
1740 // only write one non-null entry into the annotation row -
1741 // sufficient to get the visualization attributes necessary to
1749 an.setScoreOnly(true);
1751 if (!storeDS || (storeDS && !annotation.autoCalculated))
1753 // skip autocalculated annotation - these are only provided for
1755 vamsasSet.addAnnotation(an);
1761 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
1763 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
1764 if (settings != null)
1766 CalcIdParam vCalcIdParam = new CalcIdParam();
1767 vCalcIdParam.setCalcId(calcId);
1768 vCalcIdParam.addServiceURL(settings.getServiceURI());
1769 // generic URI allowing a third party to resolve another instance of the
1770 // service used for this calculation
1771 for (String urls : settings.getServiceURLs())
1773 vCalcIdParam.addServiceURL(urls);
1775 vCalcIdParam.setVersion("1.0");
1776 if (settings.getPreset() != null)
1778 WsParamSetI setting = settings.getPreset();
1779 vCalcIdParam.setName(setting.getName());
1780 vCalcIdParam.setDescription(setting.getDescription());
1784 vCalcIdParam.setName("");
1785 vCalcIdParam.setDescription("Last used parameters");
1787 // need to be able to recover 1) settings 2) user-defined presets or
1788 // recreate settings from preset 3) predefined settings provided by
1789 // service - or settings that can be transferred (or discarded)
1790 vCalcIdParam.setParameters(settings.getWsParamFile().replace("\n",
1792 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
1793 // todo - decide if updateImmediately is needed for any projects.
1795 return vCalcIdParam;
1800 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
1803 if (calcIdParam.getVersion().equals("1.0"))
1805 Jws2Instance service = Jws2Discoverer.getDiscoverer()
1806 .getPreferredServiceFor(calcIdParam.getServiceURL());
1807 if (service != null)
1809 WsParamSetI parmSet = null;
1812 parmSet = service.getParamStore().parseServiceParameterFile(
1813 calcIdParam.getName(), calcIdParam.getDescription(),
1814 calcIdParam.getServiceURL(),
1815 calcIdParam.getParameters().replace("|\\n|", "\n"));
1816 } catch (IOException x)
1818 warn("Couldn't parse parameter data for "
1819 + calcIdParam.getCalcId(), x);
1822 List<ArgumentI> argList = null;
1823 if (calcIdParam.getName().length() > 0)
1825 parmSet = service.getParamStore()
1826 .getPreset(calcIdParam.getName());
1827 if (parmSet != null)
1829 // TODO : check we have a good match with settings in AACon -
1830 // otherwise we'll need to create a new preset
1835 argList = parmSet.getArguments();
1838 AAConSettings settings = new AAConSettings(
1839 calcIdParam.isAutoUpdate(), service, parmSet, argList);
1840 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
1841 calcIdParam.isNeedsUpdate());
1846 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
1850 throw new Error(MessageManager.formatMessage(
1851 "error.unsupported_version_calcIdparam",
1852 new Object[] { calcIdParam.toString() }));
1856 * External mapping between jalview objects and objects yielding a valid and
1857 * unique object ID string. This is null for normal Jalview project IO, but
1858 * non-null when a jalview project is being read or written as part of a
1861 IdentityHashMap jv2vobj = null;
1864 * Construct a unique ID for jvobj using either existing bindings or if none
1865 * exist, the result of the hashcode call for the object.
1868 * jalview data object
1869 * @return unique ID for referring to jvobj
1871 private String makeHashCode(Object jvobj, String altCode)
1873 if (jv2vobj != null)
1875 Object id = jv2vobj.get(jvobj);
1878 return id.toString();
1880 // check string ID mappings
1881 if (jvids2vobj != null && jvobj instanceof String)
1883 id = jvids2vobj.get(jvobj);
1887 return id.toString();
1889 // give up and warn that something has gone wrong
1890 warn("Cannot find ID for object in external mapping : " + jvobj);
1896 * return local jalview object mapped to ID, if it exists
1900 * @return null or object bound to idcode
1902 private Object retrieveExistingObj(String idcode)
1904 if (idcode != null && vobj2jv != null)
1906 return vobj2jv.get(idcode);
1912 * binding from ID strings from external mapping table to jalview data model
1915 private Hashtable vobj2jv;
1917 private Sequence createVamsasSequence(String id, SequenceI jds)
1919 return createVamsasSequence(true, id, jds, null);
1922 private Sequence createVamsasSequence(boolean recurse, String id,
1923 SequenceI jds, SequenceI parentseq)
1925 Sequence vamsasSeq = new Sequence();
1926 vamsasSeq.setId(id);
1927 vamsasSeq.setName(jds.getName());
1928 vamsasSeq.setSequence(jds.getSequenceAsString());
1929 vamsasSeq.setDescription(jds.getDescription());
1930 jalview.datamodel.DBRefEntry[] dbrefs = null;
1931 if (jds.getDatasetSequence() != null)
1933 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
1934 if (jds.getDatasetSequence().getDBRefs() != null)
1936 dbrefs = jds.getDatasetSequence().getDBRefs();
1941 vamsasSeq.setDsseqid(id); // so we can tell which sequences really are
1942 // dataset sequences only
1943 dbrefs = jds.getDBRefs();
1947 for (int d = 0; d < dbrefs.length; d++)
1949 DBRef dbref = new DBRef();
1950 dbref.setSource(dbrefs[d].getSource());
1951 dbref.setVersion(dbrefs[d].getVersion());
1952 dbref.setAccessionId(dbrefs[d].getAccessionId());
1953 if (dbrefs[d].hasMap())
1955 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
1957 dbref.setMapping(mp);
1959 vamsasSeq.addDBRef(dbref);
1965 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
1966 SequenceI parentseq, SequenceI jds, boolean recurse)
1969 if (jmp.getMap() != null)
1973 jalview.util.MapList mlst = jmp.getMap();
1974 List<int[]> r = mlst.getFromRanges();
1975 for (int[] range : r)
1977 MapListFrom mfrom = new MapListFrom();
1978 mfrom.setStart(range[0]);
1979 mfrom.setEnd(range[1]);
1980 mp.addMapListFrom(mfrom);
1982 r = mlst.getToRanges();
1983 for (int[] range : r)
1985 MapListTo mto = new MapListTo();
1986 mto.setStart(range[0]);
1987 mto.setEnd(range[1]);
1988 mp.addMapListTo(mto);
1990 mp.setMapFromUnit(mlst.getFromRatio());
1991 mp.setMapToUnit(mlst.getToRatio());
1992 if (jmp.getTo() != null)
1994 MappingChoice mpc = new MappingChoice();
1996 && (parentseq != jmp.getTo() || parentseq
1997 .getDatasetSequence() != jmp.getTo()))
1999 mpc.setSequence(createVamsasSequence(false, seqHash(jmp.getTo()),
2005 SequenceI ps = null;
2006 if (parentseq != jmp.getTo()
2007 && parentseq.getDatasetSequence() != jmp.getTo())
2009 // chaining dbref rather than a handshaking one
2010 jmpid = seqHash(ps = jmp.getTo());
2014 jmpid = seqHash(ps = parentseq);
2016 mpc.setDseqFor(jmpid);
2017 if (!seqRefIds.containsKey(mpc.getDseqFor()))
2019 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2020 seqRefIds.put(mpc.getDseqFor(), ps);
2024 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2027 mp.setMappingChoice(mpc);
2033 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2034 List<UserColourScheme> userColours, JalviewModelSequence jms)
2037 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2038 boolean newucs = false;
2039 if (!userColours.contains(ucs))
2041 userColours.add(ucs);
2044 id = "ucs" + userColours.indexOf(ucs);
2047 // actually create the scheme's entry in the XML model
2048 java.awt.Color[] colours = ucs.getColours();
2049 jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
2050 jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
2052 for (int i = 0; i < colours.length; i++)
2054 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2055 col.setName(ResidueProperties.aa[i]);
2056 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2057 jbucs.addColour(col);
2059 if (ucs.getLowerCaseColours() != null)
2061 colours = ucs.getLowerCaseColours();
2062 for (int i = 0; i < colours.length; i++)
2064 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2065 col.setName(ResidueProperties.aa[i].toLowerCase());
2066 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2067 jbucs.addColour(col);
2072 uc.setUserColourScheme(jbucs);
2073 jms.addUserColours(uc);
2079 jalview.schemes.UserColourScheme getUserColourScheme(
2080 JalviewModelSequence jms, String id)
2082 UserColours[] uc = jms.getUserColours();
2083 UserColours colours = null;
2085 for (int i = 0; i < uc.length; i++)
2087 if (uc[i].getId().equals(id))
2095 java.awt.Color[] newColours = new java.awt.Color[24];
2097 for (int i = 0; i < 24; i++)
2099 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2100 .getUserColourScheme().getColour(i).getRGB(), 16));
2103 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2106 if (colours.getUserColourScheme().getColourCount() > 24)
2108 newColours = new java.awt.Color[23];
2109 for (int i = 0; i < 23; i++)
2111 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2112 .getUserColourScheme().getColour(i + 24).getRGB(), 16));
2114 ucs.setLowerCaseColours(newColours);
2121 * contains last error message (if any) encountered by XML loader.
2123 String errorMessage = null;
2126 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2127 * exceptions are raised during project XML parsing
2129 public boolean attemptversion1parse = true;
2132 * Load a jalview project archive from a jar file
2135 * - HTTP URL or filename
2137 public AlignFrame loadJalviewAlign(final String file)
2140 jalview.gui.AlignFrame af = null;
2144 // create list to store references for any new Jmol viewers created
2145 newStructureViewers = new Vector<JalviewStructureDisplayI>();
2146 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2147 // Workaround is to make sure caller implements the JarInputStreamProvider
2149 // so we can re-open the jar input stream for each entry.
2151 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2152 af = loadJalviewAlign(jprovider);
2154 } catch (MalformedURLException e)
2156 errorMessage = "Invalid URL format for '" + file + "'";
2162 SwingUtilities.invokeAndWait(new Runnable()
2167 setLoadingFinishedForNewStructureViewers();
2170 } catch (Exception x)
2172 System.err.println("Error loading alignment: " + x.getMessage());
2178 private jarInputStreamProvider createjarInputStreamProvider(
2179 final String file) throws MalformedURLException
2182 errorMessage = null;
2183 uniqueSetSuffix = null;
2185 viewportsAdded.clear();
2186 frefedSequence = null;
2188 if (file.startsWith("http://"))
2190 url = new URL(file);
2192 final URL _url = url;
2193 return new jarInputStreamProvider()
2197 public JarInputStream getJarInputStream() throws IOException
2201 return new JarInputStream(_url.openStream());
2205 return new JarInputStream(new FileInputStream(file));
2210 public String getFilename()
2218 * Recover jalview session from a jalview project archive. Caller may
2219 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2220 * themselves. Any null fields will be initialised with default values,
2221 * non-null fields are left alone.
2226 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2228 errorMessage = null;
2229 if (uniqueSetSuffix == null)
2231 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2233 if (seqRefIds == null)
2235 seqRefIds = new HashMap<String, SequenceI>();
2237 if (frefedSequence == null)
2239 frefedSequence = new Vector<Object[]>();
2242 AlignFrame af = null, _af = null;
2243 Map<String, AlignFrame> gatherToThisFrame = new HashMap<String, AlignFrame>();
2244 final String file = jprovider.getFilename();
2247 JarInputStream jin = null;
2248 JarEntry jarentry = null;
2253 jin = jprovider.getJarInputStream();
2254 for (int i = 0; i < entryCount; i++)
2256 jarentry = jin.getNextJarEntry();
2259 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2261 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2262 JalviewModel object = new JalviewModel();
2264 Unmarshaller unmar = new Unmarshaller(object);
2265 unmar.setValidation(false);
2266 object = (JalviewModel) unmar.unmarshal(in);
2267 if (true) // !skipViewport(object))
2269 _af = loadFromObject(object, file, true, jprovider);
2270 if (object.getJalviewModelSequence().getViewportCount() > 0)
2273 if (af.viewport.isGatherViewsHere())
2275 gatherToThisFrame.put(af.viewport.getSequenceSetId(), af);
2281 else if (jarentry != null)
2283 // Some other file here.
2286 } while (jarentry != null);
2287 resolveFrefedSequences();
2288 } catch (IOException ex)
2290 ex.printStackTrace();
2291 errorMessage = "Couldn't locate Jalview XML file : " + file;
2292 System.err.println("Exception whilst loading jalview XML file : "
2294 } catch (Exception ex)
2296 System.err.println("Parsing as Jalview Version 2 file failed.");
2297 ex.printStackTrace(System.err);
2298 if (attemptversion1parse)
2300 // Is Version 1 Jar file?
2303 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
2304 } catch (Exception ex2)
2306 System.err.println("Exception whilst loading as jalviewXMLV1:");
2307 ex2.printStackTrace();
2311 if (Desktop.instance != null)
2313 Desktop.instance.stopLoading();
2317 System.out.println("Successfully loaded archive file");
2320 ex.printStackTrace();
2322 System.err.println("Exception whilst loading jalview XML file : "
2324 } catch (OutOfMemoryError e)
2326 // Don't use the OOM Window here
2327 errorMessage = "Out of memory loading jalview XML file";
2328 System.err.println("Out of memory whilst loading jalview XML file");
2329 e.printStackTrace();
2332 if (Desktop.instance != null)
2334 Desktop.instance.stopLoading();
2338 * Regather multiple views (with the same sequence set id) to the frame (if
2339 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2340 * views instead of separate frames. Note this doesn't restore a state where
2341 * some expanded views in turn have tabbed views - the last "first tab" read
2342 * in will play the role of gatherer for all.
2344 for (AlignFrame fr : gatherToThisFrame.values())
2346 Desktop.instance.gatherViews(fr);
2349 restoreSplitFrames();
2351 if (errorMessage != null)
2359 * Try to reconstruct and display SplitFrame windows, where each contains
2360 * complementary dna and protein alignments. Done by pairing up AlignFrame
2361 * objects (created earlier) which have complementary viewport ids associated.
2363 protected void restoreSplitFrames()
2365 List<SplitFrame> gatherTo = new ArrayList<SplitFrame>();
2366 List<AlignFrame> addedToSplitFrames = new ArrayList<AlignFrame>();
2367 Map<String, AlignFrame> dna = new HashMap<String, AlignFrame>();
2370 * Identify the DNA alignments
2372 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2375 AlignFrame af = candidate.getValue();
2376 if (af.getViewport().getAlignment().isNucleotide())
2378 dna.put(candidate.getKey().getId(), af);
2383 * Try to match up the protein complements
2385 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2388 AlignFrame af = candidate.getValue();
2389 if (!af.getViewport().getAlignment().isNucleotide())
2391 String complementId = candidate.getKey().getComplementId();
2392 // only non-null complements should be in the Map
2393 if (complementId != null && dna.containsKey(complementId))
2395 final AlignFrame dnaFrame = dna.get(complementId);
2396 SplitFrame sf = createSplitFrame(dnaFrame, af);
2397 addedToSplitFrames.add(dnaFrame);
2398 addedToSplitFrames.add(af);
2399 if (af.viewport.isGatherViewsHere())
2408 * Open any that we failed to pair up (which shouldn't happen!) as
2409 * standalone AlignFrame's.
2411 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2414 AlignFrame af = candidate.getValue();
2415 if (!addedToSplitFrames.contains(af))
2417 Viewport view = candidate.getKey();
2418 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
2420 System.err.println("Failed to restore view " + view.getTitle()
2421 + " to split frame");
2426 * Gather back into tabbed views as flagged.
2428 for (SplitFrame sf : gatherTo)
2430 Desktop.instance.gatherViews(sf);
2433 splitFrameCandidates.clear();
2437 * Construct and display one SplitFrame holding DNA and protein alignments.
2440 * @param proteinFrame
2443 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
2444 AlignFrame proteinFrame)
2446 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
2447 String title = MessageManager.getString("label.linked_view_title");
2448 int width = (int) dnaFrame.getBounds().getWidth();
2449 int height = (int) (dnaFrame.getBounds().getHeight()
2450 + proteinFrame.getBounds().getHeight() + 50);
2453 * SplitFrame location is saved to both enclosed frames
2455 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
2456 Desktop.addInternalFrame(splitFrame, title, width, height);
2459 * And compute cDNA consensus (couldn't do earlier with consensus as
2460 * mappings were not yet present)
2462 proteinFrame.viewport.alignmentChanged(proteinFrame.alignPanel);
2468 * check errorMessage for a valid error message and raise an error box in the
2469 * GUI or write the current errorMessage to stderr and then clear the error
2472 protected void reportErrors()
2474 reportErrors(false);
2477 protected void reportErrors(final boolean saving)
2479 if (errorMessage != null)
2481 final String finalErrorMessage = errorMessage;
2484 javax.swing.SwingUtilities.invokeLater(new Runnable()
2489 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2490 finalErrorMessage, "Error "
2491 + (saving ? "saving" : "loading")
2492 + " Jalview file", JOptionPane.WARNING_MESSAGE);
2498 System.err.println("Problem loading Jalview file: " + errorMessage);
2501 errorMessage = null;
2504 Map<String, String> alreadyLoadedPDB = new HashMap<String, String>();
2507 * when set, local views will be updated from view stored in JalviewXML
2508 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2509 * sync if this is set to true.
2511 private final boolean updateLocalViews = false;
2514 * Returns the path to a temporary file holding the PDB file for the given PDB
2515 * id. The first time of asking, searches for a file of that name in the
2516 * Jalview project jar, and copies it to a new temporary file. Any repeat
2517 * requests just return the path to the file previously created.
2523 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId)
2525 if (alreadyLoadedPDB.containsKey(pdbId))
2527 return alreadyLoadedPDB.get(pdbId).toString();
2530 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb");
2531 if (tempFile != null)
2533 alreadyLoadedPDB.put(pdbId, tempFile);
2539 * Copies the jar entry of given name to a new temporary file and returns the
2540 * path to the file, or null if the entry is not found.
2543 * @param jarEntryName
2545 * a prefix for the temporary file name, must be at least three
2549 protected String copyJarEntry(jarInputStreamProvider jprovider,
2550 String jarEntryName, String prefix)
2552 BufferedReader in = null;
2553 PrintWriter out = null;
2557 JarInputStream jin = jprovider.getJarInputStream();
2559 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2560 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2561 * FileInputStream(jprovider)); }
2564 JarEntry entry = null;
2567 entry = jin.getNextJarEntry();
2568 } while (entry != null && !entry.getName().equals(jarEntryName));
2571 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
2572 File outFile = File.createTempFile(prefix, ".tmp");
2573 outFile.deleteOnExit();
2574 out = new PrintWriter(new FileOutputStream(outFile));
2577 while ((data = in.readLine()) != null)
2582 String t = outFile.getAbsolutePath();
2587 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
2589 } catch (Exception ex)
2591 ex.printStackTrace();
2599 } catch (IOException e)
2613 private class JvAnnotRow
2615 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2622 * persisted version of annotation row from which to take vis properties
2624 public jalview.datamodel.AlignmentAnnotation template;
2627 * original position of the annotation row in the alignment
2633 * Load alignment frame from jalview XML DOM object
2638 * filename source string
2639 * @param loadTreesAndStructures
2640 * when false only create Viewport
2642 * data source provider
2643 * @return alignment frame created from view stored in DOM
2645 AlignFrame loadFromObject(JalviewModel object, String file,
2646 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
2648 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
2649 Sequence[] vamsasSeq = vamsasSet.getSequence();
2651 JalviewModelSequence jms = object.getJalviewModelSequence();
2653 Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
2656 // ////////////////////////////////
2659 List<SequenceI> hiddenSeqs = null;
2660 jalview.datamodel.Sequence jseq;
2662 List<SequenceI> tmpseqs = new ArrayList<SequenceI>();
2664 boolean multipleView = false;
2666 JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
2667 int vi = 0; // counter in vamsasSeq array
2668 for (int i = 0; i < jseqs.length; i++)
2670 String seqId = jseqs[i].getId();
2672 if (seqRefIds.get(seqId) != null)
2674 tmpseqs.add(seqRefIds.get(seqId));
2675 multipleView = true;
2679 jseq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
2680 vamsasSeq[vi].getSequence());
2681 jseq.setDescription(vamsasSeq[vi].getDescription());
2682 jseq.setStart(jseqs[i].getStart());
2683 jseq.setEnd(jseqs[i].getEnd());
2684 jseq.setVamsasId(uniqueSetSuffix + seqId);
2685 seqRefIds.put(vamsasSeq[vi].getId(), jseq);
2690 if (jseqs[i].getHidden())
2692 if (hiddenSeqs == null)
2694 hiddenSeqs = new ArrayList<SequenceI>();
2697 hiddenSeqs.add(seqRefIds.get(seqId));
2703 // Create the alignment object from the sequence set
2704 // ///////////////////////////////
2705 SequenceI[] orderedSeqs = tmpseqs
2706 .toArray(new SequenceI[tmpseqs.size()]);
2708 Alignment al = new Alignment(orderedSeqs);
2710 // / Add the alignment properties
2711 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
2713 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
2714 al.setProperty(ssp.getKey(), ssp.getValue());
2718 // SequenceFeatures are added to the DatasetSequence,
2719 // so we must create or recover the dataset before loading features
2720 // ///////////////////////////////
2721 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
2723 // older jalview projects do not have a dataset id.
2724 al.setDataset(null);
2728 // recover dataset - passing on flag indicating if this a 'viewless'
2729 // sequence set (a.k.a. a stored dataset for the project)
2730 recoverDatasetFor(vamsasSet, al, object.getJalviewModelSequence()
2731 .getViewportCount() == 0);
2733 // ///////////////////////////////
2735 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
2738 // load sequence features, database references and any associated PDB
2739 // structures for the alignment
2740 for (int i = 0; i < vamsasSeq.length; i++)
2742 if (jseqs[i].getFeaturesCount() > 0)
2744 Features[] features = jseqs[i].getFeatures();
2745 for (int f = 0; f < features.length; f++)
2747 jalview.datamodel.SequenceFeature sf = new jalview.datamodel.SequenceFeature(
2748 features[f].getType(), features[f].getDescription(),
2749 features[f].getStatus(), features[f].getBegin(),
2750 features[f].getEnd(), features[f].getFeatureGroup());
2752 sf.setScore(features[f].getScore());
2753 for (int od = 0; od < features[f].getOtherDataCount(); od++)
2755 OtherData keyValue = features[f].getOtherData(od);
2756 if (keyValue.getKey().startsWith("LINK"))
2758 sf.addLink(keyValue.getValue());
2762 sf.setValue(keyValue.getKey(), keyValue.getValue());
2767 al.getSequenceAt(i).getDatasetSequence().addSequenceFeature(sf);
2770 if (vamsasSeq[i].getDBRefCount() > 0)
2772 addDBRefs(al.getSequenceAt(i).getDatasetSequence(), vamsasSeq[i]);
2774 if (jseqs[i].getPdbidsCount() > 0)
2776 Pdbids[] ids = jseqs[i].getPdbids();
2777 for (int p = 0; p < ids.length; p++)
2779 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
2780 entry.setId(ids[p].getId());
2781 if (ids[p].getType() != null)
2783 if (ids[p].getType().equalsIgnoreCase("PDB"))
2785 entry.setType(PDBEntry.Type.PDB);
2789 entry.setType(PDBEntry.Type.FILE);
2792 if (ids[p].getFile() != null)
2794 if (!pdbloaded.containsKey(ids[p].getFile()))
2796 entry.setFile(loadPDBFile(jprovider, ids[p].getId()));
2800 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
2803 StructureSelectionManager.getStructureSelectionManager(
2804 Desktop.instance).registerPDBEntry(entry);
2805 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
2809 } // end !multipleview
2811 // ///////////////////////////////
2812 // LOAD SEQUENCE MAPPINGS
2814 if (vamsasSet.getAlcodonFrameCount() > 0)
2816 // TODO Potentially this should only be done once for all views of an
2818 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
2819 for (int i = 0; i < alc.length; i++)
2821 AlignedCodonFrame cf = new AlignedCodonFrame();
2822 if (alc[i].getAlcodMapCount() > 0)
2824 AlcodMap[] maps = alc[i].getAlcodMap();
2825 for (int m = 0; m < maps.length; m++)
2827 SequenceI dnaseq = seqRefIds.get(maps[m].getDnasq());
2829 jalview.datamodel.Mapping mapping = null;
2830 // attach to dna sequence reference.
2831 if (maps[m].getMapping() != null)
2833 mapping = addMapping(maps[m].getMapping());
2835 if (dnaseq != null && mapping.getTo() != null)
2837 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
2842 frefedSequence.add(new Object[] { maps[m].getDnasq(), cf,
2847 al.addCodonFrame(cf);
2851 // ////////////////////////////////
2853 List<JvAnnotRow> autoAlan = new ArrayList<JvAnnotRow>();
2856 * store any annotations which forward reference a group's ID
2858 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<String, List<AlignmentAnnotation>>();
2860 if (vamsasSet.getAnnotationCount() > 0)
2862 Annotation[] an = vamsasSet.getAnnotation();
2864 for (int i = 0; i < an.length; i++)
2866 Annotation annotation = an[i];
2869 * test if annotation is automatically calculated for this view only
2871 boolean autoForView = false;
2872 if (annotation.getLabel().equals("Quality")
2873 || annotation.getLabel().equals("Conservation")
2874 || annotation.getLabel().equals("Consensus"))
2876 // Kludge for pre 2.5 projects which lacked the autocalculated flag
2878 if (!annotation.hasAutoCalculated())
2880 annotation.setAutoCalculated(true);
2884 || (annotation.hasAutoCalculated() && annotation
2885 .isAutoCalculated()))
2887 // remove ID - we don't recover annotation from other views for
2888 // view-specific annotation
2889 annotation.setId(null);
2892 // set visiblity for other annotation in this view
2893 String annotationId = annotation.getId();
2894 if (annotationId != null && annotationIds.containsKey(annotationId))
2896 AlignmentAnnotation jda = annotationIds.get(annotationId);
2897 // in principle Visible should always be true for annotation displayed
2898 // in multiple views
2899 if (annotation.hasVisible())
2901 jda.visible = annotation.getVisible();
2904 al.addAnnotation(jda);
2908 // Construct new annotation from model.
2909 AnnotationElement[] ae = annotation.getAnnotationElement();
2910 jalview.datamodel.Annotation[] anot = null;
2911 java.awt.Color firstColour = null;
2913 if (!annotation.getScoreOnly())
2915 anot = new jalview.datamodel.Annotation[al.getWidth()];
2916 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
2918 anpos = ae[aa].getPosition();
2920 if (anpos >= anot.length)
2925 anot[anpos] = new jalview.datamodel.Annotation(
2927 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
2928 (ae[aa].getSecondaryStructure() == null || ae[aa]
2929 .getSecondaryStructure().length() == 0) ? ' '
2930 : ae[aa].getSecondaryStructure().charAt(0),
2934 // JBPNote: Consider verifying dataflow for IO of secondary
2935 // structure annotation read from Stockholm files
2936 // this was added to try to ensure that
2937 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
2939 // anot[ae[aa].getPosition()].displayCharacter = "";
2941 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
2942 if (firstColour == null)
2944 firstColour = anot[anpos].colour;
2948 jalview.datamodel.AlignmentAnnotation jaa = null;
2950 if (annotation.getGraph())
2952 float llim = 0, hlim = 0;
2953 // if (autoForView || an[i].isAutoCalculated()) {
2956 jaa = new jalview.datamodel.AlignmentAnnotation(
2957 annotation.getLabel(), annotation.getDescription(), anot,
2958 llim, hlim, annotation.getGraphType());
2960 jaa.graphGroup = annotation.getGraphGroup();
2961 jaa._linecolour = firstColour;
2962 if (annotation.getThresholdLine() != null)
2964 jaa.setThreshold(new jalview.datamodel.GraphLine(annotation
2965 .getThresholdLine().getValue(), annotation
2966 .getThresholdLine().getLabel(), new java.awt.Color(
2967 annotation.getThresholdLine().getColour())));
2970 if (autoForView || annotation.isAutoCalculated())
2972 // Hardwire the symbol display line to ensure that labels for
2973 // histograms are displayed
2979 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
2980 an[i].getDescription(), anot);
2981 jaa._linecolour = firstColour;
2983 // register new annotation
2984 if (an[i].getId() != null)
2986 annotationIds.put(an[i].getId(), jaa);
2987 jaa.annotationId = an[i].getId();
2989 // recover sequence association
2990 String sequenceRef = an[i].getSequenceRef();
2991 if (sequenceRef != null)
2993 // from 2.9 sequenceRef is to sequence id (JAL-1781)
2994 SequenceI sequence = seqRefIds.get(sequenceRef);
2995 if (sequence == null)
2997 // in pre-2.9 projects sequence ref is to sequence name
2998 sequence = al.findName(sequenceRef);
3000 if (sequence != null)
3002 jaa.createSequenceMapping(sequence, 1, true);
3003 sequence.addAlignmentAnnotation(jaa);
3006 // and make a note of any group association
3007 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
3009 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3010 .get(an[i].getGroupRef());
3013 aal = new ArrayList<jalview.datamodel.AlignmentAnnotation>();
3014 groupAnnotRefs.put(an[i].getGroupRef(), aal);
3019 if (an[i].hasScore())
3021 jaa.setScore(an[i].getScore());
3023 if (an[i].hasVisible())
3025 jaa.visible = an[i].getVisible();
3028 if (an[i].hasCentreColLabels())
3030 jaa.centreColLabels = an[i].getCentreColLabels();
3033 if (an[i].hasScaleColLabels())
3035 jaa.scaleColLabel = an[i].getScaleColLabels();
3037 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
3039 // newer files have an 'autoCalculated' flag and store calculation
3040 // state in viewport properties
3041 jaa.autoCalculated = true; // means annotation will be marked for
3042 // update at end of load.
3044 if (an[i].hasGraphHeight())
3046 jaa.graphHeight = an[i].getGraphHeight();
3048 if (an[i].hasBelowAlignment())
3050 jaa.belowAlignment = an[i].isBelowAlignment();
3052 jaa.setCalcId(an[i].getCalcId());
3053 if (an[i].getPropertyCount() > 0)
3055 for (jalview.schemabinding.version2.Property prop : an[i]
3058 jaa.setProperty(prop.getName(), prop.getValue());
3061 if (jaa.autoCalculated)
3063 autoAlan.add(new JvAnnotRow(i, jaa));
3066 // if (!autoForView)
3068 // add autocalculated group annotation and any user created annotation
3070 al.addAnnotation(jaa);
3074 // ///////////////////////
3076 // Create alignment markup and styles for this view
3077 if (jms.getJGroupCount() > 0)
3079 JGroup[] groups = jms.getJGroup();
3080 boolean addAnnotSchemeGroup = false;
3081 for (int i = 0; i < groups.length; i++)
3083 JGroup jGroup = groups[i];
3084 ColourSchemeI cs = null;
3085 if (jGroup.getColour() != null)
3087 if (jGroup.getColour().startsWith("ucs"))
3089 cs = getUserColourScheme(jms, jGroup.getColour());
3091 else if (jGroup.getColour().equals("AnnotationColourGradient")
3092 && jGroup.getAnnotationColours() != null)
3094 addAnnotSchemeGroup = true;
3099 cs = ColourSchemeProperty.getColour(al, jGroup.getColour());
3104 cs.setThreshold(jGroup.getPidThreshold(), true);
3108 Vector<SequenceI> seqs = new Vector<SequenceI>();
3110 for (int s = 0; s < jGroup.getSeqCount(); s++)
3112 String seqId = jGroup.getSeq(s) + "";
3113 SequenceI ts = seqRefIds.get(seqId);
3117 seqs.addElement(ts);
3121 if (seqs.size() < 1)
3126 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3127 jGroup.getDisplayBoxes(), jGroup.getDisplayText(),
3128 jGroup.getColourText(), jGroup.getStart(), jGroup.getEnd());
3130 sg.setOutlineColour(new java.awt.Color(jGroup.getOutlineColour()));
3132 sg.textColour = new java.awt.Color(jGroup.getTextCol1());
3133 sg.textColour2 = new java.awt.Color(jGroup.getTextCol2());
3134 sg.setShowNonconserved(jGroup.hasShowUnconserved() ? jGroup
3135 .isShowUnconserved() : false);
3136 sg.thresholdTextColour = jGroup.getTextColThreshold();
3137 if (jGroup.hasShowConsensusHistogram())
3139 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3142 if (jGroup.hasShowSequenceLogo())
3144 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3146 if (jGroup.hasNormaliseSequenceLogo())
3148 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3150 if (jGroup.hasIgnoreGapsinConsensus())
3152 sg.setIgnoreGapsConsensus(jGroup.getIgnoreGapsinConsensus());
3154 if (jGroup.getConsThreshold() != 0)
3156 jalview.analysis.Conservation c = new jalview.analysis.Conservation(
3157 "All", ResidueProperties.propHash, 3,
3158 sg.getSequences(null), 0, sg.getWidth() - 1);
3160 c.verdict(false, 25);
3161 sg.cs.setConservation(c);
3164 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3166 // re-instate unique group/annotation row reference
3167 List<AlignmentAnnotation> jaal = groupAnnotRefs.get(jGroup
3171 for (AlignmentAnnotation jaa : jaal)
3174 if (jaa.autoCalculated)
3176 // match up and try to set group autocalc alignment row for this
3178 if (jaa.label.startsWith("Consensus for "))
3180 sg.setConsensus(jaa);
3182 // match up and try to set group autocalc alignment row for this
3184 if (jaa.label.startsWith("Conservation for "))
3186 sg.setConservationRow(jaa);
3193 if (addAnnotSchemeGroup)
3195 // reconstruct the annotation colourscheme
3196 sg.cs = constructAnnotationColour(jGroup.getAnnotationColours(),
3197 null, al, jms, false);
3203 // only dataset in this model, so just return.
3206 // ///////////////////////////////
3209 // If we just load in the same jar file again, the sequenceSetId
3210 // will be the same, and we end up with multiple references
3211 // to the same sequenceSet. We must modify this id on load
3212 // so that each load of the file gives a unique id
3213 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3214 String viewId = (view.getId() == null ? null : view.getId()
3216 AlignFrame af = null;
3217 AlignViewport av = null;
3218 // now check to see if we really need to create a new viewport.
3219 if (multipleView && viewportsAdded.size() == 0)
3221 // We recovered an alignment for which a viewport already exists.
3222 // TODO: fix up any settings necessary for overlaying stored state onto
3223 // state recovered from another document. (may not be necessary).
3224 // we may need a binding from a viewport in memory to one recovered from
3226 // and then recover its containing af to allow the settings to be applied.
3227 // TODO: fix for vamsas demo
3229 .println("About to recover a viewport for existing alignment: Sequence set ID is "
3231 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3232 if (seqsetobj != null)
3234 if (seqsetobj instanceof String)
3236 uniqueSeqSetId = (String) seqsetobj;
3238 .println("Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
3244 .println("Warning : Collision between sequence set ID string and existing jalview object mapping.");
3250 * indicate that annotation colours are applied across all groups (pre
3251 * Jalview 2.8.1 behaviour)
3253 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan(
3254 "2.8.1", object.getVersion());
3256 AlignmentPanel ap = null;
3257 boolean isnewview = true;
3260 // Check to see if this alignment already has a view id == viewId
3261 jalview.gui.AlignmentPanel views[] = Desktop
3262 .getAlignmentPanels(uniqueSeqSetId);
3263 if (views != null && views.length > 0)
3265 for (int v = 0; v < views.length; v++)
3267 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
3269 // recover the existing alignpanel, alignframe, viewport
3270 af = views[v].alignFrame;
3273 // TODO: could even skip resetting view settings if we don't want to
3274 // change the local settings from other jalview processes
3283 af = loadViewport(file, jseqs, hiddenSeqs, al, jms, view,
3284 uniqueSeqSetId, viewId, autoAlan);
3290 * Load any trees, PDB structures and viewers
3292 * Not done if flag is false (when this method is used for New View)
3294 if (loadTreesAndStructures)
3296 loadTrees(jms, view, af, av, ap);
3297 loadPDBStructures(jprovider, jseqs, af, ap);
3298 loadRnaViewers(jprovider, jseqs, ap);
3300 // and finally return.
3305 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
3306 * panel is restored from separate jar entries, two (gapped and trimmed) per
3307 * sequence and secondary structure.
3309 * Currently each viewer shows just one sequence and structure (gapped and
3310 * trimmed), however this method is designed to support multiple sequences or
3311 * structures in viewers if wanted in future.
3317 private void loadRnaViewers(jarInputStreamProvider jprovider,
3318 JSeq[] jseqs, AlignmentPanel ap)
3321 * scan the sequences for references to viewers; create each one the first
3322 * time it is referenced, add Rna models to existing viewers
3324 for (JSeq jseq : jseqs)
3326 for (int i = 0; i < jseq.getRnaViewerCount(); i++)
3328 RnaViewer viewer = jseq.getRnaViewer(i);
3329 AppVarna appVarna = findOrCreateVarnaViewer(viewer,
3330 uniqueSetSuffix, ap);
3332 for (int j = 0; j < viewer.getSecondaryStructureCount(); j++)
3334 SecondaryStructure ss = viewer.getSecondaryStructure(j);
3335 SequenceI seq = seqRefIds.get(jseq.getId());
3336 AlignmentAnnotation ann = this.annotationIds.get(ss
3337 .getAnnotationId());
3340 * add the structure to the Varna display (with session state copied
3341 * from the jar to a temporary file)
3343 boolean gapped = ss.isGapped();
3344 String rnaTitle = ss.getTitle();
3345 String sessionState = ss.getViewerState();
3346 String tempStateFile = copyJarEntry(jprovider, sessionState,
3348 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
3349 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
3351 appVarna.setInitialSelection(viewer.getSelectedRna());
3357 * Locate and return an already instantiated matching AppVarna, or create one
3361 * @param viewIdSuffix
3365 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
3366 String viewIdSuffix, AlignmentPanel ap)
3369 * on each load a suffix is appended to the saved viewId, to avoid conflicts
3370 * if load is repeated
3372 String postLoadId = viewer.getViewId() + viewIdSuffix;
3373 for (JInternalFrame frame : getAllFrames())
3375 if (frame instanceof AppVarna)
3377 AppVarna varna = (AppVarna) frame;
3378 if (postLoadId.equals(varna.getViewId()))
3380 // this viewer is already instantiated
3381 // could in future here add ap as another 'parent' of the
3382 // AppVarna window; currently just 1-to-many
3389 * viewer not found - make it
3391 RnaViewerModel model = new RnaViewerModel(postLoadId,
3392 viewer.getTitle(), viewer.getXpos(), viewer.getYpos(),
3393 viewer.getWidth(), viewer.getHeight(),
3394 viewer.getDividerLocation());
3395 AppVarna varna = new AppVarna(model, ap);
3401 * Load any saved trees
3409 protected void loadTrees(JalviewModelSequence jms, Viewport view,
3410 AlignFrame af, AlignViewport av, AlignmentPanel ap)
3412 // TODO result of automated refactoring - are all these parameters needed?
3415 for (int t = 0; t < jms.getTreeCount(); t++)
3418 Tree tree = jms.getTree(t);
3420 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
3423 tp = af.ShowNewickTree(
3424 new jalview.io.NewickFile(tree.getNewick()),
3425 tree.getTitle(), tree.getWidth(), tree.getHeight(),
3426 tree.getXpos(), tree.getYpos());
3427 if (tree.getId() != null)
3429 // perhaps bind the tree id to something ?
3434 // update local tree attributes ?
3435 // TODO: should check if tp has been manipulated by user - if so its
3436 // settings shouldn't be modified
3437 tp.setTitle(tree.getTitle());
3438 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(), tree
3439 .getWidth(), tree.getHeight()));
3440 tp.av = av; // af.viewport; // TODO: verify 'associate with all
3443 tp.treeCanvas.av = av; // af.viewport;
3444 tp.treeCanvas.ap = ap; // af.alignPanel;
3449 warn("There was a problem recovering stored Newick tree: \n"
3450 + tree.getNewick());
3454 tp.fitToWindow.setState(tree.getFitToWindow());
3455 tp.fitToWindow_actionPerformed(null);
3457 if (tree.getFontName() != null)
3459 tp.setTreeFont(new java.awt.Font(tree.getFontName(), tree
3460 .getFontStyle(), tree.getFontSize()));
3464 tp.setTreeFont(new java.awt.Font(view.getFontName(), view
3465 .getFontStyle(), tree.getFontSize()));
3468 tp.showPlaceholders(tree.getMarkUnlinked());
3469 tp.showBootstrap(tree.getShowBootstrap());
3470 tp.showDistances(tree.getShowDistances());
3472 tp.treeCanvas.threshold = tree.getThreshold();
3474 if (tree.getCurrentTree())
3476 af.viewport.setCurrentTree(tp.getTree());
3480 } catch (Exception ex)
3482 ex.printStackTrace();
3487 * Load and link any saved structure viewers.
3494 protected void loadPDBStructures(jarInputStreamProvider jprovider,
3495 JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
3498 * Run through all PDB ids on the alignment, and collect mappings between
3499 * distinct view ids and all sequences referring to that view.
3501 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<String, StructureViewerModel>();
3503 for (int i = 0; i < jseqs.length; i++)
3505 if (jseqs[i].getPdbidsCount() > 0)
3507 Pdbids[] ids = jseqs[i].getPdbids();
3508 for (int p = 0; p < ids.length; p++)
3510 final int structureStateCount = ids[p].getStructureStateCount();
3511 for (int s = 0; s < structureStateCount; s++)
3513 // check to see if we haven't already created this structure view
3514 final StructureState structureState = ids[p]
3515 .getStructureState(s);
3516 String sviewid = (structureState.getViewId() == null) ? null
3517 : structureState.getViewId() + uniqueSetSuffix;
3518 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
3519 // Originally : ids[p].getFile()
3520 // : TODO: verify external PDB file recovery still works in normal
3521 // jalview project load
3522 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId()));
3523 jpdb.setId(ids[p].getId());
3525 int x = structureState.getXpos();
3526 int y = structureState.getYpos();
3527 int width = structureState.getWidth();
3528 int height = structureState.getHeight();
3530 // Probably don't need to do this anymore...
3531 // Desktop.desktop.getComponentAt(x, y);
3532 // TODO: NOW: check that this recovers the PDB file correctly.
3533 String pdbFile = loadPDBFile(jprovider, ids[p].getId());
3534 jalview.datamodel.SequenceI seq = seqRefIds.get(jseqs[i]
3536 if (sviewid == null)
3538 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width
3541 if (!structureViewers.containsKey(sviewid))
3543 structureViewers.put(sviewid,
3544 new StructureViewerModel(x, y, width, height, false,
3545 false, true, structureState.getViewId(),
3546 structureState.getType()));
3547 // Legacy pre-2.7 conversion JAL-823 :
3548 // do not assume any view has to be linked for colour by
3552 // assemble String[] { pdb files }, String[] { id for each
3553 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3554 // seqs_file 2}, boolean[] {
3555 // linkAlignPanel,superposeWithAlignpanel}} from hash
3556 StructureViewerModel jmoldat = structureViewers.get(sviewid);
3557 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
3558 | (structureState.hasAlignwithAlignPanel() ? structureState
3559 .getAlignwithAlignPanel() : false));
3562 * Default colour by linked panel to false if not specified (e.g.
3563 * for pre-2.7 projects)
3565 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
3566 colourWithAlignPanel |= (structureState
3567 .hasColourwithAlignPanel() ? structureState
3568 .getColourwithAlignPanel() : false);
3569 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
3572 * Default colour by viewer to true if not specified (e.g. for
3575 boolean colourByViewer = jmoldat.isColourByViewer();
3576 colourByViewer &= structureState.hasColourByJmol() ? structureState
3577 .getColourByJmol() : true;
3578 jmoldat.setColourByViewer(colourByViewer);
3580 if (jmoldat.getStateData().length() < structureState
3581 .getContent().length())
3584 jmoldat.setStateData(structureState.getContent());
3587 if (ids[p].getFile() != null)
3589 File mapkey = new File(ids[p].getFile());
3590 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
3591 if (seqstrmaps == null)
3593 jmoldat.getFileData().put(
3595 seqstrmaps = jmoldat.new StructureData(pdbFile,
3598 if (!seqstrmaps.getSeqList().contains(seq))
3600 seqstrmaps.getSeqList().add(seq);
3606 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");
3613 // Instantiate the associated structure views
3614 for (Entry<String, StructureViewerModel> entry : structureViewers
3619 createOrLinkStructureViewer(entry, af, ap, jprovider);
3620 } catch (Exception e)
3622 System.err.println("Error loading structure viewer: "
3624 // failed - try the next one
3636 protected void createOrLinkStructureViewer(
3637 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3638 AlignmentPanel ap, jarInputStreamProvider jprovider)
3640 final StructureViewerModel stateData = viewerData.getValue();
3643 * Search for any viewer windows already open from other alignment views
3644 * that exactly match the stored structure state
3646 StructureViewerBase comp = findMatchingViewer(viewerData);
3650 linkStructureViewer(ap, comp, stateData);
3655 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
3656 * "viewer_"+stateData.viewId
3658 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
3660 createChimeraViewer(viewerData, af, jprovider);
3665 * else Jmol (if pre-2.9, stateData contains JMOL state string)
3667 createJmolViewer(viewerData, af, jprovider);
3672 * Create a new Chimera viewer.
3678 protected void createChimeraViewer(
3679 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3680 jarInputStreamProvider jprovider)
3682 StructureViewerModel data = viewerData.getValue();
3683 String chimeraSessionFile = data.getStateData();
3686 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
3688 * NB this is the 'saved' viewId as in the project file XML, _not_ the
3689 * 'uniquified' sviewid used to reconstruct the viewer here
3691 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
3692 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
3695 Set<Entry<File, StructureData>> fileData = data.getFileData()
3697 List<PDBEntry> pdbs = new ArrayList<PDBEntry>();
3698 List<SequenceI[]> allseqs = new ArrayList<SequenceI[]>();
3699 for (Entry<File, StructureData> pdb : fileData)
3701 String filePath = pdb.getValue().getFilePath();
3702 String pdbId = pdb.getValue().getPdbId();
3703 // pdbs.add(new PDBEntry(filePath, pdbId));
3704 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
3705 final List<SequenceI> seqList = pdb.getValue().getSeqList();
3706 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
3710 boolean colourByChimera = data.isColourByViewer();
3711 boolean colourBySequence = data.isColourWithAlignPanel();
3713 // TODO use StructureViewer as a factory here, see JAL-1761
3714 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
3715 final SequenceI[][] seqsArray = allseqs.toArray(new SequenceI[allseqs
3717 String newViewId = viewerData.getKey();
3719 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
3720 af.alignPanel, pdbArray, seqsArray, colourByChimera,
3721 colourBySequence, newViewId);
3722 cvf.setSize(data.getWidth(), data.getHeight());
3723 cvf.setLocation(data.getX(), data.getY());
3727 * Create a new Jmol window. First parse the Jmol state to translate filenames
3728 * loaded into the view, and record the order in which files are shown in the
3729 * Jmol view, so we can add the sequence mappings in same order.
3735 protected void createJmolViewer(
3736 final Entry<String, StructureViewerModel> viewerData,
3737 AlignFrame af, jarInputStreamProvider jprovider)
3739 final StructureViewerModel svattrib = viewerData.getValue();
3740 String state = svattrib.getStateData();
3743 * Pre-2.9: state element value is the Jmol state string
3745 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
3748 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
3750 state = readJarEntry(jprovider,
3751 getViewerJarEntryName(svattrib.getViewId()));
3754 List<String> pdbfilenames = new ArrayList<String>();
3755 List<SequenceI[]> seqmaps = new ArrayList<SequenceI[]>();
3756 List<String> pdbids = new ArrayList<String>();
3757 StringBuilder newFileLoc = new StringBuilder(64);
3758 int cp = 0, ncp, ecp;
3759 Map<File, StructureData> oldFiles = svattrib.getFileData();
3760 while ((ncp = state.indexOf("load ", cp)) > -1)
3764 // look for next filename in load statement
3765 newFileLoc.append(state.substring(cp,
3766 ncp = (state.indexOf("\"", ncp + 1) + 1)));
3767 String oldfilenam = state.substring(ncp,
3768 ecp = state.indexOf("\"", ncp));
3769 // recover the new mapping data for this old filename
3770 // have to normalize filename - since Jmol and jalview do
3772 // translation differently.
3773 StructureData filedat = oldFiles.get(new File(oldfilenam));
3774 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
3775 pdbfilenames.add(filedat.getFilePath());
3776 pdbids.add(filedat.getPdbId());
3777 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
3778 newFileLoc.append("\"");
3779 cp = ecp + 1; // advance beyond last \" and set cursor so we can
3780 // look for next file statement.
3781 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
3785 // just append rest of state
3786 newFileLoc.append(state.substring(cp));
3790 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
3791 newFileLoc = new StringBuilder(state);
3792 newFileLoc.append("; load append ");
3793 for (File id : oldFiles.keySet())
3795 // add this and any other pdb files that should be present in
3797 StructureData filedat = oldFiles.get(id);
3798 newFileLoc.append(filedat.getFilePath());
3799 pdbfilenames.add(filedat.getFilePath());
3800 pdbids.add(filedat.getPdbId());
3801 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
3802 newFileLoc.append(" \"");
3803 newFileLoc.append(filedat.getFilePath());
3804 newFileLoc.append("\"");
3807 newFileLoc.append(";");
3810 if (newFileLoc.length() == 0)
3814 int histbug = newFileLoc.indexOf("history = ");
3818 * change "history = [true|false];" to "history = [1|0];"
3821 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
3822 String val = (diff == -1) ? null : newFileLoc
3823 .substring(histbug, diff);
3824 if (val != null && val.length() >= 4)
3826 if (val.contains("e")) // eh? what can it be?
3828 if (val.trim().equals("true"))
3836 newFileLoc.replace(histbug, diff, val);
3841 final String[] pdbf = pdbfilenames.toArray(new String[pdbfilenames
3843 final String[] id = pdbids.toArray(new String[pdbids.size()]);
3844 final SequenceI[][] sq = seqmaps
3845 .toArray(new SequenceI[seqmaps.size()][]);
3846 final String fileloc = newFileLoc.toString();
3847 final String sviewid = viewerData.getKey();
3848 final AlignFrame alf = af;
3849 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
3850 svattrib.getWidth(), svattrib.getHeight());
3853 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
3858 JalviewStructureDisplayI sview = null;
3861 sview = new StructureViewer(alf.alignPanel
3862 .getStructureSelectionManager()).createView(
3863 StructureViewer.ViewerType.JMOL, pdbf, id, sq,
3864 alf.alignPanel, svattrib, fileloc, rect, sviewid);
3865 addNewStructureViewer(sview);
3866 } catch (OutOfMemoryError ex)
3868 new OOMWarning("restoring structure view for PDB id " + id,
3869 (OutOfMemoryError) ex.getCause());
3870 if (sview != null && sview.isVisible())
3872 sview.closeViewer(false);
3873 sview.setVisible(false);
3879 } catch (InvocationTargetException ex)
3881 warn("Unexpected error when opening Jmol view.", ex);
3883 } catch (InterruptedException e)
3885 // e.printStackTrace();
3891 * Generates a name for the entry in the project jar file to hold state
3892 * information for a structure viewer
3897 protected String getViewerJarEntryName(String viewId)
3899 return VIEWER_PREFIX + viewId;
3903 * Returns any open frame that matches given structure viewer data. The match
3904 * is based on the unique viewId, or (for older project versions) the frame's
3910 protected StructureViewerBase findMatchingViewer(
3911 Entry<String, StructureViewerModel> viewerData)
3913 final String sviewid = viewerData.getKey();
3914 final StructureViewerModel svattrib = viewerData.getValue();
3915 StructureViewerBase comp = null;
3916 JInternalFrame[] frames = getAllFrames();
3917 for (JInternalFrame frame : frames)
3919 if (frame instanceof StructureViewerBase)
3922 * Post jalview 2.4 schema includes structure view id
3925 && ((StructureViewerBase) frame).getViewId()
3928 comp = (StructureViewerBase) frame;
3929 break; // break added in 2.9
3932 * Otherwise test for matching position and size of viewer frame
3934 else if (frame.getX() == svattrib.getX()
3935 && frame.getY() == svattrib.getY()
3936 && frame.getHeight() == svattrib.getHeight()
3937 && frame.getWidth() == svattrib.getWidth())
3939 comp = (StructureViewerBase) frame;
3940 // no break in faint hope of an exact match on viewId
3948 * Link an AlignmentPanel to an existing structure viewer.
3953 * @param useinViewerSuperpos
3954 * @param usetoColourbyseq
3955 * @param viewerColouring
3957 protected void linkStructureViewer(AlignmentPanel ap,
3958 StructureViewerBase viewer, StructureViewerModel stateData)
3960 // NOTE: if the jalview project is part of a shared session then
3961 // view synchronization should/could be done here.
3963 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
3964 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
3965 final boolean viewerColouring = stateData.isColourByViewer();
3966 Map<File, StructureData> oldFiles = stateData.getFileData();
3969 * Add mapping for sequences in this view to an already open viewer
3971 final AAStructureBindingModel binding = viewer.getBinding();
3972 for (File id : oldFiles.keySet())
3974 // add this and any other pdb files that should be present in the
3976 StructureData filedat = oldFiles.get(id);
3977 String pdbFile = filedat.getFilePath();
3978 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
3979 binding.getSsm().setMapping(seq, null, pdbFile,
3980 jalview.io.AppletFormatAdapter.FILE);
3981 binding.addSequenceForStructFile(pdbFile, seq);
3983 // and add the AlignmentPanel's reference to the view panel
3984 viewer.addAlignmentPanel(ap);
3985 if (useinViewerSuperpos)
3987 viewer.useAlignmentPanelForSuperposition(ap);
3991 viewer.excludeAlignmentPanelForSuperposition(ap);
3993 if (usetoColourbyseq)
3995 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
3999 viewer.excludeAlignmentPanelForColourbyseq(ap);
4004 * Get all frames within the Desktop.
4008 protected JInternalFrame[] getAllFrames()
4010 JInternalFrame[] frames = null;
4011 // TODO is this necessary - is it safe - risk of hanging?
4016 frames = Desktop.desktop.getAllFrames();
4017 } catch (ArrayIndexOutOfBoundsException e)
4019 // occasional No such child exceptions are thrown here...
4023 } catch (InterruptedException f)
4027 } while (frames == null);
4032 * Answers true if 'version' is equal to or later than 'supported', where each
4033 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4034 * changes. Development and test values for 'version' are leniently treated
4038 * - minimum version we are comparing against
4040 * - version of data being processsed
4043 public static boolean isVersionStringLaterThan(String supported,
4046 if (supported == null || version == null
4047 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4048 || version.equalsIgnoreCase("Test")
4049 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4051 System.err.println("Assuming project file with "
4052 + (version == null ? "null" : version)
4053 + " is compatible with Jalview version " + supported);
4058 return StringUtils.compareVersions(version, supported, "b") >= 0;
4062 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4064 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4066 if (newStructureViewers != null)
4068 sview.getBinding().setFinishedLoadingFromArchive(false);
4069 newStructureViewers.add(sview);
4073 protected void setLoadingFinishedForNewStructureViewers()
4075 if (newStructureViewers != null)
4077 for (JalviewStructureDisplayI sview : newStructureViewers)
4079 sview.getBinding().setFinishedLoadingFromArchive(true);
4081 newStructureViewers.clear();
4082 newStructureViewers = null;
4086 AlignFrame loadViewport(String file, JSeq[] JSEQ,
4087 List<SequenceI> hiddenSeqs, Alignment al,
4088 JalviewModelSequence jms, Viewport view, String uniqueSeqSetId,
4089 String viewId, List<JvAnnotRow> autoAlan)
4091 AlignFrame af = null;
4092 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
4093 uniqueSeqSetId, viewId);
4095 af.setFileName(file, "Jalview");
4097 for (int i = 0; i < JSEQ.length; i++)
4099 af.viewport.setSequenceColour(af.viewport.getAlignment()
4100 .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour()));
4103 af.viewport.setGatherViewsHere(view.getGatheredViews());
4105 if (view.getSequenceSetId() != null)
4107 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4109 af.viewport.setSequenceSetId(uniqueSeqSetId);
4112 // propagate shared settings to this new view
4113 af.viewport.setHistoryList(av.getHistoryList());
4114 af.viewport.setRedoList(av.getRedoList());
4118 viewportsAdded.put(uniqueSeqSetId, af.viewport);
4120 // TODO: check if this method can be called repeatedly without
4121 // side-effects if alignpanel already registered.
4122 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4124 // apply Hidden regions to view.
4125 if (hiddenSeqs != null)
4127 for (int s = 0; s < JSEQ.length; s++)
4129 jalview.datamodel.SequenceGroup hidden = new jalview.datamodel.SequenceGroup();
4131 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
4134 al.getSequenceAt(JSEQ[s].getHiddenSequences(r)), false);
4136 af.viewport.hideRepSequences(al.getSequenceAt(s), hidden);
4139 // jalview.datamodel.SequenceI[] hseqs = new
4140 // jalview.datamodel.SequenceI[hiddenSeqs
4143 // for (int s = 0; s < hiddenSeqs.size(); s++)
4145 // hseqs[s] = (jalview.datamodel.SequenceI) hiddenSeqs.elementAt(s);
4148 SequenceI[] hseqs = hiddenSeqs.toArray(new SequenceI[hiddenSeqs
4150 af.viewport.hideSequence(hseqs);
4153 // recover view properties and display parameters
4154 if (view.getViewName() != null)
4156 af.viewport.viewName = view.getViewName();
4157 af.setInitialTabVisible();
4159 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
4162 af.viewport.setShowAnnotation(view.getShowAnnotation());
4163 af.viewport.setAbovePIDThreshold(view.getPidSelected());
4165 af.viewport.setColourText(view.getShowColourText());
4167 af.viewport.setConservationSelected(view.getConservationSelected());
4168 af.viewport.setShowJVSuffix(view.getShowFullId());
4169 af.viewport.setRightAlignIds(view.getRightAlignIds());
4170 af.viewport.setFont(
4171 new java.awt.Font(view.getFontName(), view.getFontStyle(), view
4172 .getFontSize()), true);
4173 ViewStyleI vs = af.viewport.getViewStyle();
4174 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
4175 af.viewport.setViewStyle(vs);
4176 // TODO: allow custom charWidth/Heights to be restored by updating them
4177 // after setting font - which means set above to false
4178 af.viewport.setRenderGaps(view.getRenderGaps());
4179 af.viewport.setWrapAlignment(view.getWrapAlignment());
4180 af.viewport.setShowAnnotation(view.getShowAnnotation());
4182 af.viewport.setShowBoxes(view.getShowBoxes());
4184 af.viewport.setShowText(view.getShowText());
4186 af.viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
4187 af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
4188 af.viewport.setThresholdTextColour(view.getTextColThreshold());
4189 af.viewport.setShowUnconserved(view.hasShowUnconserved() ? view
4190 .isShowUnconserved() : false);
4191 af.viewport.setStartRes(view.getStartRes());
4192 af.viewport.setStartSeq(view.getStartSeq());
4193 af.alignPanel.updateLayout();
4194 ColourSchemeI cs = null;
4195 // apply colourschemes
4196 if (view.getBgColour() != null)
4198 if (view.getBgColour().startsWith("ucs"))
4200 cs = getUserColourScheme(jms, view.getBgColour());
4202 else if (view.getBgColour().startsWith("Annotation"))
4204 AnnotationColours viewAnnColour = view.getAnnotationColours();
4205 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
4212 cs = ColourSchemeProperty.getColour(al, view.getBgColour());
4217 cs.setThreshold(view.getPidThreshold(), true);
4218 cs.setConsensus(af.viewport.getSequenceConsensusHash());
4222 af.viewport.setGlobalColourScheme(cs);
4223 af.viewport.setColourAppliesToAllGroups(false);
4225 if (view.getConservationSelected() && cs != null)
4227 cs.setConservationInc(view.getConsThreshold());
4230 af.changeColour(cs);
4232 af.viewport.setColourAppliesToAllGroups(true);
4234 af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures());
4236 if (view.hasCentreColumnLabels())
4238 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
4240 if (view.hasIgnoreGapsinConsensus())
4242 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
4245 if (view.hasFollowHighlight())
4247 af.viewport.setFollowHighlight(view.getFollowHighlight());
4249 if (view.hasFollowSelection())
4251 af.viewport.followSelection = view.getFollowSelection();
4253 if (view.hasShowConsensusHistogram())
4255 af.viewport.setShowConsensusHistogram(view
4256 .getShowConsensusHistogram());
4260 af.viewport.setShowConsensusHistogram(true);
4262 if (view.hasShowSequenceLogo())
4264 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
4268 af.viewport.setShowSequenceLogo(false);
4270 if (view.hasNormaliseSequenceLogo())
4272 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
4274 if (view.hasShowDbRefTooltip())
4276 af.viewport.setShowDBRefs(view.getShowDbRefTooltip());
4278 if (view.hasShowNPfeatureTooltip())
4280 af.viewport.setShowNPFeats(view.hasShowNPfeatureTooltip());
4282 if (view.hasShowGroupConsensus())
4284 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
4288 af.viewport.setShowGroupConsensus(false);
4290 if (view.hasShowGroupConservation())
4292 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
4296 af.viewport.setShowGroupConservation(false);
4299 // recover featre settings
4300 if (jms.getFeatureSettings() != null)
4302 FeaturesDisplayed fdi;
4303 af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
4304 String[] renderOrder = new String[jms.getFeatureSettings()
4305 .getSettingCount()];
4306 Hashtable featureGroups = new Hashtable();
4307 Hashtable featureColours = new Hashtable();
4308 Hashtable featureOrder = new Hashtable();
4310 for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
4312 Setting setting = jms.getFeatureSettings().getSetting(fs);
4313 if (setting.hasMincolour())
4315 GraduatedColor gc = setting.hasMin() ? new GraduatedColor(
4316 new java.awt.Color(setting.getMincolour()),
4317 new java.awt.Color(setting.getColour()),
4318 setting.getMin(), setting.getMax()) : new GraduatedColor(
4319 new java.awt.Color(setting.getMincolour()),
4320 new java.awt.Color(setting.getColour()), 0, 1);
4321 if (setting.hasThreshold())
4323 gc.setThresh(setting.getThreshold());
4324 gc.setThreshType(setting.getThreshstate());
4326 gc.setAutoScaled(true); // default
4327 if (setting.hasAutoScale())
4329 gc.setAutoScaled(setting.getAutoScale());
4331 if (setting.hasColourByLabel())
4333 gc.setColourByLabel(setting.getColourByLabel());
4335 // and put in the feature colour table.
4336 featureColours.put(setting.getType(), gc);
4340 featureColours.put(setting.getType(),
4341 new java.awt.Color(setting.getColour()));
4343 renderOrder[fs] = setting.getType();
4344 if (setting.hasOrder())
4346 featureOrder.put(setting.getType(), setting.getOrder());
4350 featureOrder.put(setting.getType(), new Float(fs
4351 / jms.getFeatureSettings().getSettingCount()));
4353 if (setting.getDisplay())
4355 fdi.setVisible(setting.getType());
4358 Hashtable fgtable = new Hashtable();
4359 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
4361 Group grp = jms.getFeatureSettings().getGroup(gs);
4362 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
4364 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4365 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
4366 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
4367 FeatureRendererSettings frs = new FeatureRendererSettings(
4368 renderOrder, fgtable, featureColours, 1.0f, featureOrder);
4369 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
4370 .transferSettings(frs);
4374 if (view.getHiddenColumnsCount() > 0)
4376 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
4378 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(), view
4379 .getHiddenColumns(c).getEnd() // +1
4383 if (view.getCalcIdParam() != null)
4385 for (CalcIdParam calcIdParam : view.getCalcIdParam())
4387 if (calcIdParam != null)
4389 if (recoverCalcIdParam(calcIdParam, af.viewport))
4394 warn("Couldn't recover parameters for "
4395 + calcIdParam.getCalcId());
4400 af.setMenusFromViewport(af.viewport);
4402 // TODO: we don't need to do this if the viewport is aready visible.
4404 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
4405 * has a 'cdna/protein complement' view, in which case save it in order to
4406 * populate a SplitFrame once all views have been read in.
4408 String complementaryViewId = view.getComplementId();
4409 if (complementaryViewId == null)
4411 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
4413 // recompute any autoannotation
4414 af.alignPanel.updateAnnotation(false, true);
4415 reorderAutoannotation(af, al, autoAlan);
4416 af.alignPanel.alignmentChanged();
4420 splitFrameCandidates.put(view, af);
4425 private ColourSchemeI constructAnnotationColour(
4426 AnnotationColours viewAnnColour, AlignFrame af, Alignment al,
4427 JalviewModelSequence jms, boolean checkGroupAnnColour)
4429 boolean propagateAnnColour = false;
4430 ColourSchemeI cs = null;
4431 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
4432 if (checkGroupAnnColour && al.getGroups() != null
4433 && al.getGroups().size() > 0)
4435 // pre 2.8.1 behaviour
4436 // check to see if we should transfer annotation colours
4437 propagateAnnColour = true;
4438 for (jalview.datamodel.SequenceGroup sg : al.getGroups())
4440 if (sg.cs instanceof AnnotationColourGradient)
4442 propagateAnnColour = false;
4446 // int find annotation
4447 if (annAlignment.getAlignmentAnnotation() != null)
4449 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
4451 if (annAlignment.getAlignmentAnnotation()[i].label
4452 .equals(viewAnnColour.getAnnotation()))
4454 if (annAlignment.getAlignmentAnnotation()[i].getThreshold() == null)
4456 annAlignment.getAlignmentAnnotation()[i]
4457 .setThreshold(new jalview.datamodel.GraphLine(
4458 viewAnnColour.getThreshold(), "Threshold",
4459 java.awt.Color.black)
4464 if (viewAnnColour.getColourScheme().equals("None"))
4466 cs = new AnnotationColourGradient(
4467 annAlignment.getAlignmentAnnotation()[i],
4468 new java.awt.Color(viewAnnColour.getMinColour()),
4469 new java.awt.Color(viewAnnColour.getMaxColour()),
4470 viewAnnColour.getAboveThreshold());
4472 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
4474 cs = new AnnotationColourGradient(
4475 annAlignment.getAlignmentAnnotation()[i],
4476 getUserColourScheme(jms,
4477 viewAnnColour.getColourScheme()),
4478 viewAnnColour.getAboveThreshold());
4482 cs = new AnnotationColourGradient(
4483 annAlignment.getAlignmentAnnotation()[i],
4484 ColourSchemeProperty.getColour(al,
4485 viewAnnColour.getColourScheme()),
4486 viewAnnColour.getAboveThreshold());
4488 if (viewAnnColour.hasPerSequence())
4490 ((AnnotationColourGradient) cs).setSeqAssociated(viewAnnColour
4493 if (viewAnnColour.hasPredefinedColours())
4495 ((AnnotationColourGradient) cs)
4496 .setPredefinedColours(viewAnnColour
4497 .isPredefinedColours());
4499 if (propagateAnnColour && al.getGroups() != null)
4501 // Also use these settings for all the groups
4502 for (int g = 0; g < al.getGroups().size(); g++)
4504 jalview.datamodel.SequenceGroup sg = al.getGroups().get(g);
4512 * if (viewAnnColour.getColourScheme().equals("None" )) { sg.cs =
4513 * new AnnotationColourGradient(
4514 * annAlignment.getAlignmentAnnotation()[i], new
4515 * java.awt.Color(viewAnnColour. getMinColour()), new
4516 * java.awt.Color(viewAnnColour. getMaxColour()),
4517 * viewAnnColour.getAboveThreshold()); } else
4520 sg.cs = new AnnotationColourGradient(
4521 annAlignment.getAlignmentAnnotation()[i], sg.cs,
4522 viewAnnColour.getAboveThreshold());
4523 if (cs instanceof AnnotationColourGradient)
4525 if (viewAnnColour.hasPerSequence())
4527 ((AnnotationColourGradient) cs)
4528 .setSeqAssociated(viewAnnColour.isPerSequence());
4530 if (viewAnnColour.hasPredefinedColours())
4532 ((AnnotationColourGradient) cs)
4533 .setPredefinedColours(viewAnnColour
4534 .isPredefinedColours());
4550 private void reorderAutoannotation(AlignFrame af, Alignment al,
4551 List<JvAnnotRow> autoAlan)
4553 // copy over visualization settings for autocalculated annotation in the
4555 if (al.getAlignmentAnnotation() != null)
4558 * Kludge for magic autoannotation names (see JAL-811)
4560 String[] magicNames = new String[] { "Consensus", "Quality",
4562 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
4563 Hashtable<String, JvAnnotRow> visan = new Hashtable<String, JvAnnotRow>();
4564 for (String nm : magicNames)
4566 visan.put(nm, nullAnnot);
4568 for (JvAnnotRow auan : autoAlan)
4570 visan.put(auan.template.label
4571 + (auan.template.getCalcId() == null ? "" : "\t"
4572 + auan.template.getCalcId()), auan);
4574 int hSize = al.getAlignmentAnnotation().length;
4575 List<JvAnnotRow> reorder = new ArrayList<JvAnnotRow>();
4576 // work through any autoCalculated annotation already on the view
4577 // removing it if it should be placed in a different location on the
4578 // annotation panel.
4579 List<String> remains = new ArrayList<String>(visan.keySet());
4580 for (int h = 0; h < hSize; h++)
4582 jalview.datamodel.AlignmentAnnotation jalan = al
4583 .getAlignmentAnnotation()[h];
4584 if (jalan.autoCalculated)
4587 JvAnnotRow valan = visan.get(k = jalan.label);
4588 if (jalan.getCalcId() != null)
4590 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
4595 // delete the auto calculated row from the alignment
4596 al.deleteAnnotation(jalan, false);
4600 if (valan != nullAnnot)
4602 if (jalan != valan.template)
4604 // newly created autoannotation row instance
4605 // so keep a reference to the visible annotation row
4606 // and copy over all relevant attributes
4607 if (valan.template.graphHeight >= 0)
4610 jalan.graphHeight = valan.template.graphHeight;
4612 jalan.visible = valan.template.visible;
4614 reorder.add(new JvAnnotRow(valan.order, jalan));
4619 // Add any (possibly stale) autocalculated rows that were not appended to
4620 // the view during construction
4621 for (String other : remains)
4623 JvAnnotRow othera = visan.get(other);
4624 if (othera != nullAnnot && othera.template.getCalcId() != null
4625 && othera.template.getCalcId().length() > 0)
4627 reorder.add(othera);
4630 // now put the automatic annotation in its correct place
4631 int s = 0, srt[] = new int[reorder.size()];
4632 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
4633 for (JvAnnotRow jvar : reorder)
4636 srt[s++] = jvar.order;
4639 jalview.util.QuickSort.sort(srt, rws);
4640 // and re-insert the annotation at its correct position
4641 for (JvAnnotRow jvar : rws)
4643 al.addAnnotation(jvar.template, jvar.order);
4645 af.alignPanel.adjustAnnotationHeight();
4649 Hashtable skipList = null;
4652 * TODO remove this method
4655 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
4656 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
4657 * throw new Error("Implementation Error. No skipList defined for this
4658 * Jalview2XML instance."); } return (AlignFrame)
4659 * skipList.get(view.getSequenceSetId()); }
4663 * Check if the Jalview view contained in object should be skipped or not.
4666 * @return true if view's sequenceSetId is a key in skipList
4668 private boolean skipViewport(JalviewModel object)
4670 if (skipList == null)
4675 if (skipList.containsKey(id = object.getJalviewModelSequence()
4676 .getViewport()[0].getSequenceSetId()))
4678 if (Cache.log != null && Cache.log.isDebugEnabled())
4680 Cache.log.debug("Skipping seuqence set id " + id);
4687 public void addToSkipList(AlignFrame af)
4689 if (skipList == null)
4691 skipList = new Hashtable();
4693 skipList.put(af.getViewport().getSequenceSetId(), af);
4696 public void clearSkipList()
4698 if (skipList != null)
4705 private void recoverDatasetFor(SequenceSet vamsasSet, Alignment al,
4706 boolean ignoreUnrefed)
4708 jalview.datamodel.Alignment ds = getDatasetFor(vamsasSet.getDatasetId());
4709 Vector dseqs = null;
4712 // create a list of new dataset sequences
4713 dseqs = new Vector();
4715 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
4717 Sequence vamsasSeq = vamsasSet.getSequence(i);
4718 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed);
4720 // create a new dataset
4723 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
4724 dseqs.copyInto(dsseqs);
4725 ds = new jalview.datamodel.Alignment(dsseqs);
4726 debug("Created new dataset " + vamsasSet.getDatasetId()
4727 + " for alignment " + System.identityHashCode(al));
4728 addDatasetRef(vamsasSet.getDatasetId(), ds);
4730 // set the dataset for the newly imported alignment.
4731 if (al.getDataset() == null && !ignoreUnrefed)
4740 * sequence definition to create/merge dataset sequence for
4744 * vector to add new dataset sequence to
4746 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
4747 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed)
4749 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
4751 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
4752 SequenceI dsq = null;
4753 if (sq != null && sq.getDatasetSequence() != null)
4755 dsq = sq.getDatasetSequence();
4757 if (sq == null && ignoreUnrefed)
4761 String sqid = vamsasSeq.getDsseqid();
4764 // need to create or add a new dataset sequence reference to this sequence
4767 dsq = seqRefIds.get(sqid);
4772 // make a new dataset sequence
4773 dsq = sq.createDatasetSequence();
4776 // make up a new dataset reference for this sequence
4777 sqid = seqHash(dsq);
4779 dsq.setVamsasId(uniqueSetSuffix + sqid);
4780 seqRefIds.put(sqid, dsq);
4785 dseqs.addElement(dsq);
4790 ds.addSequence(dsq);
4796 { // make this dataset sequence sq's dataset sequence
4797 sq.setDatasetSequence(dsq);
4798 // and update the current dataset alignment
4803 if (!dseqs.contains(dsq))
4810 if (ds.findIndex(dsq) < 0)
4812 ds.addSequence(dsq);
4819 // TODO: refactor this as a merge dataset sequence function
4820 // now check that sq (the dataset sequence) sequence really is the union of
4821 // all references to it
4822 // boolean pre = sq.getStart() < dsq.getStart();
4823 // boolean post = sq.getEnd() > dsq.getEnd();
4827 // StringBuffer sb = new StringBuffer();
4828 String newres = jalview.analysis.AlignSeq.extractGaps(
4829 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
4830 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
4831 && newres.length() > dsq.getLength())
4833 // Update with the longer sequence.
4837 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
4838 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
4839 * sb.append(newres.substring(newres.length() - sq.getEnd() -
4840 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
4842 dsq.setSequence(newres);
4844 // TODO: merges will never happen if we 'know' we have the real dataset
4845 // sequence - this should be detected when id==dssid
4847 .println("DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
4848 // + (pre ? "prepended" : "") + " "
4849 // + (post ? "appended" : ""));
4855 * TODO use AlignmentI here and in related methods - needs
4856 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
4858 Hashtable<String, Alignment> datasetIds = null;
4860 IdentityHashMap<Alignment, String> dataset2Ids = null;
4862 private Alignment getDatasetFor(String datasetId)
4864 if (datasetIds == null)
4866 datasetIds = new Hashtable<String, Alignment>();
4869 if (datasetIds.containsKey(datasetId))
4871 return datasetIds.get(datasetId);
4876 private void addDatasetRef(String datasetId, Alignment dataset)
4878 if (datasetIds == null)
4880 datasetIds = new Hashtable<String, Alignment>();
4882 datasetIds.put(datasetId, dataset);
4886 * make a new dataset ID for this jalview dataset alignment
4891 private String getDatasetIdRef(Alignment dataset)
4893 if (dataset.getDataset() != null)
4895 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
4897 String datasetId = makeHashCode(dataset, null);
4898 if (datasetId == null)
4900 // make a new datasetId and record it
4901 if (dataset2Ids == null)
4903 dataset2Ids = new IdentityHashMap<Alignment, String>();
4907 datasetId = dataset2Ids.get(dataset);
4909 if (datasetId == null)
4911 datasetId = "ds" + dataset2Ids.size() + 1;
4912 dataset2Ids.put(dataset, datasetId);
4918 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
4920 for (int d = 0; d < sequence.getDBRefCount(); d++)
4922 DBRef dr = sequence.getDBRef(d);
4923 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
4924 sequence.getDBRef(d).getSource(), sequence.getDBRef(d)
4925 .getVersion(), sequence.getDBRef(d).getAccessionId());
4926 if (dr.getMapping() != null)
4928 entry.setMap(addMapping(dr.getMapping()));
4930 datasetSequence.addDBRef(entry);
4934 private jalview.datamodel.Mapping addMapping(Mapping m)
4936 SequenceI dsto = null;
4937 // Mapping m = dr.getMapping();
4938 int fr[] = new int[m.getMapListFromCount() * 2];
4939 Enumeration f = m.enumerateMapListFrom();
4940 for (int _i = 0; f.hasMoreElements(); _i += 2)
4942 MapListFrom mf = (MapListFrom) f.nextElement();
4943 fr[_i] = mf.getStart();
4944 fr[_i + 1] = mf.getEnd();
4946 int fto[] = new int[m.getMapListToCount() * 2];
4947 f = m.enumerateMapListTo();
4948 for (int _i = 0; f.hasMoreElements(); _i += 2)
4950 MapListTo mf = (MapListTo) f.nextElement();
4951 fto[_i] = mf.getStart();
4952 fto[_i + 1] = mf.getEnd();
4954 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto,
4955 fr, fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
4956 if (m.getMappingChoice() != null)
4958 MappingChoice mc = m.getMappingChoice();
4959 if (mc.getDseqFor() != null)
4961 String dsfor = "" + mc.getDseqFor();
4962 if (seqRefIds.containsKey(dsfor))
4967 jmap.setTo(seqRefIds.get(dsfor));
4971 frefedSequence.add(new Object[] { dsfor, jmap });
4977 * local sequence definition
4979 Sequence ms = mc.getSequence();
4980 SequenceI djs = null;
4981 String sqid = ms.getDsseqid();
4982 if (sqid != null && sqid.length() > 0)
4985 * recover dataset sequence
4987 djs = seqRefIds.get(sqid);
4992 .println("Warning - making up dataset sequence id for DbRef sequence map reference");
4993 sqid = ((Object) ms).toString(); // make up a new hascode for
4994 // undefined dataset sequence hash
4995 // (unlikely to happen)
5001 * make a new dataset sequence and add it to refIds hash
5003 djs = new jalview.datamodel.Sequence(ms.getName(),
5005 djs.setStart(jmap.getMap().getToLowest());
5006 djs.setEnd(jmap.getMap().getToHighest());
5007 djs.setVamsasId(uniqueSetSuffix + sqid);
5009 seqRefIds.put(sqid, djs);
5012 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5021 public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
5022 boolean keepSeqRefs)
5025 JalviewModel jm = saveState(ap, null, null, null);
5030 jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
5034 uniqueSetSuffix = "";
5035 jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
5040 if (this.frefedSequence == null)
5042 frefedSequence = new Vector();
5045 viewportsAdded.clear();
5047 AlignFrame af = loadFromObject(jm, null, false, null);
5048 af.alignPanels.clear();
5049 af.closeMenuItem_actionPerformed(true);
5052 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5053 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5054 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5055 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5056 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5059 return af.alignPanel;
5063 * flag indicating if hashtables should be cleared on finalization TODO this
5064 * flag may not be necessary
5066 private final boolean _cleartables = true;
5068 private Hashtable jvids2vobj;
5073 * @see java.lang.Object#finalize()
5076 protected void finalize() throws Throwable
5078 // really make sure we have no buried refs left.
5083 this.seqRefIds = null;
5084 this.seqsToIds = null;
5088 private void warn(String msg)
5093 private void warn(String msg, Exception e)
5095 if (Cache.log != null)
5099 Cache.log.warn(msg, e);
5103 Cache.log.warn(msg);
5108 System.err.println("Warning: " + msg);
5111 e.printStackTrace();
5116 private void debug(String string)
5118 debug(string, null);
5121 private void debug(String msg, Exception e)
5123 if (Cache.log != null)
5127 Cache.log.debug(msg, e);
5131 Cache.log.debug(msg);
5136 System.err.println("Warning: " + msg);
5139 e.printStackTrace();
5145 * set the object to ID mapping tables used to write/recover objects and XML
5146 * ID strings for the jalview project. If external tables are provided then
5147 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
5148 * object goes out of scope. - also populates the datasetIds hashtable with
5149 * alignment objects containing dataset sequences
5152 * Map from ID strings to jalview datamodel
5154 * Map from jalview datamodel to ID strings
5158 public void setObjectMappingTables(Hashtable vobj2jv,
5159 IdentityHashMap jv2vobj)
5161 this.jv2vobj = jv2vobj;
5162 this.vobj2jv = vobj2jv;
5163 Iterator ds = jv2vobj.keySet().iterator();
5165 while (ds.hasNext())
5167 Object jvobj = ds.next();
5168 id = jv2vobj.get(jvobj).toString();
5169 if (jvobj instanceof jalview.datamodel.Alignment)
5171 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
5173 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
5176 else if (jvobj instanceof jalview.datamodel.Sequence)
5178 // register sequence object so the XML parser can recover it.
5179 if (seqRefIds == null)
5181 seqRefIds = new HashMap<String, SequenceI>();
5183 if (seqsToIds == null)
5185 seqsToIds = new IdentityHashMap<SequenceI, String>();
5187 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
5188 seqsToIds.put((SequenceI) jvobj, id);
5190 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
5193 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
5194 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
5195 if (jvann.annotationId == null)
5197 jvann.annotationId = anid;
5199 if (!jvann.annotationId.equals(anid))
5201 // TODO verify that this is the correct behaviour
5202 this.warn("Overriding Annotation ID for " + anid
5203 + " from different id : " + jvann.annotationId);
5204 jvann.annotationId = anid;
5207 else if (jvobj instanceof String)
5209 if (jvids2vobj == null)
5211 jvids2vobj = new Hashtable();
5212 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
5217 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
5223 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
5224 * objects created from the project archive. If string is null (default for
5225 * construction) then suffix will be set automatically.
5229 public void setUniqueSetSuffix(String string)
5231 uniqueSetSuffix = string;
5236 * uses skipList2 as the skipList for skipping views on sequence sets
5237 * associated with keys in the skipList
5241 public void setSkipList(Hashtable skipList2)
5243 skipList = skipList2;
5247 * Reads the jar entry of given name and returns its contents, or null if the
5248 * entry is not found.
5251 * @param jarEntryName
5254 protected String readJarEntry(jarInputStreamProvider jprovider,
5255 String jarEntryName)
5257 String result = null;
5258 BufferedReader in = null;
5263 * Reopen the jar input stream and traverse its entries to find a matching
5266 JarInputStream jin = jprovider.getJarInputStream();
5267 JarEntry entry = null;
5270 entry = jin.getNextJarEntry();
5271 } while (entry != null && !entry.getName().equals(jarEntryName));
5275 StringBuilder out = new StringBuilder(256);
5276 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
5279 while ((data = in.readLine()) != null)
5283 result = out.toString();
5287 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
5289 } catch (Exception ex)
5291 ex.printStackTrace();
5299 } catch (IOException e)
5310 * Returns an incrementing counter (0, 1, 2...)
5314 private synchronized int nextCounter()