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.GraphLine;
33 import jalview.datamodel.PDBEntry;
34 import jalview.datamodel.RnaViewerModel;
35 import jalview.datamodel.SequenceFeature;
36 import jalview.datamodel.SequenceGroup;
37 import jalview.datamodel.SequenceI;
38 import jalview.datamodel.StructureViewerModel;
39 import jalview.datamodel.StructureViewerModel.StructureData;
40 import jalview.ext.archaeopteryx.AptxInit;
41 import jalview.ext.treeviewer.TreeFrameI;
42 import jalview.ext.treeviewer.TreeI;
43 import jalview.ext.treeviewer.TreeViewerUtils;
44 import jalview.ext.varna.RnaModel;
45 import jalview.gui.StructureViewer.ViewerType;
46 import jalview.io.DataSourceType;
47 import jalview.io.FileFormat;
48 import jalview.io.NewickFile;
49 import jalview.renderer.ResidueShaderI;
50 import jalview.schemabinding.version2.AlcodMap;
51 import jalview.schemabinding.version2.AlcodonFrame;
52 import jalview.schemabinding.version2.Annotation;
53 import jalview.schemabinding.version2.AnnotationColours;
54 import jalview.schemabinding.version2.AnnotationElement;
55 import jalview.schemabinding.version2.CalcIdParam;
56 import jalview.schemabinding.version2.DBRef;
57 import jalview.schemabinding.version2.Features;
58 import jalview.schemabinding.version2.Group;
59 import jalview.schemabinding.version2.HiddenColumns;
60 import jalview.schemabinding.version2.JGroup;
61 import jalview.schemabinding.version2.JSeq;
62 import jalview.schemabinding.version2.JalviewModel;
63 import jalview.schemabinding.version2.JalviewModelSequence;
64 import jalview.schemabinding.version2.MapListFrom;
65 import jalview.schemabinding.version2.MapListTo;
66 import jalview.schemabinding.version2.Mapping;
67 import jalview.schemabinding.version2.MappingChoice;
68 import jalview.schemabinding.version2.OtherData;
69 import jalview.schemabinding.version2.PdbentryItem;
70 import jalview.schemabinding.version2.Pdbids;
71 import jalview.schemabinding.version2.Property;
72 import jalview.schemabinding.version2.RnaViewer;
73 import jalview.schemabinding.version2.SecondaryStructure;
74 import jalview.schemabinding.version2.Sequence;
75 import jalview.schemabinding.version2.SequenceSet;
76 import jalview.schemabinding.version2.SequenceSetProperties;
77 import jalview.schemabinding.version2.Setting;
78 import jalview.schemabinding.version2.StructureState;
79 import jalview.schemabinding.version2.ThresholdLine;
80 import jalview.schemabinding.version2.Tree;
81 import jalview.schemabinding.version2.UserColours;
82 import jalview.schemabinding.version2.Viewport;
83 import jalview.schemes.AnnotationColourGradient;
84 import jalview.schemes.ColourSchemeI;
85 import jalview.schemes.ColourSchemeProperty;
86 import jalview.schemes.FeatureColour;
87 import jalview.schemes.ResidueProperties;
88 import jalview.schemes.UserColourScheme;
89 import jalview.structure.StructureSelectionManager;
90 import jalview.structures.models.AAStructureBindingModel;
91 import jalview.util.MessageManager;
92 import jalview.util.Platform;
93 import jalview.util.StringUtils;
94 import jalview.util.jarInputStreamProvider;
95 import jalview.viewmodel.AlignmentViewport;
96 import jalview.viewmodel.ViewportRanges;
97 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
98 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
99 import jalview.ws.jws2.Jws2Discoverer;
100 import jalview.ws.jws2.dm.AAConSettings;
101 import jalview.ws.jws2.jabaws2.Jws2Instance;
102 import jalview.ws.params.ArgumentI;
103 import jalview.ws.params.AutoCalcSetting;
104 import jalview.ws.params.WsParamSetI;
106 import java.awt.Color;
107 import java.awt.Rectangle;
108 import java.io.BufferedReader;
109 import java.io.DataInputStream;
110 import java.io.DataOutputStream;
112 import java.io.FileInputStream;
113 import java.io.FileOutputStream;
114 import java.io.IOException;
115 import java.io.InputStreamReader;
116 import java.io.OutputStreamWriter;
117 import java.io.PrintWriter;
118 import java.lang.reflect.InvocationTargetException;
119 import java.net.MalformedURLException;
121 import java.util.ArrayList;
122 import java.util.Arrays;
123 import java.util.Enumeration;
124 import java.util.HashMap;
125 import java.util.HashSet;
126 import java.util.Hashtable;
127 import java.util.IdentityHashMap;
128 import java.util.Iterator;
129 import java.util.LinkedHashMap;
130 import java.util.List;
131 import java.util.Map;
132 import java.util.Map.Entry;
133 import java.util.Set;
134 import java.util.Vector;
135 import java.util.jar.JarEntry;
136 import java.util.jar.JarInputStream;
137 import java.util.jar.JarOutputStream;
139 import javax.swing.JInternalFrame;
140 import javax.swing.SwingUtilities;
142 import org.exolab.castor.xml.Marshaller;
143 import org.exolab.castor.xml.Unmarshaller;
146 * Write out the current jalview desktop state as a Jalview XML stream.
148 * Note: the vamsas objects referred to here are primitive versions of the
149 * VAMSAS project schema elements - they are not the same and most likely never
153 * @version $Revision: 1.134 $
155 public class Jalview2XML
157 private static final String VIEWER_PREFIX = "viewer_";
159 private static final String RNA_PREFIX = "rna_";
161 private static final String UTF_8 = "UTF-8";
163 // use this with nextCounter() to make unique names for entities
164 private int counter = 0;
167 * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
168 * of sequence objects are created.
170 IdentityHashMap<SequenceI, String> seqsToIds = null;
173 * jalview XML Sequence ID to jalview sequence object reference (both dataset
174 * and alignment sequences. Populated as XML reps of sequence objects are
177 Map<String, SequenceI> seqRefIds = null;
179 Map<String, SequenceI> incompleteSeqs = null;
181 List<SeqFref> frefedSequence = null;
183 boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
186 * Map of reconstructed AlignFrame objects that appear to have come from
187 * SplitFrame objects (have a dna/protein complement view).
189 private Map<Viewport, AlignFrame> splitFrameCandidates = new HashMap<>();
192 * Map from displayed rna structure models to their saved session state jar
195 private Map<RnaModel, String> rnaSessions = new HashMap<>();
198 * create/return unique hash string for sq
201 * @return new or existing unique string for sq
203 String seqHash(SequenceI sq)
205 if (seqsToIds == null)
209 if (seqsToIds.containsKey(sq))
211 return seqsToIds.get(sq);
215 // create sequential key
216 String key = "sq" + (seqsToIds.size() + 1);
217 key = makeHashCode(sq, key); // check we don't have an external reference
219 seqsToIds.put(sq, key);
226 if (seqsToIds == null)
228 seqsToIds = new IdentityHashMap<>();
230 if (seqRefIds == null)
232 seqRefIds = new HashMap<>();
234 if (incompleteSeqs == null)
236 incompleteSeqs = new HashMap<>();
238 if (frefedSequence == null)
240 frefedSequence = new ArrayList<>();
248 public Jalview2XML(boolean raiseGUI)
250 this.raiseGUI = raiseGUI;
254 * base class for resolving forward references to sequences by their ID
259 abstract class SeqFref
265 public SeqFref(String _sref, String type)
271 public String getSref()
276 public SequenceI getSrefSeq()
278 return seqRefIds.get(sref);
281 public boolean isResolvable()
283 return seqRefIds.get(sref) != null;
286 public SequenceI getSrefDatasetSeq()
288 SequenceI sq = seqRefIds.get(sref);
291 while (sq.getDatasetSequence() != null)
293 sq = sq.getDatasetSequence();
300 * @return true if the forward reference was fully resolved
302 abstract boolean resolve();
305 public String toString()
307 return type + " reference to " + sref;
312 * create forward reference for a mapping
318 public SeqFref newMappingRef(final String sref,
319 final jalview.datamodel.Mapping _jmap)
321 SeqFref fref = new SeqFref(sref, "Mapping")
323 public jalview.datamodel.Mapping jmap = _jmap;
328 SequenceI seq = getSrefDatasetSeq();
340 public SeqFref newAlcodMapRef(final String sref,
341 final AlignedCodonFrame _cf,
342 final jalview.datamodel.Mapping _jmap)
345 SeqFref fref = new SeqFref(sref, "Codon Frame")
347 AlignedCodonFrame cf = _cf;
349 public jalview.datamodel.Mapping mp = _jmap;
352 public boolean isResolvable()
354 return super.isResolvable() && mp.getTo() != null;
360 SequenceI seq = getSrefDatasetSeq();
365 cf.addMap(seq, mp.getTo(), mp.getMap());
372 public void resolveFrefedSequences()
374 Iterator<SeqFref> nextFref = frefedSequence.iterator();
375 int toresolve = frefedSequence.size();
376 int unresolved = 0, failedtoresolve = 0;
377 while (nextFref.hasNext())
379 SeqFref ref = nextFref.next();
380 if (ref.isResolvable())
392 } catch (Exception x)
395 "IMPLEMENTATION ERROR: Failed to resolve forward reference for sequence "
408 System.err.println("Jalview Project Import: There were " + unresolved
409 + " forward references left unresolved on the stack.");
411 if (failedtoresolve > 0)
413 System.err.println("SERIOUS! " + failedtoresolve
414 + " resolvable forward references failed to resolve.");
416 if (incompleteSeqs != null && incompleteSeqs.size() > 0)
419 "Jalview Project Import: There are " + incompleteSeqs.size()
420 + " sequences which may have incomplete metadata.");
421 if (incompleteSeqs.size() < 10)
423 for (SequenceI s : incompleteSeqs.values())
425 System.err.println(s.toString());
431 "Too many to report. Skipping output of incomplete sequences.");
437 * This maintains a map of viewports, the key being the seqSetId. Important to
438 * set historyItem and redoList for multiple views
440 Map<String, AlignViewport> viewportsAdded = new HashMap<>();
442 Map<String, AlignmentAnnotation> annotationIds = new HashMap<>();
444 String uniqueSetSuffix = "";
447 * List of pdbfiles added to Jar
449 List<String> pdbfiles = null;
451 // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
452 public void saveState(File statefile)
454 FileOutputStream fos = null;
457 fos = new FileOutputStream(statefile);
458 JarOutputStream jout = new JarOutputStream(fos);
461 } catch (Exception e)
463 // TODO: inform user of the problem - they need to know if their data was
465 if (errorMessage == null)
467 errorMessage = "Couldn't write Jalview Archive to output file '"
468 + statefile + "' - See console error log for details";
472 errorMessage += "(output file was '" + statefile + "')";
482 } catch (IOException e)
492 * Writes a jalview project archive to the given Jar output stream.
496 public void saveState(JarOutputStream jout)
498 AlignFrame[] frames = Desktop.getAlignFrames();
504 saveAllFrames(Arrays.asList(frames), jout);
508 * core method for storing state for a set of AlignFrames.
511 * - frames involving all data to be exported (including containing
514 * - project output stream
516 private void saveAllFrames(List<AlignFrame> frames, JarOutputStream jout)
518 Hashtable<String, AlignFrame> dsses = new Hashtable<>();
521 * ensure cached data is clear before starting
523 // todo tidy up seqRefIds, seqsToIds initialisation / reset
525 splitFrameCandidates.clear();
530 // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
531 // //////////////////////////////////////////////////
533 List<String> shortNames = new ArrayList<>();
534 List<String> viewIds = new ArrayList<>();
537 for (int i = frames.size() - 1; i > -1; i--)
539 AlignFrame af = frames.get(i);
541 if (skipList != null && skipList
542 .containsKey(af.getViewport().getSequenceSetId()))
547 String shortName = makeFilename(af, shortNames);
549 int ap, apSize = af.alignPanels.size();
551 for (ap = 0; ap < apSize; ap++)
553 AlignmentPanel apanel = af.alignPanels.get(ap);
554 String fileName = apSize == 1 ? shortName : ap + shortName;
555 if (!fileName.endsWith(".xml"))
557 fileName = fileName + ".xml";
560 saveState(apanel, fileName, jout, viewIds);
562 String dssid = getDatasetIdRef(
563 af.getViewport().getAlignment().getDataset());
564 if (!dsses.containsKey(dssid))
566 dsses.put(dssid, af);
571 writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix,
577 } catch (Exception foo)
582 } catch (Exception ex)
584 // TODO: inform user of the problem - they need to know if their data was
586 if (errorMessage == null)
588 errorMessage = "Couldn't write Jalview Archive - see error output for details";
590 ex.printStackTrace();
595 * Generates a distinct file name, based on the title of the AlignFrame, by
596 * appending _n for increasing n until an unused name is generated. The new
597 * name (without its extension) is added to the list.
601 * @return the generated name, with .xml extension
603 protected String makeFilename(AlignFrame af, List<String> namesUsed)
605 String shortName = af.getTitle();
607 if (shortName.indexOf(File.separatorChar) > -1)
609 shortName = shortName
610 .substring(shortName.lastIndexOf(File.separatorChar) + 1);
615 while (namesUsed.contains(shortName))
617 if (shortName.endsWith("_" + (count - 1)))
619 shortName = shortName.substring(0, shortName.lastIndexOf("_"));
622 shortName = shortName.concat("_" + count);
626 namesUsed.add(shortName);
628 if (!shortName.endsWith(".xml"))
630 shortName = shortName + ".xml";
635 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
636 public boolean saveAlignment(AlignFrame af, String jarFile,
641 FileOutputStream fos = new FileOutputStream(jarFile);
642 JarOutputStream jout = new JarOutputStream(fos);
643 List<AlignFrame> frames = new ArrayList<>();
645 // resolve splitframes
646 if (af.getViewport().getCodingComplement() != null)
648 frames = ((SplitFrame) af.getSplitViewContainer()).getAlignFrames();
654 saveAllFrames(frames, jout);
658 } catch (Exception foo)
664 } catch (Exception ex)
666 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
667 ex.printStackTrace();
672 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
673 String fileName, JarOutputStream jout)
676 for (String dssids : dsses.keySet())
678 AlignFrame _af = dsses.get(dssids);
679 String jfileName = fileName + " Dataset for " + _af.getTitle();
680 if (!jfileName.endsWith(".xml"))
682 jfileName = jfileName + ".xml";
684 saveState(_af.alignPanel, jfileName, true, jout, null);
689 * create a JalviewModel from an alignment view and marshall it to a
693 * panel to create jalview model for
695 * name of alignment panel written to output stream
702 public JalviewModel saveState(AlignmentPanel ap, String fileName,
703 JarOutputStream jout, List<String> viewIds)
705 return saveState(ap, fileName, false, jout, viewIds);
709 * create a JalviewModel from an alignment view and marshall it to a
713 * panel to create jalview model for
715 * name of alignment panel written to output stream
717 * when true, only write the dataset for the alignment, not the data
718 * associated with the view.
724 public JalviewModel saveState(AlignmentPanel ap, String fileName,
725 boolean storeDS, JarOutputStream jout, List<String> viewIds)
729 viewIds = new ArrayList<>();
734 List<UserColourScheme> userColours = new ArrayList<>();
736 AlignViewport av = ap.av;
737 ViewportRanges vpRanges = av.getRanges();
739 JalviewModel object = new JalviewModel();
740 object.setVamsasModel(new jalview.schemabinding.version2.VamsasModel());
742 object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
744 jalview.bin.Cache.getDefault("VERSION", "Development Build"));
747 * rjal is full height alignment, jal is actual alignment with full metadata
748 * but excludes hidden sequences.
750 jalview.datamodel.AlignmentI rjal = av.getAlignment(), jal = rjal;
752 if (av.hasHiddenRows())
754 rjal = jal.getHiddenSequences().getFullAlignment();
757 SequenceSet vamsasSet = new SequenceSet();
759 JalviewModelSequence jms = new JalviewModelSequence();
761 vamsasSet.setGapChar(jal.getGapCharacter() + "");
763 if (jal.getDataset() != null)
765 // dataset id is the dataset's hashcode
766 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
769 // switch jal and the dataset
770 jal = jal.getDataset();
774 if (jal.getProperties() != null)
776 Enumeration en = jal.getProperties().keys();
777 while (en.hasMoreElements())
779 String key = en.nextElement().toString();
780 SequenceSetProperties ssp = new SequenceSetProperties();
782 ssp.setValue(jal.getProperties().get(key).toString());
783 vamsasSet.addSequenceSetProperties(ssp);
788 Set<String> calcIdSet = new HashSet<>();
789 // record the set of vamsas sequence XML POJO we create.
790 HashMap<String, Sequence> vamsasSetIds = new HashMap<>();
792 for (final SequenceI jds : rjal.getSequences())
794 final SequenceI jdatasq = jds.getDatasetSequence() == null ? jds
795 : jds.getDatasetSequence();
796 String id = seqHash(jds);
797 if (vamsasSetIds.get(id) == null)
799 if (seqRefIds.get(id) != null && !storeDS)
801 // This happens for two reasons: 1. multiple views are being
803 // 2. the hashCode has collided with another sequence's code. This
805 // HAPPEN! (PF00072.15.stk does this)
806 // JBPNote: Uncomment to debug writing out of files that do not read
807 // back in due to ArrayOutOfBoundExceptions.
808 // System.err.println("vamsasSeq backref: "+id+"");
809 // System.err.println(jds.getName()+"
810 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
811 // System.err.println("Hashcode: "+seqHash(jds));
812 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
813 // System.err.println(rsq.getName()+"
814 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
815 // System.err.println("Hashcode: "+seqHash(rsq));
819 vamsasSeq = createVamsasSequence(id, jds);
820 vamsasSet.addSequence(vamsasSeq);
821 vamsasSetIds.put(id, vamsasSeq);
822 seqRefIds.put(id, jds);
826 jseq.setStart(jds.getStart());
827 jseq.setEnd(jds.getEnd());
828 jseq.setColour(av.getSequenceColour(jds).getRGB());
830 jseq.setId(id); // jseq id should be a string not a number
833 // Store any sequences this sequence represents
834 if (av.hasHiddenRows())
836 // use rjal, contains the full height alignment
838 av.getAlignment().getHiddenSequences().isHidden(jds));
840 if (av.isHiddenRepSequence(jds))
842 jalview.datamodel.SequenceI[] reps = av
843 .getRepresentedSequences(jds).getSequencesInOrder(rjal);
845 for (int h = 0; h < reps.length; h++)
849 jseq.addHiddenSequences(rjal.findIndex(reps[h]));
854 // mark sequence as reference - if it is the reference for this view
857 jseq.setViewreference(jds == jal.getSeqrep());
861 // TODO: omit sequence features from each alignment view's XML dump if we
862 // are storing dataset
863 List<jalview.datamodel.SequenceFeature> sfs = jds
864 .getSequenceFeatures();
865 for (SequenceFeature sf : sfs)
867 Features features = new Features();
869 features.setBegin(sf.getBegin());
870 features.setEnd(sf.getEnd());
871 features.setDescription(sf.getDescription());
872 features.setType(sf.getType());
873 features.setFeatureGroup(sf.getFeatureGroup());
874 features.setScore(sf.getScore());
875 if (sf.links != null)
877 for (int l = 0; l < sf.links.size(); l++)
879 OtherData keyValue = new OtherData();
880 keyValue.setKey("LINK_" + l);
881 keyValue.setValue(sf.links.elementAt(l).toString());
882 features.addOtherData(keyValue);
885 if (sf.otherDetails != null)
888 Iterator<String> keys = sf.otherDetails.keySet().iterator();
889 while (keys.hasNext())
892 OtherData keyValue = new OtherData();
893 keyValue.setKey(key);
894 keyValue.setValue(sf.otherDetails.get(key).toString());
895 features.addOtherData(keyValue);
899 jseq.addFeatures(features);
902 if (jdatasq.getAllPDBEntries() != null)
904 Enumeration en = jdatasq.getAllPDBEntries().elements();
905 while (en.hasMoreElements())
907 Pdbids pdb = new Pdbids();
908 jalview.datamodel.PDBEntry entry = (jalview.datamodel.PDBEntry) en
911 String pdbId = entry.getId();
913 pdb.setType(entry.getType());
916 * Store any structure views associated with this sequence. This
917 * section copes with duplicate entries in the project, so a dataset
918 * only view *should* be coped with sensibly.
920 // This must have been loaded, is it still visible?
921 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
922 String matchedFile = null;
923 for (int f = frames.length - 1; f > -1; f--)
925 if (frames[f] instanceof StructureViewerBase)
927 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
928 matchedFile = saveStructureState(ap, jds, pdb, entry, viewIds,
929 matchedFile, viewFrame);
931 * Only store each structure viewer's state once in the project
932 * jar. First time through only (storeDS==false)
934 String viewId = viewFrame.getViewId();
935 if (!storeDS && !viewIds.contains(viewId))
940 String viewerState = viewFrame.getStateInfo();
941 writeJarEntry(jout, getViewerJarEntryName(viewId),
942 viewerState.getBytes());
943 } catch (IOException e)
946 "Error saving viewer state: " + e.getMessage());
952 if (matchedFile != null || entry.getFile() != null)
954 if (entry.getFile() != null)
957 matchedFile = entry.getFile();
959 pdb.setFile(matchedFile); // entry.getFile());
960 if (pdbfiles == null)
962 pdbfiles = new ArrayList<>();
965 if (!pdbfiles.contains(pdbId))
968 copyFileToJar(jout, matchedFile, pdbId);
972 Enumeration<String> props = entry.getProperties();
973 if (props.hasMoreElements())
975 PdbentryItem item = new PdbentryItem();
976 while (props.hasMoreElements())
978 Property prop = new Property();
979 String key = props.nextElement();
981 prop.setValue(entry.getProperty(key).toString());
982 item.addProperty(prop);
984 pdb.addPdbentryItem(item);
991 saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
996 if (!storeDS && av.hasHiddenRows())
998 jal = av.getAlignment();
1002 if (storeDS && jal.getCodonFrames() != null)
1004 List<AlignedCodonFrame> jac = jal.getCodonFrames();
1005 for (AlignedCodonFrame acf : jac)
1007 AlcodonFrame alc = new AlcodonFrame();
1008 if (acf.getProtMappings() != null
1009 && acf.getProtMappings().length > 0)
1011 boolean hasMap = false;
1012 SequenceI[] dnas = acf.getdnaSeqs();
1013 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1014 for (int m = 0; m < pmaps.length; m++)
1016 AlcodMap alcmap = new AlcodMap();
1017 alcmap.setDnasq(seqHash(dnas[m]));
1019 createVamsasMapping(pmaps[m], dnas[m], null, false));
1020 alc.addAlcodMap(alcmap);
1025 vamsasSet.addAlcodonFrame(alc);
1028 // TODO: delete this ? dead code from 2.8.3->2.9 ?
1030 // AlcodonFrame alc = new AlcodonFrame();
1031 // vamsasSet.addAlcodonFrame(alc);
1032 // for (int p = 0; p < acf.aaWidth; p++)
1034 // Alcodon cmap = new Alcodon();
1035 // if (acf.codons[p] != null)
1037 // // Null codons indicate a gapped column in the translated peptide
1039 // cmap.setPos1(acf.codons[p][0]);
1040 // cmap.setPos2(acf.codons[p][1]);
1041 // cmap.setPos3(acf.codons[p][2]);
1043 // alc.addAlcodon(cmap);
1045 // if (acf.getProtMappings() != null
1046 // && acf.getProtMappings().length > 0)
1048 // SequenceI[] dnas = acf.getdnaSeqs();
1049 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1050 // for (int m = 0; m < pmaps.length; m++)
1052 // AlcodMap alcmap = new AlcodMap();
1053 // alcmap.setDnasq(seqHash(dnas[m]));
1054 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
1056 // alc.addAlcodMap(alcmap);
1063 // /////////////////////////////////
1064 if (!storeDS && av.getCurrentTree() != null)
1066 // FIND ANY ASSOCIATED TREES
1067 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
1068 if (Desktop.desktop != null)
1070 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1072 for (int t = 0; t < frames.length; t++)
1074 if (frames[t] instanceof TreePanel)
1076 TreePanel tp = (TreePanel) frames[t];
1078 if (tp.treeCanvas.av.getAlignment() == jal)
1080 Tree tree = new Tree();
1081 tree.setTitle(tp.getTitle());
1082 tree.setCurrentTree((av.getCurrentTree() == tp.getTree()));
1083 tree.setNewick(tp.getTree().print());
1084 tree.setThreshold(tp.treeCanvas.threshold);
1086 tree.setFitToWindow(tp.fitToWindow.getState());
1087 tree.setFontName(tp.getTreeFont().getName());
1088 tree.setFontSize(tp.getTreeFont().getSize());
1089 tree.setFontStyle(tp.getTreeFont().getStyle());
1090 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
1092 tree.setShowBootstrap(tp.bootstrapMenu.getState());
1093 tree.setShowDistances(tp.distanceMenu.getState());
1095 tree.setHeight(tp.getHeight());
1096 tree.setWidth(tp.getWidth());
1097 tree.setXpos(tp.getX());
1098 tree.setYpos(tp.getY());
1099 tree.setId(makeHashCode(tp, null));
1107 if (!storeDS && av.getCurrentExtTree() != null)
1109 Set<TreeFrameI> externalTreeViews = TreeViewerUtils
1110 .getActiveTreeViews()
1112 for (TreeFrameI treeView : externalTreeViews)
1114 TreeI tree = treeView.getTree();
1117 tree.writeToXml(new File("word"));
1118 copyFileToJar(jout, "word", tree.getTreeName());
1119 } catch (IOException e)
1121 // TODO Auto-generated catch block
1122 e.printStackTrace();
1132 * store forward refs from an annotationRow to any groups
1134 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<>();
1137 for (SequenceI sq : jal.getSequences())
1139 // Store annotation on dataset sequences only
1140 AlignmentAnnotation[] aa = sq.getAnnotation();
1141 if (aa != null && aa.length > 0)
1143 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1150 if (jal.getAlignmentAnnotation() != null)
1152 // Store the annotation shown on the alignment.
1153 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1154 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1159 if (jal.getGroups() != null)
1161 JGroup[] groups = new JGroup[jal.getGroups().size()];
1163 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1165 JGroup jGroup = new JGroup();
1166 groups[++i] = jGroup;
1168 jGroup.setStart(sg.getStartRes());
1169 jGroup.setEnd(sg.getEndRes());
1170 jGroup.setName(sg.getName());
1171 if (groupRefs.containsKey(sg))
1173 // group has references so set its ID field
1174 jGroup.setId(groupRefs.get(sg));
1176 ColourSchemeI colourScheme = sg.getColourScheme();
1177 if (colourScheme != null)
1179 ResidueShaderI groupColourScheme = sg.getGroupColourScheme();
1180 if (groupColourScheme.conservationApplied())
1182 jGroup.setConsThreshold(groupColourScheme.getConservationInc());
1184 if (colourScheme instanceof jalview.schemes.UserColourScheme)
1187 setUserColourScheme(colourScheme, userColours, jms));
1191 jGroup.setColour(colourScheme.getSchemeName());
1194 else if (colourScheme instanceof jalview.schemes.AnnotationColourGradient)
1196 jGroup.setColour("AnnotationColourGradient");
1197 jGroup.setAnnotationColours(constructAnnotationColours(
1198 (jalview.schemes.AnnotationColourGradient) colourScheme,
1201 else if (colourScheme instanceof jalview.schemes.UserColourScheme)
1204 setUserColourScheme(colourScheme, userColours, jms));
1208 jGroup.setColour(colourScheme.getSchemeName());
1211 jGroup.setPidThreshold(groupColourScheme.getThreshold());
1214 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1215 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1216 jGroup.setDisplayText(sg.getDisplayText());
1217 jGroup.setColourText(sg.getColourText());
1218 jGroup.setTextCol1(sg.textColour.getRGB());
1219 jGroup.setTextCol2(sg.textColour2.getRGB());
1220 jGroup.setTextColThreshold(sg.thresholdTextColour);
1221 jGroup.setShowUnconserved(sg.getShowNonconserved());
1222 jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1223 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1224 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1225 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1226 for (SequenceI seq : sg.getSequences())
1228 jGroup.addSeq(seqHash(seq));
1232 jms.setJGroup(groups);
1236 // /////////SAVE VIEWPORT
1237 Viewport view = new Viewport();
1238 view.setTitle(ap.alignFrame.getTitle());
1239 view.setSequenceSetId(
1240 makeHashCode(av.getSequenceSetId(), av.getSequenceSetId()));
1241 view.setId(av.getViewId());
1242 if (av.getCodingComplement() != null)
1244 view.setComplementId(av.getCodingComplement().getViewId());
1246 view.setViewName(av.viewName);
1247 view.setGatheredViews(av.isGatherViewsHere());
1249 Rectangle size = ap.av.getExplodedGeometry();
1250 Rectangle position = size;
1253 size = ap.alignFrame.getBounds();
1254 if (av.getCodingComplement() != null)
1256 position = ((SplitFrame) ap.alignFrame.getSplitViewContainer())
1264 view.setXpos(position.x);
1265 view.setYpos(position.y);
1267 view.setWidth(size.width);
1268 view.setHeight(size.height);
1270 view.setStartRes(vpRanges.getStartRes());
1271 view.setStartSeq(vpRanges.getStartSeq());
1273 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1275 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1279 .getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1281 AnnotationColours ac = constructAnnotationColours(
1282 (jalview.schemes.AnnotationColourGradient) av
1283 .getGlobalColourScheme(),
1286 view.setAnnotationColours(ac);
1287 view.setBgColour("AnnotationColourGradient");
1291 view.setBgColour(ColourSchemeProperty
1292 .getColourName(av.getGlobalColourScheme()));
1295 ResidueShaderI vcs = av.getResidueShading();
1296 ColourSchemeI cs = av.getGlobalColourScheme();
1300 if (vcs.conservationApplied())
1302 view.setConsThreshold(vcs.getConservationInc());
1303 if (cs instanceof jalview.schemes.UserColourScheme)
1305 view.setBgColour(setUserColourScheme(cs, userColours, jms));
1308 view.setPidThreshold(vcs.getThreshold());
1311 view.setConservationSelected(av.getConservationSelected());
1312 view.setPidSelected(av.getAbovePIDThreshold());
1313 view.setFontName(av.font.getName());
1314 view.setFontSize(av.font.getSize());
1315 view.setFontStyle(av.font.getStyle());
1316 view.setScaleProteinAsCdna(av.getViewStyle().isScaleProteinAsCdna());
1317 view.setRenderGaps(av.isRenderGaps());
1318 view.setShowAnnotation(av.isShowAnnotation());
1319 view.setShowBoxes(av.getShowBoxes());
1320 view.setShowColourText(av.getColourText());
1321 view.setShowFullId(av.getShowJVSuffix());
1322 view.setRightAlignIds(av.isRightAlignIds());
1323 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1324 view.setShowText(av.getShowText());
1325 view.setShowUnconserved(av.getShowUnconserved());
1326 view.setWrapAlignment(av.getWrapAlignment());
1327 view.setTextCol1(av.getTextColour().getRGB());
1328 view.setTextCol2(av.getTextColour2().getRGB());
1329 view.setTextColThreshold(av.getThresholdTextColour());
1330 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1331 view.setShowSequenceLogo(av.isShowSequenceLogo());
1332 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1333 view.setShowGroupConsensus(av.isShowGroupConsensus());
1334 view.setShowGroupConservation(av.isShowGroupConservation());
1335 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1336 view.setShowDbRefTooltip(av.isShowDBRefs());
1337 view.setFollowHighlight(av.isFollowHighlight());
1338 view.setFollowSelection(av.followSelection);
1339 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1340 if (av.getFeaturesDisplayed() != null)
1342 jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
1344 String[] renderOrder = ap.getSeqPanel().seqCanvas
1345 .getFeatureRenderer().getRenderOrder()
1346 .toArray(new String[0]);
1348 Vector<String> settingsAdded = new Vector<>();
1349 if (renderOrder != null)
1351 for (String featureType : renderOrder)
1353 FeatureColourI fcol = ap.getSeqPanel().seqCanvas
1354 .getFeatureRenderer().getFeatureStyle(featureType);
1355 Setting setting = new Setting();
1356 setting.setType(featureType);
1357 if (!fcol.isSimpleColour())
1359 setting.setColour(fcol.getMaxColour().getRGB());
1360 setting.setMincolour(fcol.getMinColour().getRGB());
1361 setting.setMin(fcol.getMin());
1362 setting.setMax(fcol.getMax());
1363 setting.setColourByLabel(fcol.isColourByLabel());
1364 setting.setAutoScale(fcol.isAutoScaled());
1365 setting.setThreshold(fcol.getThreshold());
1366 // -1 = No threshold, 0 = Below, 1 = Above
1367 setting.setThreshstate(fcol.isAboveThreshold() ? 1
1368 : (fcol.isBelowThreshold() ? 0 : -1));
1372 setting.setColour(fcol.getColour().getRGB());
1376 av.getFeaturesDisplayed().isVisible(featureType));
1377 float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1378 .getOrder(featureType);
1381 setting.setOrder(rorder);
1383 fs.addSetting(setting);
1384 settingsAdded.addElement(featureType);
1388 // is groups actually supposed to be a map here ?
1389 Iterator<String> en = ap.getSeqPanel().seqCanvas
1390 .getFeatureRenderer().getFeatureGroups().iterator();
1391 Vector<String> groupsAdded = new Vector<>();
1392 while (en.hasNext())
1394 String grp = en.next();
1395 if (groupsAdded.contains(grp))
1399 Group g = new Group();
1401 g.setDisplay(((Boolean) ap.getSeqPanel().seqCanvas
1402 .getFeatureRenderer().checkGroupVisibility(grp, false))
1405 groupsAdded.addElement(grp);
1407 jms.setFeatureSettings(fs);
1410 if (av.hasHiddenColumns())
1412 jalview.datamodel.HiddenColumns hidden = av.getAlignment()
1413 .getHiddenColumns();
1416 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1420 ArrayList<int[]> hiddenRegions = hidden.getHiddenColumnsCopy();
1421 for (int[] region : hiddenRegions)
1423 HiddenColumns hc = new HiddenColumns();
1424 hc.setStart(region[0]);
1425 hc.setEnd(region[1]);
1426 view.addHiddenColumns(hc);
1430 if (calcIdSet.size() > 0)
1432 for (String calcId : calcIdSet)
1434 if (calcId.trim().length() > 0)
1436 CalcIdParam cidp = createCalcIdParam(calcId, av);
1437 // Some calcIds have no parameters.
1440 view.addCalcIdParam(cidp);
1446 jms.addViewport(view);
1448 object.setJalviewModelSequence(jms);
1449 object.getVamsasModel().addSequenceSet(vamsasSet);
1451 if (jout != null && fileName != null)
1453 // We may not want to write the object to disk,
1454 // eg we can copy the alignViewport to a new view object
1455 // using save and then load
1458 System.out.println("Writing jar entry " + fileName);
1459 JarEntry entry = new JarEntry(fileName);
1460 jout.putNextEntry(entry);
1461 PrintWriter pout = new PrintWriter(
1462 new OutputStreamWriter(jout, UTF_8));
1463 Marshaller marshaller = new Marshaller(pout);
1464 marshaller.marshal(object);
1467 } catch (Exception ex)
1469 // TODO: raise error in GUI if marshalling failed.
1470 ex.printStackTrace();
1477 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1478 * for each viewer, with
1480 * <li>viewer geometry (position, size, split pane divider location)</li>
1481 * <li>index of the selected structure in the viewer (currently shows gapped
1483 * <li>the id of the annotation holding RNA secondary structure</li>
1484 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1486 * Varna viewer state is also written out (in native Varna XML) to separate
1487 * project jar entries. A separate entry is written for each RNA structure
1488 * displayed, with the naming convention
1490 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
1498 * @param storeDataset
1500 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
1501 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
1502 boolean storeDataset)
1504 if (Desktop.desktop == null)
1508 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1509 for (int f = frames.length - 1; f > -1; f--)
1511 if (frames[f] instanceof AppVarna)
1513 AppVarna varna = (AppVarna) frames[f];
1515 * link the sequence to every viewer that is showing it and is linked to
1516 * its alignment panel
1518 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1520 String viewId = varna.getViewId();
1521 RnaViewer rna = new RnaViewer();
1522 rna.setViewId(viewId);
1523 rna.setTitle(varna.getTitle());
1524 rna.setXpos(varna.getX());
1525 rna.setYpos(varna.getY());
1526 rna.setWidth(varna.getWidth());
1527 rna.setHeight(varna.getHeight());
1528 rna.setDividerLocation(varna.getDividerLocation());
1529 rna.setSelectedRna(varna.getSelectedIndex());
1530 jseq.addRnaViewer(rna);
1533 * Store each Varna panel's state once in the project per sequence.
1534 * First time through only (storeDataset==false)
1536 // boolean storeSessions = false;
1537 // String sequenceViewId = viewId + seqsToIds.get(jds);
1538 // if (!storeDataset && !viewIds.contains(sequenceViewId))
1540 // viewIds.add(sequenceViewId);
1541 // storeSessions = true;
1543 for (RnaModel model : varna.getModels())
1545 if (model.seq == jds)
1548 * VARNA saves each view (sequence or alignment secondary
1549 * structure, gapped or trimmed) as a separate XML file
1551 String jarEntryName = rnaSessions.get(model);
1552 if (jarEntryName == null)
1555 String varnaStateFile = varna.getStateInfo(model.rna);
1556 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
1558 rnaSessions.put(model, jarEntryName);
1560 SecondaryStructure ss = new SecondaryStructure();
1561 String annotationId = varna.getAnnotation(jds).annotationId;
1562 ss.setAnnotationId(annotationId);
1563 ss.setViewerState(jarEntryName);
1564 ss.setGapped(model.gapped);
1565 ss.setTitle(model.title);
1566 rna.addSecondaryStructure(ss);
1575 * Copy the contents of a file to a new entry added to the output jar
1579 * @param jarEntryName
1581 protected void copyFileToJar(JarOutputStream jout, String infilePath,
1582 String jarEntryName)
1584 DataInputStream dis = null;
1587 File file = new File(infilePath);
1588 if (file.exists() && jout != null)
1590 dis = new DataInputStream(new FileInputStream(file));
1591 byte[] data = new byte[(int) file.length()];
1592 dis.readFully(data);
1593 writeJarEntry(jout, jarEntryName, data);
1595 } catch (Exception ex)
1597 ex.printStackTrace();
1605 } catch (IOException e)
1614 * Write the data to a new entry of given name in the output jar file
1617 * @param jarEntryName
1619 * @throws IOException
1621 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
1622 byte[] data) throws IOException
1626 System.out.println("Writing jar entry " + jarEntryName);
1627 jout.putNextEntry(new JarEntry(jarEntryName));
1628 DataOutputStream dout = new DataOutputStream(jout);
1629 dout.write(data, 0, data.length);
1636 * Save the state of a structure viewer
1641 * the archive XML element under which to save the state
1644 * @param matchedFile
1648 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
1649 Pdbids pdb, PDBEntry entry, List<String> viewIds,
1650 String matchedFile, StructureViewerBase viewFrame)
1652 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
1655 * Look for any bindings for this viewer to the PDB file of interest
1656 * (including part matches excluding chain id)
1658 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
1660 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
1661 final String pdbId = pdbentry.getId();
1662 if (!pdbId.equals(entry.getId())
1663 && !(entry.getId().length() > 4 && entry.getId().toLowerCase()
1664 .startsWith(pdbId.toLowerCase())))
1667 * not interested in a binding to a different PDB entry here
1671 if (matchedFile == null)
1673 matchedFile = pdbentry.getFile();
1675 else if (!matchedFile.equals(pdbentry.getFile()))
1678 "Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
1679 + pdbentry.getFile());
1683 // can get at it if the ID
1684 // match is ambiguous (e.g.
1687 for (int smap = 0; smap < viewFrame.getBinding()
1688 .getSequence()[peid].length; smap++)
1690 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
1691 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
1693 StructureState state = new StructureState();
1694 state.setVisible(true);
1695 state.setXpos(viewFrame.getX());
1696 state.setYpos(viewFrame.getY());
1697 state.setWidth(viewFrame.getWidth());
1698 state.setHeight(viewFrame.getHeight());
1699 final String viewId = viewFrame.getViewId();
1700 state.setViewId(viewId);
1701 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
1702 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
1703 state.setColourByJmol(viewFrame.isColouredByViewer());
1704 state.setType(viewFrame.getViewerType().toString());
1705 pdb.addStructureState(state);
1713 * Populates the AnnotationColours xml for save. This captures the settings of
1714 * the options in the 'Colour by Annotation' dialog.
1717 * @param userColours
1721 private AnnotationColours constructAnnotationColours(
1722 AnnotationColourGradient acg, List<UserColourScheme> userColours,
1723 JalviewModelSequence jms)
1725 AnnotationColours ac = new AnnotationColours();
1726 ac.setAboveThreshold(acg.getAboveThreshold());
1727 ac.setThreshold(acg.getAnnotationThreshold());
1728 // 2.10.2 save annotationId (unique) not annotation label
1729 ac.setAnnotation(acg.getAnnotation().annotationId);
1730 if (acg.getBaseColour() instanceof UserColourScheme)
1733 setUserColourScheme(acg.getBaseColour(), userColours, jms));
1738 ColourSchemeProperty.getColourName(acg.getBaseColour()));
1741 ac.setMaxColour(acg.getMaxColour().getRGB());
1742 ac.setMinColour(acg.getMinColour().getRGB());
1743 ac.setPerSequence(acg.isSeqAssociated());
1744 ac.setPredefinedColours(acg.isPredefinedColours());
1748 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
1749 IdentityHashMap<SequenceGroup, String> groupRefs,
1750 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
1751 SequenceSet vamsasSet)
1754 for (int i = 0; i < aa.length; i++)
1756 Annotation an = new Annotation();
1758 AlignmentAnnotation annotation = aa[i];
1759 if (annotation.annotationId != null)
1761 annotationIds.put(annotation.annotationId, annotation);
1764 an.setId(annotation.annotationId);
1766 an.setVisible(annotation.visible);
1768 an.setDescription(annotation.description);
1770 if (annotation.sequenceRef != null)
1772 // 2.9 JAL-1781 xref on sequence id rather than name
1773 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
1775 if (annotation.groupRef != null)
1777 String groupIdr = groupRefs.get(annotation.groupRef);
1778 if (groupIdr == null)
1780 // make a locally unique String
1781 groupRefs.put(annotation.groupRef,
1782 groupIdr = ("" + System.currentTimeMillis()
1783 + annotation.groupRef.getName()
1784 + groupRefs.size()));
1786 an.setGroupRef(groupIdr.toString());
1789 // store all visualization attributes for annotation
1790 an.setGraphHeight(annotation.graphHeight);
1791 an.setCentreColLabels(annotation.centreColLabels);
1792 an.setScaleColLabels(annotation.scaleColLabel);
1793 an.setShowAllColLabels(annotation.showAllColLabels);
1794 an.setBelowAlignment(annotation.belowAlignment);
1796 if (annotation.graph > 0)
1799 an.setGraphType(annotation.graph);
1800 an.setGraphGroup(annotation.graphGroup);
1801 if (annotation.getThreshold() != null)
1803 ThresholdLine line = new ThresholdLine();
1804 line.setLabel(annotation.getThreshold().label);
1805 line.setValue(annotation.getThreshold().value);
1806 line.setColour(annotation.getThreshold().colour.getRGB());
1807 an.setThresholdLine(line);
1815 an.setLabel(annotation.label);
1817 if (annotation == av.getAlignmentQualityAnnot()
1818 || annotation == av.getAlignmentConservationAnnotation()
1819 || annotation == av.getAlignmentConsensusAnnotation()
1820 || annotation.autoCalculated)
1822 // new way of indicating autocalculated annotation -
1823 an.setAutoCalculated(annotation.autoCalculated);
1825 if (annotation.hasScore())
1827 an.setScore(annotation.getScore());
1830 if (annotation.getCalcId() != null)
1832 calcIdSet.add(annotation.getCalcId());
1833 an.setCalcId(annotation.getCalcId());
1835 if (annotation.hasProperties())
1837 for (String pr : annotation.getProperties())
1839 Property prop = new Property();
1841 prop.setValue(annotation.getProperty(pr));
1842 an.addProperty(prop);
1846 AnnotationElement ae;
1847 if (annotation.annotations != null)
1849 an.setScoreOnly(false);
1850 for (int a = 0; a < annotation.annotations.length; a++)
1852 if ((annotation == null) || (annotation.annotations[a] == null))
1857 ae = new AnnotationElement();
1858 if (annotation.annotations[a].description != null)
1860 ae.setDescription(annotation.annotations[a].description);
1862 if (annotation.annotations[a].displayCharacter != null)
1864 ae.setDisplayCharacter(
1865 annotation.annotations[a].displayCharacter);
1868 if (!Float.isNaN(annotation.annotations[a].value))
1870 ae.setValue(annotation.annotations[a].value);
1874 if (annotation.annotations[a].secondaryStructure > ' ')
1876 ae.setSecondaryStructure(
1877 annotation.annotations[a].secondaryStructure + "");
1880 if (annotation.annotations[a].colour != null
1881 && annotation.annotations[a].colour != java.awt.Color.black)
1883 ae.setColour(annotation.annotations[a].colour.getRGB());
1886 an.addAnnotationElement(ae);
1887 if (annotation.autoCalculated)
1889 // only write one non-null entry into the annotation row -
1890 // sufficient to get the visualization attributes necessary to
1898 an.setScoreOnly(true);
1900 if (!storeDS || (storeDS && !annotation.autoCalculated))
1902 // skip autocalculated annotation - these are only provided for
1904 vamsasSet.addAnnotation(an);
1910 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
1912 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
1913 if (settings != null)
1915 CalcIdParam vCalcIdParam = new CalcIdParam();
1916 vCalcIdParam.setCalcId(calcId);
1917 vCalcIdParam.addServiceURL(settings.getServiceURI());
1918 // generic URI allowing a third party to resolve another instance of the
1919 // service used for this calculation
1920 for (String urls : settings.getServiceURLs())
1922 vCalcIdParam.addServiceURL(urls);
1924 vCalcIdParam.setVersion("1.0");
1925 if (settings.getPreset() != null)
1927 WsParamSetI setting = settings.getPreset();
1928 vCalcIdParam.setName(setting.getName());
1929 vCalcIdParam.setDescription(setting.getDescription());
1933 vCalcIdParam.setName("");
1934 vCalcIdParam.setDescription("Last used parameters");
1936 // need to be able to recover 1) settings 2) user-defined presets or
1937 // recreate settings from preset 3) predefined settings provided by
1938 // service - or settings that can be transferred (or discarded)
1939 vCalcIdParam.setParameters(
1940 settings.getWsParamFile().replace("\n", "|\\n|"));
1941 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
1942 // todo - decide if updateImmediately is needed for any projects.
1944 return vCalcIdParam;
1949 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
1952 if (calcIdParam.getVersion().equals("1.0"))
1954 Jws2Instance service = Jws2Discoverer.getDiscoverer()
1955 .getPreferredServiceFor(calcIdParam.getServiceURL());
1956 if (service != null)
1958 WsParamSetI parmSet = null;
1961 parmSet = service.getParamStore().parseServiceParameterFile(
1962 calcIdParam.getName(), calcIdParam.getDescription(),
1963 calcIdParam.getServiceURL(),
1964 calcIdParam.getParameters().replace("|\\n|", "\n"));
1965 } catch (IOException x)
1967 warn("Couldn't parse parameter data for "
1968 + calcIdParam.getCalcId(), x);
1971 List<ArgumentI> argList = null;
1972 if (calcIdParam.getName().length() > 0)
1974 parmSet = service.getParamStore()
1975 .getPreset(calcIdParam.getName());
1976 if (parmSet != null)
1978 // TODO : check we have a good match with settings in AACon -
1979 // otherwise we'll need to create a new preset
1984 argList = parmSet.getArguments();
1987 AAConSettings settings = new AAConSettings(
1988 calcIdParam.isAutoUpdate(), service, parmSet, argList);
1989 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
1990 calcIdParam.isNeedsUpdate());
1995 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
1999 throw new Error(MessageManager.formatMessage(
2000 "error.unsupported_version_calcIdparam", new Object[]
2001 { calcIdParam.toString() }));
2005 * External mapping between jalview objects and objects yielding a valid and
2006 * unique object ID string. This is null for normal Jalview project IO, but
2007 * non-null when a jalview project is being read or written as part of a
2010 IdentityHashMap jv2vobj = null;
2013 * Construct a unique ID for jvobj using either existing bindings or if none
2014 * exist, the result of the hashcode call for the object.
2017 * jalview data object
2018 * @return unique ID for referring to jvobj
2020 private String makeHashCode(Object jvobj, String altCode)
2022 if (jv2vobj != null)
2024 Object id = jv2vobj.get(jvobj);
2027 return id.toString();
2029 // check string ID mappings
2030 if (jvids2vobj != null && jvobj instanceof String)
2032 id = jvids2vobj.get(jvobj);
2036 return id.toString();
2038 // give up and warn that something has gone wrong
2039 warn("Cannot find ID for object in external mapping : " + jvobj);
2045 * return local jalview object mapped to ID, if it exists
2049 * @return null or object bound to idcode
2051 private Object retrieveExistingObj(String idcode)
2053 if (idcode != null && vobj2jv != null)
2055 return vobj2jv.get(idcode);
2061 * binding from ID strings from external mapping table to jalview data model
2064 private Hashtable vobj2jv;
2066 private Sequence createVamsasSequence(String id, SequenceI jds)
2068 return createVamsasSequence(true, id, jds, null);
2071 private Sequence createVamsasSequence(boolean recurse, String id,
2072 SequenceI jds, SequenceI parentseq)
2074 Sequence vamsasSeq = new Sequence();
2075 vamsasSeq.setId(id);
2076 vamsasSeq.setName(jds.getName());
2077 vamsasSeq.setSequence(jds.getSequenceAsString());
2078 vamsasSeq.setDescription(jds.getDescription());
2079 jalview.datamodel.DBRefEntry[] dbrefs = null;
2080 if (jds.getDatasetSequence() != null)
2082 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
2086 // seqId==dsseqid so we can tell which sequences really are
2087 // dataset sequences only
2088 vamsasSeq.setDsseqid(id);
2089 dbrefs = jds.getDBRefs();
2090 if (parentseq == null)
2097 for (int d = 0; d < dbrefs.length; d++)
2099 DBRef dbref = new DBRef();
2100 dbref.setSource(dbrefs[d].getSource());
2101 dbref.setVersion(dbrefs[d].getVersion());
2102 dbref.setAccessionId(dbrefs[d].getAccessionId());
2103 if (dbrefs[d].hasMap())
2105 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
2107 dbref.setMapping(mp);
2109 vamsasSeq.addDBRef(dbref);
2115 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
2116 SequenceI parentseq, SequenceI jds, boolean recurse)
2119 if (jmp.getMap() != null)
2123 jalview.util.MapList mlst = jmp.getMap();
2124 List<int[]> r = mlst.getFromRanges();
2125 for (int[] range : r)
2127 MapListFrom mfrom = new MapListFrom();
2128 mfrom.setStart(range[0]);
2129 mfrom.setEnd(range[1]);
2130 mp.addMapListFrom(mfrom);
2132 r = mlst.getToRanges();
2133 for (int[] range : r)
2135 MapListTo mto = new MapListTo();
2136 mto.setStart(range[0]);
2137 mto.setEnd(range[1]);
2138 mp.addMapListTo(mto);
2140 mp.setMapFromUnit(mlst.getFromRatio());
2141 mp.setMapToUnit(mlst.getToRatio());
2142 if (jmp.getTo() != null)
2144 MappingChoice mpc = new MappingChoice();
2146 // check/create ID for the sequence referenced by getTo()
2149 SequenceI ps = null;
2150 if (parentseq != jmp.getTo()
2151 && parentseq.getDatasetSequence() != jmp.getTo())
2153 // chaining dbref rather than a handshaking one
2154 jmpid = seqHash(ps = jmp.getTo());
2158 jmpid = seqHash(ps = parentseq);
2160 mpc.setDseqFor(jmpid);
2161 if (!seqRefIds.containsKey(mpc.getDseqFor()))
2163 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2164 seqRefIds.put(mpc.getDseqFor(), ps);
2168 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2171 mp.setMappingChoice(mpc);
2177 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2178 List<UserColourScheme> userColours, JalviewModelSequence jms)
2181 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2182 boolean newucs = false;
2183 if (!userColours.contains(ucs))
2185 userColours.add(ucs);
2188 id = "ucs" + userColours.indexOf(ucs);
2191 // actually create the scheme's entry in the XML model
2192 java.awt.Color[] colours = ucs.getColours();
2193 jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
2194 jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
2196 for (int i = 0; i < colours.length; i++)
2198 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2199 col.setName(ResidueProperties.aa[i]);
2200 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2201 jbucs.addColour(col);
2203 if (ucs.getLowerCaseColours() != null)
2205 colours = ucs.getLowerCaseColours();
2206 for (int i = 0; i < colours.length; i++)
2208 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2209 col.setName(ResidueProperties.aa[i].toLowerCase());
2210 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2211 jbucs.addColour(col);
2216 uc.setUserColourScheme(jbucs);
2217 jms.addUserColours(uc);
2223 jalview.schemes.UserColourScheme getUserColourScheme(
2224 JalviewModelSequence jms, String id)
2226 UserColours[] uc = jms.getUserColours();
2227 UserColours colours = null;
2229 for (int i = 0; i < uc.length; i++)
2231 if (uc[i].getId().equals(id))
2239 java.awt.Color[] newColours = new java.awt.Color[24];
2241 for (int i = 0; i < 24; i++)
2243 newColours[i] = new java.awt.Color(Integer.parseInt(
2244 colours.getUserColourScheme().getColour(i).getRGB(), 16));
2247 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2250 if (colours.getUserColourScheme().getColourCount() > 24)
2252 newColours = new java.awt.Color[23];
2253 for (int i = 0; i < 23; i++)
2255 newColours[i] = new java.awt.Color(Integer.parseInt(
2256 colours.getUserColourScheme().getColour(i + 24).getRGB(),
2259 ucs.setLowerCaseColours(newColours);
2266 * contains last error message (if any) encountered by XML loader.
2268 String errorMessage = null;
2271 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2272 * exceptions are raised during project XML parsing
2274 public boolean attemptversion1parse = true;
2277 * Load a jalview project archive from a jar file
2280 * - HTTP URL or filename
2282 public AlignFrame loadJalviewAlign(final String file)
2285 jalview.gui.AlignFrame af = null;
2289 // create list to store references for any new Jmol viewers created
2290 newStructureViewers = new Vector<>();
2291 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2292 // Workaround is to make sure caller implements the JarInputStreamProvider
2294 // so we can re-open the jar input stream for each entry.
2296 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2297 af = loadJalviewAlign(jprovider);
2298 af.setMenusForViewport();
2300 } catch (MalformedURLException e)
2302 errorMessage = "Invalid URL format for '" + file + "'";
2308 SwingUtilities.invokeAndWait(new Runnable()
2313 setLoadingFinishedForNewStructureViewers();
2316 } catch (Exception x)
2318 System.err.println("Error loading alignment: " + x.getMessage());
2324 private jarInputStreamProvider createjarInputStreamProvider(
2325 final String file) throws MalformedURLException
2328 errorMessage = null;
2329 uniqueSetSuffix = null;
2331 viewportsAdded.clear();
2332 frefedSequence = null;
2334 if (file.startsWith("http://"))
2336 url = new URL(file);
2338 final URL _url = url;
2339 return new jarInputStreamProvider()
2343 public JarInputStream getJarInputStream() throws IOException
2347 return new JarInputStream(_url.openStream());
2351 return new JarInputStream(new FileInputStream(file));
2356 public String getFilename()
2364 * Recover jalview session from a jalview project archive. Caller may
2365 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2366 * themselves. Any null fields will be initialised with default values,
2367 * non-null fields are left alone.
2372 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2374 errorMessage = null;
2375 if (uniqueSetSuffix == null)
2377 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2379 if (seqRefIds == null)
2383 AlignFrame af = null, _af = null;
2384 IdentityHashMap<AlignmentI, AlignmentI> importedDatasets = new IdentityHashMap<>();
2385 Map<String, AlignFrame> gatherToThisFrame = new HashMap<>();
2386 final String file = jprovider.getFilename();
2389 JarInputStream jin = null;
2390 JarEntry jarentry = null;
2395 jin = jprovider.getJarInputStream();
2396 for (int i = 0; i < entryCount; i++)
2398 jarentry = jin.getNextJarEntry();
2401 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2403 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2404 JalviewModel object = new JalviewModel();
2406 Unmarshaller unmar = new Unmarshaller(object);
2407 unmar.setValidation(false);
2408 object = (JalviewModel) unmar.unmarshal(in);
2409 if (true) // !skipViewport(object))
2411 _af = loadFromObject(object, file, true, jprovider);
2412 if (_af != null && object.getJalviewModelSequence()
2413 .getViewportCount() > 0)
2417 // store a reference to the first view
2420 if (_af.viewport.isGatherViewsHere())
2422 // if this is a gathered view, keep its reference since
2423 // after gathering views, only this frame will remain
2425 gatherToThisFrame.put(_af.viewport.getSequenceSetId(), _af);
2427 // Save dataset to register mappings once all resolved
2428 importedDatasets.put(af.viewport.getAlignment().getDataset(),
2429 af.viewport.getAlignment().getDataset());
2434 else if (jarentry != null)
2436 // Some other file here.
2439 } while (jarentry != null);
2440 resolveFrefedSequences();
2441 } catch (IOException ex)
2443 ex.printStackTrace();
2444 errorMessage = "Couldn't locate Jalview XML file : " + file;
2446 "Exception whilst loading jalview XML file : " + ex + "\n");
2447 } catch (Exception ex)
2449 System.err.println("Parsing as Jalview Version 2 file failed.");
2450 ex.printStackTrace(System.err);
2451 if (attemptversion1parse)
2453 // Is Version 1 Jar file?
2456 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
2457 } catch (Exception ex2)
2459 System.err.println("Exception whilst loading as jalviewXMLV1:");
2460 ex2.printStackTrace();
2464 if (Desktop.instance != null)
2466 Desktop.instance.stopLoading();
2470 System.out.println("Successfully loaded archive file");
2473 ex.printStackTrace();
2476 "Exception whilst loading jalview XML file : " + ex + "\n");
2477 } catch (OutOfMemoryError e)
2479 // Don't use the OOM Window here
2480 errorMessage = "Out of memory loading jalview XML file";
2481 System.err.println("Out of memory whilst loading jalview XML file");
2482 e.printStackTrace();
2486 * Regather multiple views (with the same sequence set id) to the frame (if
2487 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2488 * views instead of separate frames. Note this doesn't restore a state where
2489 * some expanded views in turn have tabbed views - the last "first tab" read
2490 * in will play the role of gatherer for all.
2492 for (AlignFrame fr : gatherToThisFrame.values())
2494 Desktop.instance.gatherViews(fr);
2497 restoreSplitFrames();
2498 for (AlignmentI ds : importedDatasets.keySet())
2500 if (ds.getCodonFrames() != null)
2502 StructureSelectionManager
2503 .getStructureSelectionManager(Desktop.instance)
2504 .registerMappings(ds.getCodonFrames());
2507 if (errorMessage != null)
2512 if (Desktop.instance != null)
2514 Desktop.instance.stopLoading();
2521 * Try to reconstruct and display SplitFrame windows, where each contains
2522 * complementary dna and protein alignments. Done by pairing up AlignFrame
2523 * objects (created earlier) which have complementary viewport ids associated.
2525 protected void restoreSplitFrames()
2527 List<SplitFrame> gatherTo = new ArrayList<>();
2528 List<AlignFrame> addedToSplitFrames = new ArrayList<>();
2529 Map<String, AlignFrame> dna = new HashMap<>();
2532 * Identify the DNA alignments
2534 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2537 AlignFrame af = candidate.getValue();
2538 if (af.getViewport().getAlignment().isNucleotide())
2540 dna.put(candidate.getKey().getId(), af);
2545 * Try to match up the protein complements
2547 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2550 AlignFrame af = candidate.getValue();
2551 if (!af.getViewport().getAlignment().isNucleotide())
2553 String complementId = candidate.getKey().getComplementId();
2554 // only non-null complements should be in the Map
2555 if (complementId != null && dna.containsKey(complementId))
2557 final AlignFrame dnaFrame = dna.get(complementId);
2558 SplitFrame sf = createSplitFrame(dnaFrame, af);
2559 addedToSplitFrames.add(dnaFrame);
2560 addedToSplitFrames.add(af);
2561 dnaFrame.setMenusForViewport();
2562 af.setMenusForViewport();
2563 if (af.viewport.isGatherViewsHere())
2572 * Open any that we failed to pair up (which shouldn't happen!) as
2573 * standalone AlignFrame's.
2575 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2578 AlignFrame af = candidate.getValue();
2579 if (!addedToSplitFrames.contains(af))
2581 Viewport view = candidate.getKey();
2582 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
2584 af.setMenusForViewport();
2585 System.err.println("Failed to restore view " + view.getTitle()
2586 + " to split frame");
2591 * Gather back into tabbed views as flagged.
2593 for (SplitFrame sf : gatherTo)
2595 Desktop.instance.gatherViews(sf);
2598 splitFrameCandidates.clear();
2602 * Construct and display one SplitFrame holding DNA and protein alignments.
2605 * @param proteinFrame
2608 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
2609 AlignFrame proteinFrame)
2611 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
2612 String title = MessageManager.getString("label.linked_view_title");
2613 int width = (int) dnaFrame.getBounds().getWidth();
2614 int height = (int) (dnaFrame.getBounds().getHeight()
2615 + proteinFrame.getBounds().getHeight() + 50);
2618 * SplitFrame location is saved to both enclosed frames
2620 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
2621 Desktop.addInternalFrame(splitFrame, title, width, height);
2624 * And compute cDNA consensus (couldn't do earlier with consensus as
2625 * mappings were not yet present)
2627 proteinFrame.viewport.alignmentChanged(proteinFrame.alignPanel);
2633 * check errorMessage for a valid error message and raise an error box in the
2634 * GUI or write the current errorMessage to stderr and then clear the error
2637 protected void reportErrors()
2639 reportErrors(false);
2642 protected void reportErrors(final boolean saving)
2644 if (errorMessage != null)
2646 final String finalErrorMessage = errorMessage;
2649 javax.swing.SwingUtilities.invokeLater(new Runnable()
2654 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2656 "Error " + (saving ? "saving" : "loading")
2658 JvOptionPane.WARNING_MESSAGE);
2664 System.err.println("Problem loading Jalview file: " + errorMessage);
2667 errorMessage = null;
2670 Map<String, String> alreadyLoadedPDB = new HashMap<>();
2673 * when set, local views will be updated from view stored in JalviewXML
2674 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2675 * sync if this is set to true.
2677 private final boolean updateLocalViews = false;
2680 * Returns the path to a temporary file holding the PDB file for the given PDB
2681 * id. The first time of asking, searches for a file of that name in the
2682 * Jalview project jar, and copies it to a new temporary file. Any repeat
2683 * requests just return the path to the file previously created.
2689 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId,
2692 if (alreadyLoadedPDB.containsKey(pdbId))
2694 return alreadyLoadedPDB.get(pdbId).toString();
2697 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb",
2699 if (tempFile != null)
2701 alreadyLoadedPDB.put(pdbId, tempFile);
2707 * Copies the jar entry of given name to a new temporary file and returns the
2708 * path to the file, or null if the entry is not found.
2711 * @param jarEntryName
2713 * a prefix for the temporary file name, must be at least three
2716 * null or original file - so new file can be given the same suffix
2720 protected String copyJarEntry(jarInputStreamProvider jprovider,
2721 String jarEntryName, String prefix, String origFile)
2723 BufferedReader in = null;
2724 PrintWriter out = null;
2725 String suffix = ".tmp";
2726 if (origFile == null)
2728 origFile = jarEntryName;
2730 int sfpos = origFile.lastIndexOf(".");
2731 if (sfpos > -1 && sfpos < (origFile.length() - 3))
2733 suffix = "." + origFile.substring(sfpos + 1);
2737 JarInputStream jin = jprovider.getJarInputStream();
2739 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2740 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2741 * FileInputStream(jprovider)); }
2744 JarEntry entry = null;
2747 entry = jin.getNextJarEntry();
2748 } while (entry != null && !entry.getName().equals(jarEntryName));
2751 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
2752 File outFile = File.createTempFile(prefix, suffix);
2753 outFile.deleteOnExit();
2754 out = new PrintWriter(new FileOutputStream(outFile));
2757 while ((data = in.readLine()) != null)
2762 String t = outFile.getAbsolutePath();
2767 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
2769 } catch (Exception ex)
2771 ex.printStackTrace();
2779 } catch (IOException e)
2793 private class JvAnnotRow
2795 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2802 * persisted version of annotation row from which to take vis properties
2804 public jalview.datamodel.AlignmentAnnotation template;
2807 * original position of the annotation row in the alignment
2813 * Load alignment frame from jalview XML DOM object
2818 * filename source string
2819 * @param loadTreesAndStructures
2820 * when false only create Viewport
2822 * data source provider
2823 * @return alignment frame created from view stored in DOM
2825 AlignFrame loadFromObject(JalviewModel object, String file,
2826 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
2828 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
2829 Sequence[] vamsasSeq = vamsasSet.getSequence();
2831 JalviewModelSequence jms = object.getJalviewModelSequence();
2833 Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
2836 // ////////////////////////////////
2839 List<SequenceI> hiddenSeqs = null;
2841 List<SequenceI> tmpseqs = new ArrayList<>();
2843 boolean multipleView = false;
2844 SequenceI referenceseqForView = null;
2845 JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
2846 int vi = 0; // counter in vamsasSeq array
2847 for (int i = 0; i < jseqs.length; i++)
2849 String seqId = jseqs[i].getId();
2851 SequenceI tmpSeq = seqRefIds.get(seqId);
2854 if (!incompleteSeqs.containsKey(seqId))
2856 // may not need this check, but keep it for at least 2.9,1 release
2857 if (tmpSeq.getStart() != jseqs[i].getStart()
2858 || tmpSeq.getEnd() != jseqs[i].getEnd())
2861 "Warning JAL-2154 regression: updating start/end for sequence "
2862 + tmpSeq.toString() + " to " + jseqs[i]);
2867 incompleteSeqs.remove(seqId);
2869 if (vamsasSeq.length > vi && vamsasSeq[vi].getId().equals(seqId))
2871 // most likely we are reading a dataset XML document so
2872 // update from vamsasSeq section of XML for this sequence
2873 tmpSeq.setName(vamsasSeq[vi].getName());
2874 tmpSeq.setDescription(vamsasSeq[vi].getDescription());
2875 tmpSeq.setSequence(vamsasSeq[vi].getSequence());
2880 // reading multiple views, so vamsasSeq set is a subset of JSeq
2881 multipleView = true;
2883 tmpSeq.setStart(jseqs[i].getStart());
2884 tmpSeq.setEnd(jseqs[i].getEnd());
2885 tmpseqs.add(tmpSeq);
2889 tmpSeq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
2890 vamsasSeq[vi].getSequence());
2891 tmpSeq.setDescription(vamsasSeq[vi].getDescription());
2892 tmpSeq.setStart(jseqs[i].getStart());
2893 tmpSeq.setEnd(jseqs[i].getEnd());
2894 tmpSeq.setVamsasId(uniqueSetSuffix + seqId);
2895 seqRefIds.put(vamsasSeq[vi].getId(), tmpSeq);
2896 tmpseqs.add(tmpSeq);
2900 if (jseqs[i].hasViewreference() && jseqs[i].getViewreference())
2902 referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
2905 if (jseqs[i].getHidden())
2907 if (hiddenSeqs == null)
2909 hiddenSeqs = new ArrayList<>();
2912 hiddenSeqs.add(tmpSeq);
2917 // Create the alignment object from the sequence set
2918 // ///////////////////////////////
2919 SequenceI[] orderedSeqs = tmpseqs
2920 .toArray(new SequenceI[tmpseqs.size()]);
2922 AlignmentI al = null;
2923 // so we must create or recover the dataset alignment before going further
2924 // ///////////////////////////////
2925 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
2927 // older jalview projects do not have a dataset - so creat alignment and
2929 al = new Alignment(orderedSeqs);
2930 al.setDataset(null);
2934 boolean isdsal = object.getJalviewModelSequence()
2935 .getViewportCount() == 0;
2938 // we are importing a dataset record, so
2939 // recover reference to an alignment already materialsed as dataset
2940 al = getDatasetFor(vamsasSet.getDatasetId());
2944 // materialse the alignment
2945 al = new Alignment(orderedSeqs);
2949 addDatasetRef(vamsasSet.getDatasetId(), al);
2952 // finally, verify all data in vamsasSet is actually present in al
2953 // passing on flag indicating if it is actually a stored dataset
2954 recoverDatasetFor(vamsasSet, al, isdsal);
2957 if (referenceseqForView != null)
2959 al.setSeqrep(referenceseqForView);
2961 // / Add the alignment properties
2962 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
2964 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
2965 al.setProperty(ssp.getKey(), ssp.getValue());
2968 // ///////////////////////////////
2970 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
2973 // load sequence features, database references and any associated PDB
2974 // structures for the alignment
2976 // prior to 2.10, this part would only be executed the first time a
2977 // sequence was encountered, but not afterwards.
2978 // now, for 2.10 projects, this is also done if the xml doc includes
2979 // dataset sequences not actually present in any particular view.
2981 for (int i = 0; i < vamsasSeq.length; i++)
2983 if (jseqs[i].getFeaturesCount() > 0)
2985 Features[] features = jseqs[i].getFeatures();
2986 for (int f = 0; f < features.length; f++)
2988 SequenceFeature sf = new SequenceFeature(features[f].getType(),
2989 features[f].getDescription(), features[f].getBegin(),
2990 features[f].getEnd(), features[f].getScore(),
2991 features[f].getFeatureGroup());
2992 sf.setStatus(features[f].getStatus());
2993 for (int od = 0; od < features[f].getOtherDataCount(); od++)
2995 OtherData keyValue = features[f].getOtherData(od);
2996 if (keyValue.getKey().startsWith("LINK"))
2998 sf.addLink(keyValue.getValue());
3002 sf.setValue(keyValue.getKey(), keyValue.getValue());
3006 // adds feature to datasequence's feature set (since Jalview 2.10)
3007 al.getSequenceAt(i).addSequenceFeature(sf);
3010 if (vamsasSeq[i].getDBRefCount() > 0)
3012 // adds dbrefs to datasequence's set (since Jalview 2.10)
3014 al.getSequenceAt(i).getDatasetSequence() == null
3015 ? al.getSequenceAt(i)
3016 : al.getSequenceAt(i).getDatasetSequence(),
3019 if (jseqs[i].getPdbidsCount() > 0)
3021 Pdbids[] ids = jseqs[i].getPdbids();
3022 for (int p = 0; p < ids.length; p++)
3024 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
3025 entry.setId(ids[p].getId());
3026 if (ids[p].getType() != null)
3028 if (PDBEntry.Type.getType(ids[p].getType()) != null)
3030 entry.setType(PDBEntry.Type.getType(ids[p].getType()));
3034 entry.setType(PDBEntry.Type.FILE);
3037 // jprovider is null when executing 'New View'
3038 if (ids[p].getFile() != null && jprovider != null)
3040 if (!pdbloaded.containsKey(ids[p].getFile()))
3042 entry.setFile(loadPDBFile(jprovider, ids[p].getId(),
3047 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
3050 if (ids[p].getPdbentryItem() != null)
3052 for (PdbentryItem item : ids[p].getPdbentryItem())
3054 for (Property pr : item.getProperty())
3056 entry.setProperty(pr.getName(), pr.getValue());
3060 StructureSelectionManager
3061 .getStructureSelectionManager(Desktop.instance)
3062 .registerPDBEntry(entry);
3063 // adds PDBEntry to datasequence's set (since Jalview 2.10)
3064 if (al.getSequenceAt(i).getDatasetSequence() != null)
3066 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
3070 al.getSequenceAt(i).addPDBId(entry);
3075 } // end !multipleview
3077 // ///////////////////////////////
3078 // LOAD SEQUENCE MAPPINGS
3080 if (vamsasSet.getAlcodonFrameCount() > 0)
3082 // TODO Potentially this should only be done once for all views of an
3084 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
3085 for (int i = 0; i < alc.length; i++)
3087 AlignedCodonFrame cf = new AlignedCodonFrame();
3088 if (alc[i].getAlcodMapCount() > 0)
3090 AlcodMap[] maps = alc[i].getAlcodMap();
3091 for (int m = 0; m < maps.length; m++)
3093 SequenceI dnaseq = seqRefIds.get(maps[m].getDnasq());
3095 jalview.datamodel.Mapping mapping = null;
3096 // attach to dna sequence reference.
3097 if (maps[m].getMapping() != null)
3099 mapping = addMapping(maps[m].getMapping());
3100 if (dnaseq != null && mapping.getTo() != null)
3102 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
3108 newAlcodMapRef(maps[m].getDnasq(), cf, mapping));
3112 al.addCodonFrame(cf);
3117 // ////////////////////////////////
3119 List<JvAnnotRow> autoAlan = new ArrayList<>();
3122 * store any annotations which forward reference a group's ID
3124 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<>();
3126 if (vamsasSet.getAnnotationCount() > 0)
3128 Annotation[] an = vamsasSet.getAnnotation();
3130 for (int i = 0; i < an.length; i++)
3132 Annotation annotation = an[i];
3135 * test if annotation is automatically calculated for this view only
3137 boolean autoForView = false;
3138 if (annotation.getLabel().equals("Quality")
3139 || annotation.getLabel().equals("Conservation")
3140 || annotation.getLabel().equals("Consensus"))
3142 // Kludge for pre 2.5 projects which lacked the autocalculated flag
3144 if (!annotation.hasAutoCalculated())
3146 annotation.setAutoCalculated(true);
3149 if (autoForView || (annotation.hasAutoCalculated()
3150 && annotation.isAutoCalculated()))
3152 // remove ID - we don't recover annotation from other views for
3153 // view-specific annotation
3154 annotation.setId(null);
3157 // set visiblity for other annotation in this view
3158 String annotationId = annotation.getId();
3159 if (annotationId != null && annotationIds.containsKey(annotationId))
3161 AlignmentAnnotation jda = annotationIds.get(annotationId);
3162 // in principle Visible should always be true for annotation displayed
3163 // in multiple views
3164 if (annotation.hasVisible())
3166 jda.visible = annotation.getVisible();
3169 al.addAnnotation(jda);
3173 // Construct new annotation from model.
3174 AnnotationElement[] ae = annotation.getAnnotationElement();
3175 jalview.datamodel.Annotation[] anot = null;
3176 java.awt.Color firstColour = null;
3178 if (!annotation.getScoreOnly())
3180 anot = new jalview.datamodel.Annotation[al.getWidth()];
3181 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
3183 anpos = ae[aa].getPosition();
3185 if (anpos >= anot.length)
3190 anot[anpos] = new jalview.datamodel.Annotation(
3192 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
3193 (ae[aa].getSecondaryStructure() == null
3194 || ae[aa].getSecondaryStructure().length() == 0)
3196 : ae[aa].getSecondaryStructure()
3201 // JBPNote: Consider verifying dataflow for IO of secondary
3202 // structure annotation read from Stockholm files
3203 // this was added to try to ensure that
3204 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
3206 // anot[ae[aa].getPosition()].displayCharacter = "";
3208 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
3209 if (firstColour == null)
3211 firstColour = anot[anpos].colour;
3215 jalview.datamodel.AlignmentAnnotation jaa = null;
3217 if (annotation.getGraph())
3219 float llim = 0, hlim = 0;
3220 // if (autoForView || an[i].isAutoCalculated()) {
3223 jaa = new jalview.datamodel.AlignmentAnnotation(
3224 annotation.getLabel(), annotation.getDescription(), anot,
3225 llim, hlim, annotation.getGraphType());
3227 jaa.graphGroup = annotation.getGraphGroup();
3228 jaa._linecolour = firstColour;
3229 if (annotation.getThresholdLine() != null)
3231 jaa.setThreshold(new jalview.datamodel.GraphLine(
3232 annotation.getThresholdLine().getValue(),
3233 annotation.getThresholdLine().getLabel(),
3235 annotation.getThresholdLine().getColour())));
3238 if (autoForView || annotation.isAutoCalculated())
3240 // Hardwire the symbol display line to ensure that labels for
3241 // histograms are displayed
3247 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
3248 an[i].getDescription(), anot);
3249 jaa._linecolour = firstColour;
3251 // register new annotation
3252 if (an[i].getId() != null)
3254 annotationIds.put(an[i].getId(), jaa);
3255 jaa.annotationId = an[i].getId();
3257 // recover sequence association
3258 String sequenceRef = an[i].getSequenceRef();
3259 if (sequenceRef != null)
3261 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3262 SequenceI sequence = seqRefIds.get(sequenceRef);
3263 if (sequence == null)
3265 // in pre-2.9 projects sequence ref is to sequence name
3266 sequence = al.findName(sequenceRef);
3268 if (sequence != null)
3270 jaa.createSequenceMapping(sequence, 1, true);
3271 sequence.addAlignmentAnnotation(jaa);
3274 // and make a note of any group association
3275 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
3277 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3278 .get(an[i].getGroupRef());
3281 aal = new ArrayList<>();
3282 groupAnnotRefs.put(an[i].getGroupRef(), aal);
3287 if (an[i].hasScore())
3289 jaa.setScore(an[i].getScore());
3291 if (an[i].hasVisible())
3293 jaa.visible = an[i].getVisible();
3296 if (an[i].hasCentreColLabels())
3298 jaa.centreColLabels = an[i].getCentreColLabels();
3301 if (an[i].hasScaleColLabels())
3303 jaa.scaleColLabel = an[i].getScaleColLabels();
3305 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
3307 // newer files have an 'autoCalculated' flag and store calculation
3308 // state in viewport properties
3309 jaa.autoCalculated = true; // means annotation will be marked for
3310 // update at end of load.
3312 if (an[i].hasGraphHeight())
3314 jaa.graphHeight = an[i].getGraphHeight();
3316 if (an[i].hasBelowAlignment())
3318 jaa.belowAlignment = an[i].isBelowAlignment();
3320 jaa.setCalcId(an[i].getCalcId());
3321 if (an[i].getPropertyCount() > 0)
3323 for (jalview.schemabinding.version2.Property prop : an[i]
3326 jaa.setProperty(prop.getName(), prop.getValue());
3329 if (jaa.autoCalculated)
3331 autoAlan.add(new JvAnnotRow(i, jaa));
3334 // if (!autoForView)
3336 // add autocalculated group annotation and any user created annotation
3338 al.addAnnotation(jaa);
3342 // ///////////////////////
3344 // Create alignment markup and styles for this view
3345 if (jms.getJGroupCount() > 0)
3347 JGroup[] groups = jms.getJGroup();
3348 boolean addAnnotSchemeGroup = false;
3349 for (int i = 0; i < groups.length; i++)
3351 JGroup jGroup = groups[i];
3352 ColourSchemeI cs = null;
3353 if (jGroup.getColour() != null)
3355 if (jGroup.getColour().startsWith("ucs"))
3357 cs = getUserColourScheme(jms, jGroup.getColour());
3359 else if (jGroup.getColour().equals("AnnotationColourGradient")
3360 && jGroup.getAnnotationColours() != null)
3362 addAnnotSchemeGroup = true;
3366 cs = ColourSchemeProperty.getColourScheme(al,
3367 jGroup.getColour());
3370 int pidThreshold = jGroup.getPidThreshold();
3372 Vector<SequenceI> seqs = new Vector<>();
3374 for (int s = 0; s < jGroup.getSeqCount(); s++)
3376 String seqId = jGroup.getSeq(s) + "";
3377 SequenceI ts = seqRefIds.get(seqId);
3381 seqs.addElement(ts);
3385 if (seqs.size() < 1)
3390 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3391 jGroup.getDisplayBoxes(), jGroup.getDisplayText(),
3392 jGroup.getColourText(), jGroup.getStart(), jGroup.getEnd());
3393 sg.getGroupColourScheme().setThreshold(pidThreshold, true);
3394 sg.getGroupColourScheme()
3395 .setConservationInc(jGroup.getConsThreshold());
3396 sg.setOutlineColour(new java.awt.Color(jGroup.getOutlineColour()));
3398 sg.textColour = new java.awt.Color(jGroup.getTextCol1());
3399 sg.textColour2 = new java.awt.Color(jGroup.getTextCol2());
3400 sg.setShowNonconserved(
3401 jGroup.hasShowUnconserved() ? jGroup.isShowUnconserved()
3403 sg.thresholdTextColour = jGroup.getTextColThreshold();
3404 if (jGroup.hasShowConsensusHistogram())
3406 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3409 if (jGroup.hasShowSequenceLogo())
3411 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3413 if (jGroup.hasNormaliseSequenceLogo())
3415 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3417 if (jGroup.hasIgnoreGapsinConsensus())
3419 sg.setIgnoreGapsConsensus(jGroup.getIgnoreGapsinConsensus());
3421 if (jGroup.getConsThreshold() != 0)
3423 Conservation c = new Conservation("All", sg.getSequences(null), 0,
3426 c.verdict(false, 25);
3427 sg.cs.setConservation(c);
3430 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3432 // re-instate unique group/annotation row reference
3433 List<AlignmentAnnotation> jaal = groupAnnotRefs
3434 .get(jGroup.getId());
3437 for (AlignmentAnnotation jaa : jaal)
3440 if (jaa.autoCalculated)
3442 // match up and try to set group autocalc alignment row for this
3444 if (jaa.label.startsWith("Consensus for "))
3446 sg.setConsensus(jaa);
3448 // match up and try to set group autocalc alignment row for this
3450 if (jaa.label.startsWith("Conservation for "))
3452 sg.setConservationRow(jaa);
3459 if (addAnnotSchemeGroup)
3461 // reconstruct the annotation colourscheme
3462 sg.setColourScheme(constructAnnotationColour(
3463 jGroup.getAnnotationColours(), null, al, jms, false));
3469 // only dataset in this model, so just return.
3472 // ///////////////////////////////
3475 // If we just load in the same jar file again, the sequenceSetId
3476 // will be the same, and we end up with multiple references
3477 // to the same sequenceSet. We must modify this id on load
3478 // so that each load of the file gives a unique id
3479 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3480 String viewId = (view.getId() == null ? null
3481 : view.getId() + uniqueSetSuffix);
3482 AlignFrame af = null;
3483 AlignViewport av = null;
3484 // now check to see if we really need to create a new viewport.
3485 if (multipleView && viewportsAdded.size() == 0)
3487 // We recovered an alignment for which a viewport already exists.
3488 // TODO: fix up any settings necessary for overlaying stored state onto
3489 // state recovered from another document. (may not be necessary).
3490 // we may need a binding from a viewport in memory to one recovered from
3492 // and then recover its containing af to allow the settings to be applied.
3493 // TODO: fix for vamsas demo
3495 "About to recover a viewport for existing alignment: Sequence set ID is "
3497 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3498 if (seqsetobj != null)
3500 if (seqsetobj instanceof String)
3502 uniqueSeqSetId = (String) seqsetobj;
3504 "Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
3510 "Warning : Collision between sequence set ID string and existing jalview object mapping.");
3516 * indicate that annotation colours are applied across all groups (pre
3517 * Jalview 2.8.1 behaviour)
3519 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan("2.8.1",
3520 object.getVersion());
3522 AlignmentPanel ap = null;
3523 boolean isnewview = true;
3526 // Check to see if this alignment already has a view id == viewId
3527 jalview.gui.AlignmentPanel views[] = Desktop
3528 .getAlignmentPanels(uniqueSeqSetId);
3529 if (views != null && views.length > 0)
3531 for (int v = 0; v < views.length; v++)
3533 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
3535 // recover the existing alignpanel, alignframe, viewport
3536 af = views[v].alignFrame;
3539 // TODO: could even skip resetting view settings if we don't want to
3540 // change the local settings from other jalview processes
3549 af = loadViewport(file, jseqs, hiddenSeqs, al, jms, view,
3550 uniqueSeqSetId, viewId, autoAlan);
3556 * Load any trees, PDB structures and viewers
3558 * Not done if flag is false (when this method is used for New View)
3560 if (loadTreesAndStructures)
3562 loadTrees(jms, view, af, av, ap);
3563 loadPDBStructures(jprovider, jseqs, af, ap);
3564 loadRnaViewers(jprovider, jseqs, ap);
3566 // and finally return.
3571 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
3572 * panel is restored from separate jar entries, two (gapped and trimmed) per
3573 * sequence and secondary structure.
3575 * Currently each viewer shows just one sequence and structure (gapped and
3576 * trimmed), however this method is designed to support multiple sequences or
3577 * structures in viewers if wanted in future.
3583 private void loadRnaViewers(jarInputStreamProvider jprovider,
3584 JSeq[] jseqs, AlignmentPanel ap)
3587 * scan the sequences for references to viewers; create each one the first
3588 * time it is referenced, add Rna models to existing viewers
3590 for (JSeq jseq : jseqs)
3592 for (int i = 0; i < jseq.getRnaViewerCount(); i++)
3594 RnaViewer viewer = jseq.getRnaViewer(i);
3595 AppVarna appVarna = findOrCreateVarnaViewer(viewer, uniqueSetSuffix,
3598 for (int j = 0; j < viewer.getSecondaryStructureCount(); j++)
3600 SecondaryStructure ss = viewer.getSecondaryStructure(j);
3601 SequenceI seq = seqRefIds.get(jseq.getId());
3602 AlignmentAnnotation ann = this.annotationIds
3603 .get(ss.getAnnotationId());
3606 * add the structure to the Varna display (with session state copied
3607 * from the jar to a temporary file)
3609 boolean gapped = ss.isGapped();
3610 String rnaTitle = ss.getTitle();
3611 String sessionState = ss.getViewerState();
3612 String tempStateFile = copyJarEntry(jprovider, sessionState,
3614 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
3615 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
3617 appVarna.setInitialSelection(viewer.getSelectedRna());
3623 * Locate and return an already instantiated matching AppVarna, or create one
3627 * @param viewIdSuffix
3631 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
3632 String viewIdSuffix, AlignmentPanel ap)
3635 * on each load a suffix is appended to the saved viewId, to avoid conflicts
3636 * if load is repeated
3638 String postLoadId = viewer.getViewId() + viewIdSuffix;
3639 for (JInternalFrame frame : getAllFrames())
3641 if (frame instanceof AppVarna)
3643 AppVarna varna = (AppVarna) frame;
3644 if (postLoadId.equals(varna.getViewId()))
3646 // this viewer is already instantiated
3647 // could in future here add ap as another 'parent' of the
3648 // AppVarna window; currently just 1-to-many
3655 * viewer not found - make it
3657 RnaViewerModel model = new RnaViewerModel(postLoadId, viewer.getTitle(),
3658 viewer.getXpos(), viewer.getYpos(), viewer.getWidth(),
3659 viewer.getHeight(), viewer.getDividerLocation());
3660 AppVarna varna = new AppVarna(model, ap);
3666 * Load any saved trees
3674 protected void loadTrees(JalviewModelSequence jms, Viewport view,
3675 AlignFrame af, AlignViewport av, AlignmentPanel ap)
3677 // TODO result of automated refactoring - are all these parameters needed?
3680 for (int t = 0; t < jms.getTreeCount(); t++)
3683 Tree tree = jms.getTree(t);
3684 NewickFile newick = new jalview.io.NewickFile(tree.getNewick());
3686 TreeFrameI externalViewer = AptxInit.createInstanceFromNhx(
3687 tree.getTitle(), tree.getNewick(),
3691 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
3696 tp = af.showNewickTree(
3698 tree.getTitle(), tree.getWidth(), tree.getHeight(),
3699 tree.getXpos(), tree.getYpos());
3700 if (tree.getId() != null)
3702 // perhaps bind the tree id to something ?
3707 // update local tree attributes ?
3708 // TODO: should check if tp has been manipulated by user - if so its
3709 // settings shouldn't be modified
3710 tp.setTitle(tree.getTitle());
3711 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(),
3712 tree.getWidth(), tree.getHeight()));
3713 tp.av = av; // af.viewport; // TODO: verify 'associate with all
3716 tp.treeCanvas.av = av; // af.viewport;
3717 tp.treeCanvas.ap = ap; // af.alignPanel;
3722 warn("There was a problem recovering stored Newick tree: \n"
3723 + tree.getNewick());
3727 tp.fitToWindow.setState(tree.getFitToWindow());
3728 tp.fitToWindow_actionPerformed(null);
3730 if (tree.getFontName() != null)
3732 tp.setTreeFont(new java.awt.Font(tree.getFontName(),
3733 tree.getFontStyle(), tree.getFontSize()));
3737 tp.setTreeFont(new java.awt.Font(view.getFontName(),
3738 view.getFontStyle(), tree.getFontSize()));
3741 tp.showPlaceholders(tree.getMarkUnlinked());
3742 tp.showBootstrap(tree.getShowBootstrap());
3743 tp.showDistances(tree.getShowDistances());
3745 tp.treeCanvas.threshold = tree.getThreshold();
3747 if (tree.getCurrentTree())
3749 af.viewport.setCurrentTree(tp.getTree());
3753 } catch (Exception ex)
3755 ex.printStackTrace();
3760 * Load and link any saved structure viewers.
3767 protected void loadPDBStructures(jarInputStreamProvider jprovider,
3768 JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
3771 * Run through all PDB ids on the alignment, and collect mappings between
3772 * distinct view ids and all sequences referring to that view.
3774 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<>();
3776 for (int i = 0; i < jseqs.length; i++)
3778 if (jseqs[i].getPdbidsCount() > 0)
3780 Pdbids[] ids = jseqs[i].getPdbids();
3781 for (int p = 0; p < ids.length; p++)
3783 final int structureStateCount = ids[p].getStructureStateCount();
3784 for (int s = 0; s < structureStateCount; s++)
3786 // check to see if we haven't already created this structure view
3787 final StructureState structureState = ids[p]
3788 .getStructureState(s);
3789 String sviewid = (structureState.getViewId() == null) ? null
3790 : structureState.getViewId() + uniqueSetSuffix;
3791 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
3792 // Originally : ids[p].getFile()
3793 // : TODO: verify external PDB file recovery still works in normal
3794 // jalview project load
3795 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId(),
3797 jpdb.setId(ids[p].getId());
3799 int x = structureState.getXpos();
3800 int y = structureState.getYpos();
3801 int width = structureState.getWidth();
3802 int height = structureState.getHeight();
3804 // Probably don't need to do this anymore...
3805 // Desktop.desktop.getComponentAt(x, y);
3806 // TODO: NOW: check that this recovers the PDB file correctly.
3807 String pdbFile = loadPDBFile(jprovider, ids[p].getId(),
3809 jalview.datamodel.SequenceI seq = seqRefIds
3810 .get(jseqs[i].getId() + "");
3811 if (sviewid == null)
3813 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width + ","
3816 if (!structureViewers.containsKey(sviewid))
3818 structureViewers.put(sviewid,
3819 new StructureViewerModel(x, y, width, height, false,
3820 false, true, structureState.getViewId(),
3821 structureState.getType()));
3822 // Legacy pre-2.7 conversion JAL-823 :
3823 // do not assume any view has to be linked for colour by
3827 // assemble String[] { pdb files }, String[] { id for each
3828 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3829 // seqs_file 2}, boolean[] {
3830 // linkAlignPanel,superposeWithAlignpanel}} from hash
3831 StructureViewerModel jmoldat = structureViewers.get(sviewid);
3832 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
3833 | (structureState.hasAlignwithAlignPanel()
3834 ? structureState.getAlignwithAlignPanel()
3838 * Default colour by linked panel to false if not specified (e.g.
3839 * for pre-2.7 projects)
3841 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
3842 colourWithAlignPanel |= (structureState
3843 .hasColourwithAlignPanel()
3844 ? structureState.getColourwithAlignPanel()
3846 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
3849 * Default colour by viewer to true if not specified (e.g. for
3852 boolean colourByViewer = jmoldat.isColourByViewer();
3853 colourByViewer &= structureState.hasColourByJmol()
3854 ? structureState.getColourByJmol()
3856 jmoldat.setColourByViewer(colourByViewer);
3858 if (jmoldat.getStateData().length() < structureState
3859 .getContent().length())
3862 jmoldat.setStateData(structureState.getContent());
3865 if (ids[p].getFile() != null)
3867 File mapkey = new File(ids[p].getFile());
3868 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
3869 if (seqstrmaps == null)
3871 jmoldat.getFileData().put(mapkey,
3872 seqstrmaps = jmoldat.new StructureData(pdbFile,
3875 if (!seqstrmaps.getSeqList().contains(seq))
3877 seqstrmaps.getSeqList().add(seq);
3883 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");
3890 // Instantiate the associated structure views
3891 for (Entry<String, StructureViewerModel> entry : structureViewers
3896 createOrLinkStructureViewer(entry, af, ap, jprovider);
3897 } catch (Exception e)
3900 "Error loading structure viewer: " + e.getMessage());
3901 // failed - try the next one
3913 protected void createOrLinkStructureViewer(
3914 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3915 AlignmentPanel ap, jarInputStreamProvider jprovider)
3917 final StructureViewerModel stateData = viewerData.getValue();
3920 * Search for any viewer windows already open from other alignment views
3921 * that exactly match the stored structure state
3923 StructureViewerBase comp = findMatchingViewer(viewerData);
3927 linkStructureViewer(ap, comp, stateData);
3932 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
3933 * "viewer_"+stateData.viewId
3935 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
3937 createChimeraViewer(viewerData, af, jprovider);
3942 * else Jmol (if pre-2.9, stateData contains JMOL state string)
3944 createJmolViewer(viewerData, af, jprovider);
3949 * Create a new Chimera viewer.
3955 protected void createChimeraViewer(
3956 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3957 jarInputStreamProvider jprovider)
3959 StructureViewerModel data = viewerData.getValue();
3960 String chimeraSessionFile = data.getStateData();
3963 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
3965 * NB this is the 'saved' viewId as in the project file XML, _not_ the
3966 * 'uniquified' sviewid used to reconstruct the viewer here
3968 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
3969 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
3972 Set<Entry<File, StructureData>> fileData = data.getFileData()
3974 List<PDBEntry> pdbs = new ArrayList<>();
3975 List<SequenceI[]> allseqs = new ArrayList<>();
3976 for (Entry<File, StructureData> pdb : fileData)
3978 String filePath = pdb.getValue().getFilePath();
3979 String pdbId = pdb.getValue().getPdbId();
3980 // pdbs.add(new PDBEntry(filePath, pdbId));
3981 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
3982 final List<SequenceI> seqList = pdb.getValue().getSeqList();
3983 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
3987 boolean colourByChimera = data.isColourByViewer();
3988 boolean colourBySequence = data.isColourWithAlignPanel();
3990 // TODO use StructureViewer as a factory here, see JAL-1761
3991 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
3992 final SequenceI[][] seqsArray = allseqs
3993 .toArray(new SequenceI[allseqs.size()][]);
3994 String newViewId = viewerData.getKey();
3996 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
3997 af.alignPanel, pdbArray, seqsArray, colourByChimera,
3998 colourBySequence, newViewId);
3999 cvf.setSize(data.getWidth(), data.getHeight());
4000 cvf.setLocation(data.getX(), data.getY());
4004 * Create a new Jmol window. First parse the Jmol state to translate filenames
4005 * loaded into the view, and record the order in which files are shown in the
4006 * Jmol view, so we can add the sequence mappings in same order.
4012 protected void createJmolViewer(
4013 final Entry<String, StructureViewerModel> viewerData,
4014 AlignFrame af, jarInputStreamProvider jprovider)
4016 final StructureViewerModel svattrib = viewerData.getValue();
4017 String state = svattrib.getStateData();
4020 * Pre-2.9: state element value is the Jmol state string
4022 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
4025 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
4027 state = readJarEntry(jprovider,
4028 getViewerJarEntryName(svattrib.getViewId()));
4031 List<String> pdbfilenames = new ArrayList<>();
4032 List<SequenceI[]> seqmaps = new ArrayList<>();
4033 List<String> pdbids = new ArrayList<>();
4034 StringBuilder newFileLoc = new StringBuilder(64);
4035 int cp = 0, ncp, ecp;
4036 Map<File, StructureData> oldFiles = svattrib.getFileData();
4037 while ((ncp = state.indexOf("load ", cp)) > -1)
4041 // look for next filename in load statement
4042 newFileLoc.append(state.substring(cp,
4043 ncp = (state.indexOf("\"", ncp + 1) + 1)));
4044 String oldfilenam = state.substring(ncp,
4045 ecp = state.indexOf("\"", ncp));
4046 // recover the new mapping data for this old filename
4047 // have to normalize filename - since Jmol and jalview do
4049 // translation differently.
4050 StructureData filedat = oldFiles.get(new File(oldfilenam));
4051 if (filedat == null)
4053 String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\");
4054 filedat = oldFiles.get(new File(reformatedOldFilename));
4056 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
4057 pdbfilenames.add(filedat.getFilePath());
4058 pdbids.add(filedat.getPdbId());
4059 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4060 newFileLoc.append("\"");
4061 cp = ecp + 1; // advance beyond last \" and set cursor so we can
4062 // look for next file statement.
4063 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
4067 // just append rest of state
4068 newFileLoc.append(state.substring(cp));
4072 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
4073 newFileLoc = new StringBuilder(state);
4074 newFileLoc.append("; load append ");
4075 for (File id : oldFiles.keySet())
4077 // add this and any other pdb files that should be present in
4079 StructureData filedat = oldFiles.get(id);
4080 newFileLoc.append(filedat.getFilePath());
4081 pdbfilenames.add(filedat.getFilePath());
4082 pdbids.add(filedat.getPdbId());
4083 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4084 newFileLoc.append(" \"");
4085 newFileLoc.append(filedat.getFilePath());
4086 newFileLoc.append("\"");
4089 newFileLoc.append(";");
4092 if (newFileLoc.length() == 0)
4096 int histbug = newFileLoc.indexOf("history = ");
4100 * change "history = [true|false];" to "history = [1|0];"
4103 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
4104 String val = (diff == -1) ? null
4105 : newFileLoc.substring(histbug, diff);
4106 if (val != null && val.length() >= 4)
4108 if (val.contains("e")) // eh? what can it be?
4110 if (val.trim().equals("true"))
4118 newFileLoc.replace(histbug, diff, val);
4123 final String[] pdbf = pdbfilenames
4124 .toArray(new String[pdbfilenames.size()]);
4125 final String[] id = pdbids.toArray(new String[pdbids.size()]);
4126 final SequenceI[][] sq = seqmaps
4127 .toArray(new SequenceI[seqmaps.size()][]);
4128 final String fileloc = newFileLoc.toString();
4129 final String sviewid = viewerData.getKey();
4130 final AlignFrame alf = af;
4131 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
4132 svattrib.getWidth(), svattrib.getHeight());
4135 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
4140 JalviewStructureDisplayI sview = null;
4143 sview = new StructureViewer(
4144 alf.alignPanel.getStructureSelectionManager())
4145 .createView(StructureViewer.ViewerType.JMOL,
4146 pdbf, id, sq, alf.alignPanel, svattrib,
4147 fileloc, rect, sviewid);
4148 addNewStructureViewer(sview);
4149 } catch (OutOfMemoryError ex)
4151 new OOMWarning("restoring structure view for PDB id " + id,
4152 (OutOfMemoryError) ex.getCause());
4153 if (sview != null && sview.isVisible())
4155 sview.closeViewer(false);
4156 sview.setVisible(false);
4162 } catch (InvocationTargetException ex)
4164 warn("Unexpected error when opening Jmol view.", ex);
4166 } catch (InterruptedException e)
4168 // e.printStackTrace();
4174 * Generates a name for the entry in the project jar file to hold state
4175 * information for a structure viewer
4180 protected String getViewerJarEntryName(String viewId)
4182 return VIEWER_PREFIX + viewId;
4186 * Returns any open frame that matches given structure viewer data. The match
4187 * is based on the unique viewId, or (for older project versions) the frame's
4193 protected StructureViewerBase findMatchingViewer(
4194 Entry<String, StructureViewerModel> viewerData)
4196 final String sviewid = viewerData.getKey();
4197 final StructureViewerModel svattrib = viewerData.getValue();
4198 StructureViewerBase comp = null;
4199 JInternalFrame[] frames = getAllFrames();
4200 for (JInternalFrame frame : frames)
4202 if (frame instanceof StructureViewerBase)
4205 * Post jalview 2.4 schema includes structure view id
4207 if (sviewid != null && ((StructureViewerBase) frame).getViewId()
4210 comp = (StructureViewerBase) frame;
4211 break; // break added in 2.9
4214 * Otherwise test for matching position and size of viewer frame
4216 else if (frame.getX() == svattrib.getX()
4217 && frame.getY() == svattrib.getY()
4218 && frame.getHeight() == svattrib.getHeight()
4219 && frame.getWidth() == svattrib.getWidth())
4221 comp = (StructureViewerBase) frame;
4222 // no break in faint hope of an exact match on viewId
4230 * Link an AlignmentPanel to an existing structure viewer.
4235 * @param useinViewerSuperpos
4236 * @param usetoColourbyseq
4237 * @param viewerColouring
4239 protected void linkStructureViewer(AlignmentPanel ap,
4240 StructureViewerBase viewer, StructureViewerModel stateData)
4242 // NOTE: if the jalview project is part of a shared session then
4243 // view synchronization should/could be done here.
4245 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4246 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4247 final boolean viewerColouring = stateData.isColourByViewer();
4248 Map<File, StructureData> oldFiles = stateData.getFileData();
4251 * Add mapping for sequences in this view to an already open viewer
4253 final AAStructureBindingModel binding = viewer.getBinding();
4254 for (File id : oldFiles.keySet())
4256 // add this and any other pdb files that should be present in the
4258 StructureData filedat = oldFiles.get(id);
4259 String pdbFile = filedat.getFilePath();
4260 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4261 binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE,
4263 binding.addSequenceForStructFile(pdbFile, seq);
4265 // and add the AlignmentPanel's reference to the view panel
4266 viewer.addAlignmentPanel(ap);
4267 if (useinViewerSuperpos)
4269 viewer.useAlignmentPanelForSuperposition(ap);
4273 viewer.excludeAlignmentPanelForSuperposition(ap);
4275 if (usetoColourbyseq)
4277 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4281 viewer.excludeAlignmentPanelForColourbyseq(ap);
4286 * Get all frames within the Desktop.
4290 protected JInternalFrame[] getAllFrames()
4292 JInternalFrame[] frames = null;
4293 // TODO is this necessary - is it safe - risk of hanging?
4298 frames = Desktop.desktop.getAllFrames();
4299 } catch (ArrayIndexOutOfBoundsException e)
4301 // occasional No such child exceptions are thrown here...
4305 } catch (InterruptedException f)
4309 } while (frames == null);
4314 * Answers true if 'version' is equal to or later than 'supported', where each
4315 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4316 * changes. Development and test values for 'version' are leniently treated
4320 * - minimum version we are comparing against
4322 * - version of data being processsed
4325 public static boolean isVersionStringLaterThan(String supported,
4328 if (supported == null || version == null
4329 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4330 || version.equalsIgnoreCase("Test")
4331 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4333 System.err.println("Assuming project file with "
4334 + (version == null ? "null" : version)
4335 + " is compatible with Jalview version " + supported);
4340 return StringUtils.compareVersions(version, supported, "b") >= 0;
4344 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4346 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4348 if (newStructureViewers != null)
4350 sview.getBinding().setFinishedLoadingFromArchive(false);
4351 newStructureViewers.add(sview);
4355 protected void setLoadingFinishedForNewStructureViewers()
4357 if (newStructureViewers != null)
4359 for (JalviewStructureDisplayI sview : newStructureViewers)
4361 sview.getBinding().setFinishedLoadingFromArchive(true);
4363 newStructureViewers.clear();
4364 newStructureViewers = null;
4368 AlignFrame loadViewport(String file, JSeq[] JSEQ,
4369 List<SequenceI> hiddenSeqs, AlignmentI al,
4370 JalviewModelSequence jms, Viewport view, String uniqueSeqSetId,
4371 String viewId, List<JvAnnotRow> autoAlan)
4373 AlignFrame af = null;
4374 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
4375 uniqueSeqSetId, viewId);
4377 af.setFileName(file, FileFormat.Jalview);
4379 for (int i = 0; i < JSEQ.length; i++)
4381 af.viewport.setSequenceColour(
4382 af.viewport.getAlignment().getSequenceAt(i),
4383 new java.awt.Color(JSEQ[i].getColour()));
4388 af.getViewport().setColourByReferenceSeq(true);
4389 af.getViewport().setDisplayReferenceSeq(true);
4392 af.viewport.setGatherViewsHere(view.getGatheredViews());
4394 if (view.getSequenceSetId() != null)
4396 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4398 af.viewport.setSequenceSetId(uniqueSeqSetId);
4401 // propagate shared settings to this new view
4402 af.viewport.setHistoryList(av.getHistoryList());
4403 af.viewport.setRedoList(av.getRedoList());
4407 viewportsAdded.put(uniqueSeqSetId, af.viewport);
4409 // TODO: check if this method can be called repeatedly without
4410 // side-effects if alignpanel already registered.
4411 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4413 // apply Hidden regions to view.
4414 if (hiddenSeqs != null)
4416 for (int s = 0; s < JSEQ.length; s++)
4418 SequenceGroup hidden = new SequenceGroup();
4419 boolean isRepresentative = false;
4420 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
4422 isRepresentative = true;
4423 SequenceI sequenceToHide = al
4424 .getSequenceAt(JSEQ[s].getHiddenSequences(r));
4425 hidden.addSequence(sequenceToHide, false);
4426 // remove from hiddenSeqs list so we don't try to hide it twice
4427 hiddenSeqs.remove(sequenceToHide);
4429 if (isRepresentative)
4431 SequenceI representativeSequence = al.getSequenceAt(s);
4432 hidden.addSequence(representativeSequence, false);
4433 af.viewport.hideRepSequences(representativeSequence, hidden);
4437 SequenceI[] hseqs = hiddenSeqs
4438 .toArray(new SequenceI[hiddenSeqs.size()]);
4439 af.viewport.hideSequence(hseqs);
4442 // recover view properties and display parameters
4444 af.viewport.setShowAnnotation(view.getShowAnnotation());
4445 af.viewport.setAbovePIDThreshold(view.getPidSelected());
4446 af.viewport.setThreshold(view.getPidThreshold());
4448 af.viewport.setColourText(view.getShowColourText());
4450 af.viewport.setConservationSelected(view.getConservationSelected());
4451 af.viewport.setIncrement(view.getConsThreshold());
4452 af.viewport.setShowJVSuffix(view.getShowFullId());
4453 af.viewport.setRightAlignIds(view.getRightAlignIds());
4454 af.viewport.setFont(new java.awt.Font(view.getFontName(),
4455 view.getFontStyle(), view.getFontSize()), true);
4456 ViewStyleI vs = af.viewport.getViewStyle();
4457 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
4458 af.viewport.setViewStyle(vs);
4459 // TODO: allow custom charWidth/Heights to be restored by updating them
4460 // after setting font - which means set above to false
4461 af.viewport.setRenderGaps(view.getRenderGaps());
4462 af.viewport.setWrapAlignment(view.getWrapAlignment());
4463 af.viewport.setShowAnnotation(view.getShowAnnotation());
4465 af.viewport.setShowBoxes(view.getShowBoxes());
4467 af.viewport.setShowText(view.getShowText());
4469 af.viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
4470 af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
4471 af.viewport.setThresholdTextColour(view.getTextColThreshold());
4472 af.viewport.setShowUnconserved(
4473 view.hasShowUnconserved() ? view.isShowUnconserved() : false);
4474 af.viewport.getRanges().setStartRes(view.getStartRes());
4476 if (view.getViewName() != null)
4478 af.viewport.viewName = view.getViewName();
4479 af.setInitialTabVisible();
4481 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
4483 // startSeq set in af.alignPanel.updateLayout below
4484 af.alignPanel.updateLayout();
4485 ColourSchemeI cs = null;
4486 // apply colourschemes
4487 if (view.getBgColour() != null)
4489 if (view.getBgColour().startsWith("ucs"))
4491 cs = getUserColourScheme(jms, view.getBgColour());
4493 else if (view.getBgColour().startsWith("Annotation"))
4495 AnnotationColours viewAnnColour = view.getAnnotationColours();
4496 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
4503 cs = ColourSchemeProperty.getColourScheme(al, view.getBgColour());
4507 af.viewport.setGlobalColourScheme(cs);
4508 af.viewport.getResidueShading().setThreshold(view.getPidThreshold(),
4509 view.getIgnoreGapsinConsensus());
4510 af.viewport.getResidueShading()
4511 .setConsensus(af.viewport.getSequenceConsensusHash());
4512 af.viewport.setColourAppliesToAllGroups(false);
4514 if (view.getConservationSelected() && cs != null)
4516 af.viewport.getResidueShading()
4517 .setConservationInc(view.getConsThreshold());
4520 af.changeColour(cs);
4522 af.viewport.setColourAppliesToAllGroups(true);
4524 af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures());
4526 if (view.hasCentreColumnLabels())
4528 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
4530 if (view.hasIgnoreGapsinConsensus())
4532 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
4535 if (view.hasFollowHighlight())
4537 af.viewport.setFollowHighlight(view.getFollowHighlight());
4539 if (view.hasFollowSelection())
4541 af.viewport.followSelection = view.getFollowSelection();
4543 if (view.hasShowConsensusHistogram())
4546 .setShowConsensusHistogram(view.getShowConsensusHistogram());
4550 af.viewport.setShowConsensusHistogram(true);
4552 if (view.hasShowSequenceLogo())
4554 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
4558 af.viewport.setShowSequenceLogo(false);
4560 if (view.hasNormaliseSequenceLogo())
4562 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
4564 if (view.hasShowDbRefTooltip())
4566 af.viewport.setShowDBRefs(view.getShowDbRefTooltip());
4568 if (view.hasShowNPfeatureTooltip())
4570 af.viewport.setShowNPFeats(view.hasShowNPfeatureTooltip());
4572 if (view.hasShowGroupConsensus())
4574 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
4578 af.viewport.setShowGroupConsensus(false);
4580 if (view.hasShowGroupConservation())
4582 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
4586 af.viewport.setShowGroupConservation(false);
4589 // recover featre settings
4590 if (jms.getFeatureSettings() != null)
4592 FeaturesDisplayed fdi;
4593 af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
4594 String[] renderOrder = new String[jms.getFeatureSettings()
4595 .getSettingCount()];
4596 Map<String, FeatureColourI> featureColours = new Hashtable<>();
4597 Map<String, Float> featureOrder = new Hashtable<>();
4599 for (int fs = 0; fs < jms.getFeatureSettings()
4600 .getSettingCount(); fs++)
4602 Setting setting = jms.getFeatureSettings().getSetting(fs);
4603 if (setting.hasMincolour())
4605 FeatureColourI gc = setting.hasMin()
4606 ? new FeatureColour(new Color(setting.getMincolour()),
4607 new Color(setting.getColour()), setting.getMin(),
4609 : new FeatureColour(new Color(setting.getMincolour()),
4610 new Color(setting.getColour()), 0, 1);
4611 if (setting.hasThreshold())
4613 gc.setThreshold(setting.getThreshold());
4614 int threshstate = setting.getThreshstate();
4615 // -1 = None, 0 = Below, 1 = Above threshold
4616 if (threshstate == 0)
4618 gc.setBelowThreshold(true);
4620 else if (threshstate == 1)
4622 gc.setAboveThreshold(true);
4625 gc.setAutoScaled(true); // default
4626 if (setting.hasAutoScale())
4628 gc.setAutoScaled(setting.getAutoScale());
4630 if (setting.hasColourByLabel())
4632 gc.setColourByLabel(setting.getColourByLabel());
4634 // and put in the feature colour table.
4635 featureColours.put(setting.getType(), gc);
4639 featureColours.put(setting.getType(),
4640 new FeatureColour(new Color(setting.getColour())));
4642 renderOrder[fs] = setting.getType();
4643 if (setting.hasOrder())
4645 featureOrder.put(setting.getType(), setting.getOrder());
4649 featureOrder.put(setting.getType(), new Float(
4650 fs / jms.getFeatureSettings().getSettingCount()));
4652 if (setting.getDisplay())
4654 fdi.setVisible(setting.getType());
4657 Map<String, Boolean> fgtable = new Hashtable<>();
4658 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
4660 Group grp = jms.getFeatureSettings().getGroup(gs);
4661 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
4663 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4664 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
4665 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
4666 FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4667 fgtable, featureColours, 1.0f, featureOrder);
4668 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
4669 .transferSettings(frs);
4673 if (view.getHiddenColumnsCount() > 0)
4675 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
4677 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(),
4678 view.getHiddenColumns(c).getEnd() // +1
4682 if (view.getCalcIdParam() != null)
4684 for (CalcIdParam calcIdParam : view.getCalcIdParam())
4686 if (calcIdParam != null)
4688 if (recoverCalcIdParam(calcIdParam, af.viewport))
4693 warn("Couldn't recover parameters for "
4694 + calcIdParam.getCalcId());
4699 af.setMenusFromViewport(af.viewport);
4700 af.setTitle(view.getTitle());
4701 // TODO: we don't need to do this if the viewport is aready visible.
4703 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
4704 * has a 'cdna/protein complement' view, in which case save it in order to
4705 * populate a SplitFrame once all views have been read in.
4707 String complementaryViewId = view.getComplementId();
4708 if (complementaryViewId == null)
4710 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
4712 // recompute any autoannotation
4713 af.alignPanel.updateAnnotation(false, true);
4714 reorderAutoannotation(af, al, autoAlan);
4715 af.alignPanel.alignmentChanged();
4719 splitFrameCandidates.put(view, af);
4725 * Reads saved data to restore Colour by Annotation settings
4727 * @param viewAnnColour
4731 * @param checkGroupAnnColour
4734 private ColourSchemeI constructAnnotationColour(
4735 AnnotationColours viewAnnColour, AlignFrame af, AlignmentI al,
4736 JalviewModelSequence jms, boolean checkGroupAnnColour)
4738 boolean propagateAnnColour = false;
4739 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
4740 if (checkGroupAnnColour && al.getGroups() != null
4741 && al.getGroups().size() > 0)
4743 // pre 2.8.1 behaviour
4744 // check to see if we should transfer annotation colours
4745 propagateAnnColour = true;
4746 for (SequenceGroup sg : al.getGroups())
4748 if (sg.getColourScheme() instanceof AnnotationColourGradient)
4750 propagateAnnColour = false;
4756 * 2.10.2- : saved annotationId is AlignmentAnnotation.annotationId
4758 String annotationId = viewAnnColour.getAnnotation();
4759 AlignmentAnnotation matchedAnnotation = annotationIds.get(annotationId);
4762 * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
4764 if (matchedAnnotation == null
4765 && annAlignment.getAlignmentAnnotation() != null)
4767 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
4770 .equals(annAlignment.getAlignmentAnnotation()[i].label))
4772 matchedAnnotation = annAlignment.getAlignmentAnnotation()[i];
4777 if (matchedAnnotation == null)
4779 System.err.println("Failed to match annotation colour scheme for "
4783 if (matchedAnnotation.getThreshold() == null)
4785 matchedAnnotation.setThreshold(new GraphLine(
4786 viewAnnColour.getThreshold(), "Threshold", Color.black));
4789 AnnotationColourGradient cs = null;
4790 if (viewAnnColour.getColourScheme().equals("None"))
4792 cs = new AnnotationColourGradient(matchedAnnotation,
4793 new Color(viewAnnColour.getMinColour()),
4794 new Color(viewAnnColour.getMaxColour()),
4795 viewAnnColour.getAboveThreshold());
4797 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
4799 cs = new AnnotationColourGradient(matchedAnnotation,
4800 getUserColourScheme(jms, viewAnnColour.getColourScheme()),
4801 viewAnnColour.getAboveThreshold());
4805 cs = new AnnotationColourGradient(matchedAnnotation,
4806 ColourSchemeProperty.getColourScheme(al,
4807 viewAnnColour.getColourScheme()),
4808 viewAnnColour.getAboveThreshold());
4811 boolean perSequenceOnly = viewAnnColour.isPerSequence();
4812 boolean useOriginalColours = viewAnnColour.isPredefinedColours();
4813 cs.setSeqAssociated(perSequenceOnly);
4814 cs.setPredefinedColours(useOriginalColours);
4816 if (propagateAnnColour && al.getGroups() != null)
4818 // Also use these settings for all the groups
4819 for (int g = 0; g < al.getGroups().size(); g++)
4821 SequenceGroup sg = al.getGroups().get(g);
4822 if (sg.getGroupColourScheme() == null)
4827 AnnotationColourGradient groupScheme = new AnnotationColourGradient(
4828 matchedAnnotation, sg.getColourScheme(),
4829 viewAnnColour.getAboveThreshold());
4830 sg.setColourScheme(groupScheme);
4831 groupScheme.setSeqAssociated(perSequenceOnly);
4832 groupScheme.setPredefinedColours(useOriginalColours);
4838 private void reorderAutoannotation(AlignFrame af, AlignmentI al,
4839 List<JvAnnotRow> autoAlan)
4841 // copy over visualization settings for autocalculated annotation in the
4843 if (al.getAlignmentAnnotation() != null)
4846 * Kludge for magic autoannotation names (see JAL-811)
4848 String[] magicNames = new String[] { "Consensus", "Quality",
4850 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
4851 Hashtable<String, JvAnnotRow> visan = new Hashtable<>();
4852 for (String nm : magicNames)
4854 visan.put(nm, nullAnnot);
4856 for (JvAnnotRow auan : autoAlan)
4858 visan.put(auan.template.label
4859 + (auan.template.getCalcId() == null ? ""
4860 : "\t" + auan.template.getCalcId()),
4863 int hSize = al.getAlignmentAnnotation().length;
4864 List<JvAnnotRow> reorder = new ArrayList<>();
4865 // work through any autoCalculated annotation already on the view
4866 // removing it if it should be placed in a different location on the
4867 // annotation panel.
4868 List<String> remains = new ArrayList<>(visan.keySet());
4869 for (int h = 0; h < hSize; h++)
4871 jalview.datamodel.AlignmentAnnotation jalan = al
4872 .getAlignmentAnnotation()[h];
4873 if (jalan.autoCalculated)
4876 JvAnnotRow valan = visan.get(k = jalan.label);
4877 if (jalan.getCalcId() != null)
4879 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
4884 // delete the auto calculated row from the alignment
4885 al.deleteAnnotation(jalan, false);
4889 if (valan != nullAnnot)
4891 if (jalan != valan.template)
4893 // newly created autoannotation row instance
4894 // so keep a reference to the visible annotation row
4895 // and copy over all relevant attributes
4896 if (valan.template.graphHeight >= 0)
4899 jalan.graphHeight = valan.template.graphHeight;
4901 jalan.visible = valan.template.visible;
4903 reorder.add(new JvAnnotRow(valan.order, jalan));
4908 // Add any (possibly stale) autocalculated rows that were not appended to
4909 // the view during construction
4910 for (String other : remains)
4912 JvAnnotRow othera = visan.get(other);
4913 if (othera != nullAnnot && othera.template.getCalcId() != null
4914 && othera.template.getCalcId().length() > 0)
4916 reorder.add(othera);
4919 // now put the automatic annotation in its correct place
4920 int s = 0, srt[] = new int[reorder.size()];
4921 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
4922 for (JvAnnotRow jvar : reorder)
4925 srt[s++] = jvar.order;
4928 jalview.util.QuickSort.sort(srt, rws);
4929 // and re-insert the annotation at its correct position
4930 for (JvAnnotRow jvar : rws)
4932 al.addAnnotation(jvar.template, jvar.order);
4934 af.alignPanel.adjustAnnotationHeight();
4938 Hashtable skipList = null;
4941 * TODO remove this method
4944 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
4945 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
4946 * throw new Error("Implementation Error. No skipList defined for this
4947 * Jalview2XML instance."); } return (AlignFrame)
4948 * skipList.get(view.getSequenceSetId()); }
4952 * Check if the Jalview view contained in object should be skipped or not.
4955 * @return true if view's sequenceSetId is a key in skipList
4957 private boolean skipViewport(JalviewModel object)
4959 if (skipList == null)
4964 if (skipList.containsKey(
4965 id = object.getJalviewModelSequence().getViewport()[0]
4966 .getSequenceSetId()))
4968 if (Cache.log != null && Cache.log.isDebugEnabled())
4970 Cache.log.debug("Skipping seuqence set id " + id);
4977 public void addToSkipList(AlignFrame af)
4979 if (skipList == null)
4981 skipList = new Hashtable();
4983 skipList.put(af.getViewport().getSequenceSetId(), af);
4986 public void clearSkipList()
4988 if (skipList != null)
4995 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
4996 boolean ignoreUnrefed)
4998 jalview.datamodel.AlignmentI ds = getDatasetFor(
4999 vamsasSet.getDatasetId());
5000 Vector dseqs = null;
5003 // create a list of new dataset sequences
5004 dseqs = new Vector();
5006 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
5008 Sequence vamsasSeq = vamsasSet.getSequence(i);
5009 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
5011 // create a new dataset
5014 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
5015 dseqs.copyInto(dsseqs);
5016 ds = new jalview.datamodel.Alignment(dsseqs);
5017 debug("Created new dataset " + vamsasSet.getDatasetId()
5018 + " for alignment " + System.identityHashCode(al));
5019 addDatasetRef(vamsasSet.getDatasetId(), ds);
5021 // set the dataset for the newly imported alignment.
5022 if (al.getDataset() == null && !ignoreUnrefed)
5031 * sequence definition to create/merge dataset sequence for
5035 * vector to add new dataset sequence to
5036 * @param ignoreUnrefed
5037 * - when true, don't create new sequences from vamsasSeq if it's id
5038 * doesn't already have an asssociated Jalview sequence.
5040 * - used to reorder the sequence in the alignment according to the
5041 * vamsasSeq array ordering, to preserve ordering of dataset
5043 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
5044 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed, int vseqpos)
5046 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
5048 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
5049 boolean reorder = false;
5050 SequenceI dsq = null;
5051 if (sq != null && sq.getDatasetSequence() != null)
5053 dsq = sq.getDatasetSequence();
5059 if (sq == null && ignoreUnrefed)
5063 String sqid = vamsasSeq.getDsseqid();
5066 // need to create or add a new dataset sequence reference to this sequence
5069 dsq = seqRefIds.get(sqid);
5074 // make a new dataset sequence
5075 dsq = sq.createDatasetSequence();
5078 // make up a new dataset reference for this sequence
5079 sqid = seqHash(dsq);
5081 dsq.setVamsasId(uniqueSetSuffix + sqid);
5082 seqRefIds.put(sqid, dsq);
5087 dseqs.addElement(dsq);
5092 ds.addSequence(dsq);
5098 { // make this dataset sequence sq's dataset sequence
5099 sq.setDatasetSequence(dsq);
5100 // and update the current dataset alignment
5105 if (!dseqs.contains(dsq))
5112 if (ds.findIndex(dsq) < 0)
5114 ds.addSequence(dsq);
5121 // TODO: refactor this as a merge dataset sequence function
5122 // now check that sq (the dataset sequence) sequence really is the union of
5123 // all references to it
5124 // boolean pre = sq.getStart() < dsq.getStart();
5125 // boolean post = sq.getEnd() > dsq.getEnd();
5129 // StringBuffer sb = new StringBuffer();
5130 String newres = jalview.analysis.AlignSeq.extractGaps(
5131 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
5132 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
5133 && newres.length() > dsq.getLength())
5135 // Update with the longer sequence.
5139 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
5140 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
5141 * sb.append(newres.substring(newres.length() - sq.getEnd() -
5142 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
5144 dsq.setSequence(newres);
5146 // TODO: merges will never happen if we 'know' we have the real dataset
5147 // sequence - this should be detected when id==dssid
5149 "DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
5150 // + (pre ? "prepended" : "") + " "
5151 // + (post ? "appended" : ""));
5156 // sequence refs are identical. We may need to update the existing dataset
5157 // alignment with this one, though.
5158 if (ds != null && dseqs == null)
5160 int opos = ds.findIndex(dsq);
5161 SequenceI tseq = null;
5162 if (opos != -1 && vseqpos != opos)
5164 // remove from old position
5165 ds.deleteSequence(dsq);
5167 if (vseqpos < ds.getHeight())
5169 if (vseqpos != opos)
5171 // save sequence at destination position
5172 tseq = ds.getSequenceAt(vseqpos);
5173 ds.replaceSequenceAt(vseqpos, dsq);
5174 ds.addSequence(tseq);
5179 ds.addSequence(dsq);
5186 * TODO use AlignmentI here and in related methods - needs
5187 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
5189 Hashtable<String, AlignmentI> datasetIds = null;
5191 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
5193 private AlignmentI getDatasetFor(String datasetId)
5195 if (datasetIds == null)
5197 datasetIds = new Hashtable<>();
5200 if (datasetIds.containsKey(datasetId))
5202 return datasetIds.get(datasetId);
5207 private void addDatasetRef(String datasetId, AlignmentI dataset)
5209 if (datasetIds == null)
5211 datasetIds = new Hashtable<>();
5213 datasetIds.put(datasetId, dataset);
5217 * make a new dataset ID for this jalview dataset alignment
5222 private String getDatasetIdRef(AlignmentI dataset)
5224 if (dataset.getDataset() != null)
5226 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
5228 String datasetId = makeHashCode(dataset, null);
5229 if (datasetId == null)
5231 // make a new datasetId and record it
5232 if (dataset2Ids == null)
5234 dataset2Ids = new IdentityHashMap<>();
5238 datasetId = dataset2Ids.get(dataset);
5240 if (datasetId == null)
5242 datasetId = "ds" + dataset2Ids.size() + 1;
5243 dataset2Ids.put(dataset, datasetId);
5249 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5251 for (int d = 0; d < sequence.getDBRefCount(); d++)
5253 DBRef dr = sequence.getDBRef(d);
5254 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
5255 sequence.getDBRef(d).getSource(),
5256 sequence.getDBRef(d).getVersion(),
5257 sequence.getDBRef(d).getAccessionId());
5258 if (dr.getMapping() != null)
5260 entry.setMap(addMapping(dr.getMapping()));
5262 datasetSequence.addDBRef(entry);
5266 private jalview.datamodel.Mapping addMapping(Mapping m)
5268 SequenceI dsto = null;
5269 // Mapping m = dr.getMapping();
5270 int fr[] = new int[m.getMapListFromCount() * 2];
5271 Enumeration f = m.enumerateMapListFrom();
5272 for (int _i = 0; f.hasMoreElements(); _i += 2)
5274 MapListFrom mf = (MapListFrom) f.nextElement();
5275 fr[_i] = mf.getStart();
5276 fr[_i + 1] = mf.getEnd();
5278 int fto[] = new int[m.getMapListToCount() * 2];
5279 f = m.enumerateMapListTo();
5280 for (int _i = 0; f.hasMoreElements(); _i += 2)
5282 MapListTo mf = (MapListTo) f.nextElement();
5283 fto[_i] = mf.getStart();
5284 fto[_i + 1] = mf.getEnd();
5286 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto, fr,
5287 fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
5288 if (m.getMappingChoice() != null)
5290 MappingChoice mc = m.getMappingChoice();
5291 if (mc.getDseqFor() != null)
5293 String dsfor = "" + mc.getDseqFor();
5294 if (seqRefIds.containsKey(dsfor))
5299 jmap.setTo(seqRefIds.get(dsfor));
5303 frefedSequence.add(newMappingRef(dsfor, jmap));
5309 * local sequence definition
5311 Sequence ms = mc.getSequence();
5312 SequenceI djs = null;
5313 String sqid = ms.getDsseqid();
5314 if (sqid != null && sqid.length() > 0)
5317 * recover dataset sequence
5319 djs = seqRefIds.get(sqid);
5324 "Warning - making up dataset sequence id for DbRef sequence map reference");
5325 sqid = ((Object) ms).toString(); // make up a new hascode for
5326 // undefined dataset sequence hash
5327 // (unlikely to happen)
5333 * make a new dataset sequence and add it to refIds hash
5335 djs = new jalview.datamodel.Sequence(ms.getName(),
5337 djs.setStart(jmap.getMap().getToLowest());
5338 djs.setEnd(jmap.getMap().getToHighest());
5339 djs.setVamsasId(uniqueSetSuffix + sqid);
5341 incompleteSeqs.put(sqid, djs);
5342 seqRefIds.put(sqid, djs);
5345 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5355 * Provides a 'copy' of an alignment view (on action New View) by 'saving' the
5356 * view as XML (but not to file), and then reloading it
5361 public AlignmentPanel copyAlignPanel(AlignmentPanel ap)
5364 JalviewModel jm = saveState(ap, null, null, null);
5366 uniqueSetSuffix = "";
5367 jm.getJalviewModelSequence().getViewport(0).setId(null);
5368 // we don't overwrite the view we just copied
5370 if (this.frefedSequence == null)
5372 frefedSequence = new Vector<>();
5375 viewportsAdded.clear();
5377 AlignFrame af = loadFromObject(jm, null, false, null);
5378 af.alignPanels.clear();
5379 af.closeMenuItem_actionPerformed(true);
5382 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5383 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5384 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5385 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5386 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5389 return af.alignPanel;
5392 private Hashtable jvids2vobj;
5394 private void warn(String msg)
5399 private void warn(String msg, Exception e)
5401 if (Cache.log != null)
5405 Cache.log.warn(msg, e);
5409 Cache.log.warn(msg);
5414 System.err.println("Warning: " + msg);
5417 e.printStackTrace();
5422 private void debug(String string)
5424 debug(string, null);
5427 private void debug(String msg, Exception e)
5429 if (Cache.log != null)
5433 Cache.log.debug(msg, e);
5437 Cache.log.debug(msg);
5442 System.err.println("Warning: " + msg);
5445 e.printStackTrace();
5451 * set the object to ID mapping tables used to write/recover objects and XML
5452 * ID strings for the jalview project. If external tables are provided then
5453 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
5454 * object goes out of scope. - also populates the datasetIds hashtable with
5455 * alignment objects containing dataset sequences
5458 * Map from ID strings to jalview datamodel
5460 * Map from jalview datamodel to ID strings
5464 public void setObjectMappingTables(Hashtable vobj2jv,
5465 IdentityHashMap jv2vobj)
5467 this.jv2vobj = jv2vobj;
5468 this.vobj2jv = vobj2jv;
5469 Iterator ds = jv2vobj.keySet().iterator();
5471 while (ds.hasNext())
5473 Object jvobj = ds.next();
5474 id = jv2vobj.get(jvobj).toString();
5475 if (jvobj instanceof jalview.datamodel.Alignment)
5477 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
5479 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
5482 else if (jvobj instanceof jalview.datamodel.Sequence)
5484 // register sequence object so the XML parser can recover it.
5485 if (seqRefIds == null)
5487 seqRefIds = new HashMap<>();
5489 if (seqsToIds == null)
5491 seqsToIds = new IdentityHashMap<>();
5493 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
5494 seqsToIds.put((SequenceI) jvobj, id);
5496 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
5499 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
5500 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
5501 if (jvann.annotationId == null)
5503 jvann.annotationId = anid;
5505 if (!jvann.annotationId.equals(anid))
5507 // TODO verify that this is the correct behaviour
5508 this.warn("Overriding Annotation ID for " + anid
5509 + " from different id : " + jvann.annotationId);
5510 jvann.annotationId = anid;
5513 else if (jvobj instanceof String)
5515 if (jvids2vobj == null)
5517 jvids2vobj = new Hashtable();
5518 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
5523 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
5529 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
5530 * objects created from the project archive. If string is null (default for
5531 * construction) then suffix will be set automatically.
5535 public void setUniqueSetSuffix(String string)
5537 uniqueSetSuffix = string;
5542 * uses skipList2 as the skipList for skipping views on sequence sets
5543 * associated with keys in the skipList
5547 public void setSkipList(Hashtable skipList2)
5549 skipList = skipList2;
5553 * Reads the jar entry of given name and returns its contents, or null if the
5554 * entry is not found.
5557 * @param jarEntryName
5560 protected String readJarEntry(jarInputStreamProvider jprovider,
5561 String jarEntryName)
5563 String result = null;
5564 BufferedReader in = null;
5569 * Reopen the jar input stream and traverse its entries to find a matching
5572 JarInputStream jin = jprovider.getJarInputStream();
5573 JarEntry entry = null;
5576 entry = jin.getNextJarEntry();
5577 } while (entry != null && !entry.getName().equals(jarEntryName));
5581 StringBuilder out = new StringBuilder(256);
5582 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
5585 while ((data = in.readLine()) != null)
5589 result = out.toString();
5593 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
5595 } catch (Exception ex)
5597 ex.printStackTrace();
5605 } catch (IOException e)
5616 * Returns an incrementing counter (0, 1, 2...)
5620 private synchronized int nextCounter()