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 jms.addExtTreeViewer(treeView);
1121 } catch (IOException e)
1123 // TODO Auto-generated catch block
1124 e.printStackTrace();
1135 * store forward refs from an annotationRow to any groups
1137 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<>();
1140 for (SequenceI sq : jal.getSequences())
1142 // Store annotation on dataset sequences only
1143 AlignmentAnnotation[] aa = sq.getAnnotation();
1144 if (aa != null && aa.length > 0)
1146 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1153 if (jal.getAlignmentAnnotation() != null)
1155 // Store the annotation shown on the alignment.
1156 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1157 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1162 if (jal.getGroups() != null)
1164 JGroup[] groups = new JGroup[jal.getGroups().size()];
1166 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1168 JGroup jGroup = new JGroup();
1169 groups[++i] = jGroup;
1171 jGroup.setStart(sg.getStartRes());
1172 jGroup.setEnd(sg.getEndRes());
1173 jGroup.setName(sg.getName());
1174 if (groupRefs.containsKey(sg))
1176 // group has references so set its ID field
1177 jGroup.setId(groupRefs.get(sg));
1179 ColourSchemeI colourScheme = sg.getColourScheme();
1180 if (colourScheme != null)
1182 ResidueShaderI groupColourScheme = sg.getGroupColourScheme();
1183 if (groupColourScheme.conservationApplied())
1185 jGroup.setConsThreshold(groupColourScheme.getConservationInc());
1187 if (colourScheme instanceof jalview.schemes.UserColourScheme)
1190 setUserColourScheme(colourScheme, userColours, jms));
1194 jGroup.setColour(colourScheme.getSchemeName());
1197 else if (colourScheme instanceof jalview.schemes.AnnotationColourGradient)
1199 jGroup.setColour("AnnotationColourGradient");
1200 jGroup.setAnnotationColours(constructAnnotationColours(
1201 (jalview.schemes.AnnotationColourGradient) colourScheme,
1204 else if (colourScheme instanceof jalview.schemes.UserColourScheme)
1207 setUserColourScheme(colourScheme, userColours, jms));
1211 jGroup.setColour(colourScheme.getSchemeName());
1214 jGroup.setPidThreshold(groupColourScheme.getThreshold());
1217 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1218 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1219 jGroup.setDisplayText(sg.getDisplayText());
1220 jGroup.setColourText(sg.getColourText());
1221 jGroup.setTextCol1(sg.textColour.getRGB());
1222 jGroup.setTextCol2(sg.textColour2.getRGB());
1223 jGroup.setTextColThreshold(sg.thresholdTextColour);
1224 jGroup.setShowUnconserved(sg.getShowNonconserved());
1225 jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1226 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1227 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1228 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1229 for (SequenceI seq : sg.getSequences())
1231 jGroup.addSeq(seqHash(seq));
1235 jms.setJGroup(groups);
1239 // /////////SAVE VIEWPORT
1240 Viewport view = new Viewport();
1241 view.setTitle(ap.alignFrame.getTitle());
1242 view.setSequenceSetId(
1243 makeHashCode(av.getSequenceSetId(), av.getSequenceSetId()));
1244 view.setId(av.getViewId());
1245 if (av.getCodingComplement() != null)
1247 view.setComplementId(av.getCodingComplement().getViewId());
1249 view.setViewName(av.viewName);
1250 view.setGatheredViews(av.isGatherViewsHere());
1252 Rectangle size = ap.av.getExplodedGeometry();
1253 Rectangle position = size;
1256 size = ap.alignFrame.getBounds();
1257 if (av.getCodingComplement() != null)
1259 position = ((SplitFrame) ap.alignFrame.getSplitViewContainer())
1267 view.setXpos(position.x);
1268 view.setYpos(position.y);
1270 view.setWidth(size.width);
1271 view.setHeight(size.height);
1273 view.setStartRes(vpRanges.getStartRes());
1274 view.setStartSeq(vpRanges.getStartSeq());
1276 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1278 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1282 .getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1284 AnnotationColours ac = constructAnnotationColours(
1285 (jalview.schemes.AnnotationColourGradient) av
1286 .getGlobalColourScheme(),
1289 view.setAnnotationColours(ac);
1290 view.setBgColour("AnnotationColourGradient");
1294 view.setBgColour(ColourSchemeProperty
1295 .getColourName(av.getGlobalColourScheme()));
1298 ResidueShaderI vcs = av.getResidueShading();
1299 ColourSchemeI cs = av.getGlobalColourScheme();
1303 if (vcs.conservationApplied())
1305 view.setConsThreshold(vcs.getConservationInc());
1306 if (cs instanceof jalview.schemes.UserColourScheme)
1308 view.setBgColour(setUserColourScheme(cs, userColours, jms));
1311 view.setPidThreshold(vcs.getThreshold());
1314 view.setConservationSelected(av.getConservationSelected());
1315 view.setPidSelected(av.getAbovePIDThreshold());
1316 view.setFontName(av.font.getName());
1317 view.setFontSize(av.font.getSize());
1318 view.setFontStyle(av.font.getStyle());
1319 view.setScaleProteinAsCdna(av.getViewStyle().isScaleProteinAsCdna());
1320 view.setRenderGaps(av.isRenderGaps());
1321 view.setShowAnnotation(av.isShowAnnotation());
1322 view.setShowBoxes(av.getShowBoxes());
1323 view.setShowColourText(av.getColourText());
1324 view.setShowFullId(av.getShowJVSuffix());
1325 view.setRightAlignIds(av.isRightAlignIds());
1326 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1327 view.setShowText(av.getShowText());
1328 view.setShowUnconserved(av.getShowUnconserved());
1329 view.setWrapAlignment(av.getWrapAlignment());
1330 view.setTextCol1(av.getTextColour().getRGB());
1331 view.setTextCol2(av.getTextColour2().getRGB());
1332 view.setTextColThreshold(av.getThresholdTextColour());
1333 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1334 view.setShowSequenceLogo(av.isShowSequenceLogo());
1335 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1336 view.setShowGroupConsensus(av.isShowGroupConsensus());
1337 view.setShowGroupConservation(av.isShowGroupConservation());
1338 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1339 view.setShowDbRefTooltip(av.isShowDBRefs());
1340 view.setFollowHighlight(av.isFollowHighlight());
1341 view.setFollowSelection(av.followSelection);
1342 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1343 if (av.getFeaturesDisplayed() != null)
1345 jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
1347 String[] renderOrder = ap.getSeqPanel().seqCanvas
1348 .getFeatureRenderer().getRenderOrder()
1349 .toArray(new String[0]);
1351 Vector<String> settingsAdded = new Vector<>();
1352 if (renderOrder != null)
1354 for (String featureType : renderOrder)
1356 FeatureColourI fcol = ap.getSeqPanel().seqCanvas
1357 .getFeatureRenderer().getFeatureStyle(featureType);
1358 Setting setting = new Setting();
1359 setting.setType(featureType);
1360 if (!fcol.isSimpleColour())
1362 setting.setColour(fcol.getMaxColour().getRGB());
1363 setting.setMincolour(fcol.getMinColour().getRGB());
1364 setting.setMin(fcol.getMin());
1365 setting.setMax(fcol.getMax());
1366 setting.setColourByLabel(fcol.isColourByLabel());
1367 setting.setAutoScale(fcol.isAutoScaled());
1368 setting.setThreshold(fcol.getThreshold());
1369 // -1 = No threshold, 0 = Below, 1 = Above
1370 setting.setThreshstate(fcol.isAboveThreshold() ? 1
1371 : (fcol.isBelowThreshold() ? 0 : -1));
1375 setting.setColour(fcol.getColour().getRGB());
1379 av.getFeaturesDisplayed().isVisible(featureType));
1380 float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1381 .getOrder(featureType);
1384 setting.setOrder(rorder);
1386 fs.addSetting(setting);
1387 settingsAdded.addElement(featureType);
1391 // is groups actually supposed to be a map here ?
1392 Iterator<String> en = ap.getSeqPanel().seqCanvas
1393 .getFeatureRenderer().getFeatureGroups().iterator();
1394 Vector<String> groupsAdded = new Vector<>();
1395 while (en.hasNext())
1397 String grp = en.next();
1398 if (groupsAdded.contains(grp))
1402 Group g = new Group();
1404 g.setDisplay(((Boolean) ap.getSeqPanel().seqCanvas
1405 .getFeatureRenderer().checkGroupVisibility(grp, false))
1408 groupsAdded.addElement(grp);
1410 jms.setFeatureSettings(fs);
1413 if (av.hasHiddenColumns())
1415 jalview.datamodel.HiddenColumns hidden = av.getAlignment()
1416 .getHiddenColumns();
1419 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1423 ArrayList<int[]> hiddenRegions = hidden.getHiddenColumnsCopy();
1424 for (int[] region : hiddenRegions)
1426 HiddenColumns hc = new HiddenColumns();
1427 hc.setStart(region[0]);
1428 hc.setEnd(region[1]);
1429 view.addHiddenColumns(hc);
1433 if (calcIdSet.size() > 0)
1435 for (String calcId : calcIdSet)
1437 if (calcId.trim().length() > 0)
1439 CalcIdParam cidp = createCalcIdParam(calcId, av);
1440 // Some calcIds have no parameters.
1443 view.addCalcIdParam(cidp);
1449 jms.addViewport(view);
1451 object.setJalviewModelSequence(jms);
1452 object.getVamsasModel().addSequenceSet(vamsasSet);
1454 if (jout != null && fileName != null)
1456 // We may not want to write the object to disk,
1457 // eg we can copy the alignViewport to a new view object
1458 // using save and then load
1461 System.out.println("Writing jar entry " + fileName);
1462 JarEntry entry = new JarEntry(fileName);
1463 jout.putNextEntry(entry);
1464 PrintWriter pout = new PrintWriter(
1465 new OutputStreamWriter(jout, UTF_8));
1466 Marshaller marshaller = new Marshaller(pout);
1467 marshaller.marshal(object);
1470 } catch (Exception ex)
1472 // TODO: raise error in GUI if marshalling failed.
1473 ex.printStackTrace();
1480 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1481 * for each viewer, with
1483 * <li>viewer geometry (position, size, split pane divider location)</li>
1484 * <li>index of the selected structure in the viewer (currently shows gapped
1486 * <li>the id of the annotation holding RNA secondary structure</li>
1487 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1489 * Varna viewer state is also written out (in native Varna XML) to separate
1490 * project jar entries. A separate entry is written for each RNA structure
1491 * displayed, with the naming convention
1493 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
1501 * @param storeDataset
1503 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
1504 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
1505 boolean storeDataset)
1507 if (Desktop.desktop == null)
1511 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1512 for (int f = frames.length - 1; f > -1; f--)
1514 if (frames[f] instanceof AppVarna)
1516 AppVarna varna = (AppVarna) frames[f];
1518 * link the sequence to every viewer that is showing it and is linked to
1519 * its alignment panel
1521 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1523 String viewId = varna.getViewId();
1524 RnaViewer rna = new RnaViewer();
1525 rna.setViewId(viewId);
1526 rna.setTitle(varna.getTitle());
1527 rna.setXpos(varna.getX());
1528 rna.setYpos(varna.getY());
1529 rna.setWidth(varna.getWidth());
1530 rna.setHeight(varna.getHeight());
1531 rna.setDividerLocation(varna.getDividerLocation());
1532 rna.setSelectedRna(varna.getSelectedIndex());
1533 jseq.addRnaViewer(rna);
1536 * Store each Varna panel's state once in the project per sequence.
1537 * First time through only (storeDataset==false)
1539 // boolean storeSessions = false;
1540 // String sequenceViewId = viewId + seqsToIds.get(jds);
1541 // if (!storeDataset && !viewIds.contains(sequenceViewId))
1543 // viewIds.add(sequenceViewId);
1544 // storeSessions = true;
1546 for (RnaModel model : varna.getModels())
1548 if (model.seq == jds)
1551 * VARNA saves each view (sequence or alignment secondary
1552 * structure, gapped or trimmed) as a separate XML file
1554 String jarEntryName = rnaSessions.get(model);
1555 if (jarEntryName == null)
1558 String varnaStateFile = varna.getStateInfo(model.rna);
1559 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
1561 rnaSessions.put(model, jarEntryName);
1563 SecondaryStructure ss = new SecondaryStructure();
1564 String annotationId = varna.getAnnotation(jds).annotationId;
1565 ss.setAnnotationId(annotationId);
1566 ss.setViewerState(jarEntryName);
1567 ss.setGapped(model.gapped);
1568 ss.setTitle(model.title);
1569 rna.addSecondaryStructure(ss);
1578 * Copy the contents of a file to a new entry added to the output jar
1582 * @param jarEntryName
1584 protected void copyFileToJar(JarOutputStream jout, String infilePath,
1585 String jarEntryName)
1587 DataInputStream dis = null;
1590 File file = new File(infilePath);
1591 if (file.exists() && jout != null)
1593 dis = new DataInputStream(new FileInputStream(file));
1594 byte[] data = new byte[(int) file.length()];
1595 dis.readFully(data);
1596 writeJarEntry(jout, jarEntryName, data);
1598 } catch (Exception ex)
1600 ex.printStackTrace();
1608 } catch (IOException e)
1617 * Write the data to a new entry of given name in the output jar file
1620 * @param jarEntryName
1622 * @throws IOException
1624 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
1625 byte[] data) throws IOException
1629 System.out.println("Writing jar entry " + jarEntryName);
1630 jout.putNextEntry(new JarEntry(jarEntryName));
1631 DataOutputStream dout = new DataOutputStream(jout);
1632 dout.write(data, 0, data.length);
1639 * Save the state of a structure viewer
1644 * the archive XML element under which to save the state
1647 * @param matchedFile
1651 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
1652 Pdbids pdb, PDBEntry entry, List<String> viewIds,
1653 String matchedFile, StructureViewerBase viewFrame)
1655 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
1658 * Look for any bindings for this viewer to the PDB file of interest
1659 * (including part matches excluding chain id)
1661 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
1663 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
1664 final String pdbId = pdbentry.getId();
1665 if (!pdbId.equals(entry.getId())
1666 && !(entry.getId().length() > 4 && entry.getId().toLowerCase()
1667 .startsWith(pdbId.toLowerCase())))
1670 * not interested in a binding to a different PDB entry here
1674 if (matchedFile == null)
1676 matchedFile = pdbentry.getFile();
1678 else if (!matchedFile.equals(pdbentry.getFile()))
1681 "Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
1682 + pdbentry.getFile());
1686 // can get at it if the ID
1687 // match is ambiguous (e.g.
1690 for (int smap = 0; smap < viewFrame.getBinding()
1691 .getSequence()[peid].length; smap++)
1693 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
1694 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
1696 StructureState state = new StructureState();
1697 state.setVisible(true);
1698 state.setXpos(viewFrame.getX());
1699 state.setYpos(viewFrame.getY());
1700 state.setWidth(viewFrame.getWidth());
1701 state.setHeight(viewFrame.getHeight());
1702 final String viewId = viewFrame.getViewId();
1703 state.setViewId(viewId);
1704 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
1705 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
1706 state.setColourByJmol(viewFrame.isColouredByViewer());
1707 state.setType(viewFrame.getViewerType().toString());
1708 pdb.addStructureState(state);
1716 * Populates the AnnotationColours xml for save. This captures the settings of
1717 * the options in the 'Colour by Annotation' dialog.
1720 * @param userColours
1724 private AnnotationColours constructAnnotationColours(
1725 AnnotationColourGradient acg, List<UserColourScheme> userColours,
1726 JalviewModelSequence jms)
1728 AnnotationColours ac = new AnnotationColours();
1729 ac.setAboveThreshold(acg.getAboveThreshold());
1730 ac.setThreshold(acg.getAnnotationThreshold());
1731 // 2.10.2 save annotationId (unique) not annotation label
1732 ac.setAnnotation(acg.getAnnotation().annotationId);
1733 if (acg.getBaseColour() instanceof UserColourScheme)
1736 setUserColourScheme(acg.getBaseColour(), userColours, jms));
1741 ColourSchemeProperty.getColourName(acg.getBaseColour()));
1744 ac.setMaxColour(acg.getMaxColour().getRGB());
1745 ac.setMinColour(acg.getMinColour().getRGB());
1746 ac.setPerSequence(acg.isSeqAssociated());
1747 ac.setPredefinedColours(acg.isPredefinedColours());
1751 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
1752 IdentityHashMap<SequenceGroup, String> groupRefs,
1753 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
1754 SequenceSet vamsasSet)
1757 for (int i = 0; i < aa.length; i++)
1759 Annotation an = new Annotation();
1761 AlignmentAnnotation annotation = aa[i];
1762 if (annotation.annotationId != null)
1764 annotationIds.put(annotation.annotationId, annotation);
1767 an.setId(annotation.annotationId);
1769 an.setVisible(annotation.visible);
1771 an.setDescription(annotation.description);
1773 if (annotation.sequenceRef != null)
1775 // 2.9 JAL-1781 xref on sequence id rather than name
1776 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
1778 if (annotation.groupRef != null)
1780 String groupIdr = groupRefs.get(annotation.groupRef);
1781 if (groupIdr == null)
1783 // make a locally unique String
1784 groupRefs.put(annotation.groupRef,
1785 groupIdr = ("" + System.currentTimeMillis()
1786 + annotation.groupRef.getName()
1787 + groupRefs.size()));
1789 an.setGroupRef(groupIdr.toString());
1792 // store all visualization attributes for annotation
1793 an.setGraphHeight(annotation.graphHeight);
1794 an.setCentreColLabels(annotation.centreColLabels);
1795 an.setScaleColLabels(annotation.scaleColLabel);
1796 an.setShowAllColLabels(annotation.showAllColLabels);
1797 an.setBelowAlignment(annotation.belowAlignment);
1799 if (annotation.graph > 0)
1802 an.setGraphType(annotation.graph);
1803 an.setGraphGroup(annotation.graphGroup);
1804 if (annotation.getThreshold() != null)
1806 ThresholdLine line = new ThresholdLine();
1807 line.setLabel(annotation.getThreshold().label);
1808 line.setValue(annotation.getThreshold().value);
1809 line.setColour(annotation.getThreshold().colour.getRGB());
1810 an.setThresholdLine(line);
1818 an.setLabel(annotation.label);
1820 if (annotation == av.getAlignmentQualityAnnot()
1821 || annotation == av.getAlignmentConservationAnnotation()
1822 || annotation == av.getAlignmentConsensusAnnotation()
1823 || annotation.autoCalculated)
1825 // new way of indicating autocalculated annotation -
1826 an.setAutoCalculated(annotation.autoCalculated);
1828 if (annotation.hasScore())
1830 an.setScore(annotation.getScore());
1833 if (annotation.getCalcId() != null)
1835 calcIdSet.add(annotation.getCalcId());
1836 an.setCalcId(annotation.getCalcId());
1838 if (annotation.hasProperties())
1840 for (String pr : annotation.getProperties())
1842 Property prop = new Property();
1844 prop.setValue(annotation.getProperty(pr));
1845 an.addProperty(prop);
1849 AnnotationElement ae;
1850 if (annotation.annotations != null)
1852 an.setScoreOnly(false);
1853 for (int a = 0; a < annotation.annotations.length; a++)
1855 if ((annotation == null) || (annotation.annotations[a] == null))
1860 ae = new AnnotationElement();
1861 if (annotation.annotations[a].description != null)
1863 ae.setDescription(annotation.annotations[a].description);
1865 if (annotation.annotations[a].displayCharacter != null)
1867 ae.setDisplayCharacter(
1868 annotation.annotations[a].displayCharacter);
1871 if (!Float.isNaN(annotation.annotations[a].value))
1873 ae.setValue(annotation.annotations[a].value);
1877 if (annotation.annotations[a].secondaryStructure > ' ')
1879 ae.setSecondaryStructure(
1880 annotation.annotations[a].secondaryStructure + "");
1883 if (annotation.annotations[a].colour != null
1884 && annotation.annotations[a].colour != java.awt.Color.black)
1886 ae.setColour(annotation.annotations[a].colour.getRGB());
1889 an.addAnnotationElement(ae);
1890 if (annotation.autoCalculated)
1892 // only write one non-null entry into the annotation row -
1893 // sufficient to get the visualization attributes necessary to
1901 an.setScoreOnly(true);
1903 if (!storeDS || (storeDS && !annotation.autoCalculated))
1905 // skip autocalculated annotation - these are only provided for
1907 vamsasSet.addAnnotation(an);
1913 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
1915 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
1916 if (settings != null)
1918 CalcIdParam vCalcIdParam = new CalcIdParam();
1919 vCalcIdParam.setCalcId(calcId);
1920 vCalcIdParam.addServiceURL(settings.getServiceURI());
1921 // generic URI allowing a third party to resolve another instance of the
1922 // service used for this calculation
1923 for (String urls : settings.getServiceURLs())
1925 vCalcIdParam.addServiceURL(urls);
1927 vCalcIdParam.setVersion("1.0");
1928 if (settings.getPreset() != null)
1930 WsParamSetI setting = settings.getPreset();
1931 vCalcIdParam.setName(setting.getName());
1932 vCalcIdParam.setDescription(setting.getDescription());
1936 vCalcIdParam.setName("");
1937 vCalcIdParam.setDescription("Last used parameters");
1939 // need to be able to recover 1) settings 2) user-defined presets or
1940 // recreate settings from preset 3) predefined settings provided by
1941 // service - or settings that can be transferred (or discarded)
1942 vCalcIdParam.setParameters(
1943 settings.getWsParamFile().replace("\n", "|\\n|"));
1944 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
1945 // todo - decide if updateImmediately is needed for any projects.
1947 return vCalcIdParam;
1952 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
1955 if (calcIdParam.getVersion().equals("1.0"))
1957 Jws2Instance service = Jws2Discoverer.getDiscoverer()
1958 .getPreferredServiceFor(calcIdParam.getServiceURL());
1959 if (service != null)
1961 WsParamSetI parmSet = null;
1964 parmSet = service.getParamStore().parseServiceParameterFile(
1965 calcIdParam.getName(), calcIdParam.getDescription(),
1966 calcIdParam.getServiceURL(),
1967 calcIdParam.getParameters().replace("|\\n|", "\n"));
1968 } catch (IOException x)
1970 warn("Couldn't parse parameter data for "
1971 + calcIdParam.getCalcId(), x);
1974 List<ArgumentI> argList = null;
1975 if (calcIdParam.getName().length() > 0)
1977 parmSet = service.getParamStore()
1978 .getPreset(calcIdParam.getName());
1979 if (parmSet != null)
1981 // TODO : check we have a good match with settings in AACon -
1982 // otherwise we'll need to create a new preset
1987 argList = parmSet.getArguments();
1990 AAConSettings settings = new AAConSettings(
1991 calcIdParam.isAutoUpdate(), service, parmSet, argList);
1992 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
1993 calcIdParam.isNeedsUpdate());
1998 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
2002 throw new Error(MessageManager.formatMessage(
2003 "error.unsupported_version_calcIdparam", new Object[]
2004 { calcIdParam.toString() }));
2008 * External mapping between jalview objects and objects yielding a valid and
2009 * unique object ID string. This is null for normal Jalview project IO, but
2010 * non-null when a jalview project is being read or written as part of a
2013 IdentityHashMap jv2vobj = null;
2016 * Construct a unique ID for jvobj using either existing bindings or if none
2017 * exist, the result of the hashcode call for the object.
2020 * jalview data object
2021 * @return unique ID for referring to jvobj
2023 private String makeHashCode(Object jvobj, String altCode)
2025 if (jv2vobj != null)
2027 Object id = jv2vobj.get(jvobj);
2030 return id.toString();
2032 // check string ID mappings
2033 if (jvids2vobj != null && jvobj instanceof String)
2035 id = jvids2vobj.get(jvobj);
2039 return id.toString();
2041 // give up and warn that something has gone wrong
2042 warn("Cannot find ID for object in external mapping : " + jvobj);
2048 * return local jalview object mapped to ID, if it exists
2052 * @return null or object bound to idcode
2054 private Object retrieveExistingObj(String idcode)
2056 if (idcode != null && vobj2jv != null)
2058 return vobj2jv.get(idcode);
2064 * binding from ID strings from external mapping table to jalview data model
2067 private Hashtable vobj2jv;
2069 private Sequence createVamsasSequence(String id, SequenceI jds)
2071 return createVamsasSequence(true, id, jds, null);
2074 private Sequence createVamsasSequence(boolean recurse, String id,
2075 SequenceI jds, SequenceI parentseq)
2077 Sequence vamsasSeq = new Sequence();
2078 vamsasSeq.setId(id);
2079 vamsasSeq.setName(jds.getName());
2080 vamsasSeq.setSequence(jds.getSequenceAsString());
2081 vamsasSeq.setDescription(jds.getDescription());
2082 jalview.datamodel.DBRefEntry[] dbrefs = null;
2083 if (jds.getDatasetSequence() != null)
2085 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
2089 // seqId==dsseqid so we can tell which sequences really are
2090 // dataset sequences only
2091 vamsasSeq.setDsseqid(id);
2092 dbrefs = jds.getDBRefs();
2093 if (parentseq == null)
2100 for (int d = 0; d < dbrefs.length; d++)
2102 DBRef dbref = new DBRef();
2103 dbref.setSource(dbrefs[d].getSource());
2104 dbref.setVersion(dbrefs[d].getVersion());
2105 dbref.setAccessionId(dbrefs[d].getAccessionId());
2106 if (dbrefs[d].hasMap())
2108 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
2110 dbref.setMapping(mp);
2112 vamsasSeq.addDBRef(dbref);
2118 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
2119 SequenceI parentseq, SequenceI jds, boolean recurse)
2122 if (jmp.getMap() != null)
2126 jalview.util.MapList mlst = jmp.getMap();
2127 List<int[]> r = mlst.getFromRanges();
2128 for (int[] range : r)
2130 MapListFrom mfrom = new MapListFrom();
2131 mfrom.setStart(range[0]);
2132 mfrom.setEnd(range[1]);
2133 mp.addMapListFrom(mfrom);
2135 r = mlst.getToRanges();
2136 for (int[] range : r)
2138 MapListTo mto = new MapListTo();
2139 mto.setStart(range[0]);
2140 mto.setEnd(range[1]);
2141 mp.addMapListTo(mto);
2143 mp.setMapFromUnit(mlst.getFromRatio());
2144 mp.setMapToUnit(mlst.getToRatio());
2145 if (jmp.getTo() != null)
2147 MappingChoice mpc = new MappingChoice();
2149 // check/create ID for the sequence referenced by getTo()
2152 SequenceI ps = null;
2153 if (parentseq != jmp.getTo()
2154 && parentseq.getDatasetSequence() != jmp.getTo())
2156 // chaining dbref rather than a handshaking one
2157 jmpid = seqHash(ps = jmp.getTo());
2161 jmpid = seqHash(ps = parentseq);
2163 mpc.setDseqFor(jmpid);
2164 if (!seqRefIds.containsKey(mpc.getDseqFor()))
2166 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2167 seqRefIds.put(mpc.getDseqFor(), ps);
2171 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2174 mp.setMappingChoice(mpc);
2180 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2181 List<UserColourScheme> userColours, JalviewModelSequence jms)
2184 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2185 boolean newucs = false;
2186 if (!userColours.contains(ucs))
2188 userColours.add(ucs);
2191 id = "ucs" + userColours.indexOf(ucs);
2194 // actually create the scheme's entry in the XML model
2195 java.awt.Color[] colours = ucs.getColours();
2196 jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
2197 jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
2199 for (int i = 0; i < colours.length; i++)
2201 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2202 col.setName(ResidueProperties.aa[i]);
2203 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2204 jbucs.addColour(col);
2206 if (ucs.getLowerCaseColours() != null)
2208 colours = ucs.getLowerCaseColours();
2209 for (int i = 0; i < colours.length; i++)
2211 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2212 col.setName(ResidueProperties.aa[i].toLowerCase());
2213 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2214 jbucs.addColour(col);
2219 uc.setUserColourScheme(jbucs);
2220 jms.addUserColours(uc);
2226 jalview.schemes.UserColourScheme getUserColourScheme(
2227 JalviewModelSequence jms, String id)
2229 UserColours[] uc = jms.getUserColours();
2230 UserColours colours = null;
2232 for (int i = 0; i < uc.length; i++)
2234 if (uc[i].getId().equals(id))
2242 java.awt.Color[] newColours = new java.awt.Color[24];
2244 for (int i = 0; i < 24; i++)
2246 newColours[i] = new java.awt.Color(Integer.parseInt(
2247 colours.getUserColourScheme().getColour(i).getRGB(), 16));
2250 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2253 if (colours.getUserColourScheme().getColourCount() > 24)
2255 newColours = new java.awt.Color[23];
2256 for (int i = 0; i < 23; i++)
2258 newColours[i] = new java.awt.Color(Integer.parseInt(
2259 colours.getUserColourScheme().getColour(i + 24).getRGB(),
2262 ucs.setLowerCaseColours(newColours);
2269 * contains last error message (if any) encountered by XML loader.
2271 String errorMessage = null;
2274 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2275 * exceptions are raised during project XML parsing
2277 public boolean attemptversion1parse = true;
2280 * Load a jalview project archive from a jar file
2283 * - HTTP URL or filename
2285 public AlignFrame loadJalviewAlign(final String file)
2288 jalview.gui.AlignFrame af = null;
2292 // create list to store references for any new Jmol viewers created
2293 newStructureViewers = new Vector<>();
2294 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2295 // Workaround is to make sure caller implements the JarInputStreamProvider
2297 // so we can re-open the jar input stream for each entry.
2299 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2300 af = loadJalviewAlign(jprovider);
2301 af.setMenusForViewport();
2303 } catch (MalformedURLException e)
2305 errorMessage = "Invalid URL format for '" + file + "'";
2311 SwingUtilities.invokeAndWait(new Runnable()
2316 setLoadingFinishedForNewStructureViewers();
2319 } catch (Exception x)
2321 System.err.println("Error loading alignment: " + x.getMessage());
2327 private jarInputStreamProvider createjarInputStreamProvider(
2328 final String file) throws MalformedURLException
2331 errorMessage = null;
2332 uniqueSetSuffix = null;
2334 viewportsAdded.clear();
2335 frefedSequence = null;
2337 if (file.startsWith("http://"))
2339 url = new URL(file);
2341 final URL _url = url;
2342 return new jarInputStreamProvider()
2346 public JarInputStream getJarInputStream() throws IOException
2350 return new JarInputStream(_url.openStream());
2354 return new JarInputStream(new FileInputStream(file));
2359 public String getFilename()
2367 * Recover jalview session from a jalview project archive. Caller may
2368 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2369 * themselves. Any null fields will be initialised with default values,
2370 * non-null fields are left alone.
2375 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2377 errorMessage = null;
2378 if (uniqueSetSuffix == null)
2380 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2382 if (seqRefIds == null)
2386 AlignFrame af = null, _af = null;
2387 IdentityHashMap<AlignmentI, AlignmentI> importedDatasets = new IdentityHashMap<>();
2388 Map<String, AlignFrame> gatherToThisFrame = new HashMap<>();
2389 final String file = jprovider.getFilename();
2392 JarInputStream jin = null;
2393 JarEntry jarentry = null;
2398 jin = jprovider.getJarInputStream();
2399 for (int i = 0; i < entryCount; i++)
2401 jarentry = jin.getNextJarEntry();
2404 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2406 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2407 JalviewModel object = new JalviewModel();
2409 Unmarshaller unmar = new Unmarshaller(object);
2410 unmar.setValidation(false);
2411 object = (JalviewModel) unmar.unmarshal(in);
2412 if (true) // !skipViewport(object))
2414 _af = loadFromObject(object, file, true, jprovider);
2415 if (_af != null && object.getJalviewModelSequence()
2416 .getViewportCount() > 0)
2420 // store a reference to the first view
2423 if (_af.viewport.isGatherViewsHere())
2425 // if this is a gathered view, keep its reference since
2426 // after gathering views, only this frame will remain
2428 gatherToThisFrame.put(_af.viewport.getSequenceSetId(), _af);
2430 // Save dataset to register mappings once all resolved
2431 importedDatasets.put(af.viewport.getAlignment().getDataset(),
2432 af.viewport.getAlignment().getDataset());
2437 else if (jarentry != null)
2439 // Some other file here.
2442 } while (jarentry != null);
2443 resolveFrefedSequences();
2444 } catch (IOException ex)
2446 ex.printStackTrace();
2447 errorMessage = "Couldn't locate Jalview XML file : " + file;
2449 "Exception whilst loading jalview XML file : " + ex + "\n");
2450 } catch (Exception ex)
2452 System.err.println("Parsing as Jalview Version 2 file failed.");
2453 ex.printStackTrace(System.err);
2454 if (attemptversion1parse)
2456 // Is Version 1 Jar file?
2459 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
2460 } catch (Exception ex2)
2462 System.err.println("Exception whilst loading as jalviewXMLV1:");
2463 ex2.printStackTrace();
2467 if (Desktop.instance != null)
2469 Desktop.instance.stopLoading();
2473 System.out.println("Successfully loaded archive file");
2476 ex.printStackTrace();
2479 "Exception whilst loading jalview XML file : " + ex + "\n");
2480 } catch (OutOfMemoryError e)
2482 // Don't use the OOM Window here
2483 errorMessage = "Out of memory loading jalview XML file";
2484 System.err.println("Out of memory whilst loading jalview XML file");
2485 e.printStackTrace();
2489 * Regather multiple views (with the same sequence set id) to the frame (if
2490 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2491 * views instead of separate frames. Note this doesn't restore a state where
2492 * some expanded views in turn have tabbed views - the last "first tab" read
2493 * in will play the role of gatherer for all.
2495 for (AlignFrame fr : gatherToThisFrame.values())
2497 Desktop.instance.gatherViews(fr);
2500 restoreSplitFrames();
2501 for (AlignmentI ds : importedDatasets.keySet())
2503 if (ds.getCodonFrames() != null)
2505 StructureSelectionManager
2506 .getStructureSelectionManager(Desktop.instance)
2507 .registerMappings(ds.getCodonFrames());
2510 if (errorMessage != null)
2515 if (Desktop.instance != null)
2517 Desktop.instance.stopLoading();
2524 * Try to reconstruct and display SplitFrame windows, where each contains
2525 * complementary dna and protein alignments. Done by pairing up AlignFrame
2526 * objects (created earlier) which have complementary viewport ids associated.
2528 protected void restoreSplitFrames()
2530 List<SplitFrame> gatherTo = new ArrayList<>();
2531 List<AlignFrame> addedToSplitFrames = new ArrayList<>();
2532 Map<String, AlignFrame> dna = new HashMap<>();
2535 * Identify the DNA alignments
2537 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2540 AlignFrame af = candidate.getValue();
2541 if (af.getViewport().getAlignment().isNucleotide())
2543 dna.put(candidate.getKey().getId(), af);
2548 * Try to match up the protein complements
2550 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2553 AlignFrame af = candidate.getValue();
2554 if (!af.getViewport().getAlignment().isNucleotide())
2556 String complementId = candidate.getKey().getComplementId();
2557 // only non-null complements should be in the Map
2558 if (complementId != null && dna.containsKey(complementId))
2560 final AlignFrame dnaFrame = dna.get(complementId);
2561 SplitFrame sf = createSplitFrame(dnaFrame, af);
2562 addedToSplitFrames.add(dnaFrame);
2563 addedToSplitFrames.add(af);
2564 dnaFrame.setMenusForViewport();
2565 af.setMenusForViewport();
2566 if (af.viewport.isGatherViewsHere())
2575 * Open any that we failed to pair up (which shouldn't happen!) as
2576 * standalone AlignFrame's.
2578 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2581 AlignFrame af = candidate.getValue();
2582 if (!addedToSplitFrames.contains(af))
2584 Viewport view = candidate.getKey();
2585 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
2587 af.setMenusForViewport();
2588 System.err.println("Failed to restore view " + view.getTitle()
2589 + " to split frame");
2594 * Gather back into tabbed views as flagged.
2596 for (SplitFrame sf : gatherTo)
2598 Desktop.instance.gatherViews(sf);
2601 splitFrameCandidates.clear();
2605 * Construct and display one SplitFrame holding DNA and protein alignments.
2608 * @param proteinFrame
2611 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
2612 AlignFrame proteinFrame)
2614 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
2615 String title = MessageManager.getString("label.linked_view_title");
2616 int width = (int) dnaFrame.getBounds().getWidth();
2617 int height = (int) (dnaFrame.getBounds().getHeight()
2618 + proteinFrame.getBounds().getHeight() + 50);
2621 * SplitFrame location is saved to both enclosed frames
2623 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
2624 Desktop.addInternalFrame(splitFrame, title, width, height);
2627 * And compute cDNA consensus (couldn't do earlier with consensus as
2628 * mappings were not yet present)
2630 proteinFrame.viewport.alignmentChanged(proteinFrame.alignPanel);
2636 * check errorMessage for a valid error message and raise an error box in the
2637 * GUI or write the current errorMessage to stderr and then clear the error
2640 protected void reportErrors()
2642 reportErrors(false);
2645 protected void reportErrors(final boolean saving)
2647 if (errorMessage != null)
2649 final String finalErrorMessage = errorMessage;
2652 javax.swing.SwingUtilities.invokeLater(new Runnable()
2657 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2659 "Error " + (saving ? "saving" : "loading")
2661 JvOptionPane.WARNING_MESSAGE);
2667 System.err.println("Problem loading Jalview file: " + errorMessage);
2670 errorMessage = null;
2673 Map<String, String> alreadyLoadedPDB = new HashMap<>();
2676 * when set, local views will be updated from view stored in JalviewXML
2677 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2678 * sync if this is set to true.
2680 private final boolean updateLocalViews = false;
2683 * Returns the path to a temporary file holding the PDB file for the given PDB
2684 * id. The first time of asking, searches for a file of that name in the
2685 * Jalview project jar, and copies it to a new temporary file. Any repeat
2686 * requests just return the path to the file previously created.
2692 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId,
2695 if (alreadyLoadedPDB.containsKey(pdbId))
2697 return alreadyLoadedPDB.get(pdbId).toString();
2700 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb",
2702 if (tempFile != null)
2704 alreadyLoadedPDB.put(pdbId, tempFile);
2710 * Copies the jar entry of given name to a new temporary file and returns the
2711 * path to the file, or null if the entry is not found.
2714 * @param jarEntryName
2716 * a prefix for the temporary file name, must be at least three
2719 * null or original file - so new file can be given the same suffix
2723 protected String copyJarEntry(jarInputStreamProvider jprovider,
2724 String jarEntryName, String prefix, String origFile)
2726 BufferedReader in = null;
2727 PrintWriter out = null;
2728 String suffix = ".tmp";
2729 if (origFile == null)
2731 origFile = jarEntryName;
2733 int sfpos = origFile.lastIndexOf(".");
2734 if (sfpos > -1 && sfpos < (origFile.length() - 3))
2736 suffix = "." + origFile.substring(sfpos + 1);
2740 JarInputStream jin = jprovider.getJarInputStream();
2742 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2743 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2744 * FileInputStream(jprovider)); }
2747 JarEntry entry = null;
2750 entry = jin.getNextJarEntry();
2751 } while (entry != null && !entry.getName().equals(jarEntryName));
2754 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
2755 File outFile = File.createTempFile(prefix, suffix);
2756 outFile.deleteOnExit();
2757 out = new PrintWriter(new FileOutputStream(outFile));
2760 while ((data = in.readLine()) != null)
2765 String t = outFile.getAbsolutePath();
2770 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
2772 } catch (Exception ex)
2774 ex.printStackTrace();
2782 } catch (IOException e)
2796 private class JvAnnotRow
2798 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2805 * persisted version of annotation row from which to take vis properties
2807 public jalview.datamodel.AlignmentAnnotation template;
2810 * original position of the annotation row in the alignment
2816 * Load alignment frame from jalview XML DOM object
2821 * filename source string
2822 * @param loadTreesAndStructures
2823 * when false only create Viewport
2825 * data source provider
2826 * @return alignment frame created from view stored in DOM
2828 AlignFrame loadFromObject(JalviewModel object, String file,
2829 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
2831 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
2832 Sequence[] vamsasSeq = vamsasSet.getSequence();
2834 JalviewModelSequence jms = object.getJalviewModelSequence();
2836 Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
2839 // ////////////////////////////////
2842 List<SequenceI> hiddenSeqs = null;
2844 List<SequenceI> tmpseqs = new ArrayList<>();
2846 boolean multipleView = false;
2847 SequenceI referenceseqForView = null;
2848 JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
2849 int vi = 0; // counter in vamsasSeq array
2850 for (int i = 0; i < jseqs.length; i++)
2852 String seqId = jseqs[i].getId();
2854 SequenceI tmpSeq = seqRefIds.get(seqId);
2857 if (!incompleteSeqs.containsKey(seqId))
2859 // may not need this check, but keep it for at least 2.9,1 release
2860 if (tmpSeq.getStart() != jseqs[i].getStart()
2861 || tmpSeq.getEnd() != jseqs[i].getEnd())
2864 "Warning JAL-2154 regression: updating start/end for sequence "
2865 + tmpSeq.toString() + " to " + jseqs[i]);
2870 incompleteSeqs.remove(seqId);
2872 if (vamsasSeq.length > vi && vamsasSeq[vi].getId().equals(seqId))
2874 // most likely we are reading a dataset XML document so
2875 // update from vamsasSeq section of XML for this sequence
2876 tmpSeq.setName(vamsasSeq[vi].getName());
2877 tmpSeq.setDescription(vamsasSeq[vi].getDescription());
2878 tmpSeq.setSequence(vamsasSeq[vi].getSequence());
2883 // reading multiple views, so vamsasSeq set is a subset of JSeq
2884 multipleView = true;
2886 tmpSeq.setStart(jseqs[i].getStart());
2887 tmpSeq.setEnd(jseqs[i].getEnd());
2888 tmpseqs.add(tmpSeq);
2892 tmpSeq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
2893 vamsasSeq[vi].getSequence());
2894 tmpSeq.setDescription(vamsasSeq[vi].getDescription());
2895 tmpSeq.setStart(jseqs[i].getStart());
2896 tmpSeq.setEnd(jseqs[i].getEnd());
2897 tmpSeq.setVamsasId(uniqueSetSuffix + seqId);
2898 seqRefIds.put(vamsasSeq[vi].getId(), tmpSeq);
2899 tmpseqs.add(tmpSeq);
2903 if (jseqs[i].hasViewreference() && jseqs[i].getViewreference())
2905 referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
2908 if (jseqs[i].getHidden())
2910 if (hiddenSeqs == null)
2912 hiddenSeqs = new ArrayList<>();
2915 hiddenSeqs.add(tmpSeq);
2920 // Create the alignment object from the sequence set
2921 // ///////////////////////////////
2922 SequenceI[] orderedSeqs = tmpseqs
2923 .toArray(new SequenceI[tmpseqs.size()]);
2925 AlignmentI al = null;
2926 // so we must create or recover the dataset alignment before going further
2927 // ///////////////////////////////
2928 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
2930 // older jalview projects do not have a dataset - so creat alignment and
2932 al = new Alignment(orderedSeqs);
2933 al.setDataset(null);
2937 boolean isdsal = object.getJalviewModelSequence()
2938 .getViewportCount() == 0;
2941 // we are importing a dataset record, so
2942 // recover reference to an alignment already materialsed as dataset
2943 al = getDatasetFor(vamsasSet.getDatasetId());
2947 // materialse the alignment
2948 al = new Alignment(orderedSeqs);
2952 addDatasetRef(vamsasSet.getDatasetId(), al);
2955 // finally, verify all data in vamsasSet is actually present in al
2956 // passing on flag indicating if it is actually a stored dataset
2957 recoverDatasetFor(vamsasSet, al, isdsal);
2960 if (referenceseqForView != null)
2962 al.setSeqrep(referenceseqForView);
2964 // / Add the alignment properties
2965 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
2967 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
2968 al.setProperty(ssp.getKey(), ssp.getValue());
2971 // ///////////////////////////////
2973 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
2976 // load sequence features, database references and any associated PDB
2977 // structures for the alignment
2979 // prior to 2.10, this part would only be executed the first time a
2980 // sequence was encountered, but not afterwards.
2981 // now, for 2.10 projects, this is also done if the xml doc includes
2982 // dataset sequences not actually present in any particular view.
2984 for (int i = 0; i < vamsasSeq.length; i++)
2986 if (jseqs[i].getFeaturesCount() > 0)
2988 Features[] features = jseqs[i].getFeatures();
2989 for (int f = 0; f < features.length; f++)
2991 SequenceFeature sf = new SequenceFeature(features[f].getType(),
2992 features[f].getDescription(), features[f].getBegin(),
2993 features[f].getEnd(), features[f].getScore(),
2994 features[f].getFeatureGroup());
2995 sf.setStatus(features[f].getStatus());
2996 for (int od = 0; od < features[f].getOtherDataCount(); od++)
2998 OtherData keyValue = features[f].getOtherData(od);
2999 if (keyValue.getKey().startsWith("LINK"))
3001 sf.addLink(keyValue.getValue());
3005 sf.setValue(keyValue.getKey(), keyValue.getValue());
3009 // adds feature to datasequence's feature set (since Jalview 2.10)
3010 al.getSequenceAt(i).addSequenceFeature(sf);
3013 if (vamsasSeq[i].getDBRefCount() > 0)
3015 // adds dbrefs to datasequence's set (since Jalview 2.10)
3017 al.getSequenceAt(i).getDatasetSequence() == null
3018 ? al.getSequenceAt(i)
3019 : al.getSequenceAt(i).getDatasetSequence(),
3022 if (jseqs[i].getPdbidsCount() > 0)
3024 Pdbids[] ids = jseqs[i].getPdbids();
3025 for (int p = 0; p < ids.length; p++)
3027 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
3028 entry.setId(ids[p].getId());
3029 if (ids[p].getType() != null)
3031 if (PDBEntry.Type.getType(ids[p].getType()) != null)
3033 entry.setType(PDBEntry.Type.getType(ids[p].getType()));
3037 entry.setType(PDBEntry.Type.FILE);
3040 // jprovider is null when executing 'New View'
3041 if (ids[p].getFile() != null && jprovider != null)
3043 if (!pdbloaded.containsKey(ids[p].getFile()))
3045 entry.setFile(loadPDBFile(jprovider, ids[p].getId(),
3050 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
3053 if (ids[p].getPdbentryItem() != null)
3055 for (PdbentryItem item : ids[p].getPdbentryItem())
3057 for (Property pr : item.getProperty())
3059 entry.setProperty(pr.getName(), pr.getValue());
3063 StructureSelectionManager
3064 .getStructureSelectionManager(Desktop.instance)
3065 .registerPDBEntry(entry);
3066 // adds PDBEntry to datasequence's set (since Jalview 2.10)
3067 if (al.getSequenceAt(i).getDatasetSequence() != null)
3069 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
3073 al.getSequenceAt(i).addPDBId(entry);
3078 } // end !multipleview
3080 // ///////////////////////////////
3081 // LOAD SEQUENCE MAPPINGS
3083 if (vamsasSet.getAlcodonFrameCount() > 0)
3085 // TODO Potentially this should only be done once for all views of an
3087 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
3088 for (int i = 0; i < alc.length; i++)
3090 AlignedCodonFrame cf = new AlignedCodonFrame();
3091 if (alc[i].getAlcodMapCount() > 0)
3093 AlcodMap[] maps = alc[i].getAlcodMap();
3094 for (int m = 0; m < maps.length; m++)
3096 SequenceI dnaseq = seqRefIds.get(maps[m].getDnasq());
3098 jalview.datamodel.Mapping mapping = null;
3099 // attach to dna sequence reference.
3100 if (maps[m].getMapping() != null)
3102 mapping = addMapping(maps[m].getMapping());
3103 if (dnaseq != null && mapping.getTo() != null)
3105 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
3111 newAlcodMapRef(maps[m].getDnasq(), cf, mapping));
3115 al.addCodonFrame(cf);
3120 // ////////////////////////////////
3122 List<JvAnnotRow> autoAlan = new ArrayList<>();
3125 * store any annotations which forward reference a group's ID
3127 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<>();
3129 if (vamsasSet.getAnnotationCount() > 0)
3131 Annotation[] an = vamsasSet.getAnnotation();
3133 for (int i = 0; i < an.length; i++)
3135 Annotation annotation = an[i];
3138 * test if annotation is automatically calculated for this view only
3140 boolean autoForView = false;
3141 if (annotation.getLabel().equals("Quality")
3142 || annotation.getLabel().equals("Conservation")
3143 || annotation.getLabel().equals("Consensus"))
3145 // Kludge for pre 2.5 projects which lacked the autocalculated flag
3147 if (!annotation.hasAutoCalculated())
3149 annotation.setAutoCalculated(true);
3152 if (autoForView || (annotation.hasAutoCalculated()
3153 && annotation.isAutoCalculated()))
3155 // remove ID - we don't recover annotation from other views for
3156 // view-specific annotation
3157 annotation.setId(null);
3160 // set visiblity for other annotation in this view
3161 String annotationId = annotation.getId();
3162 if (annotationId != null && annotationIds.containsKey(annotationId))
3164 AlignmentAnnotation jda = annotationIds.get(annotationId);
3165 // in principle Visible should always be true for annotation displayed
3166 // in multiple views
3167 if (annotation.hasVisible())
3169 jda.visible = annotation.getVisible();
3172 al.addAnnotation(jda);
3176 // Construct new annotation from model.
3177 AnnotationElement[] ae = annotation.getAnnotationElement();
3178 jalview.datamodel.Annotation[] anot = null;
3179 java.awt.Color firstColour = null;
3181 if (!annotation.getScoreOnly())
3183 anot = new jalview.datamodel.Annotation[al.getWidth()];
3184 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
3186 anpos = ae[aa].getPosition();
3188 if (anpos >= anot.length)
3193 anot[anpos] = new jalview.datamodel.Annotation(
3195 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
3196 (ae[aa].getSecondaryStructure() == null
3197 || ae[aa].getSecondaryStructure().length() == 0)
3199 : ae[aa].getSecondaryStructure()
3204 // JBPNote: Consider verifying dataflow for IO of secondary
3205 // structure annotation read from Stockholm files
3206 // this was added to try to ensure that
3207 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
3209 // anot[ae[aa].getPosition()].displayCharacter = "";
3211 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
3212 if (firstColour == null)
3214 firstColour = anot[anpos].colour;
3218 jalview.datamodel.AlignmentAnnotation jaa = null;
3220 if (annotation.getGraph())
3222 float llim = 0, hlim = 0;
3223 // if (autoForView || an[i].isAutoCalculated()) {
3226 jaa = new jalview.datamodel.AlignmentAnnotation(
3227 annotation.getLabel(), annotation.getDescription(), anot,
3228 llim, hlim, annotation.getGraphType());
3230 jaa.graphGroup = annotation.getGraphGroup();
3231 jaa._linecolour = firstColour;
3232 if (annotation.getThresholdLine() != null)
3234 jaa.setThreshold(new jalview.datamodel.GraphLine(
3235 annotation.getThresholdLine().getValue(),
3236 annotation.getThresholdLine().getLabel(),
3238 annotation.getThresholdLine().getColour())));
3241 if (autoForView || annotation.isAutoCalculated())
3243 // Hardwire the symbol display line to ensure that labels for
3244 // histograms are displayed
3250 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
3251 an[i].getDescription(), anot);
3252 jaa._linecolour = firstColour;
3254 // register new annotation
3255 if (an[i].getId() != null)
3257 annotationIds.put(an[i].getId(), jaa);
3258 jaa.annotationId = an[i].getId();
3260 // recover sequence association
3261 String sequenceRef = an[i].getSequenceRef();
3262 if (sequenceRef != null)
3264 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3265 SequenceI sequence = seqRefIds.get(sequenceRef);
3266 if (sequence == null)
3268 // in pre-2.9 projects sequence ref is to sequence name
3269 sequence = al.findName(sequenceRef);
3271 if (sequence != null)
3273 jaa.createSequenceMapping(sequence, 1, true);
3274 sequence.addAlignmentAnnotation(jaa);
3277 // and make a note of any group association
3278 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
3280 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3281 .get(an[i].getGroupRef());
3284 aal = new ArrayList<>();
3285 groupAnnotRefs.put(an[i].getGroupRef(), aal);
3290 if (an[i].hasScore())
3292 jaa.setScore(an[i].getScore());
3294 if (an[i].hasVisible())
3296 jaa.visible = an[i].getVisible();
3299 if (an[i].hasCentreColLabels())
3301 jaa.centreColLabels = an[i].getCentreColLabels();
3304 if (an[i].hasScaleColLabels())
3306 jaa.scaleColLabel = an[i].getScaleColLabels();
3308 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
3310 // newer files have an 'autoCalculated' flag and store calculation
3311 // state in viewport properties
3312 jaa.autoCalculated = true; // means annotation will be marked for
3313 // update at end of load.
3315 if (an[i].hasGraphHeight())
3317 jaa.graphHeight = an[i].getGraphHeight();
3319 if (an[i].hasBelowAlignment())
3321 jaa.belowAlignment = an[i].isBelowAlignment();
3323 jaa.setCalcId(an[i].getCalcId());
3324 if (an[i].getPropertyCount() > 0)
3326 for (jalview.schemabinding.version2.Property prop : an[i]
3329 jaa.setProperty(prop.getName(), prop.getValue());
3332 if (jaa.autoCalculated)
3334 autoAlan.add(new JvAnnotRow(i, jaa));
3337 // if (!autoForView)
3339 // add autocalculated group annotation and any user created annotation
3341 al.addAnnotation(jaa);
3345 // ///////////////////////
3347 // Create alignment markup and styles for this view
3348 if (jms.getJGroupCount() > 0)
3350 JGroup[] groups = jms.getJGroup();
3351 boolean addAnnotSchemeGroup = false;
3352 for (int i = 0; i < groups.length; i++)
3354 JGroup jGroup = groups[i];
3355 ColourSchemeI cs = null;
3356 if (jGroup.getColour() != null)
3358 if (jGroup.getColour().startsWith("ucs"))
3360 cs = getUserColourScheme(jms, jGroup.getColour());
3362 else if (jGroup.getColour().equals("AnnotationColourGradient")
3363 && jGroup.getAnnotationColours() != null)
3365 addAnnotSchemeGroup = true;
3369 cs = ColourSchemeProperty.getColourScheme(al,
3370 jGroup.getColour());
3373 int pidThreshold = jGroup.getPidThreshold();
3375 Vector<SequenceI> seqs = new Vector<>();
3377 for (int s = 0; s < jGroup.getSeqCount(); s++)
3379 String seqId = jGroup.getSeq(s) + "";
3380 SequenceI ts = seqRefIds.get(seqId);
3384 seqs.addElement(ts);
3388 if (seqs.size() < 1)
3393 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3394 jGroup.getDisplayBoxes(), jGroup.getDisplayText(),
3395 jGroup.getColourText(), jGroup.getStart(), jGroup.getEnd());
3396 sg.getGroupColourScheme().setThreshold(pidThreshold, true);
3397 sg.getGroupColourScheme()
3398 .setConservationInc(jGroup.getConsThreshold());
3399 sg.setOutlineColour(new java.awt.Color(jGroup.getOutlineColour()));
3401 sg.textColour = new java.awt.Color(jGroup.getTextCol1());
3402 sg.textColour2 = new java.awt.Color(jGroup.getTextCol2());
3403 sg.setShowNonconserved(
3404 jGroup.hasShowUnconserved() ? jGroup.isShowUnconserved()
3406 sg.thresholdTextColour = jGroup.getTextColThreshold();
3407 if (jGroup.hasShowConsensusHistogram())
3409 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3412 if (jGroup.hasShowSequenceLogo())
3414 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3416 if (jGroup.hasNormaliseSequenceLogo())
3418 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3420 if (jGroup.hasIgnoreGapsinConsensus())
3422 sg.setIgnoreGapsConsensus(jGroup.getIgnoreGapsinConsensus());
3424 if (jGroup.getConsThreshold() != 0)
3426 Conservation c = new Conservation("All", sg.getSequences(null), 0,
3429 c.verdict(false, 25);
3430 sg.cs.setConservation(c);
3433 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3435 // re-instate unique group/annotation row reference
3436 List<AlignmentAnnotation> jaal = groupAnnotRefs
3437 .get(jGroup.getId());
3440 for (AlignmentAnnotation jaa : jaal)
3443 if (jaa.autoCalculated)
3445 // match up and try to set group autocalc alignment row for this
3447 if (jaa.label.startsWith("Consensus for "))
3449 sg.setConsensus(jaa);
3451 // match up and try to set group autocalc alignment row for this
3453 if (jaa.label.startsWith("Conservation for "))
3455 sg.setConservationRow(jaa);
3462 if (addAnnotSchemeGroup)
3464 // reconstruct the annotation colourscheme
3465 sg.setColourScheme(constructAnnotationColour(
3466 jGroup.getAnnotationColours(), null, al, jms, false));
3472 // only dataset in this model, so just return.
3475 // ///////////////////////////////
3478 // If we just load in the same jar file again, the sequenceSetId
3479 // will be the same, and we end up with multiple references
3480 // to the same sequenceSet. We must modify this id on load
3481 // so that each load of the file gives a unique id
3482 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3483 String viewId = (view.getId() == null ? null
3484 : view.getId() + uniqueSetSuffix);
3485 AlignFrame af = null;
3486 AlignViewport av = null;
3487 // now check to see if we really need to create a new viewport.
3488 if (multipleView && viewportsAdded.size() == 0)
3490 // We recovered an alignment for which a viewport already exists.
3491 // TODO: fix up any settings necessary for overlaying stored state onto
3492 // state recovered from another document. (may not be necessary).
3493 // we may need a binding from a viewport in memory to one recovered from
3495 // and then recover its containing af to allow the settings to be applied.
3496 // TODO: fix for vamsas demo
3498 "About to recover a viewport for existing alignment: Sequence set ID is "
3500 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3501 if (seqsetobj != null)
3503 if (seqsetobj instanceof String)
3505 uniqueSeqSetId = (String) seqsetobj;
3507 "Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
3513 "Warning : Collision between sequence set ID string and existing jalview object mapping.");
3519 * indicate that annotation colours are applied across all groups (pre
3520 * Jalview 2.8.1 behaviour)
3522 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan("2.8.1",
3523 object.getVersion());
3525 AlignmentPanel ap = null;
3526 boolean isnewview = true;
3529 // Check to see if this alignment already has a view id == viewId
3530 jalview.gui.AlignmentPanel views[] = Desktop
3531 .getAlignmentPanels(uniqueSeqSetId);
3532 if (views != null && views.length > 0)
3534 for (int v = 0; v < views.length; v++)
3536 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
3538 // recover the existing alignpanel, alignframe, viewport
3539 af = views[v].alignFrame;
3542 // TODO: could even skip resetting view settings if we don't want to
3543 // change the local settings from other jalview processes
3552 af = loadViewport(file, jseqs, hiddenSeqs, al, jms, view,
3553 uniqueSeqSetId, viewId, autoAlan);
3559 * Load any trees, PDB structures and viewers
3561 * Not done if flag is false (when this method is used for New View)
3563 if (loadTreesAndStructures)
3565 loadTrees(jms, view, af, av, ap);
3566 loadExternalTrees(jprovider, jms, av);
3567 loadPDBStructures(jprovider, jseqs, af, ap);
3568 loadRnaViewers(jprovider, jseqs, ap);
3570 // and finally return.
3574 private void loadExternalTrees(jarInputStreamProvider jprovider,
3575 JalviewModelSequence jms, AlignViewport av)
3577 for (TreeFrameI externalTreeViewer: jms.getExtTreeViewer()) {
3578 // String treeFile = copyJarEntry(jprovider, errorMessage, "aptx", null);
3579 TreeViewerUtils.addTreeViewFrameToJalview(externalTreeViewer);
3588 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
3589 * panel is restored from separate jar entries, two (gapped and trimmed) per
3590 * sequence and secondary structure.
3592 * Currently each viewer shows just one sequence and structure (gapped and
3593 * trimmed), however this method is designed to support multiple sequences or
3594 * structures in viewers if wanted in future.
3600 private void loadRnaViewers(jarInputStreamProvider jprovider,
3601 JSeq[] jseqs, AlignmentPanel ap)
3604 * scan the sequences for references to viewers; create each one the first
3605 * time it is referenced, add Rna models to existing viewers
3607 for (JSeq jseq : jseqs)
3609 for (int i = 0; i < jseq.getRnaViewerCount(); i++)
3611 RnaViewer viewer = jseq.getRnaViewer(i);
3612 AppVarna appVarna = findOrCreateVarnaViewer(viewer, uniqueSetSuffix,
3615 for (int j = 0; j < viewer.getSecondaryStructureCount(); j++)
3617 SecondaryStructure ss = viewer.getSecondaryStructure(j);
3618 SequenceI seq = seqRefIds.get(jseq.getId());
3619 AlignmentAnnotation ann = this.annotationIds
3620 .get(ss.getAnnotationId());
3623 * add the structure to the Varna display (with session state copied
3624 * from the jar to a temporary file)
3626 boolean gapped = ss.isGapped();
3627 String rnaTitle = ss.getTitle();
3628 String sessionState = ss.getViewerState();
3629 String tempStateFile = copyJarEntry(jprovider, sessionState,
3631 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
3632 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
3634 appVarna.setInitialSelection(viewer.getSelectedRna());
3640 * Locate and return an already instantiated matching AppVarna, or create one
3644 * @param viewIdSuffix
3648 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
3649 String viewIdSuffix, AlignmentPanel ap)
3652 * on each load a suffix is appended to the saved viewId, to avoid conflicts
3653 * if load is repeated
3655 String postLoadId = viewer.getViewId() + viewIdSuffix;
3656 for (JInternalFrame frame : getAllFrames())
3658 if (frame instanceof AppVarna)
3660 AppVarna varna = (AppVarna) frame;
3661 if (postLoadId.equals(varna.getViewId()))
3663 // this viewer is already instantiated
3664 // could in future here add ap as another 'parent' of the
3665 // AppVarna window; currently just 1-to-many
3672 * viewer not found - make it
3674 RnaViewerModel model = new RnaViewerModel(postLoadId, viewer.getTitle(),
3675 viewer.getXpos(), viewer.getYpos(), viewer.getWidth(),
3676 viewer.getHeight(), viewer.getDividerLocation());
3677 AppVarna varna = new AppVarna(model, ap);
3683 * Load any saved trees
3691 protected void loadTrees(JalviewModelSequence jms, Viewport view,
3692 AlignFrame af, AlignViewport av, AlignmentPanel ap)
3694 // TODO result of automated refactoring - are all these parameters needed?
3697 for (int t = 0; t < jms.getTreeCount(); t++)
3700 Tree tree = jms.getTree(t);
3701 NewickFile newick = new jalview.io.NewickFile(tree.getNewick());
3703 TreeFrameI externalViewer = AptxInit.createInstanceFromNhx(
3704 tree.getTitle(), tree.getNewick(),
3708 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
3713 tp = af.showNewickTree(
3715 tree.getTitle(), tree.getWidth(), tree.getHeight(),
3716 tree.getXpos(), tree.getYpos());
3717 if (tree.getId() != null)
3719 // perhaps bind the tree id to something ?
3724 // update local tree attributes ?
3725 // TODO: should check if tp has been manipulated by user - if so its
3726 // settings shouldn't be modified
3727 tp.setTitle(tree.getTitle());
3728 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(),
3729 tree.getWidth(), tree.getHeight()));
3730 tp.av = av; // af.viewport; // TODO: verify 'associate with all
3733 tp.treeCanvas.av = av; // af.viewport;
3734 tp.treeCanvas.ap = ap; // af.alignPanel;
3739 warn("There was a problem recovering stored Newick tree: \n"
3740 + tree.getNewick());
3744 tp.fitToWindow.setState(tree.getFitToWindow());
3745 tp.fitToWindow_actionPerformed(null);
3747 if (tree.getFontName() != null)
3749 tp.setTreeFont(new java.awt.Font(tree.getFontName(),
3750 tree.getFontStyle(), tree.getFontSize()));
3754 tp.setTreeFont(new java.awt.Font(view.getFontName(),
3755 view.getFontStyle(), tree.getFontSize()));
3758 tp.showPlaceholders(tree.getMarkUnlinked());
3759 tp.showBootstrap(tree.getShowBootstrap());
3760 tp.showDistances(tree.getShowDistances());
3762 tp.treeCanvas.threshold = tree.getThreshold();
3764 if (tree.getCurrentTree())
3766 af.viewport.setCurrentTree(tp.getTree());
3770 } catch (Exception ex)
3772 ex.printStackTrace();
3777 * Load and link any saved structure viewers.
3784 protected void loadPDBStructures(jarInputStreamProvider jprovider,
3785 JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
3788 * Run through all PDB ids on the alignment, and collect mappings between
3789 * distinct view ids and all sequences referring to that view.
3791 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<>();
3793 for (int i = 0; i < jseqs.length; i++)
3795 if (jseqs[i].getPdbidsCount() > 0)
3797 Pdbids[] ids = jseqs[i].getPdbids();
3798 for (int p = 0; p < ids.length; p++)
3800 final int structureStateCount = ids[p].getStructureStateCount();
3801 for (int s = 0; s < structureStateCount; s++)
3803 // check to see if we haven't already created this structure view
3804 final StructureState structureState = ids[p]
3805 .getStructureState(s);
3806 String sviewid = (structureState.getViewId() == null) ? null
3807 : structureState.getViewId() + uniqueSetSuffix;
3808 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
3809 // Originally : ids[p].getFile()
3810 // : TODO: verify external PDB file recovery still works in normal
3811 // jalview project load
3812 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId(),
3814 jpdb.setId(ids[p].getId());
3816 int x = structureState.getXpos();
3817 int y = structureState.getYpos();
3818 int width = structureState.getWidth();
3819 int height = structureState.getHeight();
3821 // Probably don't need to do this anymore...
3822 // Desktop.desktop.getComponentAt(x, y);
3823 // TODO: NOW: check that this recovers the PDB file correctly.
3824 String pdbFile = loadPDBFile(jprovider, ids[p].getId(),
3826 jalview.datamodel.SequenceI seq = seqRefIds
3827 .get(jseqs[i].getId() + "");
3828 if (sviewid == null)
3830 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width + ","
3833 if (!structureViewers.containsKey(sviewid))
3835 structureViewers.put(sviewid,
3836 new StructureViewerModel(x, y, width, height, false,
3837 false, true, structureState.getViewId(),
3838 structureState.getType()));
3839 // Legacy pre-2.7 conversion JAL-823 :
3840 // do not assume any view has to be linked for colour by
3844 // assemble String[] { pdb files }, String[] { id for each
3845 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3846 // seqs_file 2}, boolean[] {
3847 // linkAlignPanel,superposeWithAlignpanel}} from hash
3848 StructureViewerModel jmoldat = structureViewers.get(sviewid);
3849 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
3850 | (structureState.hasAlignwithAlignPanel()
3851 ? structureState.getAlignwithAlignPanel()
3855 * Default colour by linked panel to false if not specified (e.g.
3856 * for pre-2.7 projects)
3858 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
3859 colourWithAlignPanel |= (structureState
3860 .hasColourwithAlignPanel()
3861 ? structureState.getColourwithAlignPanel()
3863 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
3866 * Default colour by viewer to true if not specified (e.g. for
3869 boolean colourByViewer = jmoldat.isColourByViewer();
3870 colourByViewer &= structureState.hasColourByJmol()
3871 ? structureState.getColourByJmol()
3873 jmoldat.setColourByViewer(colourByViewer);
3875 if (jmoldat.getStateData().length() < structureState
3876 .getContent().length())
3879 jmoldat.setStateData(structureState.getContent());
3882 if (ids[p].getFile() != null)
3884 File mapkey = new File(ids[p].getFile());
3885 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
3886 if (seqstrmaps == null)
3888 jmoldat.getFileData().put(mapkey,
3889 seqstrmaps = jmoldat.new StructureData(pdbFile,
3892 if (!seqstrmaps.getSeqList().contains(seq))
3894 seqstrmaps.getSeqList().add(seq);
3900 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");
3907 // Instantiate the associated structure views
3908 for (Entry<String, StructureViewerModel> entry : structureViewers
3913 createOrLinkStructureViewer(entry, af, ap, jprovider);
3914 } catch (Exception e)
3917 "Error loading structure viewer: " + e.getMessage());
3918 // failed - try the next one
3930 protected void createOrLinkStructureViewer(
3931 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3932 AlignmentPanel ap, jarInputStreamProvider jprovider)
3934 final StructureViewerModel stateData = viewerData.getValue();
3937 * Search for any viewer windows already open from other alignment views
3938 * that exactly match the stored structure state
3940 StructureViewerBase comp = findMatchingViewer(viewerData);
3944 linkStructureViewer(ap, comp, stateData);
3949 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
3950 * "viewer_"+stateData.viewId
3952 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
3954 createChimeraViewer(viewerData, af, jprovider);
3959 * else Jmol (if pre-2.9, stateData contains JMOL state string)
3961 createJmolViewer(viewerData, af, jprovider);
3966 * Create a new Chimera viewer.
3972 protected void createChimeraViewer(
3973 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3974 jarInputStreamProvider jprovider)
3976 StructureViewerModel data = viewerData.getValue();
3977 String chimeraSessionFile = data.getStateData();
3980 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
3982 * NB this is the 'saved' viewId as in the project file XML, _not_ the
3983 * 'uniquified' sviewid used to reconstruct the viewer here
3985 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
3986 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
3989 Set<Entry<File, StructureData>> fileData = data.getFileData()
3991 List<PDBEntry> pdbs = new ArrayList<>();
3992 List<SequenceI[]> allseqs = new ArrayList<>();
3993 for (Entry<File, StructureData> pdb : fileData)
3995 String filePath = pdb.getValue().getFilePath();
3996 String pdbId = pdb.getValue().getPdbId();
3997 // pdbs.add(new PDBEntry(filePath, pdbId));
3998 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
3999 final List<SequenceI> seqList = pdb.getValue().getSeqList();
4000 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
4004 boolean colourByChimera = data.isColourByViewer();
4005 boolean colourBySequence = data.isColourWithAlignPanel();
4007 // TODO use StructureViewer as a factory here, see JAL-1761
4008 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
4009 final SequenceI[][] seqsArray = allseqs
4010 .toArray(new SequenceI[allseqs.size()][]);
4011 String newViewId = viewerData.getKey();
4013 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
4014 af.alignPanel, pdbArray, seqsArray, colourByChimera,
4015 colourBySequence, newViewId);
4016 cvf.setSize(data.getWidth(), data.getHeight());
4017 cvf.setLocation(data.getX(), data.getY());
4021 * Create a new Jmol window. First parse the Jmol state to translate filenames
4022 * loaded into the view, and record the order in which files are shown in the
4023 * Jmol view, so we can add the sequence mappings in same order.
4029 protected void createJmolViewer(
4030 final Entry<String, StructureViewerModel> viewerData,
4031 AlignFrame af, jarInputStreamProvider jprovider)
4033 final StructureViewerModel svattrib = viewerData.getValue();
4034 String state = svattrib.getStateData();
4037 * Pre-2.9: state element value is the Jmol state string
4039 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
4042 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
4044 state = readJarEntry(jprovider,
4045 getViewerJarEntryName(svattrib.getViewId()));
4048 List<String> pdbfilenames = new ArrayList<>();
4049 List<SequenceI[]> seqmaps = new ArrayList<>();
4050 List<String> pdbids = new ArrayList<>();
4051 StringBuilder newFileLoc = new StringBuilder(64);
4052 int cp = 0, ncp, ecp;
4053 Map<File, StructureData> oldFiles = svattrib.getFileData();
4054 while ((ncp = state.indexOf("load ", cp)) > -1)
4058 // look for next filename in load statement
4059 newFileLoc.append(state.substring(cp,
4060 ncp = (state.indexOf("\"", ncp + 1) + 1)));
4061 String oldfilenam = state.substring(ncp,
4062 ecp = state.indexOf("\"", ncp));
4063 // recover the new mapping data for this old filename
4064 // have to normalize filename - since Jmol and jalview do
4066 // translation differently.
4067 StructureData filedat = oldFiles.get(new File(oldfilenam));
4068 if (filedat == null)
4070 String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\");
4071 filedat = oldFiles.get(new File(reformatedOldFilename));
4073 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
4074 pdbfilenames.add(filedat.getFilePath());
4075 pdbids.add(filedat.getPdbId());
4076 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4077 newFileLoc.append("\"");
4078 cp = ecp + 1; // advance beyond last \" and set cursor so we can
4079 // look for next file statement.
4080 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
4084 // just append rest of state
4085 newFileLoc.append(state.substring(cp));
4089 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
4090 newFileLoc = new StringBuilder(state);
4091 newFileLoc.append("; load append ");
4092 for (File id : oldFiles.keySet())
4094 // add this and any other pdb files that should be present in
4096 StructureData filedat = oldFiles.get(id);
4097 newFileLoc.append(filedat.getFilePath());
4098 pdbfilenames.add(filedat.getFilePath());
4099 pdbids.add(filedat.getPdbId());
4100 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4101 newFileLoc.append(" \"");
4102 newFileLoc.append(filedat.getFilePath());
4103 newFileLoc.append("\"");
4106 newFileLoc.append(";");
4109 if (newFileLoc.length() == 0)
4113 int histbug = newFileLoc.indexOf("history = ");
4117 * change "history = [true|false];" to "history = [1|0];"
4120 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
4121 String val = (diff == -1) ? null
4122 : newFileLoc.substring(histbug, diff);
4123 if (val != null && val.length() >= 4)
4125 if (val.contains("e")) // eh? what can it be?
4127 if (val.trim().equals("true"))
4135 newFileLoc.replace(histbug, diff, val);
4140 final String[] pdbf = pdbfilenames
4141 .toArray(new String[pdbfilenames.size()]);
4142 final String[] id = pdbids.toArray(new String[pdbids.size()]);
4143 final SequenceI[][] sq = seqmaps
4144 .toArray(new SequenceI[seqmaps.size()][]);
4145 final String fileloc = newFileLoc.toString();
4146 final String sviewid = viewerData.getKey();
4147 final AlignFrame alf = af;
4148 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
4149 svattrib.getWidth(), svattrib.getHeight());
4152 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
4157 JalviewStructureDisplayI sview = null;
4160 sview = new StructureViewer(
4161 alf.alignPanel.getStructureSelectionManager())
4162 .createView(StructureViewer.ViewerType.JMOL,
4163 pdbf, id, sq, alf.alignPanel, svattrib,
4164 fileloc, rect, sviewid);
4165 addNewStructureViewer(sview);
4166 } catch (OutOfMemoryError ex)
4168 new OOMWarning("restoring structure view for PDB id " + id,
4169 (OutOfMemoryError) ex.getCause());
4170 if (sview != null && sview.isVisible())
4172 sview.closeViewer(false);
4173 sview.setVisible(false);
4179 } catch (InvocationTargetException ex)
4181 warn("Unexpected error when opening Jmol view.", ex);
4183 } catch (InterruptedException e)
4185 // e.printStackTrace();
4191 * Generates a name for the entry in the project jar file to hold state
4192 * information for a structure viewer
4197 protected String getViewerJarEntryName(String viewId)
4199 return VIEWER_PREFIX + viewId;
4203 * Returns any open frame that matches given structure viewer data. The match
4204 * is based on the unique viewId, or (for older project versions) the frame's
4210 protected StructureViewerBase findMatchingViewer(
4211 Entry<String, StructureViewerModel> viewerData)
4213 final String sviewid = viewerData.getKey();
4214 final StructureViewerModel svattrib = viewerData.getValue();
4215 StructureViewerBase comp = null;
4216 JInternalFrame[] frames = getAllFrames();
4217 for (JInternalFrame frame : frames)
4219 if (frame instanceof StructureViewerBase)
4222 * Post jalview 2.4 schema includes structure view id
4224 if (sviewid != null && ((StructureViewerBase) frame).getViewId()
4227 comp = (StructureViewerBase) frame;
4228 break; // break added in 2.9
4231 * Otherwise test for matching position and size of viewer frame
4233 else if (frame.getX() == svattrib.getX()
4234 && frame.getY() == svattrib.getY()
4235 && frame.getHeight() == svattrib.getHeight()
4236 && frame.getWidth() == svattrib.getWidth())
4238 comp = (StructureViewerBase) frame;
4239 // no break in faint hope of an exact match on viewId
4247 * Link an AlignmentPanel to an existing structure viewer.
4252 * @param useinViewerSuperpos
4253 * @param usetoColourbyseq
4254 * @param viewerColouring
4256 protected void linkStructureViewer(AlignmentPanel ap,
4257 StructureViewerBase viewer, StructureViewerModel stateData)
4259 // NOTE: if the jalview project is part of a shared session then
4260 // view synchronization should/could be done here.
4262 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4263 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4264 final boolean viewerColouring = stateData.isColourByViewer();
4265 Map<File, StructureData> oldFiles = stateData.getFileData();
4268 * Add mapping for sequences in this view to an already open viewer
4270 final AAStructureBindingModel binding = viewer.getBinding();
4271 for (File id : oldFiles.keySet())
4273 // add this and any other pdb files that should be present in the
4275 StructureData filedat = oldFiles.get(id);
4276 String pdbFile = filedat.getFilePath();
4277 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4278 binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE,
4280 binding.addSequenceForStructFile(pdbFile, seq);
4282 // and add the AlignmentPanel's reference to the view panel
4283 viewer.addAlignmentPanel(ap);
4284 if (useinViewerSuperpos)
4286 viewer.useAlignmentPanelForSuperposition(ap);
4290 viewer.excludeAlignmentPanelForSuperposition(ap);
4292 if (usetoColourbyseq)
4294 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4298 viewer.excludeAlignmentPanelForColourbyseq(ap);
4303 * Get all frames within the Desktop.
4307 protected JInternalFrame[] getAllFrames()
4309 JInternalFrame[] frames = null;
4310 // TODO is this necessary - is it safe - risk of hanging?
4315 frames = Desktop.desktop.getAllFrames();
4316 } catch (ArrayIndexOutOfBoundsException e)
4318 // occasional No such child exceptions are thrown here...
4322 } catch (InterruptedException f)
4326 } while (frames == null);
4331 * Answers true if 'version' is equal to or later than 'supported', where each
4332 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4333 * changes. Development and test values for 'version' are leniently treated
4337 * - minimum version we are comparing against
4339 * - version of data being processsed
4342 public static boolean isVersionStringLaterThan(String supported,
4345 if (supported == null || version == null
4346 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4347 || version.equalsIgnoreCase("Test")
4348 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4350 System.err.println("Assuming project file with "
4351 + (version == null ? "null" : version)
4352 + " is compatible with Jalview version " + supported);
4357 return StringUtils.compareVersions(version, supported, "b") >= 0;
4361 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4363 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4365 if (newStructureViewers != null)
4367 sview.getBinding().setFinishedLoadingFromArchive(false);
4368 newStructureViewers.add(sview);
4372 protected void setLoadingFinishedForNewStructureViewers()
4374 if (newStructureViewers != null)
4376 for (JalviewStructureDisplayI sview : newStructureViewers)
4378 sview.getBinding().setFinishedLoadingFromArchive(true);
4380 newStructureViewers.clear();
4381 newStructureViewers = null;
4385 AlignFrame loadViewport(String file, JSeq[] JSEQ,
4386 List<SequenceI> hiddenSeqs, AlignmentI al,
4387 JalviewModelSequence jms, Viewport view, String uniqueSeqSetId,
4388 String viewId, List<JvAnnotRow> autoAlan)
4390 AlignFrame af = null;
4391 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
4392 uniqueSeqSetId, viewId);
4394 af.setFileName(file, FileFormat.Jalview);
4396 for (int i = 0; i < JSEQ.length; i++)
4398 af.viewport.setSequenceColour(
4399 af.viewport.getAlignment().getSequenceAt(i),
4400 new java.awt.Color(JSEQ[i].getColour()));
4405 af.getViewport().setColourByReferenceSeq(true);
4406 af.getViewport().setDisplayReferenceSeq(true);
4409 af.viewport.setGatherViewsHere(view.getGatheredViews());
4411 if (view.getSequenceSetId() != null)
4413 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4415 af.viewport.setSequenceSetId(uniqueSeqSetId);
4418 // propagate shared settings to this new view
4419 af.viewport.setHistoryList(av.getHistoryList());
4420 af.viewport.setRedoList(av.getRedoList());
4424 viewportsAdded.put(uniqueSeqSetId, af.viewport);
4426 // TODO: check if this method can be called repeatedly without
4427 // side-effects if alignpanel already registered.
4428 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4430 // apply Hidden regions to view.
4431 if (hiddenSeqs != null)
4433 for (int s = 0; s < JSEQ.length; s++)
4435 SequenceGroup hidden = new SequenceGroup();
4436 boolean isRepresentative = false;
4437 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
4439 isRepresentative = true;
4440 SequenceI sequenceToHide = al
4441 .getSequenceAt(JSEQ[s].getHiddenSequences(r));
4442 hidden.addSequence(sequenceToHide, false);
4443 // remove from hiddenSeqs list so we don't try to hide it twice
4444 hiddenSeqs.remove(sequenceToHide);
4446 if (isRepresentative)
4448 SequenceI representativeSequence = al.getSequenceAt(s);
4449 hidden.addSequence(representativeSequence, false);
4450 af.viewport.hideRepSequences(representativeSequence, hidden);
4454 SequenceI[] hseqs = hiddenSeqs
4455 .toArray(new SequenceI[hiddenSeqs.size()]);
4456 af.viewport.hideSequence(hseqs);
4459 // recover view properties and display parameters
4461 af.viewport.setShowAnnotation(view.getShowAnnotation());
4462 af.viewport.setAbovePIDThreshold(view.getPidSelected());
4463 af.viewport.setThreshold(view.getPidThreshold());
4465 af.viewport.setColourText(view.getShowColourText());
4467 af.viewport.setConservationSelected(view.getConservationSelected());
4468 af.viewport.setIncrement(view.getConsThreshold());
4469 af.viewport.setShowJVSuffix(view.getShowFullId());
4470 af.viewport.setRightAlignIds(view.getRightAlignIds());
4471 af.viewport.setFont(new java.awt.Font(view.getFontName(),
4472 view.getFontStyle(), view.getFontSize()), true);
4473 ViewStyleI vs = af.viewport.getViewStyle();
4474 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
4475 af.viewport.setViewStyle(vs);
4476 // TODO: allow custom charWidth/Heights to be restored by updating them
4477 // after setting font - which means set above to false
4478 af.viewport.setRenderGaps(view.getRenderGaps());
4479 af.viewport.setWrapAlignment(view.getWrapAlignment());
4480 af.viewport.setShowAnnotation(view.getShowAnnotation());
4482 af.viewport.setShowBoxes(view.getShowBoxes());
4484 af.viewport.setShowText(view.getShowText());
4486 af.viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
4487 af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
4488 af.viewport.setThresholdTextColour(view.getTextColThreshold());
4489 af.viewport.setShowUnconserved(
4490 view.hasShowUnconserved() ? view.isShowUnconserved() : false);
4491 af.viewport.getRanges().setStartRes(view.getStartRes());
4493 if (view.getViewName() != null)
4495 af.viewport.viewName = view.getViewName();
4496 af.setInitialTabVisible();
4498 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
4500 // startSeq set in af.alignPanel.updateLayout below
4501 af.alignPanel.updateLayout();
4502 ColourSchemeI cs = null;
4503 // apply colourschemes
4504 if (view.getBgColour() != null)
4506 if (view.getBgColour().startsWith("ucs"))
4508 cs = getUserColourScheme(jms, view.getBgColour());
4510 else if (view.getBgColour().startsWith("Annotation"))
4512 AnnotationColours viewAnnColour = view.getAnnotationColours();
4513 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
4520 cs = ColourSchemeProperty.getColourScheme(al, view.getBgColour());
4524 af.viewport.setGlobalColourScheme(cs);
4525 af.viewport.getResidueShading().setThreshold(view.getPidThreshold(),
4526 view.getIgnoreGapsinConsensus());
4527 af.viewport.getResidueShading()
4528 .setConsensus(af.viewport.getSequenceConsensusHash());
4529 af.viewport.setColourAppliesToAllGroups(false);
4531 if (view.getConservationSelected() && cs != null)
4533 af.viewport.getResidueShading()
4534 .setConservationInc(view.getConsThreshold());
4537 af.changeColour(cs);
4539 af.viewport.setColourAppliesToAllGroups(true);
4541 af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures());
4543 if (view.hasCentreColumnLabels())
4545 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
4547 if (view.hasIgnoreGapsinConsensus())
4549 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
4552 if (view.hasFollowHighlight())
4554 af.viewport.setFollowHighlight(view.getFollowHighlight());
4556 if (view.hasFollowSelection())
4558 af.viewport.followSelection = view.getFollowSelection();
4560 if (view.hasShowConsensusHistogram())
4563 .setShowConsensusHistogram(view.getShowConsensusHistogram());
4567 af.viewport.setShowConsensusHistogram(true);
4569 if (view.hasShowSequenceLogo())
4571 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
4575 af.viewport.setShowSequenceLogo(false);
4577 if (view.hasNormaliseSequenceLogo())
4579 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
4581 if (view.hasShowDbRefTooltip())
4583 af.viewport.setShowDBRefs(view.getShowDbRefTooltip());
4585 if (view.hasShowNPfeatureTooltip())
4587 af.viewport.setShowNPFeats(view.hasShowNPfeatureTooltip());
4589 if (view.hasShowGroupConsensus())
4591 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
4595 af.viewport.setShowGroupConsensus(false);
4597 if (view.hasShowGroupConservation())
4599 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
4603 af.viewport.setShowGroupConservation(false);
4606 // recover featre settings
4607 if (jms.getFeatureSettings() != null)
4609 FeaturesDisplayed fdi;
4610 af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
4611 String[] renderOrder = new String[jms.getFeatureSettings()
4612 .getSettingCount()];
4613 Map<String, FeatureColourI> featureColours = new Hashtable<>();
4614 Map<String, Float> featureOrder = new Hashtable<>();
4616 for (int fs = 0; fs < jms.getFeatureSettings()
4617 .getSettingCount(); fs++)
4619 Setting setting = jms.getFeatureSettings().getSetting(fs);
4620 if (setting.hasMincolour())
4622 FeatureColourI gc = setting.hasMin()
4623 ? new FeatureColour(new Color(setting.getMincolour()),
4624 new Color(setting.getColour()), setting.getMin(),
4626 : new FeatureColour(new Color(setting.getMincolour()),
4627 new Color(setting.getColour()), 0, 1);
4628 if (setting.hasThreshold())
4630 gc.setThreshold(setting.getThreshold());
4631 int threshstate = setting.getThreshstate();
4632 // -1 = None, 0 = Below, 1 = Above threshold
4633 if (threshstate == 0)
4635 gc.setBelowThreshold(true);
4637 else if (threshstate == 1)
4639 gc.setAboveThreshold(true);
4642 gc.setAutoScaled(true); // default
4643 if (setting.hasAutoScale())
4645 gc.setAutoScaled(setting.getAutoScale());
4647 if (setting.hasColourByLabel())
4649 gc.setColourByLabel(setting.getColourByLabel());
4651 // and put in the feature colour table.
4652 featureColours.put(setting.getType(), gc);
4656 featureColours.put(setting.getType(),
4657 new FeatureColour(new Color(setting.getColour())));
4659 renderOrder[fs] = setting.getType();
4660 if (setting.hasOrder())
4662 featureOrder.put(setting.getType(), setting.getOrder());
4666 featureOrder.put(setting.getType(), new Float(
4667 fs / jms.getFeatureSettings().getSettingCount()));
4669 if (setting.getDisplay())
4671 fdi.setVisible(setting.getType());
4674 Map<String, Boolean> fgtable = new Hashtable<>();
4675 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
4677 Group grp = jms.getFeatureSettings().getGroup(gs);
4678 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
4680 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4681 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
4682 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
4683 FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4684 fgtable, featureColours, 1.0f, featureOrder);
4685 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
4686 .transferSettings(frs);
4690 if (view.getHiddenColumnsCount() > 0)
4692 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
4694 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(),
4695 view.getHiddenColumns(c).getEnd() // +1
4699 if (view.getCalcIdParam() != null)
4701 for (CalcIdParam calcIdParam : view.getCalcIdParam())
4703 if (calcIdParam != null)
4705 if (recoverCalcIdParam(calcIdParam, af.viewport))
4710 warn("Couldn't recover parameters for "
4711 + calcIdParam.getCalcId());
4716 af.setMenusFromViewport(af.viewport);
4717 af.setTitle(view.getTitle());
4718 // TODO: we don't need to do this if the viewport is aready visible.
4720 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
4721 * has a 'cdna/protein complement' view, in which case save it in order to
4722 * populate a SplitFrame once all views have been read in.
4724 String complementaryViewId = view.getComplementId();
4725 if (complementaryViewId == null)
4727 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
4729 // recompute any autoannotation
4730 af.alignPanel.updateAnnotation(false, true);
4731 reorderAutoannotation(af, al, autoAlan);
4732 af.alignPanel.alignmentChanged();
4736 splitFrameCandidates.put(view, af);
4742 * Reads saved data to restore Colour by Annotation settings
4744 * @param viewAnnColour
4748 * @param checkGroupAnnColour
4751 private ColourSchemeI constructAnnotationColour(
4752 AnnotationColours viewAnnColour, AlignFrame af, AlignmentI al,
4753 JalviewModelSequence jms, boolean checkGroupAnnColour)
4755 boolean propagateAnnColour = false;
4756 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
4757 if (checkGroupAnnColour && al.getGroups() != null
4758 && al.getGroups().size() > 0)
4760 // pre 2.8.1 behaviour
4761 // check to see if we should transfer annotation colours
4762 propagateAnnColour = true;
4763 for (SequenceGroup sg : al.getGroups())
4765 if (sg.getColourScheme() instanceof AnnotationColourGradient)
4767 propagateAnnColour = false;
4773 * 2.10.2- : saved annotationId is AlignmentAnnotation.annotationId
4775 String annotationId = viewAnnColour.getAnnotation();
4776 AlignmentAnnotation matchedAnnotation = annotationIds.get(annotationId);
4779 * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
4781 if (matchedAnnotation == null
4782 && annAlignment.getAlignmentAnnotation() != null)
4784 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
4787 .equals(annAlignment.getAlignmentAnnotation()[i].label))
4789 matchedAnnotation = annAlignment.getAlignmentAnnotation()[i];
4794 if (matchedAnnotation == null)
4796 System.err.println("Failed to match annotation colour scheme for "
4800 if (matchedAnnotation.getThreshold() == null)
4802 matchedAnnotation.setThreshold(new GraphLine(
4803 viewAnnColour.getThreshold(), "Threshold", Color.black));
4806 AnnotationColourGradient cs = null;
4807 if (viewAnnColour.getColourScheme().equals("None"))
4809 cs = new AnnotationColourGradient(matchedAnnotation,
4810 new Color(viewAnnColour.getMinColour()),
4811 new Color(viewAnnColour.getMaxColour()),
4812 viewAnnColour.getAboveThreshold());
4814 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
4816 cs = new AnnotationColourGradient(matchedAnnotation,
4817 getUserColourScheme(jms, viewAnnColour.getColourScheme()),
4818 viewAnnColour.getAboveThreshold());
4822 cs = new AnnotationColourGradient(matchedAnnotation,
4823 ColourSchemeProperty.getColourScheme(al,
4824 viewAnnColour.getColourScheme()),
4825 viewAnnColour.getAboveThreshold());
4828 boolean perSequenceOnly = viewAnnColour.isPerSequence();
4829 boolean useOriginalColours = viewAnnColour.isPredefinedColours();
4830 cs.setSeqAssociated(perSequenceOnly);
4831 cs.setPredefinedColours(useOriginalColours);
4833 if (propagateAnnColour && al.getGroups() != null)
4835 // Also use these settings for all the groups
4836 for (int g = 0; g < al.getGroups().size(); g++)
4838 SequenceGroup sg = al.getGroups().get(g);
4839 if (sg.getGroupColourScheme() == null)
4844 AnnotationColourGradient groupScheme = new AnnotationColourGradient(
4845 matchedAnnotation, sg.getColourScheme(),
4846 viewAnnColour.getAboveThreshold());
4847 sg.setColourScheme(groupScheme);
4848 groupScheme.setSeqAssociated(perSequenceOnly);
4849 groupScheme.setPredefinedColours(useOriginalColours);
4855 private void reorderAutoannotation(AlignFrame af, AlignmentI al,
4856 List<JvAnnotRow> autoAlan)
4858 // copy over visualization settings for autocalculated annotation in the
4860 if (al.getAlignmentAnnotation() != null)
4863 * Kludge for magic autoannotation names (see JAL-811)
4865 String[] magicNames = new String[] { "Consensus", "Quality",
4867 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
4868 Hashtable<String, JvAnnotRow> visan = new Hashtable<>();
4869 for (String nm : magicNames)
4871 visan.put(nm, nullAnnot);
4873 for (JvAnnotRow auan : autoAlan)
4875 visan.put(auan.template.label
4876 + (auan.template.getCalcId() == null ? ""
4877 : "\t" + auan.template.getCalcId()),
4880 int hSize = al.getAlignmentAnnotation().length;
4881 List<JvAnnotRow> reorder = new ArrayList<>();
4882 // work through any autoCalculated annotation already on the view
4883 // removing it if it should be placed in a different location on the
4884 // annotation panel.
4885 List<String> remains = new ArrayList<>(visan.keySet());
4886 for (int h = 0; h < hSize; h++)
4888 jalview.datamodel.AlignmentAnnotation jalan = al
4889 .getAlignmentAnnotation()[h];
4890 if (jalan.autoCalculated)
4893 JvAnnotRow valan = visan.get(k = jalan.label);
4894 if (jalan.getCalcId() != null)
4896 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
4901 // delete the auto calculated row from the alignment
4902 al.deleteAnnotation(jalan, false);
4906 if (valan != nullAnnot)
4908 if (jalan != valan.template)
4910 // newly created autoannotation row instance
4911 // so keep a reference to the visible annotation row
4912 // and copy over all relevant attributes
4913 if (valan.template.graphHeight >= 0)
4916 jalan.graphHeight = valan.template.graphHeight;
4918 jalan.visible = valan.template.visible;
4920 reorder.add(new JvAnnotRow(valan.order, jalan));
4925 // Add any (possibly stale) autocalculated rows that were not appended to
4926 // the view during construction
4927 for (String other : remains)
4929 JvAnnotRow othera = visan.get(other);
4930 if (othera != nullAnnot && othera.template.getCalcId() != null
4931 && othera.template.getCalcId().length() > 0)
4933 reorder.add(othera);
4936 // now put the automatic annotation in its correct place
4937 int s = 0, srt[] = new int[reorder.size()];
4938 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
4939 for (JvAnnotRow jvar : reorder)
4942 srt[s++] = jvar.order;
4945 jalview.util.QuickSort.sort(srt, rws);
4946 // and re-insert the annotation at its correct position
4947 for (JvAnnotRow jvar : rws)
4949 al.addAnnotation(jvar.template, jvar.order);
4951 af.alignPanel.adjustAnnotationHeight();
4955 Hashtable skipList = null;
4958 * TODO remove this method
4961 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
4962 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
4963 * throw new Error("Implementation Error. No skipList defined for this
4964 * Jalview2XML instance."); } return (AlignFrame)
4965 * skipList.get(view.getSequenceSetId()); }
4969 * Check if the Jalview view contained in object should be skipped or not.
4972 * @return true if view's sequenceSetId is a key in skipList
4974 private boolean skipViewport(JalviewModel object)
4976 if (skipList == null)
4981 if (skipList.containsKey(
4982 id = object.getJalviewModelSequence().getViewport()[0]
4983 .getSequenceSetId()))
4985 if (Cache.log != null && Cache.log.isDebugEnabled())
4987 Cache.log.debug("Skipping seuqence set id " + id);
4994 public void addToSkipList(AlignFrame af)
4996 if (skipList == null)
4998 skipList = new Hashtable();
5000 skipList.put(af.getViewport().getSequenceSetId(), af);
5003 public void clearSkipList()
5005 if (skipList != null)
5012 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
5013 boolean ignoreUnrefed)
5015 jalview.datamodel.AlignmentI ds = getDatasetFor(
5016 vamsasSet.getDatasetId());
5017 Vector dseqs = null;
5020 // create a list of new dataset sequences
5021 dseqs = new Vector();
5023 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
5025 Sequence vamsasSeq = vamsasSet.getSequence(i);
5026 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
5028 // create a new dataset
5031 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
5032 dseqs.copyInto(dsseqs);
5033 ds = new jalview.datamodel.Alignment(dsseqs);
5034 debug("Created new dataset " + vamsasSet.getDatasetId()
5035 + " for alignment " + System.identityHashCode(al));
5036 addDatasetRef(vamsasSet.getDatasetId(), ds);
5038 // set the dataset for the newly imported alignment.
5039 if (al.getDataset() == null && !ignoreUnrefed)
5048 * sequence definition to create/merge dataset sequence for
5052 * vector to add new dataset sequence to
5053 * @param ignoreUnrefed
5054 * - when true, don't create new sequences from vamsasSeq if it's id
5055 * doesn't already have an asssociated Jalview sequence.
5057 * - used to reorder the sequence in the alignment according to the
5058 * vamsasSeq array ordering, to preserve ordering of dataset
5060 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
5061 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed, int vseqpos)
5063 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
5065 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
5066 boolean reorder = false;
5067 SequenceI dsq = null;
5068 if (sq != null && sq.getDatasetSequence() != null)
5070 dsq = sq.getDatasetSequence();
5076 if (sq == null && ignoreUnrefed)
5080 String sqid = vamsasSeq.getDsseqid();
5083 // need to create or add a new dataset sequence reference to this sequence
5086 dsq = seqRefIds.get(sqid);
5091 // make a new dataset sequence
5092 dsq = sq.createDatasetSequence();
5095 // make up a new dataset reference for this sequence
5096 sqid = seqHash(dsq);
5098 dsq.setVamsasId(uniqueSetSuffix + sqid);
5099 seqRefIds.put(sqid, dsq);
5104 dseqs.addElement(dsq);
5109 ds.addSequence(dsq);
5115 { // make this dataset sequence sq's dataset sequence
5116 sq.setDatasetSequence(dsq);
5117 // and update the current dataset alignment
5122 if (!dseqs.contains(dsq))
5129 if (ds.findIndex(dsq) < 0)
5131 ds.addSequence(dsq);
5138 // TODO: refactor this as a merge dataset sequence function
5139 // now check that sq (the dataset sequence) sequence really is the union of
5140 // all references to it
5141 // boolean pre = sq.getStart() < dsq.getStart();
5142 // boolean post = sq.getEnd() > dsq.getEnd();
5146 // StringBuffer sb = new StringBuffer();
5147 String newres = jalview.analysis.AlignSeq.extractGaps(
5148 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
5149 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
5150 && newres.length() > dsq.getLength())
5152 // Update with the longer sequence.
5156 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
5157 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
5158 * sb.append(newres.substring(newres.length() - sq.getEnd() -
5159 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
5161 dsq.setSequence(newres);
5163 // TODO: merges will never happen if we 'know' we have the real dataset
5164 // sequence - this should be detected when id==dssid
5166 "DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
5167 // + (pre ? "prepended" : "") + " "
5168 // + (post ? "appended" : ""));
5173 // sequence refs are identical. We may need to update the existing dataset
5174 // alignment with this one, though.
5175 if (ds != null && dseqs == null)
5177 int opos = ds.findIndex(dsq);
5178 SequenceI tseq = null;
5179 if (opos != -1 && vseqpos != opos)
5181 // remove from old position
5182 ds.deleteSequence(dsq);
5184 if (vseqpos < ds.getHeight())
5186 if (vseqpos != opos)
5188 // save sequence at destination position
5189 tseq = ds.getSequenceAt(vseqpos);
5190 ds.replaceSequenceAt(vseqpos, dsq);
5191 ds.addSequence(tseq);
5196 ds.addSequence(dsq);
5203 * TODO use AlignmentI here and in related methods - needs
5204 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
5206 Hashtable<String, AlignmentI> datasetIds = null;
5208 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
5210 private AlignmentI getDatasetFor(String datasetId)
5212 if (datasetIds == null)
5214 datasetIds = new Hashtable<>();
5217 if (datasetIds.containsKey(datasetId))
5219 return datasetIds.get(datasetId);
5224 private void addDatasetRef(String datasetId, AlignmentI dataset)
5226 if (datasetIds == null)
5228 datasetIds = new Hashtable<>();
5230 datasetIds.put(datasetId, dataset);
5234 * make a new dataset ID for this jalview dataset alignment
5239 private String getDatasetIdRef(AlignmentI dataset)
5241 if (dataset.getDataset() != null)
5243 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
5245 String datasetId = makeHashCode(dataset, null);
5246 if (datasetId == null)
5248 // make a new datasetId and record it
5249 if (dataset2Ids == null)
5251 dataset2Ids = new IdentityHashMap<>();
5255 datasetId = dataset2Ids.get(dataset);
5257 if (datasetId == null)
5259 datasetId = "ds" + dataset2Ids.size() + 1;
5260 dataset2Ids.put(dataset, datasetId);
5266 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5268 for (int d = 0; d < sequence.getDBRefCount(); d++)
5270 DBRef dr = sequence.getDBRef(d);
5271 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
5272 sequence.getDBRef(d).getSource(),
5273 sequence.getDBRef(d).getVersion(),
5274 sequence.getDBRef(d).getAccessionId());
5275 if (dr.getMapping() != null)
5277 entry.setMap(addMapping(dr.getMapping()));
5279 datasetSequence.addDBRef(entry);
5283 private jalview.datamodel.Mapping addMapping(Mapping m)
5285 SequenceI dsto = null;
5286 // Mapping m = dr.getMapping();
5287 int fr[] = new int[m.getMapListFromCount() * 2];
5288 Enumeration f = m.enumerateMapListFrom();
5289 for (int _i = 0; f.hasMoreElements(); _i += 2)
5291 MapListFrom mf = (MapListFrom) f.nextElement();
5292 fr[_i] = mf.getStart();
5293 fr[_i + 1] = mf.getEnd();
5295 int fto[] = new int[m.getMapListToCount() * 2];
5296 f = m.enumerateMapListTo();
5297 for (int _i = 0; f.hasMoreElements(); _i += 2)
5299 MapListTo mf = (MapListTo) f.nextElement();
5300 fto[_i] = mf.getStart();
5301 fto[_i + 1] = mf.getEnd();
5303 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto, fr,
5304 fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
5305 if (m.getMappingChoice() != null)
5307 MappingChoice mc = m.getMappingChoice();
5308 if (mc.getDseqFor() != null)
5310 String dsfor = "" + mc.getDseqFor();
5311 if (seqRefIds.containsKey(dsfor))
5316 jmap.setTo(seqRefIds.get(dsfor));
5320 frefedSequence.add(newMappingRef(dsfor, jmap));
5326 * local sequence definition
5328 Sequence ms = mc.getSequence();
5329 SequenceI djs = null;
5330 String sqid = ms.getDsseqid();
5331 if (sqid != null && sqid.length() > 0)
5334 * recover dataset sequence
5336 djs = seqRefIds.get(sqid);
5341 "Warning - making up dataset sequence id for DbRef sequence map reference");
5342 sqid = ((Object) ms).toString(); // make up a new hascode for
5343 // undefined dataset sequence hash
5344 // (unlikely to happen)
5350 * make a new dataset sequence and add it to refIds hash
5352 djs = new jalview.datamodel.Sequence(ms.getName(),
5354 djs.setStart(jmap.getMap().getToLowest());
5355 djs.setEnd(jmap.getMap().getToHighest());
5356 djs.setVamsasId(uniqueSetSuffix + sqid);
5358 incompleteSeqs.put(sqid, djs);
5359 seqRefIds.put(sqid, djs);
5362 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5372 * Provides a 'copy' of an alignment view (on action New View) by 'saving' the
5373 * view as XML (but not to file), and then reloading it
5378 public AlignmentPanel copyAlignPanel(AlignmentPanel ap)
5381 JalviewModel jm = saveState(ap, null, null, null);
5383 uniqueSetSuffix = "";
5384 jm.getJalviewModelSequence().getViewport(0).setId(null);
5385 // we don't overwrite the view we just copied
5387 if (this.frefedSequence == null)
5389 frefedSequence = new Vector<>();
5392 viewportsAdded.clear();
5394 AlignFrame af = loadFromObject(jm, null, false, null);
5395 af.alignPanels.clear();
5396 af.closeMenuItem_actionPerformed(true);
5399 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5400 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5401 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5402 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5403 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5406 return af.alignPanel;
5409 private Hashtable jvids2vobj;
5411 private void warn(String msg)
5416 private void warn(String msg, Exception e)
5418 if (Cache.log != null)
5422 Cache.log.warn(msg, e);
5426 Cache.log.warn(msg);
5431 System.err.println("Warning: " + msg);
5434 e.printStackTrace();
5439 private void debug(String string)
5441 debug(string, null);
5444 private void debug(String msg, Exception e)
5446 if (Cache.log != null)
5450 Cache.log.debug(msg, e);
5454 Cache.log.debug(msg);
5459 System.err.println("Warning: " + msg);
5462 e.printStackTrace();
5468 * set the object to ID mapping tables used to write/recover objects and XML
5469 * ID strings for the jalview project. If external tables are provided then
5470 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
5471 * object goes out of scope. - also populates the datasetIds hashtable with
5472 * alignment objects containing dataset sequences
5475 * Map from ID strings to jalview datamodel
5477 * Map from jalview datamodel to ID strings
5481 public void setObjectMappingTables(Hashtable vobj2jv,
5482 IdentityHashMap jv2vobj)
5484 this.jv2vobj = jv2vobj;
5485 this.vobj2jv = vobj2jv;
5486 Iterator ds = jv2vobj.keySet().iterator();
5488 while (ds.hasNext())
5490 Object jvobj = ds.next();
5491 id = jv2vobj.get(jvobj).toString();
5492 if (jvobj instanceof jalview.datamodel.Alignment)
5494 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
5496 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
5499 else if (jvobj instanceof jalview.datamodel.Sequence)
5501 // register sequence object so the XML parser can recover it.
5502 if (seqRefIds == null)
5504 seqRefIds = new HashMap<>();
5506 if (seqsToIds == null)
5508 seqsToIds = new IdentityHashMap<>();
5510 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
5511 seqsToIds.put((SequenceI) jvobj, id);
5513 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
5516 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
5517 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
5518 if (jvann.annotationId == null)
5520 jvann.annotationId = anid;
5522 if (!jvann.annotationId.equals(anid))
5524 // TODO verify that this is the correct behaviour
5525 this.warn("Overriding Annotation ID for " + anid
5526 + " from different id : " + jvann.annotationId);
5527 jvann.annotationId = anid;
5530 else if (jvobj instanceof String)
5532 if (jvids2vobj == null)
5534 jvids2vobj = new Hashtable();
5535 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
5540 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
5546 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
5547 * objects created from the project archive. If string is null (default for
5548 * construction) then suffix will be set automatically.
5552 public void setUniqueSetSuffix(String string)
5554 uniqueSetSuffix = string;
5559 * uses skipList2 as the skipList for skipping views on sequence sets
5560 * associated with keys in the skipList
5564 public void setSkipList(Hashtable skipList2)
5566 skipList = skipList2;
5570 * Reads the jar entry of given name and returns its contents, or null if the
5571 * entry is not found.
5574 * @param jarEntryName
5577 protected String readJarEntry(jarInputStreamProvider jprovider,
5578 String jarEntryName)
5580 String result = null;
5581 BufferedReader in = null;
5586 * Reopen the jar input stream and traverse its entries to find a matching
5589 JarInputStream jin = jprovider.getJarInputStream();
5590 JarEntry entry = null;
5593 entry = jin.getNextJarEntry();
5594 } while (entry != null && !entry.getName().equals(jarEntryName));
5598 StringBuilder out = new StringBuilder(256);
5599 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
5602 while ((data = in.readLine()) != null)
5606 result = out.toString();
5610 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
5612 } catch (Exception ex)
5614 ex.printStackTrace();
5622 } catch (IOException e)
5633 * Returns an incrementing counter (0, 1, 2...)
5637 private synchronized int nextCounter()