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.analysis.Conservation;
24 import jalview.api.FeatureColourI;
25 import jalview.api.ViewStyleI;
26 import jalview.api.structures.JalviewStructureDisplayI;
27 import jalview.bin.Cache;
28 import jalview.datamodel.AlignedCodonFrame;
29 import jalview.datamodel.Alignment;
30 import jalview.datamodel.AlignmentAnnotation;
31 import jalview.datamodel.AlignmentI;
32 import jalview.datamodel.PDBEntry;
33 import jalview.datamodel.RnaViewerModel;
34 import jalview.datamodel.SequenceGroup;
35 import jalview.datamodel.SequenceI;
36 import jalview.datamodel.StructureViewerModel;
37 import jalview.datamodel.StructureViewerModel.StructureData;
38 import jalview.ext.varna.RnaModel;
39 import jalview.gui.StructureViewer.ViewerType;
40 import jalview.io.DataSourceType;
41 import jalview.io.FileFormat;
42 import jalview.renderer.ResidueShaderI;
43 import jalview.schemabinding.version2.AlcodMap;
44 import jalview.schemabinding.version2.AlcodonFrame;
45 import jalview.schemabinding.version2.Annotation;
46 import jalview.schemabinding.version2.AnnotationColours;
47 import jalview.schemabinding.version2.AnnotationElement;
48 import jalview.schemabinding.version2.CalcIdParam;
49 import jalview.schemabinding.version2.DBRef;
50 import jalview.schemabinding.version2.Features;
51 import jalview.schemabinding.version2.Group;
52 import jalview.schemabinding.version2.HiddenColumns;
53 import jalview.schemabinding.version2.JGroup;
54 import jalview.schemabinding.version2.JSeq;
55 import jalview.schemabinding.version2.JalviewModel;
56 import jalview.schemabinding.version2.JalviewModelSequence;
57 import jalview.schemabinding.version2.MapListFrom;
58 import jalview.schemabinding.version2.MapListTo;
59 import jalview.schemabinding.version2.Mapping;
60 import jalview.schemabinding.version2.MappingChoice;
61 import jalview.schemabinding.version2.OtherData;
62 import jalview.schemabinding.version2.PdbentryItem;
63 import jalview.schemabinding.version2.Pdbids;
64 import jalview.schemabinding.version2.Property;
65 import jalview.schemabinding.version2.RnaViewer;
66 import jalview.schemabinding.version2.SecondaryStructure;
67 import jalview.schemabinding.version2.Sequence;
68 import jalview.schemabinding.version2.SequenceSet;
69 import jalview.schemabinding.version2.SequenceSetProperties;
70 import jalview.schemabinding.version2.Setting;
71 import jalview.schemabinding.version2.StructureState;
72 import jalview.schemabinding.version2.ThresholdLine;
73 import jalview.schemabinding.version2.Tree;
74 import jalview.schemabinding.version2.UserColours;
75 import jalview.schemabinding.version2.Viewport;
76 import jalview.schemes.AnnotationColourGradient;
77 import jalview.schemes.ColourSchemeI;
78 import jalview.schemes.ColourSchemeProperty;
79 import jalview.schemes.FeatureColour;
80 import jalview.schemes.ResidueColourScheme;
81 import jalview.schemes.ResidueProperties;
82 import jalview.schemes.UserColourScheme;
83 import jalview.structure.StructureSelectionManager;
84 import jalview.structures.models.AAStructureBindingModel;
85 import jalview.util.MessageManager;
86 import jalview.util.Platform;
87 import jalview.util.StringUtils;
88 import jalview.util.jarInputStreamProvider;
89 import jalview.viewmodel.AlignmentViewport;
90 import jalview.viewmodel.ViewportRanges;
91 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
92 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
93 import jalview.ws.jws2.Jws2Discoverer;
94 import jalview.ws.jws2.dm.AAConSettings;
95 import jalview.ws.jws2.jabaws2.Jws2Instance;
96 import jalview.ws.params.ArgumentI;
97 import jalview.ws.params.AutoCalcSetting;
98 import jalview.ws.params.WsParamSetI;
100 import java.awt.Color;
101 import java.awt.Rectangle;
102 import java.io.BufferedReader;
103 import java.io.DataInputStream;
104 import java.io.DataOutputStream;
106 import java.io.FileInputStream;
107 import java.io.FileOutputStream;
108 import java.io.IOException;
109 import java.io.InputStreamReader;
110 import java.io.OutputStreamWriter;
111 import java.io.PrintWriter;
112 import java.lang.reflect.InvocationTargetException;
113 import java.net.MalformedURLException;
115 import java.util.ArrayList;
116 import java.util.Arrays;
117 import java.util.Enumeration;
118 import java.util.HashMap;
119 import java.util.HashSet;
120 import java.util.Hashtable;
121 import java.util.IdentityHashMap;
122 import java.util.Iterator;
123 import java.util.LinkedHashMap;
124 import java.util.List;
125 import java.util.Map;
126 import java.util.Map.Entry;
127 import java.util.Set;
128 import java.util.Vector;
129 import java.util.jar.JarEntry;
130 import java.util.jar.JarInputStream;
131 import java.util.jar.JarOutputStream;
133 import javax.swing.JInternalFrame;
134 import javax.swing.SwingUtilities;
136 import org.exolab.castor.xml.Marshaller;
137 import org.exolab.castor.xml.Unmarshaller;
140 * Write out the current jalview desktop state as a Jalview XML stream.
142 * Note: the vamsas objects referred to here are primitive versions of the
143 * VAMSAS project schema elements - they are not the same and most likely never
147 * @version $Revision: 1.134 $
149 public class Jalview2XML
151 private static final String VIEWER_PREFIX = "viewer_";
153 private static final String RNA_PREFIX = "rna_";
155 private static final String UTF_8 = "UTF-8";
157 // use this with nextCounter() to make unique names for entities
158 private int counter = 0;
161 * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
162 * of sequence objects are created.
164 IdentityHashMap<SequenceI, String> seqsToIds = null;
167 * jalview XML Sequence ID to jalview sequence object reference (both dataset
168 * and alignment sequences. Populated as XML reps of sequence objects are
171 Map<String, SequenceI> seqRefIds = null;
173 Map<String, SequenceI> incompleteSeqs = null;
175 List<SeqFref> frefedSequence = null;
177 boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
180 * Map of reconstructed AlignFrame objects that appear to have come from
181 * SplitFrame objects (have a dna/protein complement view).
183 private Map<Viewport, AlignFrame> splitFrameCandidates = new HashMap<Viewport, AlignFrame>();
186 * Map from displayed rna structure models to their saved session state jar
189 private Map<RnaModel, String> rnaSessions = new HashMap<RnaModel, String>();
192 * create/return unique hash string for sq
195 * @return new or existing unique string for sq
197 String seqHash(SequenceI sq)
199 if (seqsToIds == null)
203 if (seqsToIds.containsKey(sq))
205 return seqsToIds.get(sq);
209 // create sequential key
210 String key = "sq" + (seqsToIds.size() + 1);
211 key = makeHashCode(sq, key); // check we don't have an external reference
213 seqsToIds.put(sq, key);
222 if (seqRefIds != null)
226 if (seqsToIds != null)
230 if (incompleteSeqs != null)
232 incompleteSeqs.clear();
240 warn("clearSeqRefs called when _cleartables was not set. Doing nothing.");
241 // seqRefIds = new Hashtable();
242 // seqsToIds = new IdentityHashMap();
248 if (seqsToIds == null)
250 seqsToIds = new IdentityHashMap<SequenceI, String>();
252 if (seqRefIds == null)
254 seqRefIds = new HashMap<String, SequenceI>();
256 if (incompleteSeqs == null)
258 incompleteSeqs = new HashMap<String, SequenceI>();
260 if (frefedSequence == null)
262 frefedSequence = new ArrayList<SeqFref>();
270 public Jalview2XML(boolean raiseGUI)
272 this.raiseGUI = raiseGUI;
276 * base class for resolving forward references to sequences by their ID
281 abstract class SeqFref
287 public SeqFref(String _sref, String type)
293 public String getSref()
298 public SequenceI getSrefSeq()
300 return seqRefIds.get(sref);
303 public boolean isResolvable()
305 return seqRefIds.get(sref) != null;
308 public SequenceI getSrefDatasetSeq()
310 SequenceI sq = seqRefIds.get(sref);
313 while (sq.getDatasetSequence() != null)
315 sq = sq.getDatasetSequence();
322 * @return true if the forward reference was fully resolved
324 abstract boolean resolve();
327 public String toString()
329 return type + " reference to " + sref;
334 * create forward reference for a mapping
340 public SeqFref newMappingRef(final String sref,
341 final jalview.datamodel.Mapping _jmap)
343 SeqFref fref = new SeqFref(sref, "Mapping")
345 public jalview.datamodel.Mapping jmap = _jmap;
350 SequenceI seq = getSrefDatasetSeq();
362 public SeqFref newAlcodMapRef(final String sref,
363 final AlignedCodonFrame _cf, final jalview.datamodel.Mapping _jmap)
366 SeqFref fref = new SeqFref(sref, "Codon Frame")
368 AlignedCodonFrame cf = _cf;
370 public jalview.datamodel.Mapping mp = _jmap;
373 public boolean isResolvable()
375 return super.isResolvable() && mp.getTo() != null;
381 SequenceI seq = getSrefDatasetSeq();
386 cf.addMap(seq, mp.getTo(), mp.getMap());
393 public void resolveFrefedSequences()
395 Iterator<SeqFref> nextFref = frefedSequence.iterator();
396 int toresolve = frefedSequence.size();
397 int unresolved = 0, failedtoresolve = 0;
398 while (nextFref.hasNext())
400 SeqFref ref = nextFref.next();
401 if (ref.isResolvable())
413 } catch (Exception x)
416 .println("IMPLEMENTATION ERROR: Failed to resolve forward reference for sequence "
429 System.err.println("Jalview Project Import: There were " + unresolved
430 + " forward references left unresolved on the stack.");
432 if (failedtoresolve > 0)
434 System.err.println("SERIOUS! " + failedtoresolve
435 + " resolvable forward references failed to resolve.");
437 if (incompleteSeqs != null && incompleteSeqs.size() > 0)
439 System.err.println("Jalview Project Import: There are "
440 + incompleteSeqs.size()
441 + " sequences which may have incomplete metadata.");
442 if (incompleteSeqs.size() < 10)
444 for (SequenceI s : incompleteSeqs.values())
446 System.err.println(s.toString());
452 .println("Too many to report. Skipping output of incomplete sequences.");
458 * This maintains a map of viewports, the key being the seqSetId. Important to
459 * set historyItem and redoList for multiple views
461 Map<String, AlignViewport> viewportsAdded = new HashMap<String, AlignViewport>();
463 Map<String, AlignmentAnnotation> annotationIds = new HashMap<String, AlignmentAnnotation>();
465 String uniqueSetSuffix = "";
468 * List of pdbfiles added to Jar
470 List<String> pdbfiles = null;
472 // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
473 public void saveState(File statefile)
475 FileOutputStream fos = null;
478 fos = new FileOutputStream(statefile);
479 JarOutputStream jout = new JarOutputStream(fos);
482 } catch (Exception e)
484 // TODO: inform user of the problem - they need to know if their data was
486 if (errorMessage == null)
488 errorMessage = "Couldn't write Jalview Archive to output file '"
489 + statefile + "' - See console error log for details";
493 errorMessage += "(output file was '" + statefile + "')";
503 } catch (IOException e)
513 * Writes a jalview project archive to the given Jar output stream.
517 public void saveState(JarOutputStream jout)
519 AlignFrame[] frames = Desktop.getAlignFrames();
525 saveAllFrames(Arrays.asList(frames), jout);
529 * core method for storing state for a set of AlignFrames.
532 * - frames involving all data to be exported (including containing
535 * - project output stream
537 private void saveAllFrames(List<AlignFrame> frames, JarOutputStream jout)
539 Hashtable<String, AlignFrame> dsses = new Hashtable<String, AlignFrame>();
542 * ensure cached data is clear before starting
544 // todo tidy up seqRefIds, seqsToIds initialisation / reset
546 splitFrameCandidates.clear();
551 // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
552 // //////////////////////////////////////////////////
554 List<String> shortNames = new ArrayList<String>();
555 List<String> viewIds = new ArrayList<String>();
558 for (int i = frames.size() - 1; i > -1; i--)
560 AlignFrame af = frames.get(i);
564 .containsKey(af.getViewport().getSequenceSetId()))
569 String shortName = makeFilename(af, shortNames);
571 int ap, apSize = af.alignPanels.size();
573 for (ap = 0; ap < apSize; ap++)
575 AlignmentPanel apanel = af.alignPanels.get(ap);
576 String fileName = apSize == 1 ? shortName : ap + shortName;
577 if (!fileName.endsWith(".xml"))
579 fileName = fileName + ".xml";
582 saveState(apanel, fileName, jout, viewIds);
584 String dssid = getDatasetIdRef(af.getViewport().getAlignment()
586 if (!dsses.containsKey(dssid))
588 dsses.put(dssid, af);
593 writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix,
599 } catch (Exception foo)
604 } catch (Exception ex)
606 // TODO: inform user of the problem - they need to know if their data was
608 if (errorMessage == null)
610 errorMessage = "Couldn't write Jalview Archive - see error output for details";
612 ex.printStackTrace();
617 * Generates a distinct file name, based on the title of the AlignFrame, by
618 * appending _n for increasing n until an unused name is generated. The new
619 * name (without its extension) is added to the list.
623 * @return the generated name, with .xml extension
625 protected String makeFilename(AlignFrame af, List<String> namesUsed)
627 String shortName = af.getTitle();
629 if (shortName.indexOf(File.separatorChar) > -1)
631 shortName = shortName.substring(shortName
632 .lastIndexOf(File.separatorChar) + 1);
637 while (namesUsed.contains(shortName))
639 if (shortName.endsWith("_" + (count - 1)))
641 shortName = shortName.substring(0, shortName.lastIndexOf("_"));
644 shortName = shortName.concat("_" + count);
648 namesUsed.add(shortName);
650 if (!shortName.endsWith(".xml"))
652 shortName = shortName + ".xml";
657 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
658 public boolean saveAlignment(AlignFrame af, String jarFile,
663 FileOutputStream fos = new FileOutputStream(jarFile);
664 JarOutputStream jout = new JarOutputStream(fos);
665 List<AlignFrame> frames = new ArrayList<AlignFrame>();
667 // resolve splitframes
668 if (af.getViewport().getCodingComplement() != null)
670 frames = ((SplitFrame) af.getSplitViewContainer()).getAlignFrames();
676 saveAllFrames(frames, jout);
680 } catch (Exception foo)
686 } catch (Exception ex)
688 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
689 ex.printStackTrace();
694 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
695 String fileName, JarOutputStream jout)
698 for (String dssids : dsses.keySet())
700 AlignFrame _af = dsses.get(dssids);
701 String jfileName = fileName + " Dataset for " + _af.getTitle();
702 if (!jfileName.endsWith(".xml"))
704 jfileName = jfileName + ".xml";
706 saveState(_af.alignPanel, jfileName, true, jout, null);
711 * create a JalviewModel from an alignment view and marshall it to a
715 * panel to create jalview model for
717 * name of alignment panel written to output stream
724 public JalviewModel saveState(AlignmentPanel ap, String fileName,
725 JarOutputStream jout, List<String> viewIds)
727 return saveState(ap, fileName, false, jout, viewIds);
731 * create a JalviewModel from an alignment view and marshall it to a
735 * panel to create jalview model for
737 * name of alignment panel written to output stream
739 * when true, only write the dataset for the alignment, not the data
740 * associated with the view.
746 public JalviewModel saveState(AlignmentPanel ap, String fileName,
747 boolean storeDS, JarOutputStream jout, List<String> viewIds)
751 viewIds = new ArrayList<String>();
756 List<UserColourScheme> userColours = new ArrayList<UserColourScheme>();
758 AlignViewport av = ap.av;
759 ViewportRanges vpRanges = av.getRanges();
761 JalviewModel object = new JalviewModel();
762 object.setVamsasModel(new jalview.schemabinding.version2.VamsasModel());
764 object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
765 object.setVersion(jalview.bin.Cache.getDefault("VERSION",
766 "Development Build"));
769 * rjal is full height alignment, jal is actual alignment with full metadata
770 * but excludes hidden sequences.
772 jalview.datamodel.AlignmentI rjal = av.getAlignment(), jal = rjal;
774 if (av.hasHiddenRows())
776 rjal = jal.getHiddenSequences().getFullAlignment();
779 SequenceSet vamsasSet = new SequenceSet();
781 JalviewModelSequence jms = new JalviewModelSequence();
783 vamsasSet.setGapChar(jal.getGapCharacter() + "");
785 if (jal.getDataset() != null)
787 // dataset id is the dataset's hashcode
788 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
791 // switch jal and the dataset
792 jal = jal.getDataset();
796 if (jal.getProperties() != null)
798 Enumeration en = jal.getProperties().keys();
799 while (en.hasMoreElements())
801 String key = en.nextElement().toString();
802 SequenceSetProperties ssp = new SequenceSetProperties();
804 ssp.setValue(jal.getProperties().get(key).toString());
805 vamsasSet.addSequenceSetProperties(ssp);
810 Set<String> calcIdSet = new HashSet<String>();
811 // record the set of vamsas sequence XML POJO we create.
812 HashMap<String, Sequence> vamsasSetIds = new HashMap<String, Sequence>();
814 for (final SequenceI jds : rjal.getSequences())
816 final SequenceI jdatasq = jds.getDatasetSequence() == null ? jds
817 : jds.getDatasetSequence();
818 String id = seqHash(jds);
819 if (vamsasSetIds.get(id) == null)
821 if (seqRefIds.get(id) != null && !storeDS)
823 // This happens for two reasons: 1. multiple views are being
825 // 2. the hashCode has collided with another sequence's code. This
827 // HAPPEN! (PF00072.15.stk does this)
828 // JBPNote: Uncomment to debug writing out of files that do not read
829 // back in due to ArrayOutOfBoundExceptions.
830 // System.err.println("vamsasSeq backref: "+id+"");
831 // System.err.println(jds.getName()+"
832 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
833 // System.err.println("Hashcode: "+seqHash(jds));
834 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
835 // System.err.println(rsq.getName()+"
836 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
837 // System.err.println("Hashcode: "+seqHash(rsq));
841 vamsasSeq = createVamsasSequence(id, jds);
842 vamsasSet.addSequence(vamsasSeq);
843 vamsasSetIds.put(id, vamsasSeq);
844 seqRefIds.put(id, jds);
848 jseq.setStart(jds.getStart());
849 jseq.setEnd(jds.getEnd());
850 jseq.setColour(av.getSequenceColour(jds).getRGB());
852 jseq.setId(id); // jseq id should be a string not a number
855 // Store any sequences this sequence represents
856 if (av.hasHiddenRows())
858 // use rjal, contains the full height alignment
859 jseq.setHidden(av.getAlignment().getHiddenSequences()
862 if (av.isHiddenRepSequence(jds))
864 jalview.datamodel.SequenceI[] reps = av
865 .getRepresentedSequences(jds).getSequencesInOrder(rjal);
867 for (int h = 0; h < reps.length; h++)
871 jseq.addHiddenSequences(rjal.findIndex(reps[h]));
876 // mark sequence as reference - if it is the reference for this view
879 jseq.setViewreference(jds == jal.getSeqrep());
883 // TODO: omit sequence features from each alignment view's XML dump if we
884 // are storing dataset
885 if (jds.getSequenceFeatures() != null)
887 jalview.datamodel.SequenceFeature[] sf = jds.getSequenceFeatures();
889 while (index < sf.length)
891 Features features = new Features();
893 features.setBegin(sf[index].getBegin());
894 features.setEnd(sf[index].getEnd());
895 features.setDescription(sf[index].getDescription());
896 features.setType(sf[index].getType());
897 features.setFeatureGroup(sf[index].getFeatureGroup());
898 features.setScore(sf[index].getScore());
899 if (sf[index].links != null)
901 for (int l = 0; l < sf[index].links.size(); l++)
903 OtherData keyValue = new OtherData();
904 keyValue.setKey("LINK_" + l);
905 keyValue.setValue(sf[index].links.elementAt(l).toString());
906 features.addOtherData(keyValue);
909 if (sf[index].otherDetails != null)
912 Iterator<String> keys = sf[index].otherDetails.keySet()
914 while (keys.hasNext())
917 OtherData keyValue = new OtherData();
918 keyValue.setKey(key);
919 keyValue.setValue(sf[index].otherDetails.get(key).toString());
920 features.addOtherData(keyValue);
924 jseq.addFeatures(features);
929 if (jdatasq.getAllPDBEntries() != null)
931 Enumeration en = jdatasq.getAllPDBEntries().elements();
932 while (en.hasMoreElements())
934 Pdbids pdb = new Pdbids();
935 jalview.datamodel.PDBEntry entry = (jalview.datamodel.PDBEntry) en
938 String pdbId = entry.getId();
940 pdb.setType(entry.getType());
943 * Store any structure views associated with this sequence. This
944 * section copes with duplicate entries in the project, so a dataset
945 * only view *should* be coped with sensibly.
947 // This must have been loaded, is it still visible?
948 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
949 String matchedFile = null;
950 for (int f = frames.length - 1; f > -1; f--)
952 if (frames[f] instanceof StructureViewerBase)
954 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
955 matchedFile = saveStructureState(ap, jds, pdb, entry,
956 viewIds, matchedFile, viewFrame);
958 * Only store each structure viewer's state once in the project
959 * jar. First time through only (storeDS==false)
961 String viewId = viewFrame.getViewId();
962 if (!storeDS && !viewIds.contains(viewId))
967 String viewerState = viewFrame.getStateInfo();
968 writeJarEntry(jout, getViewerJarEntryName(viewId),
969 viewerState.getBytes());
970 } catch (IOException e)
972 System.err.println("Error saving viewer state: "
979 if (matchedFile != null || entry.getFile() != null)
981 if (entry.getFile() != null)
984 matchedFile = entry.getFile();
986 pdb.setFile(matchedFile); // entry.getFile());
987 if (pdbfiles == null)
989 pdbfiles = new ArrayList<String>();
992 if (!pdbfiles.contains(pdbId))
995 copyFileToJar(jout, matchedFile, pdbId);
999 Enumeration<String> props = entry.getProperties();
1000 if (props.hasMoreElements())
1002 PdbentryItem item = new PdbentryItem();
1003 while (props.hasMoreElements())
1005 Property prop = new Property();
1006 String key = props.nextElement();
1008 prop.setValue(entry.getProperty(key).toString());
1009 item.addProperty(prop);
1011 pdb.addPdbentryItem(item);
1014 jseq.addPdbids(pdb);
1018 saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
1023 if (!storeDS && av.hasHiddenRows())
1025 jal = av.getAlignment();
1029 if (storeDS && jal.getCodonFrames() != null)
1031 List<AlignedCodonFrame> jac = jal.getCodonFrames();
1032 for (AlignedCodonFrame acf : jac)
1034 AlcodonFrame alc = new AlcodonFrame();
1035 if (acf.getProtMappings() != null
1036 && acf.getProtMappings().length > 0)
1038 boolean hasMap = false;
1039 SequenceI[] dnas = acf.getdnaSeqs();
1040 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1041 for (int m = 0; m < pmaps.length; m++)
1043 AlcodMap alcmap = new AlcodMap();
1044 alcmap.setDnasq(seqHash(dnas[m]));
1045 alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
1047 alc.addAlcodMap(alcmap);
1052 vamsasSet.addAlcodonFrame(alc);
1055 // TODO: delete this ? dead code from 2.8.3->2.9 ?
1057 // AlcodonFrame alc = new AlcodonFrame();
1058 // vamsasSet.addAlcodonFrame(alc);
1059 // for (int p = 0; p < acf.aaWidth; p++)
1061 // Alcodon cmap = new Alcodon();
1062 // if (acf.codons[p] != null)
1064 // // Null codons indicate a gapped column in the translated peptide
1066 // cmap.setPos1(acf.codons[p][0]);
1067 // cmap.setPos2(acf.codons[p][1]);
1068 // cmap.setPos3(acf.codons[p][2]);
1070 // alc.addAlcodon(cmap);
1072 // if (acf.getProtMappings() != null
1073 // && acf.getProtMappings().length > 0)
1075 // SequenceI[] dnas = acf.getdnaSeqs();
1076 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1077 // for (int m = 0; m < pmaps.length; m++)
1079 // AlcodMap alcmap = new AlcodMap();
1080 // alcmap.setDnasq(seqHash(dnas[m]));
1081 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
1083 // alc.addAlcodMap(alcmap);
1090 // /////////////////////////////////
1091 if (!storeDS && av.currentTree != null)
1093 // FIND ANY ASSOCIATED TREES
1094 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
1095 if (Desktop.desktop != null)
1097 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1099 for (int t = 0; t < frames.length; t++)
1101 if (frames[t] instanceof TreePanel)
1103 TreePanel tp = (TreePanel) frames[t];
1105 if (tp.treeCanvas.av.getAlignment() == jal)
1107 Tree tree = new Tree();
1108 tree.setTitle(tp.getTitle());
1109 tree.setCurrentTree((av.currentTree == tp.getTree()));
1110 tree.setNewick(tp.getTree().toString());
1111 tree.setThreshold(tp.treeCanvas.threshold);
1113 tree.setFitToWindow(tp.fitToWindow.getState());
1114 tree.setFontName(tp.getTreeFont().getName());
1115 tree.setFontSize(tp.getTreeFont().getSize());
1116 tree.setFontStyle(tp.getTreeFont().getStyle());
1117 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
1119 tree.setShowBootstrap(tp.bootstrapMenu.getState());
1120 tree.setShowDistances(tp.distanceMenu.getState());
1122 tree.setHeight(tp.getHeight());
1123 tree.setWidth(tp.getWidth());
1124 tree.setXpos(tp.getX());
1125 tree.setYpos(tp.getY());
1126 tree.setId(makeHashCode(tp, null));
1136 * store forward refs from an annotationRow to any groups
1138 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<SequenceGroup, String>();
1141 for (SequenceI sq : jal.getSequences())
1143 // Store annotation on dataset sequences only
1144 AlignmentAnnotation[] aa = sq.getAnnotation();
1145 if (aa != null && aa.length > 0)
1147 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1154 if (jal.getAlignmentAnnotation() != null)
1156 // Store the annotation shown on the alignment.
1157 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1158 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1163 if (jal.getGroups() != null)
1165 JGroup[] groups = new JGroup[jal.getGroups().size()];
1167 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1169 JGroup jGroup = new JGroup();
1170 groups[++i] = jGroup;
1172 jGroup.setStart(sg.getStartRes());
1173 jGroup.setEnd(sg.getEndRes());
1174 jGroup.setName(sg.getName());
1175 if (groupRefs.containsKey(sg))
1177 // group has references so set its ID field
1178 jGroup.setId(groupRefs.get(sg));
1180 ColourSchemeI colourScheme = sg.getColourScheme();
1181 if (colourScheme != null)
1183 ResidueShaderI groupColourScheme = sg
1184 .getGroupColourScheme();
1185 if (groupColourScheme.conservationApplied())
1187 jGroup.setConsThreshold(groupColourScheme.getConservationInc());
1189 if (colourScheme instanceof jalview.schemes.UserColourScheme)
1191 jGroup.setColour(setUserColourScheme(colourScheme,
1196 jGroup.setColour(colourScheme.getSchemeName());
1199 else if (colourScheme instanceof jalview.schemes.AnnotationColourGradient)
1201 jGroup.setColour("AnnotationColourGradient");
1202 jGroup.setAnnotationColours(constructAnnotationColours(
1203 (jalview.schemes.AnnotationColourGradient) colourScheme,
1206 else if (colourScheme instanceof jalview.schemes.UserColourScheme)
1208 jGroup.setColour(setUserColourScheme(colourScheme,
1213 jGroup.setColour(colourScheme.getSchemeName());
1216 jGroup.setPidThreshold(groupColourScheme.getThreshold());
1219 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1220 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1221 jGroup.setDisplayText(sg.getDisplayText());
1222 jGroup.setColourText(sg.getColourText());
1223 jGroup.setTextCol1(sg.textColour.getRGB());
1224 jGroup.setTextCol2(sg.textColour2.getRGB());
1225 jGroup.setTextColThreshold(sg.thresholdTextColour);
1226 jGroup.setShowUnconserved(sg.getShowNonconserved());
1227 jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1228 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1229 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1230 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1231 for (SequenceI seq : sg.getSequences())
1233 jGroup.addSeq(seqHash(seq));
1237 jms.setJGroup(groups);
1241 // /////////SAVE VIEWPORT
1242 Viewport view = new Viewport();
1243 view.setTitle(ap.alignFrame.getTitle());
1244 view.setSequenceSetId(makeHashCode(av.getSequenceSetId(),
1245 av.getSequenceSetId()));
1246 view.setId(av.getViewId());
1247 if (av.getCodingComplement() != null)
1249 view.setComplementId(av.getCodingComplement().getViewId());
1251 view.setViewName(av.viewName);
1252 view.setGatheredViews(av.isGatherViewsHere());
1254 Rectangle size = ap.av.getExplodedGeometry();
1255 Rectangle position = size;
1258 size = ap.alignFrame.getBounds();
1259 if (av.getCodingComplement() != null)
1261 position = ((SplitFrame) ap.alignFrame.getSplitViewContainer())
1269 view.setXpos(position.x);
1270 view.setYpos(position.y);
1272 view.setWidth(size.width);
1273 view.setHeight(size.height);
1275 view.setStartRes(vpRanges.getStartRes());
1276 view.setStartSeq(vpRanges.getStartSeq());
1278 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1280 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1283 else if (av.getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1285 AnnotationColours ac = constructAnnotationColours(
1286 (jalview.schemes.AnnotationColourGradient) av
1287 .getGlobalColourScheme(),
1290 view.setAnnotationColours(ac);
1291 view.setBgColour("AnnotationColourGradient");
1295 view.setBgColour(ColourSchemeProperty.getColourName(av
1296 .getGlobalColourScheme()));
1299 ResidueShaderI vcs = av.getResidueShading();
1300 ColourSchemeI cs = av.getGlobalColourScheme();
1304 if (vcs.conservationApplied())
1306 view.setConsThreshold(vcs.getConservationInc());
1307 if (cs instanceof jalview.schemes.UserColourScheme)
1309 view.setBgColour(setUserColourScheme(cs, userColours, jms));
1312 view.setPidThreshold(vcs.getThreshold());
1315 view.setConservationSelected(av.getConservationSelected());
1316 view.setPidSelected(av.getAbovePIDThreshold());
1317 view.setFontName(av.font.getName());
1318 view.setFontSize(av.font.getSize());
1319 view.setFontStyle(av.font.getStyle());
1320 view.setScaleProteinAsCdna(av.getViewStyle().isScaleProteinAsCdna());
1321 view.setRenderGaps(av.isRenderGaps());
1322 view.setShowAnnotation(av.isShowAnnotation());
1323 view.setShowBoxes(av.getShowBoxes());
1324 view.setShowColourText(av.getColourText());
1325 view.setShowFullId(av.getShowJVSuffix());
1326 view.setRightAlignIds(av.isRightAlignIds());
1327 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1328 view.setShowText(av.getShowText());
1329 view.setShowUnconserved(av.getShowUnconserved());
1330 view.setWrapAlignment(av.getWrapAlignment());
1331 view.setTextCol1(av.getTextColour().getRGB());
1332 view.setTextCol2(av.getTextColour2().getRGB());
1333 view.setTextColThreshold(av.getThresholdTextColour());
1334 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1335 view.setShowSequenceLogo(av.isShowSequenceLogo());
1336 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1337 view.setShowGroupConsensus(av.isShowGroupConsensus());
1338 view.setShowGroupConservation(av.isShowGroupConservation());
1339 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1340 view.setShowDbRefTooltip(av.isShowDBRefs());
1341 view.setFollowHighlight(av.isFollowHighlight());
1342 view.setFollowSelection(av.followSelection);
1343 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1344 if (av.getFeaturesDisplayed() != null)
1346 jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
1348 String[] renderOrder = ap.getSeqPanel().seqCanvas
1349 .getFeatureRenderer().getRenderOrder()
1350 .toArray(new String[0]);
1352 Vector<String> settingsAdded = new Vector<String>();
1353 if (renderOrder != null)
1355 for (String featureType : renderOrder)
1357 FeatureColourI fcol = ap.getSeqPanel().seqCanvas
1358 .getFeatureRenderer().getFeatureStyle(featureType);
1359 Setting setting = new Setting();
1360 setting.setType(featureType);
1361 if (!fcol.isSimpleColour())
1363 setting.setColour(fcol.getMaxColour().getRGB());
1364 setting.setMincolour(fcol.getMinColour().getRGB());
1365 setting.setMin(fcol.getMin());
1366 setting.setMax(fcol.getMax());
1367 setting.setColourByLabel(fcol.isColourByLabel());
1368 setting.setAutoScale(fcol.isAutoScaled());
1369 setting.setThreshold(fcol.getThreshold());
1370 // -1 = No threshold, 0 = Below, 1 = Above
1371 setting.setThreshstate(fcol.isAboveThreshold() ? 1 : (fcol
1372 .isBelowThreshold() ? 0 : -1));
1376 setting.setColour(fcol.getColour().getRGB());
1379 setting.setDisplay(av.getFeaturesDisplayed().isVisible(
1381 float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1382 .getOrder(featureType);
1385 setting.setOrder(rorder);
1387 fs.addSetting(setting);
1388 settingsAdded.addElement(featureType);
1392 // is groups actually supposed to be a map here ?
1393 Iterator<String> en = ap.getSeqPanel().seqCanvas
1394 .getFeatureRenderer().getFeatureGroups().iterator();
1395 Vector<String> groupsAdded = new Vector<String>();
1396 while (en.hasNext())
1398 String grp = en.next();
1399 if (groupsAdded.contains(grp))
1403 Group g = new Group();
1405 g.setDisplay(((Boolean) ap.getSeqPanel().seqCanvas
1406 .getFeatureRenderer().checkGroupVisibility(grp, false))
1409 groupsAdded.addElement(grp);
1411 jms.setFeatureSettings(fs);
1414 if (av.hasHiddenColumns())
1416 if (av.getColumnSelection() == null
1417 || av.getColumnSelection().getHiddenColumns() == null)
1419 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1423 for (int c = 0; c < av.getColumnSelection().getHiddenColumns()
1426 int[] region = av.getColumnSelection().getHiddenColumns()
1428 HiddenColumns hc = new HiddenColumns();
1429 hc.setStart(region[0]);
1430 hc.setEnd(region[1]);
1431 view.addHiddenColumns(hc);
1435 if (calcIdSet.size() > 0)
1437 for (String calcId : calcIdSet)
1439 if (calcId.trim().length() > 0)
1441 CalcIdParam cidp = createCalcIdParam(calcId, av);
1442 // Some calcIds have no parameters.
1445 view.addCalcIdParam(cidp);
1451 jms.addViewport(view);
1453 object.setJalviewModelSequence(jms);
1454 object.getVamsasModel().addSequenceSet(vamsasSet);
1456 if (jout != null && fileName != null)
1458 // We may not want to write the object to disk,
1459 // eg we can copy the alignViewport to a new view object
1460 // using save and then load
1463 System.out.println("Writing jar entry " + fileName);
1464 JarEntry entry = new JarEntry(fileName);
1465 jout.putNextEntry(entry);
1466 PrintWriter pout = new PrintWriter(new OutputStreamWriter(jout,
1468 Marshaller marshaller = new Marshaller(pout);
1469 marshaller.marshal(object);
1472 } catch (Exception ex)
1474 // TODO: raise error in GUI if marshalling failed.
1475 ex.printStackTrace();
1482 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1483 * for each viewer, with
1485 * <li>viewer geometry (position, size, split pane divider location)</li>
1486 * <li>index of the selected structure in the viewer (currently shows gapped
1488 * <li>the id of the annotation holding RNA secondary structure</li>
1489 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1491 * Varna viewer state is also written out (in native Varna XML) to separate
1492 * project jar entries. A separate entry is written for each RNA structure
1493 * displayed, with the naming convention
1495 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
1503 * @param storeDataset
1505 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
1506 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
1507 boolean storeDataset)
1509 if (Desktop.desktop == null)
1513 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1514 for (int f = frames.length - 1; f > -1; f--)
1516 if (frames[f] instanceof AppVarna)
1518 AppVarna varna = (AppVarna) frames[f];
1520 * link the sequence to every viewer that is showing it and is linked to
1521 * its alignment panel
1523 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1525 String viewId = varna.getViewId();
1526 RnaViewer rna = new RnaViewer();
1527 rna.setViewId(viewId);
1528 rna.setTitle(varna.getTitle());
1529 rna.setXpos(varna.getX());
1530 rna.setYpos(varna.getY());
1531 rna.setWidth(varna.getWidth());
1532 rna.setHeight(varna.getHeight());
1533 rna.setDividerLocation(varna.getDividerLocation());
1534 rna.setSelectedRna(varna.getSelectedIndex());
1535 jseq.addRnaViewer(rna);
1538 * Store each Varna panel's state once in the project per sequence.
1539 * First time through only (storeDataset==false)
1541 // boolean storeSessions = false;
1542 // String sequenceViewId = viewId + seqsToIds.get(jds);
1543 // if (!storeDataset && !viewIds.contains(sequenceViewId))
1545 // viewIds.add(sequenceViewId);
1546 // storeSessions = true;
1548 for (RnaModel model : varna.getModels())
1550 if (model.seq == jds)
1553 * VARNA saves each view (sequence or alignment secondary
1554 * structure, gapped or trimmed) as a separate XML file
1556 String jarEntryName = rnaSessions.get(model);
1557 if (jarEntryName == null)
1560 String varnaStateFile = varna.getStateInfo(model.rna);
1561 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
1562 copyFileToJar(jout, varnaStateFile, jarEntryName);
1563 rnaSessions.put(model, jarEntryName);
1565 SecondaryStructure ss = new SecondaryStructure();
1566 String annotationId = varna.getAnnotation(jds).annotationId;
1567 ss.setAnnotationId(annotationId);
1568 ss.setViewerState(jarEntryName);
1569 ss.setGapped(model.gapped);
1570 ss.setTitle(model.title);
1571 rna.addSecondaryStructure(ss);
1580 * Copy the contents of a file to a new entry added to the output jar
1584 * @param jarEntryName
1586 protected void copyFileToJar(JarOutputStream jout, String infilePath,
1587 String jarEntryName)
1589 DataInputStream dis = null;
1592 File file = new File(infilePath);
1593 if (file.exists() && jout != null)
1595 dis = new DataInputStream(new FileInputStream(file));
1596 byte[] data = new byte[(int) file.length()];
1597 dis.readFully(data);
1598 writeJarEntry(jout, jarEntryName, data);
1600 } catch (Exception ex)
1602 ex.printStackTrace();
1610 } catch (IOException e)
1619 * Write the data to a new entry of given name in the output jar file
1622 * @param jarEntryName
1624 * @throws IOException
1626 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
1627 byte[] data) throws IOException
1631 System.out.println("Writing jar entry " + jarEntryName);
1632 jout.putNextEntry(new JarEntry(jarEntryName));
1633 DataOutputStream dout = new DataOutputStream(jout);
1634 dout.write(data, 0, data.length);
1641 * Save the state of a structure viewer
1646 * the archive XML element under which to save the state
1649 * @param matchedFile
1653 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
1654 Pdbids pdb, PDBEntry entry, List<String> viewIds,
1655 String matchedFile, StructureViewerBase viewFrame)
1657 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
1660 * Look for any bindings for this viewer to the PDB file of interest
1661 * (including part matches excluding chain id)
1663 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
1665 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
1666 final String pdbId = pdbentry.getId();
1667 if (!pdbId.equals(entry.getId())
1668 && !(entry.getId().length() > 4 && entry.getId()
1669 .toLowerCase().startsWith(pdbId.toLowerCase())))
1672 * not interested in a binding to a different PDB entry here
1676 if (matchedFile == null)
1678 matchedFile = pdbentry.getFile();
1680 else if (!matchedFile.equals(pdbentry.getFile()))
1683 .warn("Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
1684 + pdbentry.getFile());
1688 // can get at it if the ID
1689 // match is ambiguous (e.g.
1692 for (int smap = 0; smap < viewFrame.getBinding().getSequence()[peid].length; smap++)
1694 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
1695 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
1697 StructureState state = new StructureState();
1698 state.setVisible(true);
1699 state.setXpos(viewFrame.getX());
1700 state.setYpos(viewFrame.getY());
1701 state.setWidth(viewFrame.getWidth());
1702 state.setHeight(viewFrame.getHeight());
1703 final String viewId = viewFrame.getViewId();
1704 state.setViewId(viewId);
1705 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
1706 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
1707 state.setColourByJmol(viewFrame.isColouredByViewer());
1708 state.setType(viewFrame.getViewerType().toString());
1709 pdb.addStructureState(state);
1716 private AnnotationColours constructAnnotationColours(
1717 AnnotationColourGradient acg, List<UserColourScheme> userColours,
1718 JalviewModelSequence jms)
1720 AnnotationColours ac = new AnnotationColours();
1721 ac.setAboveThreshold(acg.getAboveThreshold());
1722 ac.setThreshold(acg.getAnnotationThreshold());
1723 ac.setAnnotation(acg.getAnnotation());
1724 if (acg.getBaseColour() instanceof jalview.schemes.UserColourScheme)
1726 ac.setColourScheme(setUserColourScheme(acg.getBaseColour(),
1731 ac.setColourScheme(ColourSchemeProperty.getColourName(acg.getBaseColour()));
1734 ac.setMaxColour(acg.getMaxColour().getRGB());
1735 ac.setMinColour(acg.getMinColour().getRGB());
1736 ac.setPerSequence(acg.isSeqAssociated());
1737 ac.setPredefinedColours(acg.isPredefinedColours());
1741 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
1742 IdentityHashMap<SequenceGroup, String> groupRefs,
1743 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
1744 SequenceSet vamsasSet)
1747 for (int i = 0; i < aa.length; i++)
1749 Annotation an = new Annotation();
1751 AlignmentAnnotation annotation = aa[i];
1752 if (annotation.annotationId != null)
1754 annotationIds.put(annotation.annotationId, annotation);
1757 an.setId(annotation.annotationId);
1759 an.setVisible(annotation.visible);
1761 an.setDescription(annotation.description);
1763 if (annotation.sequenceRef != null)
1765 // 2.9 JAL-1781 xref on sequence id rather than name
1766 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
1768 if (annotation.groupRef != null)
1770 String groupIdr = groupRefs.get(annotation.groupRef);
1771 if (groupIdr == null)
1773 // make a locally unique String
1775 annotation.groupRef,
1776 groupIdr = ("" + System.currentTimeMillis()
1777 + annotation.groupRef.getName() + groupRefs
1780 an.setGroupRef(groupIdr.toString());
1783 // store all visualization attributes for annotation
1784 an.setGraphHeight(annotation.graphHeight);
1785 an.setCentreColLabels(annotation.centreColLabels);
1786 an.setScaleColLabels(annotation.scaleColLabel);
1787 an.setShowAllColLabels(annotation.showAllColLabels);
1788 an.setBelowAlignment(annotation.belowAlignment);
1790 if (annotation.graph > 0)
1793 an.setGraphType(annotation.graph);
1794 an.setGraphGroup(annotation.graphGroup);
1795 if (annotation.getThreshold() != null)
1797 ThresholdLine line = new ThresholdLine();
1798 line.setLabel(annotation.getThreshold().label);
1799 line.setValue(annotation.getThreshold().value);
1800 line.setColour(annotation.getThreshold().colour.getRGB());
1801 an.setThresholdLine(line);
1809 an.setLabel(annotation.label);
1811 if (annotation == av.getAlignmentQualityAnnot()
1812 || annotation == av.getAlignmentConservationAnnotation()
1813 || annotation == av.getAlignmentConsensusAnnotation()
1814 || annotation.autoCalculated)
1816 // new way of indicating autocalculated annotation -
1817 an.setAutoCalculated(annotation.autoCalculated);
1819 if (annotation.hasScore())
1821 an.setScore(annotation.getScore());
1824 if (annotation.getCalcId() != null)
1826 calcIdSet.add(annotation.getCalcId());
1827 an.setCalcId(annotation.getCalcId());
1829 if (annotation.hasProperties())
1831 for (String pr : annotation.getProperties())
1833 Property prop = new Property();
1835 prop.setValue(annotation.getProperty(pr));
1836 an.addProperty(prop);
1840 AnnotationElement ae;
1841 if (annotation.annotations != null)
1843 an.setScoreOnly(false);
1844 for (int a = 0; a < annotation.annotations.length; a++)
1846 if ((annotation == null) || (annotation.annotations[a] == null))
1851 ae = new AnnotationElement();
1852 if (annotation.annotations[a].description != null)
1854 ae.setDescription(annotation.annotations[a].description);
1856 if (annotation.annotations[a].displayCharacter != null)
1858 ae.setDisplayCharacter(annotation.annotations[a].displayCharacter);
1861 if (!Float.isNaN(annotation.annotations[a].value))
1863 ae.setValue(annotation.annotations[a].value);
1867 if (annotation.annotations[a].secondaryStructure > ' ')
1869 ae.setSecondaryStructure(annotation.annotations[a].secondaryStructure
1873 if (annotation.annotations[a].colour != null
1874 && annotation.annotations[a].colour != java.awt.Color.black)
1876 ae.setColour(annotation.annotations[a].colour.getRGB());
1879 an.addAnnotationElement(ae);
1880 if (annotation.autoCalculated)
1882 // only write one non-null entry into the annotation row -
1883 // sufficient to get the visualization attributes necessary to
1891 an.setScoreOnly(true);
1893 if (!storeDS || (storeDS && !annotation.autoCalculated))
1895 // skip autocalculated annotation - these are only provided for
1897 vamsasSet.addAnnotation(an);
1903 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
1905 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
1906 if (settings != null)
1908 CalcIdParam vCalcIdParam = new CalcIdParam();
1909 vCalcIdParam.setCalcId(calcId);
1910 vCalcIdParam.addServiceURL(settings.getServiceURI());
1911 // generic URI allowing a third party to resolve another instance of the
1912 // service used for this calculation
1913 for (String urls : settings.getServiceURLs())
1915 vCalcIdParam.addServiceURL(urls);
1917 vCalcIdParam.setVersion("1.0");
1918 if (settings.getPreset() != null)
1920 WsParamSetI setting = settings.getPreset();
1921 vCalcIdParam.setName(setting.getName());
1922 vCalcIdParam.setDescription(setting.getDescription());
1926 vCalcIdParam.setName("");
1927 vCalcIdParam.setDescription("Last used parameters");
1929 // need to be able to recover 1) settings 2) user-defined presets or
1930 // recreate settings from preset 3) predefined settings provided by
1931 // service - or settings that can be transferred (or discarded)
1932 vCalcIdParam.setParameters(settings.getWsParamFile().replace("\n",
1934 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
1935 // todo - decide if updateImmediately is needed for any projects.
1937 return vCalcIdParam;
1942 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
1945 if (calcIdParam.getVersion().equals("1.0"))
1947 Jws2Instance service = Jws2Discoverer.getDiscoverer()
1948 .getPreferredServiceFor(calcIdParam.getServiceURL());
1949 if (service != null)
1951 WsParamSetI parmSet = null;
1954 parmSet = service.getParamStore().parseServiceParameterFile(
1955 calcIdParam.getName(), calcIdParam.getDescription(),
1956 calcIdParam.getServiceURL(),
1957 calcIdParam.getParameters().replace("|\\n|", "\n"));
1958 } catch (IOException x)
1960 warn("Couldn't parse parameter data for "
1961 + calcIdParam.getCalcId(), x);
1964 List<ArgumentI> argList = null;
1965 if (calcIdParam.getName().length() > 0)
1967 parmSet = service.getParamStore()
1968 .getPreset(calcIdParam.getName());
1969 if (parmSet != null)
1971 // TODO : check we have a good match with settings in AACon -
1972 // otherwise we'll need to create a new preset
1977 argList = parmSet.getArguments();
1980 AAConSettings settings = new AAConSettings(
1981 calcIdParam.isAutoUpdate(), service, parmSet, argList);
1982 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
1983 calcIdParam.isNeedsUpdate());
1988 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
1992 throw new Error(MessageManager.formatMessage(
1993 "error.unsupported_version_calcIdparam",
1994 new Object[] { calcIdParam.toString() }));
1998 * External mapping between jalview objects and objects yielding a valid and
1999 * unique object ID string. This is null for normal Jalview project IO, but
2000 * non-null when a jalview project is being read or written as part of a
2003 IdentityHashMap jv2vobj = null;
2006 * Construct a unique ID for jvobj using either existing bindings or if none
2007 * exist, the result of the hashcode call for the object.
2010 * jalview data object
2011 * @return unique ID for referring to jvobj
2013 private String makeHashCode(Object jvobj, String altCode)
2015 if (jv2vobj != null)
2017 Object id = jv2vobj.get(jvobj);
2020 return id.toString();
2022 // check string ID mappings
2023 if (jvids2vobj != null && jvobj instanceof String)
2025 id = jvids2vobj.get(jvobj);
2029 return id.toString();
2031 // give up and warn that something has gone wrong
2032 warn("Cannot find ID for object in external mapping : " + jvobj);
2038 * return local jalview object mapped to ID, if it exists
2042 * @return null or object bound to idcode
2044 private Object retrieveExistingObj(String idcode)
2046 if (idcode != null && vobj2jv != null)
2048 return vobj2jv.get(idcode);
2054 * binding from ID strings from external mapping table to jalview data model
2057 private Hashtable vobj2jv;
2059 private Sequence createVamsasSequence(String id, SequenceI jds)
2061 return createVamsasSequence(true, id, jds, null);
2064 private Sequence createVamsasSequence(boolean recurse, String id,
2065 SequenceI jds, SequenceI parentseq)
2067 Sequence vamsasSeq = new Sequence();
2068 vamsasSeq.setId(id);
2069 vamsasSeq.setName(jds.getName());
2070 vamsasSeq.setSequence(jds.getSequenceAsString());
2071 vamsasSeq.setDescription(jds.getDescription());
2072 jalview.datamodel.DBRefEntry[] dbrefs = null;
2073 if (jds.getDatasetSequence() != null)
2075 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
2079 // seqId==dsseqid so we can tell which sequences really are
2080 // dataset sequences only
2081 vamsasSeq.setDsseqid(id);
2082 dbrefs = jds.getDBRefs();
2083 if (parentseq == null)
2090 for (int d = 0; d < dbrefs.length; d++)
2092 DBRef dbref = new DBRef();
2093 dbref.setSource(dbrefs[d].getSource());
2094 dbref.setVersion(dbrefs[d].getVersion());
2095 dbref.setAccessionId(dbrefs[d].getAccessionId());
2096 if (dbrefs[d].hasMap())
2098 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
2100 dbref.setMapping(mp);
2102 vamsasSeq.addDBRef(dbref);
2108 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
2109 SequenceI parentseq, SequenceI jds, boolean recurse)
2112 if (jmp.getMap() != null)
2116 jalview.util.MapList mlst = jmp.getMap();
2117 List<int[]> r = mlst.getFromRanges();
2118 for (int[] range : r)
2120 MapListFrom mfrom = new MapListFrom();
2121 mfrom.setStart(range[0]);
2122 mfrom.setEnd(range[1]);
2123 mp.addMapListFrom(mfrom);
2125 r = mlst.getToRanges();
2126 for (int[] range : r)
2128 MapListTo mto = new MapListTo();
2129 mto.setStart(range[0]);
2130 mto.setEnd(range[1]);
2131 mp.addMapListTo(mto);
2133 mp.setMapFromUnit(mlst.getFromRatio());
2134 mp.setMapToUnit(mlst.getToRatio());
2135 if (jmp.getTo() != null)
2137 MappingChoice mpc = new MappingChoice();
2139 // check/create ID for the sequence referenced by getTo()
2142 SequenceI ps = null;
2143 if (parentseq != jmp.getTo()
2144 && parentseq.getDatasetSequence() != jmp.getTo())
2146 // chaining dbref rather than a handshaking one
2147 jmpid = seqHash(ps = jmp.getTo());
2151 jmpid = seqHash(ps = parentseq);
2153 mpc.setDseqFor(jmpid);
2154 if (!seqRefIds.containsKey(mpc.getDseqFor()))
2156 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2157 seqRefIds.put(mpc.getDseqFor(), ps);
2161 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2164 mp.setMappingChoice(mpc);
2170 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2171 List<UserColourScheme> userColours, JalviewModelSequence jms)
2174 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2175 boolean newucs = false;
2176 if (!userColours.contains(ucs))
2178 userColours.add(ucs);
2181 id = "ucs" + userColours.indexOf(ucs);
2184 // actually create the scheme's entry in the XML model
2185 java.awt.Color[] colours = ucs.getColours();
2186 jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
2187 jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
2189 for (int i = 0; i < colours.length; i++)
2191 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2192 col.setName(ResidueProperties.aa[i]);
2193 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2194 jbucs.addColour(col);
2196 if (ucs.getLowerCaseColours() != null)
2198 colours = ucs.getLowerCaseColours();
2199 for (int i = 0; i < colours.length; i++)
2201 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2202 col.setName(ResidueProperties.aa[i].toLowerCase());
2203 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2204 jbucs.addColour(col);
2209 uc.setUserColourScheme(jbucs);
2210 jms.addUserColours(uc);
2216 jalview.schemes.UserColourScheme getUserColourScheme(
2217 JalviewModelSequence jms, String id)
2219 UserColours[] uc = jms.getUserColours();
2220 UserColours colours = null;
2222 for (int i = 0; i < uc.length; i++)
2224 if (uc[i].getId().equals(id))
2232 java.awt.Color[] newColours = new java.awt.Color[24];
2234 for (int i = 0; i < 24; i++)
2236 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2237 .getUserColourScheme().getColour(i).getRGB(), 16));
2240 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2243 if (colours.getUserColourScheme().getColourCount() > 24)
2245 newColours = new java.awt.Color[23];
2246 for (int i = 0; i < 23; i++)
2248 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2249 .getUserColourScheme().getColour(i + 24).getRGB(), 16));
2251 ucs.setLowerCaseColours(newColours);
2258 * contains last error message (if any) encountered by XML loader.
2260 String errorMessage = null;
2263 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2264 * exceptions are raised during project XML parsing
2266 public boolean attemptversion1parse = true;
2269 * Load a jalview project archive from a jar file
2272 * - HTTP URL or filename
2274 public AlignFrame loadJalviewAlign(final String file)
2277 jalview.gui.AlignFrame af = null;
2281 // create list to store references for any new Jmol viewers created
2282 newStructureViewers = new Vector<JalviewStructureDisplayI>();
2283 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2284 // Workaround is to make sure caller implements the JarInputStreamProvider
2286 // so we can re-open the jar input stream for each entry.
2288 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2289 af = loadJalviewAlign(jprovider);
2291 } catch (MalformedURLException e)
2293 errorMessage = "Invalid URL format for '" + file + "'";
2299 SwingUtilities.invokeAndWait(new Runnable()
2304 setLoadingFinishedForNewStructureViewers();
2307 } catch (Exception x)
2309 System.err.println("Error loading alignment: " + x.getMessage());
2315 private jarInputStreamProvider createjarInputStreamProvider(
2316 final String file) throws MalformedURLException
2319 errorMessage = null;
2320 uniqueSetSuffix = null;
2322 viewportsAdded.clear();
2323 frefedSequence = null;
2325 if (file.startsWith("http://"))
2327 url = new URL(file);
2329 final URL _url = url;
2330 return new jarInputStreamProvider()
2334 public JarInputStream getJarInputStream() throws IOException
2338 return new JarInputStream(_url.openStream());
2342 return new JarInputStream(new FileInputStream(file));
2347 public String getFilename()
2355 * Recover jalview session from a jalview project archive. Caller may
2356 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2357 * themselves. Any null fields will be initialised with default values,
2358 * non-null fields are left alone.
2363 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2365 errorMessage = null;
2366 if (uniqueSetSuffix == null)
2368 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2370 if (seqRefIds == null)
2374 AlignFrame af = null, _af = null;
2375 IdentityHashMap<AlignmentI, AlignmentI> importedDatasets = new IdentityHashMap<AlignmentI, AlignmentI>();
2376 Map<String, AlignFrame> gatherToThisFrame = new HashMap<String, AlignFrame>();
2377 final String file = jprovider.getFilename();
2380 JarInputStream jin = null;
2381 JarEntry jarentry = null;
2386 jin = jprovider.getJarInputStream();
2387 for (int i = 0; i < entryCount; i++)
2389 jarentry = jin.getNextJarEntry();
2392 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2394 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2395 JalviewModel object = new JalviewModel();
2397 Unmarshaller unmar = new Unmarshaller(object);
2398 unmar.setValidation(false);
2399 object = (JalviewModel) unmar.unmarshal(in);
2400 if (true) // !skipViewport(object))
2402 _af = loadFromObject(object, file, true, jprovider);
2404 && object.getJalviewModelSequence().getViewportCount() > 0)
2408 // store a reference to the first view
2411 if (_af.viewport.isGatherViewsHere())
2413 // if this is a gathered view, keep its reference since
2414 // after gathering views, only this frame will remain
2416 gatherToThisFrame.put(_af.viewport.getSequenceSetId(), _af);
2418 // Save dataset to register mappings once all resolved
2419 importedDatasets.put(af.viewport.getAlignment().getDataset(),
2420 af.viewport.getAlignment().getDataset());
2425 else if (jarentry != null)
2427 // Some other file here.
2430 } while (jarentry != null);
2431 resolveFrefedSequences();
2432 } catch (IOException ex)
2434 ex.printStackTrace();
2435 errorMessage = "Couldn't locate Jalview XML file : " + file;
2436 System.err.println("Exception whilst loading jalview XML file : "
2438 } catch (Exception ex)
2440 System.err.println("Parsing as Jalview Version 2 file failed.");
2441 ex.printStackTrace(System.err);
2442 if (attemptversion1parse)
2444 // Is Version 1 Jar file?
2447 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
2448 } catch (Exception ex2)
2450 System.err.println("Exception whilst loading as jalviewXMLV1:");
2451 ex2.printStackTrace();
2455 if (Desktop.instance != null)
2457 Desktop.instance.stopLoading();
2461 System.out.println("Successfully loaded archive file");
2464 ex.printStackTrace();
2466 System.err.println("Exception whilst loading jalview XML file : "
2468 } catch (OutOfMemoryError e)
2470 // Don't use the OOM Window here
2471 errorMessage = "Out of memory loading jalview XML file";
2472 System.err.println("Out of memory whilst loading jalview XML file");
2473 e.printStackTrace();
2477 * Regather multiple views (with the same sequence set id) to the frame (if
2478 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2479 * views instead of separate frames. Note this doesn't restore a state where
2480 * some expanded views in turn have tabbed views - the last "first tab" read
2481 * in will play the role of gatherer for all.
2483 for (AlignFrame fr : gatherToThisFrame.values())
2485 Desktop.instance.gatherViews(fr);
2488 restoreSplitFrames();
2489 for (AlignmentI ds : importedDatasets.keySet())
2491 if (ds.getCodonFrames() != null)
2493 StructureSelectionManager.getStructureSelectionManager(
2494 Desktop.instance).registerMappings(ds.getCodonFrames());
2497 if (errorMessage != null)
2502 if (Desktop.instance != null)
2504 Desktop.instance.stopLoading();
2511 * Try to reconstruct and display SplitFrame windows, where each contains
2512 * complementary dna and protein alignments. Done by pairing up AlignFrame
2513 * objects (created earlier) which have complementary viewport ids associated.
2515 protected void restoreSplitFrames()
2517 List<SplitFrame> gatherTo = new ArrayList<SplitFrame>();
2518 List<AlignFrame> addedToSplitFrames = new ArrayList<AlignFrame>();
2519 Map<String, AlignFrame> dna = new HashMap<String, AlignFrame>();
2522 * Identify the DNA alignments
2524 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2527 AlignFrame af = candidate.getValue();
2528 if (af.getViewport().getAlignment().isNucleotide())
2530 dna.put(candidate.getKey().getId(), af);
2535 * Try to match up the protein complements
2537 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2540 AlignFrame af = candidate.getValue();
2541 if (!af.getViewport().getAlignment().isNucleotide())
2543 String complementId = candidate.getKey().getComplementId();
2544 // only non-null complements should be in the Map
2545 if (complementId != null && dna.containsKey(complementId))
2547 final AlignFrame dnaFrame = dna.get(complementId);
2548 SplitFrame sf = createSplitFrame(dnaFrame, af);
2549 addedToSplitFrames.add(dnaFrame);
2550 addedToSplitFrames.add(af);
2551 dnaFrame.setMenusForViewport();
2552 af.setMenusForViewport();
2553 if (af.viewport.isGatherViewsHere())
2562 * Open any that we failed to pair up (which shouldn't happen!) as
2563 * standalone AlignFrame's.
2565 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2568 AlignFrame af = candidate.getValue();
2569 if (!addedToSplitFrames.contains(af))
2571 Viewport view = candidate.getKey();
2572 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
2574 af.setMenusForViewport();
2575 System.err.println("Failed to restore view " + view.getTitle()
2576 + " to split frame");
2581 * Gather back into tabbed views as flagged.
2583 for (SplitFrame sf : gatherTo)
2585 Desktop.instance.gatherViews(sf);
2588 splitFrameCandidates.clear();
2592 * Construct and display one SplitFrame holding DNA and protein alignments.
2595 * @param proteinFrame
2598 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
2599 AlignFrame proteinFrame)
2601 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
2602 String title = MessageManager.getString("label.linked_view_title");
2603 int width = (int) dnaFrame.getBounds().getWidth();
2604 int height = (int) (dnaFrame.getBounds().getHeight()
2605 + proteinFrame.getBounds().getHeight() + 50);
2608 * SplitFrame location is saved to both enclosed frames
2610 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
2611 Desktop.addInternalFrame(splitFrame, title, width, height);
2614 * And compute cDNA consensus (couldn't do earlier with consensus as
2615 * mappings were not yet present)
2617 proteinFrame.viewport.alignmentChanged(proteinFrame.alignPanel);
2623 * check errorMessage for a valid error message and raise an error box in the
2624 * GUI or write the current errorMessage to stderr and then clear the error
2627 protected void reportErrors()
2629 reportErrors(false);
2632 protected void reportErrors(final boolean saving)
2634 if (errorMessage != null)
2636 final String finalErrorMessage = errorMessage;
2639 javax.swing.SwingUtilities.invokeLater(new Runnable()
2644 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2645 finalErrorMessage, "Error "
2646 + (saving ? "saving" : "loading")
2647 + " Jalview file", JvOptionPane.WARNING_MESSAGE);
2653 System.err.println("Problem loading Jalview file: " + errorMessage);
2656 errorMessage = null;
2659 Map<String, String> alreadyLoadedPDB = new HashMap<String, String>();
2662 * when set, local views will be updated from view stored in JalviewXML
2663 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2664 * sync if this is set to true.
2666 private final boolean updateLocalViews = false;
2669 * Returns the path to a temporary file holding the PDB file for the given PDB
2670 * id. The first time of asking, searches for a file of that name in the
2671 * Jalview project jar, and copies it to a new temporary file. Any repeat
2672 * requests just return the path to the file previously created.
2678 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId,
2681 if (alreadyLoadedPDB.containsKey(pdbId))
2683 return alreadyLoadedPDB.get(pdbId).toString();
2686 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb",
2688 if (tempFile != null)
2690 alreadyLoadedPDB.put(pdbId, tempFile);
2696 * Copies the jar entry of given name to a new temporary file and returns the
2697 * path to the file, or null if the entry is not found.
2700 * @param jarEntryName
2702 * a prefix for the temporary file name, must be at least three
2705 * null or original file - so new file can be given the same suffix
2709 protected String copyJarEntry(jarInputStreamProvider jprovider,
2710 String jarEntryName, String prefix, String origFile)
2712 BufferedReader in = null;
2713 PrintWriter out = null;
2714 String suffix = ".tmp";
2715 if (origFile == null)
2717 origFile = jarEntryName;
2719 int sfpos = origFile.lastIndexOf(".");
2720 if (sfpos > -1 && sfpos < (origFile.length() - 3))
2722 suffix = "." + origFile.substring(sfpos + 1);
2726 JarInputStream jin = jprovider.getJarInputStream();
2728 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2729 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2730 * FileInputStream(jprovider)); }
2733 JarEntry entry = null;
2736 entry = jin.getNextJarEntry();
2737 } while (entry != null && !entry.getName().equals(jarEntryName));
2740 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
2741 File outFile = File.createTempFile(prefix, suffix);
2742 outFile.deleteOnExit();
2743 out = new PrintWriter(new FileOutputStream(outFile));
2746 while ((data = in.readLine()) != null)
2751 String t = outFile.getAbsolutePath();
2756 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
2758 } catch (Exception ex)
2760 ex.printStackTrace();
2768 } catch (IOException e)
2782 private class JvAnnotRow
2784 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2791 * persisted version of annotation row from which to take vis properties
2793 public jalview.datamodel.AlignmentAnnotation template;
2796 * original position of the annotation row in the alignment
2802 * Load alignment frame from jalview XML DOM object
2807 * filename source string
2808 * @param loadTreesAndStructures
2809 * when false only create Viewport
2811 * data source provider
2812 * @return alignment frame created from view stored in DOM
2814 AlignFrame loadFromObject(JalviewModel object, String file,
2815 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
2817 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
2818 Sequence[] vamsasSeq = vamsasSet.getSequence();
2820 JalviewModelSequence jms = object.getJalviewModelSequence();
2822 Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
2825 // ////////////////////////////////
2828 List<SequenceI> hiddenSeqs = null;
2830 List<SequenceI> tmpseqs = new ArrayList<SequenceI>();
2832 boolean multipleView = false;
2833 SequenceI referenceseqForView = null;
2834 JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
2835 int vi = 0; // counter in vamsasSeq array
2836 for (int i = 0; i < jseqs.length; i++)
2838 String seqId = jseqs[i].getId();
2840 SequenceI tmpSeq = seqRefIds.get(seqId);
2843 if (!incompleteSeqs.containsKey(seqId))
2845 // may not need this check, but keep it for at least 2.9,1 release
2846 if (tmpSeq.getStart() != jseqs[i].getStart()
2847 || tmpSeq.getEnd() != jseqs[i].getEnd())
2850 .println("Warning JAL-2154 regression: updating start/end for sequence "
2851 + tmpSeq.toString() + " to " + jseqs[i]);
2856 incompleteSeqs.remove(seqId);
2858 if (vamsasSeq.length > vi && vamsasSeq[vi].getId().equals(seqId))
2860 // most likely we are reading a dataset XML document so
2861 // update from vamsasSeq section of XML for this sequence
2862 tmpSeq.setName(vamsasSeq[vi].getName());
2863 tmpSeq.setDescription(vamsasSeq[vi].getDescription());
2864 tmpSeq.setSequence(vamsasSeq[vi].getSequence());
2869 // reading multiple views, so vamsasSeq set is a subset of JSeq
2870 multipleView = true;
2872 tmpSeq.setStart(jseqs[i].getStart());
2873 tmpSeq.setEnd(jseqs[i].getEnd());
2874 tmpseqs.add(tmpSeq);
2878 tmpSeq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
2879 vamsasSeq[vi].getSequence());
2880 tmpSeq.setDescription(vamsasSeq[vi].getDescription());
2881 tmpSeq.setStart(jseqs[i].getStart());
2882 tmpSeq.setEnd(jseqs[i].getEnd());
2883 tmpSeq.setVamsasId(uniqueSetSuffix + seqId);
2884 seqRefIds.put(vamsasSeq[vi].getId(), tmpSeq);
2885 tmpseqs.add(tmpSeq);
2889 if (jseqs[i].hasViewreference() && jseqs[i].getViewreference())
2891 referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
2894 if (jseqs[i].getHidden())
2896 if (hiddenSeqs == null)
2898 hiddenSeqs = new ArrayList<SequenceI>();
2901 hiddenSeqs.add(tmpSeq);
2906 // Create the alignment object from the sequence set
2907 // ///////////////////////////////
2908 SequenceI[] orderedSeqs = tmpseqs
2909 .toArray(new SequenceI[tmpseqs.size()]);
2911 AlignmentI al = null;
2912 // so we must create or recover the dataset alignment before going further
2913 // ///////////////////////////////
2914 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
2916 // older jalview projects do not have a dataset - so creat alignment and
2918 al = new Alignment(orderedSeqs);
2919 al.setDataset(null);
2923 boolean isdsal = object.getJalviewModelSequence().getViewportCount() == 0;
2926 // we are importing a dataset record, so
2927 // recover reference to an alignment already materialsed as dataset
2928 al = getDatasetFor(vamsasSet.getDatasetId());
2932 // materialse the alignment
2933 al = new Alignment(orderedSeqs);
2937 addDatasetRef(vamsasSet.getDatasetId(), al);
2940 // finally, verify all data in vamsasSet is actually present in al
2941 // passing on flag indicating if it is actually a stored dataset
2942 recoverDatasetFor(vamsasSet, al, isdsal);
2945 if (referenceseqForView != null)
2947 al.setSeqrep(referenceseqForView);
2949 // / Add the alignment properties
2950 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
2952 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
2953 al.setProperty(ssp.getKey(), ssp.getValue());
2956 // ///////////////////////////////
2958 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
2961 // load sequence features, database references and any associated PDB
2962 // structures for the alignment
2964 // prior to 2.10, this part would only be executed the first time a
2965 // sequence was encountered, but not afterwards.
2966 // now, for 2.10 projects, this is also done if the xml doc includes
2967 // dataset sequences not actually present in any particular view.
2969 for (int i = 0; i < vamsasSeq.length; i++)
2971 if (jseqs[i].getFeaturesCount() > 0)
2973 Features[] features = jseqs[i].getFeatures();
2974 for (int f = 0; f < features.length; f++)
2976 jalview.datamodel.SequenceFeature sf = new jalview.datamodel.SequenceFeature(
2977 features[f].getType(), features[f].getDescription(),
2978 features[f].getStatus(), features[f].getBegin(),
2979 features[f].getEnd(), features[f].getFeatureGroup());
2981 sf.setScore(features[f].getScore());
2982 for (int od = 0; od < features[f].getOtherDataCount(); od++)
2984 OtherData keyValue = features[f].getOtherData(od);
2985 if (keyValue.getKey().startsWith("LINK"))
2987 sf.addLink(keyValue.getValue());
2991 sf.setValue(keyValue.getKey(), keyValue.getValue());
2995 // adds feature to datasequence's feature set (since Jalview 2.10)
2996 al.getSequenceAt(i).addSequenceFeature(sf);
2999 if (vamsasSeq[i].getDBRefCount() > 0)
3001 // adds dbrefs to datasequence's set (since Jalview 2.10)
3003 al.getSequenceAt(i).getDatasetSequence() == null ? al.getSequenceAt(i)
3004 : al.getSequenceAt(i).getDatasetSequence(),
3007 if (jseqs[i].getPdbidsCount() > 0)
3009 Pdbids[] ids = jseqs[i].getPdbids();
3010 for (int p = 0; p < ids.length; p++)
3012 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
3013 entry.setId(ids[p].getId());
3014 if (ids[p].getType() != null)
3016 if (PDBEntry.Type.getType(ids[p].getType()) != null)
3018 entry.setType(PDBEntry.Type.getType(ids[p].getType()));
3022 entry.setType(PDBEntry.Type.FILE);
3025 // jprovider is null when executing 'New View'
3026 if (ids[p].getFile() != null && jprovider != null)
3028 if (!pdbloaded.containsKey(ids[p].getFile()))
3030 entry.setFile(loadPDBFile(jprovider, ids[p].getId(),
3035 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
3038 if (ids[p].getPdbentryItem() != null)
3040 for (PdbentryItem item : ids[p].getPdbentryItem())
3042 for (Property pr : item.getProperty())
3044 entry.setProperty(pr.getName(), pr.getValue());
3048 StructureSelectionManager.getStructureSelectionManager(
3049 Desktop.instance).registerPDBEntry(entry);
3050 // adds PDBEntry to datasequence's set (since Jalview 2.10)
3051 if (al.getSequenceAt(i).getDatasetSequence() != null)
3053 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
3057 al.getSequenceAt(i).addPDBId(entry);
3062 } // end !multipleview
3064 // ///////////////////////////////
3065 // LOAD SEQUENCE MAPPINGS
3067 if (vamsasSet.getAlcodonFrameCount() > 0)
3069 // TODO Potentially this should only be done once for all views of an
3071 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
3072 for (int i = 0; i < alc.length; i++)
3074 AlignedCodonFrame cf = new AlignedCodonFrame();
3075 if (alc[i].getAlcodMapCount() > 0)
3077 AlcodMap[] maps = alc[i].getAlcodMap();
3078 for (int m = 0; m < maps.length; m++)
3080 SequenceI dnaseq = seqRefIds.get(maps[m].getDnasq());
3082 jalview.datamodel.Mapping mapping = null;
3083 // attach to dna sequence reference.
3084 if (maps[m].getMapping() != null)
3086 mapping = addMapping(maps[m].getMapping());
3087 if (dnaseq != null && mapping.getTo() != null)
3089 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
3094 frefedSequence.add(newAlcodMapRef(maps[m].getDnasq(), cf,
3099 al.addCodonFrame(cf);
3104 // ////////////////////////////////
3106 List<JvAnnotRow> autoAlan = new ArrayList<JvAnnotRow>();
3109 * store any annotations which forward reference a group's ID
3111 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<String, List<AlignmentAnnotation>>();
3113 if (vamsasSet.getAnnotationCount() > 0)
3115 Annotation[] an = vamsasSet.getAnnotation();
3117 for (int i = 0; i < an.length; i++)
3119 Annotation annotation = an[i];
3122 * test if annotation is automatically calculated for this view only
3124 boolean autoForView = false;
3125 if (annotation.getLabel().equals("Quality")
3126 || annotation.getLabel().equals("Conservation")
3127 || annotation.getLabel().equals("Consensus"))
3129 // Kludge for pre 2.5 projects which lacked the autocalculated flag
3131 if (!annotation.hasAutoCalculated())
3133 annotation.setAutoCalculated(true);
3137 || (annotation.hasAutoCalculated() && annotation
3138 .isAutoCalculated()))
3140 // remove ID - we don't recover annotation from other views for
3141 // view-specific annotation
3142 annotation.setId(null);
3145 // set visiblity for other annotation in this view
3146 String annotationId = annotation.getId();
3147 if (annotationId != null && annotationIds.containsKey(annotationId))
3149 AlignmentAnnotation jda = annotationIds.get(annotationId);
3150 // in principle Visible should always be true for annotation displayed
3151 // in multiple views
3152 if (annotation.hasVisible())
3154 jda.visible = annotation.getVisible();
3157 al.addAnnotation(jda);
3161 // Construct new annotation from model.
3162 AnnotationElement[] ae = annotation.getAnnotationElement();
3163 jalview.datamodel.Annotation[] anot = null;
3164 java.awt.Color firstColour = null;
3166 if (!annotation.getScoreOnly())
3168 anot = new jalview.datamodel.Annotation[al.getWidth()];
3169 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
3171 anpos = ae[aa].getPosition();
3173 if (anpos >= anot.length)
3178 anot[anpos] = new jalview.datamodel.Annotation(
3180 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
3181 (ae[aa].getSecondaryStructure() == null || ae[aa]
3182 .getSecondaryStructure().length() == 0) ? ' '
3183 : ae[aa].getSecondaryStructure().charAt(0),
3187 // JBPNote: Consider verifying dataflow for IO of secondary
3188 // structure annotation read from Stockholm files
3189 // this was added to try to ensure that
3190 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
3192 // anot[ae[aa].getPosition()].displayCharacter = "";
3194 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
3195 if (firstColour == null)
3197 firstColour = anot[anpos].colour;
3201 jalview.datamodel.AlignmentAnnotation jaa = null;
3203 if (annotation.getGraph())
3205 float llim = 0, hlim = 0;
3206 // if (autoForView || an[i].isAutoCalculated()) {
3209 jaa = new jalview.datamodel.AlignmentAnnotation(
3210 annotation.getLabel(), annotation.getDescription(), anot,
3211 llim, hlim, annotation.getGraphType());
3213 jaa.graphGroup = annotation.getGraphGroup();
3214 jaa._linecolour = firstColour;
3215 if (annotation.getThresholdLine() != null)
3217 jaa.setThreshold(new jalview.datamodel.GraphLine(annotation
3218 .getThresholdLine().getValue(), annotation
3219 .getThresholdLine().getLabel(), new java.awt.Color(
3220 annotation.getThresholdLine().getColour())));
3223 if (autoForView || annotation.isAutoCalculated())
3225 // Hardwire the symbol display line to ensure that labels for
3226 // histograms are displayed
3232 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
3233 an[i].getDescription(), anot);
3234 jaa._linecolour = firstColour;
3236 // register new annotation
3237 if (an[i].getId() != null)
3239 annotationIds.put(an[i].getId(), jaa);
3240 jaa.annotationId = an[i].getId();
3242 // recover sequence association
3243 String sequenceRef = an[i].getSequenceRef();
3244 if (sequenceRef != null)
3246 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3247 SequenceI sequence = seqRefIds.get(sequenceRef);
3248 if (sequence == null)
3250 // in pre-2.9 projects sequence ref is to sequence name
3251 sequence = al.findName(sequenceRef);
3253 if (sequence != null)
3255 jaa.createSequenceMapping(sequence, 1, true);
3256 sequence.addAlignmentAnnotation(jaa);
3259 // and make a note of any group association
3260 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
3262 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3263 .get(an[i].getGroupRef());
3266 aal = new ArrayList<jalview.datamodel.AlignmentAnnotation>();
3267 groupAnnotRefs.put(an[i].getGroupRef(), aal);
3272 if (an[i].hasScore())
3274 jaa.setScore(an[i].getScore());
3276 if (an[i].hasVisible())
3278 jaa.visible = an[i].getVisible();
3281 if (an[i].hasCentreColLabels())
3283 jaa.centreColLabels = an[i].getCentreColLabels();
3286 if (an[i].hasScaleColLabels())
3288 jaa.scaleColLabel = an[i].getScaleColLabels();
3290 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
3292 // newer files have an 'autoCalculated' flag and store calculation
3293 // state in viewport properties
3294 jaa.autoCalculated = true; // means annotation will be marked for
3295 // update at end of load.
3297 if (an[i].hasGraphHeight())
3299 jaa.graphHeight = an[i].getGraphHeight();
3301 if (an[i].hasBelowAlignment())
3303 jaa.belowAlignment = an[i].isBelowAlignment();
3305 jaa.setCalcId(an[i].getCalcId());
3306 if (an[i].getPropertyCount() > 0)
3308 for (jalview.schemabinding.version2.Property prop : an[i]
3311 jaa.setProperty(prop.getName(), prop.getValue());
3314 if (jaa.autoCalculated)
3316 autoAlan.add(new JvAnnotRow(i, jaa));
3319 // if (!autoForView)
3321 // add autocalculated group annotation and any user created annotation
3323 al.addAnnotation(jaa);
3327 // ///////////////////////
3329 // Create alignment markup and styles for this view
3330 if (jms.getJGroupCount() > 0)
3332 JGroup[] groups = jms.getJGroup();
3333 boolean addAnnotSchemeGroup = false;
3334 for (int i = 0; i < groups.length; i++)
3336 JGroup jGroup = groups[i];
3337 ColourSchemeI cs = null;
3338 if (jGroup.getColour() != null)
3340 if (jGroup.getColour().startsWith("ucs"))
3342 cs = getUserColourScheme(jms, jGroup.getColour());
3344 else if (jGroup.getColour().equals("AnnotationColourGradient")
3345 && jGroup.getAnnotationColours() != null)
3347 addAnnotSchemeGroup = true;
3351 cs = ColourSchemeProperty.getColourScheme(al, jGroup.getColour());
3354 int pidThreshold = jGroup.getPidThreshold();
3356 Vector<SequenceI> seqs = new Vector<SequenceI>();
3358 for (int s = 0; s < jGroup.getSeqCount(); s++)
3360 String seqId = jGroup.getSeq(s) + "";
3361 SequenceI ts = seqRefIds.get(seqId);
3365 seqs.addElement(ts);
3369 if (seqs.size() < 1)
3374 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3375 jGroup.getDisplayBoxes(), jGroup.getDisplayText(),
3376 jGroup.getColourText(), jGroup.getStart(), jGroup.getEnd());
3377 sg.getGroupColourScheme().setThreshold(pidThreshold, true);
3378 sg.getGroupColourScheme().setConservationInc(jGroup.getConsThreshold());
3379 sg.setOutlineColour(new java.awt.Color(jGroup.getOutlineColour()));
3381 sg.textColour = new java.awt.Color(jGroup.getTextCol1());
3382 sg.textColour2 = new java.awt.Color(jGroup.getTextCol2());
3383 sg.setShowNonconserved(jGroup.hasShowUnconserved() ? jGroup
3384 .isShowUnconserved() : false);
3385 sg.thresholdTextColour = jGroup.getTextColThreshold();
3386 if (jGroup.hasShowConsensusHistogram())
3388 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3391 if (jGroup.hasShowSequenceLogo())
3393 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3395 if (jGroup.hasNormaliseSequenceLogo())
3397 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3399 if (jGroup.hasIgnoreGapsinConsensus())
3401 sg.setIgnoreGapsConsensus(jGroup.getIgnoreGapsinConsensus());
3403 if (jGroup.getConsThreshold() != 0)
3405 Conservation c = new Conservation("All", sg.getSequences(null),
3406 0, sg.getWidth() - 1);
3408 c.verdict(false, 25);
3409 sg.cs.setConservation(c);
3412 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3414 // re-instate unique group/annotation row reference
3415 List<AlignmentAnnotation> jaal = groupAnnotRefs.get(jGroup
3419 for (AlignmentAnnotation jaa : jaal)
3422 if (jaa.autoCalculated)
3424 // match up and try to set group autocalc alignment row for this
3426 if (jaa.label.startsWith("Consensus for "))
3428 sg.setConsensus(jaa);
3430 // match up and try to set group autocalc alignment row for this
3432 if (jaa.label.startsWith("Conservation for "))
3434 sg.setConservationRow(jaa);
3441 if (addAnnotSchemeGroup)
3443 // reconstruct the annotation colourscheme
3444 sg.setColourScheme(constructAnnotationColour(
3445 jGroup.getAnnotationColours(), null, al, jms, false));
3451 // only dataset in this model, so just return.
3454 // ///////////////////////////////
3457 // If we just load in the same jar file again, the sequenceSetId
3458 // will be the same, and we end up with multiple references
3459 // to the same sequenceSet. We must modify this id on load
3460 // so that each load of the file gives a unique id
3461 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3462 String viewId = (view.getId() == null ? null : view.getId()
3464 AlignFrame af = null;
3465 AlignViewport av = null;
3466 // now check to see if we really need to create a new viewport.
3467 if (multipleView && viewportsAdded.size() == 0)
3469 // We recovered an alignment for which a viewport already exists.
3470 // TODO: fix up any settings necessary for overlaying stored state onto
3471 // state recovered from another document. (may not be necessary).
3472 // we may need a binding from a viewport in memory to one recovered from
3474 // and then recover its containing af to allow the settings to be applied.
3475 // TODO: fix for vamsas demo
3477 .println("About to recover a viewport for existing alignment: Sequence set ID is "
3479 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3480 if (seqsetobj != null)
3482 if (seqsetobj instanceof String)
3484 uniqueSeqSetId = (String) seqsetobj;
3486 .println("Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
3492 .println("Warning : Collision between sequence set ID string and existing jalview object mapping.");
3498 * indicate that annotation colours are applied across all groups (pre
3499 * Jalview 2.8.1 behaviour)
3501 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan(
3502 "2.8.1", object.getVersion());
3504 AlignmentPanel ap = null;
3505 boolean isnewview = true;
3508 // Check to see if this alignment already has a view id == viewId
3509 jalview.gui.AlignmentPanel views[] = Desktop
3510 .getAlignmentPanels(uniqueSeqSetId);
3511 if (views != null && views.length > 0)
3513 for (int v = 0; v < views.length; v++)
3515 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
3517 // recover the existing alignpanel, alignframe, viewport
3518 af = views[v].alignFrame;
3521 // TODO: could even skip resetting view settings if we don't want to
3522 // change the local settings from other jalview processes
3531 af = loadViewport(file, jseqs, hiddenSeqs, al, jms, view,
3532 uniqueSeqSetId, viewId, autoAlan);
3538 * Load any trees, PDB structures and viewers
3540 * Not done if flag is false (when this method is used for New View)
3542 if (loadTreesAndStructures)
3544 loadTrees(jms, view, af, av, ap);
3545 loadPDBStructures(jprovider, jseqs, af, ap);
3546 loadRnaViewers(jprovider, jseqs, ap);
3548 // and finally return.
3553 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
3554 * panel is restored from separate jar entries, two (gapped and trimmed) per
3555 * sequence and secondary structure.
3557 * Currently each viewer shows just one sequence and structure (gapped and
3558 * trimmed), however this method is designed to support multiple sequences or
3559 * structures in viewers if wanted in future.
3565 private void loadRnaViewers(jarInputStreamProvider jprovider,
3566 JSeq[] jseqs, AlignmentPanel ap)
3569 * scan the sequences for references to viewers; create each one the first
3570 * time it is referenced, add Rna models to existing viewers
3572 for (JSeq jseq : jseqs)
3574 for (int i = 0; i < jseq.getRnaViewerCount(); i++)
3576 RnaViewer viewer = jseq.getRnaViewer(i);
3577 AppVarna appVarna = findOrCreateVarnaViewer(viewer,
3578 uniqueSetSuffix, ap);
3580 for (int j = 0; j < viewer.getSecondaryStructureCount(); j++)
3582 SecondaryStructure ss = viewer.getSecondaryStructure(j);
3583 SequenceI seq = seqRefIds.get(jseq.getId());
3584 AlignmentAnnotation ann = this.annotationIds.get(ss
3585 .getAnnotationId());
3588 * add the structure to the Varna display (with session state copied
3589 * from the jar to a temporary file)
3591 boolean gapped = ss.isGapped();
3592 String rnaTitle = ss.getTitle();
3593 String sessionState = ss.getViewerState();
3594 String tempStateFile = copyJarEntry(jprovider, sessionState,
3596 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
3597 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
3599 appVarna.setInitialSelection(viewer.getSelectedRna());
3605 * Locate and return an already instantiated matching AppVarna, or create one
3609 * @param viewIdSuffix
3613 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
3614 String viewIdSuffix, AlignmentPanel ap)
3617 * on each load a suffix is appended to the saved viewId, to avoid conflicts
3618 * if load is repeated
3620 String postLoadId = viewer.getViewId() + viewIdSuffix;
3621 for (JInternalFrame frame : getAllFrames())
3623 if (frame instanceof AppVarna)
3625 AppVarna varna = (AppVarna) frame;
3626 if (postLoadId.equals(varna.getViewId()))
3628 // this viewer is already instantiated
3629 // could in future here add ap as another 'parent' of the
3630 // AppVarna window; currently just 1-to-many
3637 * viewer not found - make it
3639 RnaViewerModel model = new RnaViewerModel(postLoadId,
3640 viewer.getTitle(), viewer.getXpos(), viewer.getYpos(),
3641 viewer.getWidth(), viewer.getHeight(),
3642 viewer.getDividerLocation());
3643 AppVarna varna = new AppVarna(model, ap);
3649 * Load any saved trees
3657 protected void loadTrees(JalviewModelSequence jms, Viewport view,
3658 AlignFrame af, AlignViewport av, AlignmentPanel ap)
3660 // TODO result of automated refactoring - are all these parameters needed?
3663 for (int t = 0; t < jms.getTreeCount(); t++)
3666 Tree tree = jms.getTree(t);
3668 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
3671 tp = af.ShowNewickTree(
3672 new jalview.io.NewickFile(tree.getNewick()),
3673 tree.getTitle(), tree.getWidth(), tree.getHeight(),
3674 tree.getXpos(), tree.getYpos());
3675 if (tree.getId() != null)
3677 // perhaps bind the tree id to something ?
3682 // update local tree attributes ?
3683 // TODO: should check if tp has been manipulated by user - if so its
3684 // settings shouldn't be modified
3685 tp.setTitle(tree.getTitle());
3686 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(), tree
3687 .getWidth(), tree.getHeight()));
3688 tp.av = av; // af.viewport; // TODO: verify 'associate with all
3691 tp.treeCanvas.av = av; // af.viewport;
3692 tp.treeCanvas.ap = ap; // af.alignPanel;
3697 warn("There was a problem recovering stored Newick tree: \n"
3698 + tree.getNewick());
3702 tp.fitToWindow.setState(tree.getFitToWindow());
3703 tp.fitToWindow_actionPerformed(null);
3705 if (tree.getFontName() != null)
3707 tp.setTreeFont(new java.awt.Font(tree.getFontName(), tree
3708 .getFontStyle(), tree.getFontSize()));
3712 tp.setTreeFont(new java.awt.Font(view.getFontName(), view
3713 .getFontStyle(), tree.getFontSize()));
3716 tp.showPlaceholders(tree.getMarkUnlinked());
3717 tp.showBootstrap(tree.getShowBootstrap());
3718 tp.showDistances(tree.getShowDistances());
3720 tp.treeCanvas.threshold = tree.getThreshold();
3722 if (tree.getCurrentTree())
3724 af.viewport.setCurrentTree(tp.getTree());
3728 } catch (Exception ex)
3730 ex.printStackTrace();
3735 * Load and link any saved structure viewers.
3742 protected void loadPDBStructures(jarInputStreamProvider jprovider,
3743 JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
3746 * Run through all PDB ids on the alignment, and collect mappings between
3747 * distinct view ids and all sequences referring to that view.
3749 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<String, StructureViewerModel>();
3751 for (int i = 0; i < jseqs.length; i++)
3753 if (jseqs[i].getPdbidsCount() > 0)
3755 Pdbids[] ids = jseqs[i].getPdbids();
3756 for (int p = 0; p < ids.length; p++)
3758 final int structureStateCount = ids[p].getStructureStateCount();
3759 for (int s = 0; s < structureStateCount; s++)
3761 // check to see if we haven't already created this structure view
3762 final StructureState structureState = ids[p]
3763 .getStructureState(s);
3764 String sviewid = (structureState.getViewId() == null) ? null
3765 : structureState.getViewId() + uniqueSetSuffix;
3766 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
3767 // Originally : ids[p].getFile()
3768 // : TODO: verify external PDB file recovery still works in normal
3769 // jalview project load
3770 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId(),
3772 jpdb.setId(ids[p].getId());
3774 int x = structureState.getXpos();
3775 int y = structureState.getYpos();
3776 int width = structureState.getWidth();
3777 int height = structureState.getHeight();
3779 // Probably don't need to do this anymore...
3780 // Desktop.desktop.getComponentAt(x, y);
3781 // TODO: NOW: check that this recovers the PDB file correctly.
3782 String pdbFile = loadPDBFile(jprovider, ids[p].getId(),
3784 jalview.datamodel.SequenceI seq = seqRefIds.get(jseqs[i]
3786 if (sviewid == null)
3788 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width
3791 if (!structureViewers.containsKey(sviewid))
3793 structureViewers.put(sviewid,
3794 new StructureViewerModel(x, y, width, height, false,
3795 false, true, structureState.getViewId(),
3796 structureState.getType()));
3797 // Legacy pre-2.7 conversion JAL-823 :
3798 // do not assume any view has to be linked for colour by
3802 // assemble String[] { pdb files }, String[] { id for each
3803 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3804 // seqs_file 2}, boolean[] {
3805 // linkAlignPanel,superposeWithAlignpanel}} from hash
3806 StructureViewerModel jmoldat = structureViewers.get(sviewid);
3807 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
3808 | (structureState.hasAlignwithAlignPanel() ? structureState
3809 .getAlignwithAlignPanel() : false));
3812 * Default colour by linked panel to false if not specified (e.g.
3813 * for pre-2.7 projects)
3815 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
3816 colourWithAlignPanel |= (structureState
3817 .hasColourwithAlignPanel() ? structureState
3818 .getColourwithAlignPanel() : false);
3819 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
3822 * Default colour by viewer to true if not specified (e.g. for
3825 boolean colourByViewer = jmoldat.isColourByViewer();
3826 colourByViewer &= structureState.hasColourByJmol() ? structureState
3827 .getColourByJmol() : true;
3828 jmoldat.setColourByViewer(colourByViewer);
3830 if (jmoldat.getStateData().length() < structureState
3831 .getContent().length())
3834 jmoldat.setStateData(structureState.getContent());
3837 if (ids[p].getFile() != null)
3839 File mapkey = new File(ids[p].getFile());
3840 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
3841 if (seqstrmaps == null)
3843 jmoldat.getFileData().put(
3845 seqstrmaps = jmoldat.new StructureData(pdbFile,
3848 if (!seqstrmaps.getSeqList().contains(seq))
3850 seqstrmaps.getSeqList().add(seq);
3856 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");
3863 // Instantiate the associated structure views
3864 for (Entry<String, StructureViewerModel> entry : structureViewers
3869 createOrLinkStructureViewer(entry, af, ap, jprovider);
3870 } catch (Exception e)
3872 System.err.println("Error loading structure viewer: "
3874 // failed - try the next one
3886 protected void createOrLinkStructureViewer(
3887 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3888 AlignmentPanel ap, jarInputStreamProvider jprovider)
3890 final StructureViewerModel stateData = viewerData.getValue();
3893 * Search for any viewer windows already open from other alignment views
3894 * that exactly match the stored structure state
3896 StructureViewerBase comp = findMatchingViewer(viewerData);
3900 linkStructureViewer(ap, comp, stateData);
3905 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
3906 * "viewer_"+stateData.viewId
3908 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
3910 createChimeraViewer(viewerData, af, jprovider);
3915 * else Jmol (if pre-2.9, stateData contains JMOL state string)
3917 createJmolViewer(viewerData, af, jprovider);
3922 * Create a new Chimera viewer.
3928 protected void createChimeraViewer(
3929 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3930 jarInputStreamProvider jprovider)
3932 StructureViewerModel data = viewerData.getValue();
3933 String chimeraSessionFile = data.getStateData();
3936 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
3938 * NB this is the 'saved' viewId as in the project file XML, _not_ the
3939 * 'uniquified' sviewid used to reconstruct the viewer here
3941 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
3942 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
3945 Set<Entry<File, StructureData>> fileData = data.getFileData()
3947 List<PDBEntry> pdbs = new ArrayList<PDBEntry>();
3948 List<SequenceI[]> allseqs = new ArrayList<SequenceI[]>();
3949 for (Entry<File, StructureData> pdb : fileData)
3951 String filePath = pdb.getValue().getFilePath();
3952 String pdbId = pdb.getValue().getPdbId();
3953 // pdbs.add(new PDBEntry(filePath, pdbId));
3954 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
3955 final List<SequenceI> seqList = pdb.getValue().getSeqList();
3956 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
3960 boolean colourByChimera = data.isColourByViewer();
3961 boolean colourBySequence = data.isColourWithAlignPanel();
3963 // TODO use StructureViewer as a factory here, see JAL-1761
3964 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
3965 final SequenceI[][] seqsArray = allseqs.toArray(new SequenceI[allseqs
3967 String newViewId = viewerData.getKey();
3969 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
3970 af.alignPanel, pdbArray, seqsArray, colourByChimera,
3971 colourBySequence, newViewId);
3972 cvf.setSize(data.getWidth(), data.getHeight());
3973 cvf.setLocation(data.getX(), data.getY());
3977 * Create a new Jmol window. First parse the Jmol state to translate filenames
3978 * loaded into the view, and record the order in which files are shown in the
3979 * Jmol view, so we can add the sequence mappings in same order.
3985 protected void createJmolViewer(
3986 final Entry<String, StructureViewerModel> viewerData,
3987 AlignFrame af, jarInputStreamProvider jprovider)
3989 final StructureViewerModel svattrib = viewerData.getValue();
3990 String state = svattrib.getStateData();
3993 * Pre-2.9: state element value is the Jmol state string
3995 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
3998 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
4000 state = readJarEntry(jprovider,
4001 getViewerJarEntryName(svattrib.getViewId()));
4004 List<String> pdbfilenames = new ArrayList<String>();
4005 List<SequenceI[]> seqmaps = new ArrayList<SequenceI[]>();
4006 List<String> pdbids = new ArrayList<String>();
4007 StringBuilder newFileLoc = new StringBuilder(64);
4008 int cp = 0, ncp, ecp;
4009 Map<File, StructureData> oldFiles = svattrib.getFileData();
4010 while ((ncp = state.indexOf("load ", cp)) > -1)
4014 // look for next filename in load statement
4015 newFileLoc.append(state.substring(cp,
4016 ncp = (state.indexOf("\"", ncp + 1) + 1)));
4017 String oldfilenam = state.substring(ncp,
4018 ecp = state.indexOf("\"", ncp));
4019 // recover the new mapping data for this old filename
4020 // have to normalize filename - since Jmol and jalview do
4022 // translation differently.
4023 StructureData filedat = oldFiles.get(new File(oldfilenam));
4024 if (filedat == null)
4026 String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\");
4027 filedat = oldFiles.get(new File(reformatedOldFilename));
4029 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
4030 pdbfilenames.add(filedat.getFilePath());
4031 pdbids.add(filedat.getPdbId());
4032 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4033 newFileLoc.append("\"");
4034 cp = ecp + 1; // advance beyond last \" and set cursor so we can
4035 // look for next file statement.
4036 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
4040 // just append rest of state
4041 newFileLoc.append(state.substring(cp));
4045 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
4046 newFileLoc = new StringBuilder(state);
4047 newFileLoc.append("; load append ");
4048 for (File id : oldFiles.keySet())
4050 // add this and any other pdb files that should be present in
4052 StructureData filedat = oldFiles.get(id);
4053 newFileLoc.append(filedat.getFilePath());
4054 pdbfilenames.add(filedat.getFilePath());
4055 pdbids.add(filedat.getPdbId());
4056 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4057 newFileLoc.append(" \"");
4058 newFileLoc.append(filedat.getFilePath());
4059 newFileLoc.append("\"");
4062 newFileLoc.append(";");
4065 if (newFileLoc.length() == 0)
4069 int histbug = newFileLoc.indexOf("history = ");
4073 * change "history = [true|false];" to "history = [1|0];"
4076 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
4077 String val = (diff == -1) ? null : newFileLoc
4078 .substring(histbug, diff);
4079 if (val != null && val.length() >= 4)
4081 if (val.contains("e")) // eh? what can it be?
4083 if (val.trim().equals("true"))
4091 newFileLoc.replace(histbug, diff, val);
4096 final String[] pdbf = pdbfilenames.toArray(new String[pdbfilenames
4098 final String[] id = pdbids.toArray(new String[pdbids.size()]);
4099 final SequenceI[][] sq = seqmaps
4100 .toArray(new SequenceI[seqmaps.size()][]);
4101 final String fileloc = newFileLoc.toString();
4102 final String sviewid = viewerData.getKey();
4103 final AlignFrame alf = af;
4104 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
4105 svattrib.getWidth(), svattrib.getHeight());
4108 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
4113 JalviewStructureDisplayI sview = null;
4116 sview = new StructureViewer(alf.alignPanel
4117 .getStructureSelectionManager()).createView(
4118 StructureViewer.ViewerType.JMOL, pdbf, id, sq,
4119 alf.alignPanel, svattrib, fileloc, rect, sviewid);
4120 addNewStructureViewer(sview);
4121 } catch (OutOfMemoryError ex)
4123 new OOMWarning("restoring structure view for PDB id " + id,
4124 (OutOfMemoryError) ex.getCause());
4125 if (sview != null && sview.isVisible())
4127 sview.closeViewer(false);
4128 sview.setVisible(false);
4134 } catch (InvocationTargetException ex)
4136 warn("Unexpected error when opening Jmol view.", ex);
4138 } catch (InterruptedException e)
4140 // e.printStackTrace();
4146 * Generates a name for the entry in the project jar file to hold state
4147 * information for a structure viewer
4152 protected String getViewerJarEntryName(String viewId)
4154 return VIEWER_PREFIX + viewId;
4158 * Returns any open frame that matches given structure viewer data. The match
4159 * is based on the unique viewId, or (for older project versions) the frame's
4165 protected StructureViewerBase findMatchingViewer(
4166 Entry<String, StructureViewerModel> viewerData)
4168 final String sviewid = viewerData.getKey();
4169 final StructureViewerModel svattrib = viewerData.getValue();
4170 StructureViewerBase comp = null;
4171 JInternalFrame[] frames = getAllFrames();
4172 for (JInternalFrame frame : frames)
4174 if (frame instanceof StructureViewerBase)
4177 * Post jalview 2.4 schema includes structure view id
4180 && ((StructureViewerBase) frame).getViewId()
4183 comp = (StructureViewerBase) frame;
4184 break; // break added in 2.9
4187 * Otherwise test for matching position and size of viewer frame
4189 else if (frame.getX() == svattrib.getX()
4190 && frame.getY() == svattrib.getY()
4191 && frame.getHeight() == svattrib.getHeight()
4192 && frame.getWidth() == svattrib.getWidth())
4194 comp = (StructureViewerBase) frame;
4195 // no break in faint hope of an exact match on viewId
4203 * Link an AlignmentPanel to an existing structure viewer.
4208 * @param useinViewerSuperpos
4209 * @param usetoColourbyseq
4210 * @param viewerColouring
4212 protected void linkStructureViewer(AlignmentPanel ap,
4213 StructureViewerBase viewer, StructureViewerModel stateData)
4215 // NOTE: if the jalview project is part of a shared session then
4216 // view synchronization should/could be done here.
4218 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4219 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4220 final boolean viewerColouring = stateData.isColourByViewer();
4221 Map<File, StructureData> oldFiles = stateData.getFileData();
4224 * Add mapping for sequences in this view to an already open viewer
4226 final AAStructureBindingModel binding = viewer.getBinding();
4227 for (File id : oldFiles.keySet())
4229 // add this and any other pdb files that should be present in the
4231 StructureData filedat = oldFiles.get(id);
4232 String pdbFile = filedat.getFilePath();
4233 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4234 binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE);
4235 binding.addSequenceForStructFile(pdbFile, seq);
4237 // and add the AlignmentPanel's reference to the view panel
4238 viewer.addAlignmentPanel(ap);
4239 if (useinViewerSuperpos)
4241 viewer.useAlignmentPanelForSuperposition(ap);
4245 viewer.excludeAlignmentPanelForSuperposition(ap);
4247 if (usetoColourbyseq)
4249 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4253 viewer.excludeAlignmentPanelForColourbyseq(ap);
4258 * Get all frames within the Desktop.
4262 protected JInternalFrame[] getAllFrames()
4264 JInternalFrame[] frames = null;
4265 // TODO is this necessary - is it safe - risk of hanging?
4270 frames = Desktop.desktop.getAllFrames();
4271 } catch (ArrayIndexOutOfBoundsException e)
4273 // occasional No such child exceptions are thrown here...
4277 } catch (InterruptedException f)
4281 } while (frames == null);
4286 * Answers true if 'version' is equal to or later than 'supported', where each
4287 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4288 * changes. Development and test values for 'version' are leniently treated
4292 * - minimum version we are comparing against
4294 * - version of data being processsed
4297 public static boolean isVersionStringLaterThan(String supported,
4300 if (supported == null || version == null
4301 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4302 || version.equalsIgnoreCase("Test")
4303 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4305 System.err.println("Assuming project file with "
4306 + (version == null ? "null" : version)
4307 + " is compatible with Jalview version " + supported);
4312 return StringUtils.compareVersions(version, supported, "b") >= 0;
4316 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4318 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4320 if (newStructureViewers != null)
4322 sview.getBinding().setFinishedLoadingFromArchive(false);
4323 newStructureViewers.add(sview);
4327 protected void setLoadingFinishedForNewStructureViewers()
4329 if (newStructureViewers != null)
4331 for (JalviewStructureDisplayI sview : newStructureViewers)
4333 sview.getBinding().setFinishedLoadingFromArchive(true);
4335 newStructureViewers.clear();
4336 newStructureViewers = null;
4340 AlignFrame loadViewport(String file, JSeq[] JSEQ,
4341 List<SequenceI> hiddenSeqs, AlignmentI al,
4342 JalviewModelSequence jms, Viewport view, String uniqueSeqSetId,
4343 String viewId, List<JvAnnotRow> autoAlan)
4345 AlignFrame af = null;
4346 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
4347 uniqueSeqSetId, viewId);
4349 af.setFileName(file, FileFormat.Jalview);
4351 for (int i = 0; i < JSEQ.length; i++)
4353 af.viewport.setSequenceColour(af.viewport.getAlignment()
4354 .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour()));
4359 af.getViewport().setColourByReferenceSeq(true);
4360 af.getViewport().setDisplayReferenceSeq(true);
4363 af.viewport.setGatherViewsHere(view.getGatheredViews());
4365 if (view.getSequenceSetId() != null)
4367 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4369 af.viewport.setSequenceSetId(uniqueSeqSetId);
4372 // propagate shared settings to this new view
4373 af.viewport.setHistoryList(av.getHistoryList());
4374 af.viewport.setRedoList(av.getRedoList());
4378 viewportsAdded.put(uniqueSeqSetId, af.viewport);
4380 // TODO: check if this method can be called repeatedly without
4381 // side-effects if alignpanel already registered.
4382 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4384 // apply Hidden regions to view.
4385 if (hiddenSeqs != null)
4387 for (int s = 0; s < JSEQ.length; s++)
4389 SequenceGroup hidden = new SequenceGroup();
4390 boolean isRepresentative = false;
4391 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
4393 isRepresentative = true;
4394 SequenceI sequenceToHide = al.getSequenceAt(JSEQ[s]
4395 .getHiddenSequences(r));
4396 hidden.addSequence(sequenceToHide, false);
4397 // remove from hiddenSeqs list so we don't try to hide it twice
4398 hiddenSeqs.remove(sequenceToHide);
4400 if (isRepresentative)
4402 SequenceI representativeSequence = al.getSequenceAt(s);
4403 hidden.addSequence(representativeSequence, false);
4404 af.viewport.hideRepSequences(representativeSequence, hidden);
4408 SequenceI[] hseqs = hiddenSeqs.toArray(new SequenceI[hiddenSeqs
4410 af.viewport.hideSequence(hseqs);
4413 // recover view properties and display parameters
4414 if (view.getViewName() != null)
4416 af.viewport.viewName = view.getViewName();
4417 af.setInitialTabVisible();
4419 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
4422 af.viewport.setShowAnnotation(view.getShowAnnotation());
4423 af.viewport.setAbovePIDThreshold(view.getPidSelected());
4424 af.viewport.setThreshold(view.getPidThreshold());
4426 af.viewport.setColourText(view.getShowColourText());
4428 af.viewport.setConservationSelected(view.getConservationSelected());
4429 af.viewport.setIncrement(view.getConsThreshold());
4430 af.viewport.setShowJVSuffix(view.getShowFullId());
4431 af.viewport.setRightAlignIds(view.getRightAlignIds());
4432 af.viewport.setFont(
4433 new java.awt.Font(view.getFontName(), view.getFontStyle(), view
4434 .getFontSize()), true);
4435 ViewStyleI vs = af.viewport.getViewStyle();
4436 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
4437 af.viewport.setViewStyle(vs);
4438 // TODO: allow custom charWidth/Heights to be restored by updating them
4439 // after setting font - which means set above to false
4440 af.viewport.setRenderGaps(view.getRenderGaps());
4441 af.viewport.setWrapAlignment(view.getWrapAlignment());
4442 af.viewport.setShowAnnotation(view.getShowAnnotation());
4444 af.viewport.setShowBoxes(view.getShowBoxes());
4446 af.viewport.setShowText(view.getShowText());
4448 af.viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
4449 af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
4450 af.viewport.setThresholdTextColour(view.getTextColThreshold());
4451 af.viewport.setShowUnconserved(view.hasShowUnconserved() ? view
4452 .isShowUnconserved() : false);
4453 af.viewport.getRanges().setStartRes(view.getStartRes());
4454 af.viewport.getRanges().setStartSeq(view.getStartSeq());
4455 af.alignPanel.updateLayout();
4456 ColourSchemeI cs = null;
4457 // apply colourschemes
4458 if (view.getBgColour() != null)
4460 if (view.getBgColour().startsWith("ucs"))
4462 cs = getUserColourScheme(jms, view.getBgColour());
4464 else if (view.getBgColour().startsWith("Annotation"))
4466 AnnotationColours viewAnnColour = view.getAnnotationColours();
4467 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
4474 cs = ColourSchemeProperty.getColourScheme(al, view.getBgColour());
4478 af.viewport.setGlobalColourScheme(cs);
4479 af.viewport.getResidueShading().setThreshold(
4480 view.getPidThreshold(), true);
4481 af.viewport.getResidueShading().setConsensus(
4482 af.viewport.getSequenceConsensusHash());
4483 af.viewport.setColourAppliesToAllGroups(false);
4485 if (view.getConservationSelected() && cs != null)
4487 af.viewport.getResidueShading().setConservationInc(
4488 view.getConsThreshold());
4491 af.changeColour(cs);
4493 af.viewport.setColourAppliesToAllGroups(true);
4495 af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures());
4497 if (view.hasCentreColumnLabels())
4499 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
4501 if (view.hasIgnoreGapsinConsensus())
4503 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
4506 if (view.hasFollowHighlight())
4508 af.viewport.setFollowHighlight(view.getFollowHighlight());
4510 if (view.hasFollowSelection())
4512 af.viewport.followSelection = view.getFollowSelection();
4514 if (view.hasShowConsensusHistogram())
4516 af.viewport.setShowConsensusHistogram(view
4517 .getShowConsensusHistogram());
4521 af.viewport.setShowConsensusHistogram(true);
4523 if (view.hasShowSequenceLogo())
4525 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
4529 af.viewport.setShowSequenceLogo(false);
4531 if (view.hasNormaliseSequenceLogo())
4533 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
4535 if (view.hasShowDbRefTooltip())
4537 af.viewport.setShowDBRefs(view.getShowDbRefTooltip());
4539 if (view.hasShowNPfeatureTooltip())
4541 af.viewport.setShowNPFeats(view.hasShowNPfeatureTooltip());
4543 if (view.hasShowGroupConsensus())
4545 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
4549 af.viewport.setShowGroupConsensus(false);
4551 if (view.hasShowGroupConservation())
4553 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
4557 af.viewport.setShowGroupConservation(false);
4560 // recover featre settings
4561 if (jms.getFeatureSettings() != null)
4563 FeaturesDisplayed fdi;
4564 af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
4565 String[] renderOrder = new String[jms.getFeatureSettings()
4566 .getSettingCount()];
4567 Map<String, FeatureColourI> featureColours = new Hashtable<String, FeatureColourI>();
4568 Map<String, Float> featureOrder = new Hashtable<String, Float>();
4570 for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
4572 Setting setting = jms.getFeatureSettings().getSetting(fs);
4573 if (setting.hasMincolour())
4575 FeatureColourI gc = setting.hasMin() ? new FeatureColour(
4576 new Color(setting.getMincolour()), new Color(
4577 setting.getColour()), setting.getMin(),
4578 setting.getMax()) : new FeatureColour(new Color(
4579 setting.getMincolour()), new Color(setting.getColour()),
4581 if (setting.hasThreshold())
4583 gc.setThreshold(setting.getThreshold());
4584 int threshstate = setting.getThreshstate();
4585 // -1 = None, 0 = Below, 1 = Above threshold
4586 if (threshstate == 0)
4588 gc.setBelowThreshold(true);
4590 else if (threshstate == 1)
4592 gc.setAboveThreshold(true);
4595 gc.setAutoScaled(true); // default
4596 if (setting.hasAutoScale())
4598 gc.setAutoScaled(setting.getAutoScale());
4600 if (setting.hasColourByLabel())
4602 gc.setColourByLabel(setting.getColourByLabel());
4604 // and put in the feature colour table.
4605 featureColours.put(setting.getType(), gc);
4609 featureColours.put(setting.getType(), new FeatureColour(
4610 new Color(setting.getColour())));
4612 renderOrder[fs] = setting.getType();
4613 if (setting.hasOrder())
4615 featureOrder.put(setting.getType(), setting.getOrder());
4619 featureOrder.put(setting.getType(), new Float(fs
4620 / jms.getFeatureSettings().getSettingCount()));
4622 if (setting.getDisplay())
4624 fdi.setVisible(setting.getType());
4627 Map<String, Boolean> fgtable = new Hashtable<String, Boolean>();
4628 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
4630 Group grp = jms.getFeatureSettings().getGroup(gs);
4631 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
4633 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4634 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
4635 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
4636 FeatureRendererSettings frs = new FeatureRendererSettings(
4637 renderOrder, fgtable, featureColours, 1.0f, featureOrder);
4638 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
4639 .transferSettings(frs);
4643 if (view.getHiddenColumnsCount() > 0)
4645 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
4647 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(), view
4648 .getHiddenColumns(c).getEnd() // +1
4652 if (view.getCalcIdParam() != null)
4654 for (CalcIdParam calcIdParam : view.getCalcIdParam())
4656 if (calcIdParam != null)
4658 if (recoverCalcIdParam(calcIdParam, af.viewport))
4663 warn("Couldn't recover parameters for "
4664 + calcIdParam.getCalcId());
4669 af.setMenusFromViewport(af.viewport);
4670 af.setTitle(view.getTitle());
4671 // TODO: we don't need to do this if the viewport is aready visible.
4673 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
4674 * has a 'cdna/protein complement' view, in which case save it in order to
4675 * populate a SplitFrame once all views have been read in.
4677 String complementaryViewId = view.getComplementId();
4678 if (complementaryViewId == null)
4680 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
4682 // recompute any autoannotation
4683 af.alignPanel.updateAnnotation(false, true);
4684 reorderAutoannotation(af, al, autoAlan);
4685 af.alignPanel.alignmentChanged();
4689 splitFrameCandidates.put(view, af);
4694 private ColourSchemeI constructAnnotationColour(
4695 AnnotationColours viewAnnColour, AlignFrame af, AlignmentI al,
4696 JalviewModelSequence jms, boolean checkGroupAnnColour)
4698 boolean propagateAnnColour = false;
4699 ColourSchemeI cs = null;
4700 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
4701 if (checkGroupAnnColour && al.getGroups() != null
4702 && al.getGroups().size() > 0)
4704 // pre 2.8.1 behaviour
4705 // check to see if we should transfer annotation colours
4706 propagateAnnColour = true;
4707 for (jalview.datamodel.SequenceGroup sg : al.getGroups())
4709 if (sg.getColourScheme() instanceof AnnotationColourGradient)
4711 propagateAnnColour = false;
4715 // int find annotation
4716 if (annAlignment.getAlignmentAnnotation() != null)
4718 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
4720 if (annAlignment.getAlignmentAnnotation()[i].label
4721 .equals(viewAnnColour.getAnnotation()))
4723 if (annAlignment.getAlignmentAnnotation()[i].getThreshold() == null)
4725 annAlignment.getAlignmentAnnotation()[i]
4726 .setThreshold(new jalview.datamodel.GraphLine(
4727 viewAnnColour.getThreshold(), "Threshold",
4728 java.awt.Color.black)
4733 if (viewAnnColour.getColourScheme().equals(
4734 ResidueColourScheme.NONE))
4736 cs = new AnnotationColourGradient(
4737 annAlignment.getAlignmentAnnotation()[i],
4738 new java.awt.Color(viewAnnColour.getMinColour()),
4739 new java.awt.Color(viewAnnColour.getMaxColour()),
4740 viewAnnColour.getAboveThreshold());
4742 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
4744 cs = new AnnotationColourGradient(
4745 annAlignment.getAlignmentAnnotation()[i],
4746 getUserColourScheme(jms,
4747 viewAnnColour.getColourScheme()),
4748 viewAnnColour.getAboveThreshold());
4752 cs = new AnnotationColourGradient(
4753 annAlignment.getAlignmentAnnotation()[i],
4754 ColourSchemeProperty.getColourScheme(al,
4755 viewAnnColour.getColourScheme()),
4756 viewAnnColour.getAboveThreshold());
4758 if (viewAnnColour.hasPerSequence())
4760 ((AnnotationColourGradient) cs).setSeqAssociated(viewAnnColour
4763 if (viewAnnColour.hasPredefinedColours())
4765 ((AnnotationColourGradient) cs)
4766 .setPredefinedColours(viewAnnColour
4767 .isPredefinedColours());
4769 if (propagateAnnColour && al.getGroups() != null)
4771 // Also use these settings for all the groups
4772 for (int g = 0; g < al.getGroups().size(); g++)
4774 jalview.datamodel.SequenceGroup sg = al.getGroups().get(g);
4782 * if (viewAnnColour.getColourScheme().equals(ResidueColourScheme.NONE)) { sg.cs =
4783 * new AnnotationColourGradient(
4784 * annAlignment.getAlignmentAnnotation()[i], new
4785 * java.awt.Color(viewAnnColour. getMinColour()), new
4786 * java.awt.Color(viewAnnColour. getMaxColour()),
4787 * viewAnnColour.getAboveThreshold()); } else
4790 sg.setColourScheme(new AnnotationColourGradient(
4791 annAlignment.getAlignmentAnnotation()[i], sg
4792 .getColourScheme(), viewAnnColour
4793 .getAboveThreshold()));
4794 if (cs instanceof AnnotationColourGradient)
4796 if (viewAnnColour.hasPerSequence())
4798 ((AnnotationColourGradient) cs)
4799 .setSeqAssociated(viewAnnColour.isPerSequence());
4801 if (viewAnnColour.hasPredefinedColours())
4803 ((AnnotationColourGradient) cs)
4804 .setPredefinedColours(viewAnnColour
4805 .isPredefinedColours());
4821 private void reorderAutoannotation(AlignFrame af, AlignmentI al,
4822 List<JvAnnotRow> autoAlan)
4824 // copy over visualization settings for autocalculated annotation in the
4826 if (al.getAlignmentAnnotation() != null)
4829 * Kludge for magic autoannotation names (see JAL-811)
4831 String[] magicNames = new String[] { "Consensus", "Quality",
4833 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
4834 Hashtable<String, JvAnnotRow> visan = new Hashtable<String, JvAnnotRow>();
4835 for (String nm : magicNames)
4837 visan.put(nm, nullAnnot);
4839 for (JvAnnotRow auan : autoAlan)
4841 visan.put(auan.template.label
4842 + (auan.template.getCalcId() == null ? "" : "\t"
4843 + auan.template.getCalcId()), auan);
4845 int hSize = al.getAlignmentAnnotation().length;
4846 List<JvAnnotRow> reorder = new ArrayList<JvAnnotRow>();
4847 // work through any autoCalculated annotation already on the view
4848 // removing it if it should be placed in a different location on the
4849 // annotation panel.
4850 List<String> remains = new ArrayList<String>(visan.keySet());
4851 for (int h = 0; h < hSize; h++)
4853 jalview.datamodel.AlignmentAnnotation jalan = al
4854 .getAlignmentAnnotation()[h];
4855 if (jalan.autoCalculated)
4858 JvAnnotRow valan = visan.get(k = jalan.label);
4859 if (jalan.getCalcId() != null)
4861 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
4866 // delete the auto calculated row from the alignment
4867 al.deleteAnnotation(jalan, false);
4871 if (valan != nullAnnot)
4873 if (jalan != valan.template)
4875 // newly created autoannotation row instance
4876 // so keep a reference to the visible annotation row
4877 // and copy over all relevant attributes
4878 if (valan.template.graphHeight >= 0)
4881 jalan.graphHeight = valan.template.graphHeight;
4883 jalan.visible = valan.template.visible;
4885 reorder.add(new JvAnnotRow(valan.order, jalan));
4890 // Add any (possibly stale) autocalculated rows that were not appended to
4891 // the view during construction
4892 for (String other : remains)
4894 JvAnnotRow othera = visan.get(other);
4895 if (othera != nullAnnot && othera.template.getCalcId() != null
4896 && othera.template.getCalcId().length() > 0)
4898 reorder.add(othera);
4901 // now put the automatic annotation in its correct place
4902 int s = 0, srt[] = new int[reorder.size()];
4903 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
4904 for (JvAnnotRow jvar : reorder)
4907 srt[s++] = jvar.order;
4910 jalview.util.QuickSort.sort(srt, rws);
4911 // and re-insert the annotation at its correct position
4912 for (JvAnnotRow jvar : rws)
4914 al.addAnnotation(jvar.template, jvar.order);
4916 af.alignPanel.adjustAnnotationHeight();
4920 Hashtable skipList = null;
4923 * TODO remove this method
4926 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
4927 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
4928 * throw new Error("Implementation Error. No skipList defined for this
4929 * Jalview2XML instance."); } return (AlignFrame)
4930 * skipList.get(view.getSequenceSetId()); }
4934 * Check if the Jalview view contained in object should be skipped or not.
4937 * @return true if view's sequenceSetId is a key in skipList
4939 private boolean skipViewport(JalviewModel object)
4941 if (skipList == null)
4946 if (skipList.containsKey(id = object.getJalviewModelSequence()
4947 .getViewport()[0].getSequenceSetId()))
4949 if (Cache.log != null && Cache.log.isDebugEnabled())
4951 Cache.log.debug("Skipping seuqence set id " + id);
4958 public void addToSkipList(AlignFrame af)
4960 if (skipList == null)
4962 skipList = new Hashtable();
4964 skipList.put(af.getViewport().getSequenceSetId(), af);
4967 public void clearSkipList()
4969 if (skipList != null)
4976 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
4977 boolean ignoreUnrefed)
4979 jalview.datamodel.AlignmentI ds = getDatasetFor(vamsasSet
4981 Vector dseqs = null;
4984 // create a list of new dataset sequences
4985 dseqs = new Vector();
4987 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
4989 Sequence vamsasSeq = vamsasSet.getSequence(i);
4990 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
4992 // create a new dataset
4995 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
4996 dseqs.copyInto(dsseqs);
4997 ds = new jalview.datamodel.Alignment(dsseqs);
4998 debug("Created new dataset " + vamsasSet.getDatasetId()
4999 + " for alignment " + System.identityHashCode(al));
5000 addDatasetRef(vamsasSet.getDatasetId(), ds);
5002 // set the dataset for the newly imported alignment.
5003 if (al.getDataset() == null && !ignoreUnrefed)
5012 * sequence definition to create/merge dataset sequence for
5016 * vector to add new dataset sequence to
5017 * @param ignoreUnrefed
5018 * - when true, don't create new sequences from vamsasSeq if it's id
5019 * doesn't already have an asssociated Jalview sequence.
5021 * - used to reorder the sequence in the alignment according to the
5022 * vamsasSeq array ordering, to preserve ordering of dataset
5024 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
5025 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed, int vseqpos)
5027 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
5029 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
5030 boolean reorder = false;
5031 SequenceI dsq = null;
5032 if (sq != null && sq.getDatasetSequence() != null)
5034 dsq = sq.getDatasetSequence();
5040 if (sq == null && ignoreUnrefed)
5044 String sqid = vamsasSeq.getDsseqid();
5047 // need to create or add a new dataset sequence reference to this sequence
5050 dsq = seqRefIds.get(sqid);
5055 // make a new dataset sequence
5056 dsq = sq.createDatasetSequence();
5059 // make up a new dataset reference for this sequence
5060 sqid = seqHash(dsq);
5062 dsq.setVamsasId(uniqueSetSuffix + sqid);
5063 seqRefIds.put(sqid, dsq);
5068 dseqs.addElement(dsq);
5073 ds.addSequence(dsq);
5079 { // make this dataset sequence sq's dataset sequence
5080 sq.setDatasetSequence(dsq);
5081 // and update the current dataset alignment
5086 if (!dseqs.contains(dsq))
5093 if (ds.findIndex(dsq) < 0)
5095 ds.addSequence(dsq);
5102 // TODO: refactor this as a merge dataset sequence function
5103 // now check that sq (the dataset sequence) sequence really is the union of
5104 // all references to it
5105 // boolean pre = sq.getStart() < dsq.getStart();
5106 // boolean post = sq.getEnd() > dsq.getEnd();
5110 // StringBuffer sb = new StringBuffer();
5111 String newres = jalview.analysis.AlignSeq.extractGaps(
5112 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
5113 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
5114 && newres.length() > dsq.getLength())
5116 // Update with the longer sequence.
5120 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
5121 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
5122 * sb.append(newres.substring(newres.length() - sq.getEnd() -
5123 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
5125 dsq.setSequence(newres);
5127 // TODO: merges will never happen if we 'know' we have the real dataset
5128 // sequence - this should be detected when id==dssid
5130 .println("DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
5131 // + (pre ? "prepended" : "") + " "
5132 // + (post ? "appended" : ""));
5137 // sequence refs are identical. We may need to update the existing dataset
5138 // alignment with this one, though.
5139 if (ds != null && dseqs == null)
5141 int opos = ds.findIndex(dsq);
5142 SequenceI tseq = null;
5143 if (opos != -1 && vseqpos != opos)
5145 // remove from old position
5146 ds.deleteSequence(dsq);
5148 if (vseqpos < ds.getHeight())
5150 if (vseqpos != opos)
5152 // save sequence at destination position
5153 tseq = ds.getSequenceAt(vseqpos);
5154 ds.replaceSequenceAt(vseqpos, dsq);
5155 ds.addSequence(tseq);
5160 ds.addSequence(dsq);
5167 * TODO use AlignmentI here and in related methods - needs
5168 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
5170 Hashtable<String, AlignmentI> datasetIds = null;
5172 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
5174 private AlignmentI getDatasetFor(String datasetId)
5176 if (datasetIds == null)
5178 datasetIds = new Hashtable<String, AlignmentI>();
5181 if (datasetIds.containsKey(datasetId))
5183 return datasetIds.get(datasetId);
5188 private void addDatasetRef(String datasetId, AlignmentI dataset)
5190 if (datasetIds == null)
5192 datasetIds = new Hashtable<String, AlignmentI>();
5194 datasetIds.put(datasetId, dataset);
5198 * make a new dataset ID for this jalview dataset alignment
5203 private String getDatasetIdRef(AlignmentI dataset)
5205 if (dataset.getDataset() != null)
5207 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
5209 String datasetId = makeHashCode(dataset, null);
5210 if (datasetId == null)
5212 // make a new datasetId and record it
5213 if (dataset2Ids == null)
5215 dataset2Ids = new IdentityHashMap<AlignmentI, String>();
5219 datasetId = dataset2Ids.get(dataset);
5221 if (datasetId == null)
5223 datasetId = "ds" + dataset2Ids.size() + 1;
5224 dataset2Ids.put(dataset, datasetId);
5230 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5232 for (int d = 0; d < sequence.getDBRefCount(); d++)
5234 DBRef dr = sequence.getDBRef(d);
5235 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
5236 sequence.getDBRef(d).getSource(), sequence.getDBRef(d)
5237 .getVersion(), sequence.getDBRef(d).getAccessionId());
5238 if (dr.getMapping() != null)
5240 entry.setMap(addMapping(dr.getMapping()));
5242 datasetSequence.addDBRef(entry);
5246 private jalview.datamodel.Mapping addMapping(Mapping m)
5248 SequenceI dsto = null;
5249 // Mapping m = dr.getMapping();
5250 int fr[] = new int[m.getMapListFromCount() * 2];
5251 Enumeration f = m.enumerateMapListFrom();
5252 for (int _i = 0; f.hasMoreElements(); _i += 2)
5254 MapListFrom mf = (MapListFrom) f.nextElement();
5255 fr[_i] = mf.getStart();
5256 fr[_i + 1] = mf.getEnd();
5258 int fto[] = new int[m.getMapListToCount() * 2];
5259 f = m.enumerateMapListTo();
5260 for (int _i = 0; f.hasMoreElements(); _i += 2)
5262 MapListTo mf = (MapListTo) f.nextElement();
5263 fto[_i] = mf.getStart();
5264 fto[_i + 1] = mf.getEnd();
5266 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto,
5267 fr, fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
5268 if (m.getMappingChoice() != null)
5270 MappingChoice mc = m.getMappingChoice();
5271 if (mc.getDseqFor() != null)
5273 String dsfor = "" + mc.getDseqFor();
5274 if (seqRefIds.containsKey(dsfor))
5279 jmap.setTo(seqRefIds.get(dsfor));
5283 frefedSequence.add(newMappingRef(dsfor, jmap));
5289 * local sequence definition
5291 Sequence ms = mc.getSequence();
5292 SequenceI djs = null;
5293 String sqid = ms.getDsseqid();
5294 if (sqid != null && sqid.length() > 0)
5297 * recover dataset sequence
5299 djs = seqRefIds.get(sqid);
5304 .println("Warning - making up dataset sequence id for DbRef sequence map reference");
5305 sqid = ((Object) ms).toString(); // make up a new hascode for
5306 // undefined dataset sequence hash
5307 // (unlikely to happen)
5313 * make a new dataset sequence and add it to refIds hash
5315 djs = new jalview.datamodel.Sequence(ms.getName(),
5317 djs.setStart(jmap.getMap().getToLowest());
5318 djs.setEnd(jmap.getMap().getToHighest());
5319 djs.setVamsasId(uniqueSetSuffix + sqid);
5321 incompleteSeqs.put(sqid, djs);
5322 seqRefIds.put(sqid, djs);
5325 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5334 public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
5335 boolean keepSeqRefs)
5338 JalviewModel jm = saveState(ap, null, null, null);
5343 jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
5347 uniqueSetSuffix = "";
5348 jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
5353 if (this.frefedSequence == null)
5355 frefedSequence = new Vector();
5358 viewportsAdded.clear();
5360 AlignFrame af = loadFromObject(jm, null, false, null);
5361 af.alignPanels.clear();
5362 af.closeMenuItem_actionPerformed(true);
5365 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5366 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5367 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5368 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5369 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5372 return af.alignPanel;
5376 * flag indicating if hashtables should be cleared on finalization TODO this
5377 * flag may not be necessary
5379 private final boolean _cleartables = true;
5381 private Hashtable jvids2vobj;
5386 * @see java.lang.Object#finalize()
5389 protected void finalize() throws Throwable
5391 // really make sure we have no buried refs left.
5396 this.seqRefIds = null;
5397 this.seqsToIds = null;
5401 private void warn(String msg)
5406 private void warn(String msg, Exception e)
5408 if (Cache.log != null)
5412 Cache.log.warn(msg, e);
5416 Cache.log.warn(msg);
5421 System.err.println("Warning: " + msg);
5424 e.printStackTrace();
5429 private void debug(String string)
5431 debug(string, null);
5434 private void debug(String msg, Exception e)
5436 if (Cache.log != null)
5440 Cache.log.debug(msg, e);
5444 Cache.log.debug(msg);
5449 System.err.println("Warning: " + msg);
5452 e.printStackTrace();
5458 * set the object to ID mapping tables used to write/recover objects and XML
5459 * ID strings for the jalview project. If external tables are provided then
5460 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
5461 * object goes out of scope. - also populates the datasetIds hashtable with
5462 * alignment objects containing dataset sequences
5465 * Map from ID strings to jalview datamodel
5467 * Map from jalview datamodel to ID strings
5471 public void setObjectMappingTables(Hashtable vobj2jv,
5472 IdentityHashMap jv2vobj)
5474 this.jv2vobj = jv2vobj;
5475 this.vobj2jv = vobj2jv;
5476 Iterator ds = jv2vobj.keySet().iterator();
5478 while (ds.hasNext())
5480 Object jvobj = ds.next();
5481 id = jv2vobj.get(jvobj).toString();
5482 if (jvobj instanceof jalview.datamodel.Alignment)
5484 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
5486 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
5489 else if (jvobj instanceof jalview.datamodel.Sequence)
5491 // register sequence object so the XML parser can recover it.
5492 if (seqRefIds == null)
5494 seqRefIds = new HashMap<String, SequenceI>();
5496 if (seqsToIds == null)
5498 seqsToIds = new IdentityHashMap<SequenceI, String>();
5500 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
5501 seqsToIds.put((SequenceI) jvobj, id);
5503 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
5506 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
5507 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
5508 if (jvann.annotationId == null)
5510 jvann.annotationId = anid;
5512 if (!jvann.annotationId.equals(anid))
5514 // TODO verify that this is the correct behaviour
5515 this.warn("Overriding Annotation ID for " + anid
5516 + " from different id : " + jvann.annotationId);
5517 jvann.annotationId = anid;
5520 else if (jvobj instanceof String)
5522 if (jvids2vobj == null)
5524 jvids2vobj = new Hashtable();
5525 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
5530 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
5536 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
5537 * objects created from the project archive. If string is null (default for
5538 * construction) then suffix will be set automatically.
5542 public void setUniqueSetSuffix(String string)
5544 uniqueSetSuffix = string;
5549 * uses skipList2 as the skipList for skipping views on sequence sets
5550 * associated with keys in the skipList
5554 public void setSkipList(Hashtable skipList2)
5556 skipList = skipList2;
5560 * Reads the jar entry of given name and returns its contents, or null if the
5561 * entry is not found.
5564 * @param jarEntryName
5567 protected String readJarEntry(jarInputStreamProvider jprovider,
5568 String jarEntryName)
5570 String result = null;
5571 BufferedReader in = null;
5576 * Reopen the jar input stream and traverse its entries to find a matching
5579 JarInputStream jin = jprovider.getJarInputStream();
5580 JarEntry entry = null;
5583 entry = jin.getNextJarEntry();
5584 } while (entry != null && !entry.getName().equals(jarEntryName));
5588 StringBuilder out = new StringBuilder(256);
5589 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
5592 while ((data = in.readLine()) != null)
5596 result = out.toString();
5600 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
5602 } catch (Exception ex)
5604 ex.printStackTrace();
5612 } catch (IOException e)
5623 * Returns an incrementing counter (0, 1, 2...)
5627 private synchronized int nextCounter()