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", "aptx-test");
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 String treeFile = copyJarEntry(jprovider, "aptx-test", "aptx", null);
3580 AptxInit.createInstancesFromFile(treeFile, av);
3581 } catch (IOException e)
3583 // TODO Auto-generated catch block
3584 e.printStackTrace();
3592 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
3593 * panel is restored from separate jar entries, two (gapped and trimmed) per
3594 * sequence and secondary structure.
3596 * Currently each viewer shows just one sequence and structure (gapped and
3597 * trimmed), however this method is designed to support multiple sequences or
3598 * structures in viewers if wanted in future.
3604 private void loadRnaViewers(jarInputStreamProvider jprovider,
3605 JSeq[] jseqs, AlignmentPanel ap)
3608 * scan the sequences for references to viewers; create each one the first
3609 * time it is referenced, add Rna models to existing viewers
3611 for (JSeq jseq : jseqs)
3613 for (int i = 0; i < jseq.getRnaViewerCount(); i++)
3615 RnaViewer viewer = jseq.getRnaViewer(i);
3616 AppVarna appVarna = findOrCreateVarnaViewer(viewer, uniqueSetSuffix,
3619 for (int j = 0; j < viewer.getSecondaryStructureCount(); j++)
3621 SecondaryStructure ss = viewer.getSecondaryStructure(j);
3622 SequenceI seq = seqRefIds.get(jseq.getId());
3623 AlignmentAnnotation ann = this.annotationIds
3624 .get(ss.getAnnotationId());
3627 * add the structure to the Varna display (with session state copied
3628 * from the jar to a temporary file)
3630 boolean gapped = ss.isGapped();
3631 String rnaTitle = ss.getTitle();
3632 String sessionState = ss.getViewerState();
3633 String tempStateFile = copyJarEntry(jprovider, sessionState,
3635 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
3636 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
3638 appVarna.setInitialSelection(viewer.getSelectedRna());
3644 * Locate and return an already instantiated matching AppVarna, or create one
3648 * @param viewIdSuffix
3652 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
3653 String viewIdSuffix, AlignmentPanel ap)
3656 * on each load a suffix is appended to the saved viewId, to avoid conflicts
3657 * if load is repeated
3659 String postLoadId = viewer.getViewId() + viewIdSuffix;
3660 for (JInternalFrame frame : getAllFrames())
3662 if (frame instanceof AppVarna)
3664 AppVarna varna = (AppVarna) frame;
3665 if (postLoadId.equals(varna.getViewId()))
3667 // this viewer is already instantiated
3668 // could in future here add ap as another 'parent' of the
3669 // AppVarna window; currently just 1-to-many
3676 * viewer not found - make it
3678 RnaViewerModel model = new RnaViewerModel(postLoadId, viewer.getTitle(),
3679 viewer.getXpos(), viewer.getYpos(), viewer.getWidth(),
3680 viewer.getHeight(), viewer.getDividerLocation());
3681 AppVarna varna = new AppVarna(model, ap);
3687 * Load any saved trees
3695 protected void loadTrees(JalviewModelSequence jms, Viewport view,
3696 AlignFrame af, AlignViewport av, AlignmentPanel ap)
3698 // TODO result of automated refactoring - are all these parameters needed?
3701 for (int t = 0; t < jms.getTreeCount(); t++)
3704 Tree tree = jms.getTree(t);
3705 NewickFile newick = new jalview.io.NewickFile(tree.getNewick());
3707 TreeFrameI externalViewer = AptxInit.createInstanceFromNhx(
3708 tree.getTitle(), tree.getNewick(),
3712 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
3717 tp = af.showNewickTree(
3719 tree.getTitle(), tree.getWidth(), tree.getHeight(),
3720 tree.getXpos(), tree.getYpos());
3721 if (tree.getId() != null)
3723 // perhaps bind the tree id to something ?
3728 // update local tree attributes ?
3729 // TODO: should check if tp has been manipulated by user - if so its
3730 // settings shouldn't be modified
3731 tp.setTitle(tree.getTitle());
3732 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(),
3733 tree.getWidth(), tree.getHeight()));
3734 tp.av = av; // af.viewport; // TODO: verify 'associate with all
3737 tp.treeCanvas.av = av; // af.viewport;
3738 tp.treeCanvas.ap = ap; // af.alignPanel;
3743 warn("There was a problem recovering stored Newick tree: \n"
3744 + tree.getNewick());
3748 tp.fitToWindow.setState(tree.getFitToWindow());
3749 tp.fitToWindow_actionPerformed(null);
3751 if (tree.getFontName() != null)
3753 tp.setTreeFont(new java.awt.Font(tree.getFontName(),
3754 tree.getFontStyle(), tree.getFontSize()));
3758 tp.setTreeFont(new java.awt.Font(view.getFontName(),
3759 view.getFontStyle(), tree.getFontSize()));
3762 tp.showPlaceholders(tree.getMarkUnlinked());
3763 tp.showBootstrap(tree.getShowBootstrap());
3764 tp.showDistances(tree.getShowDistances());
3766 tp.treeCanvas.threshold = tree.getThreshold();
3768 if (tree.getCurrentTree())
3770 af.viewport.setCurrentTree(tp.getTree());
3774 } catch (Exception ex)
3776 ex.printStackTrace();
3781 * Load and link any saved structure viewers.
3788 protected void loadPDBStructures(jarInputStreamProvider jprovider,
3789 JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
3792 * Run through all PDB ids on the alignment, and collect mappings between
3793 * distinct view ids and all sequences referring to that view.
3795 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<>();
3797 for (int i = 0; i < jseqs.length; i++)
3799 if (jseqs[i].getPdbidsCount() > 0)
3801 Pdbids[] ids = jseqs[i].getPdbids();
3802 for (int p = 0; p < ids.length; p++)
3804 final int structureStateCount = ids[p].getStructureStateCount();
3805 for (int s = 0; s < structureStateCount; s++)
3807 // check to see if we haven't already created this structure view
3808 final StructureState structureState = ids[p]
3809 .getStructureState(s);
3810 String sviewid = (structureState.getViewId() == null) ? null
3811 : structureState.getViewId() + uniqueSetSuffix;
3812 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
3813 // Originally : ids[p].getFile()
3814 // : TODO: verify external PDB file recovery still works in normal
3815 // jalview project load
3816 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId(),
3818 jpdb.setId(ids[p].getId());
3820 int x = structureState.getXpos();
3821 int y = structureState.getYpos();
3822 int width = structureState.getWidth();
3823 int height = structureState.getHeight();
3825 // Probably don't need to do this anymore...
3826 // Desktop.desktop.getComponentAt(x, y);
3827 // TODO: NOW: check that this recovers the PDB file correctly.
3828 String pdbFile = loadPDBFile(jprovider, ids[p].getId(),
3830 jalview.datamodel.SequenceI seq = seqRefIds
3831 .get(jseqs[i].getId() + "");
3832 if (sviewid == null)
3834 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width + ","
3837 if (!structureViewers.containsKey(sviewid))
3839 structureViewers.put(sviewid,
3840 new StructureViewerModel(x, y, width, height, false,
3841 false, true, structureState.getViewId(),
3842 structureState.getType()));
3843 // Legacy pre-2.7 conversion JAL-823 :
3844 // do not assume any view has to be linked for colour by
3848 // assemble String[] { pdb files }, String[] { id for each
3849 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3850 // seqs_file 2}, boolean[] {
3851 // linkAlignPanel,superposeWithAlignpanel}} from hash
3852 StructureViewerModel jmoldat = structureViewers.get(sviewid);
3853 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
3854 | (structureState.hasAlignwithAlignPanel()
3855 ? structureState.getAlignwithAlignPanel()
3859 * Default colour by linked panel to false if not specified (e.g.
3860 * for pre-2.7 projects)
3862 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
3863 colourWithAlignPanel |= (structureState
3864 .hasColourwithAlignPanel()
3865 ? structureState.getColourwithAlignPanel()
3867 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
3870 * Default colour by viewer to true if not specified (e.g. for
3873 boolean colourByViewer = jmoldat.isColourByViewer();
3874 colourByViewer &= structureState.hasColourByJmol()
3875 ? structureState.getColourByJmol()
3877 jmoldat.setColourByViewer(colourByViewer);
3879 if (jmoldat.getStateData().length() < structureState
3880 .getContent().length())
3883 jmoldat.setStateData(structureState.getContent());
3886 if (ids[p].getFile() != null)
3888 File mapkey = new File(ids[p].getFile());
3889 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
3890 if (seqstrmaps == null)
3892 jmoldat.getFileData().put(mapkey,
3893 seqstrmaps = jmoldat.new StructureData(pdbFile,
3896 if (!seqstrmaps.getSeqList().contains(seq))
3898 seqstrmaps.getSeqList().add(seq);
3904 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");
3911 // Instantiate the associated structure views
3912 for (Entry<String, StructureViewerModel> entry : structureViewers
3917 createOrLinkStructureViewer(entry, af, ap, jprovider);
3918 } catch (Exception e)
3921 "Error loading structure viewer: " + e.getMessage());
3922 // failed - try the next one
3934 protected void createOrLinkStructureViewer(
3935 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3936 AlignmentPanel ap, jarInputStreamProvider jprovider)
3938 final StructureViewerModel stateData = viewerData.getValue();
3941 * Search for any viewer windows already open from other alignment views
3942 * that exactly match the stored structure state
3944 StructureViewerBase comp = findMatchingViewer(viewerData);
3948 linkStructureViewer(ap, comp, stateData);
3953 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
3954 * "viewer_"+stateData.viewId
3956 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
3958 createChimeraViewer(viewerData, af, jprovider);
3963 * else Jmol (if pre-2.9, stateData contains JMOL state string)
3965 createJmolViewer(viewerData, af, jprovider);
3970 * Create a new Chimera viewer.
3976 protected void createChimeraViewer(
3977 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3978 jarInputStreamProvider jprovider)
3980 StructureViewerModel data = viewerData.getValue();
3981 String chimeraSessionFile = data.getStateData();
3984 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
3986 * NB this is the 'saved' viewId as in the project file XML, _not_ the
3987 * 'uniquified' sviewid used to reconstruct the viewer here
3989 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
3990 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
3993 Set<Entry<File, StructureData>> fileData = data.getFileData()
3995 List<PDBEntry> pdbs = new ArrayList<>();
3996 List<SequenceI[]> allseqs = new ArrayList<>();
3997 for (Entry<File, StructureData> pdb : fileData)
3999 String filePath = pdb.getValue().getFilePath();
4000 String pdbId = pdb.getValue().getPdbId();
4001 // pdbs.add(new PDBEntry(filePath, pdbId));
4002 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
4003 final List<SequenceI> seqList = pdb.getValue().getSeqList();
4004 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
4008 boolean colourByChimera = data.isColourByViewer();
4009 boolean colourBySequence = data.isColourWithAlignPanel();
4011 // TODO use StructureViewer as a factory here, see JAL-1761
4012 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
4013 final SequenceI[][] seqsArray = allseqs
4014 .toArray(new SequenceI[allseqs.size()][]);
4015 String newViewId = viewerData.getKey();
4017 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
4018 af.alignPanel, pdbArray, seqsArray, colourByChimera,
4019 colourBySequence, newViewId);
4020 cvf.setSize(data.getWidth(), data.getHeight());
4021 cvf.setLocation(data.getX(), data.getY());
4025 * Create a new Jmol window. First parse the Jmol state to translate filenames
4026 * loaded into the view, and record the order in which files are shown in the
4027 * Jmol view, so we can add the sequence mappings in same order.
4033 protected void createJmolViewer(
4034 final Entry<String, StructureViewerModel> viewerData,
4035 AlignFrame af, jarInputStreamProvider jprovider)
4037 final StructureViewerModel svattrib = viewerData.getValue();
4038 String state = svattrib.getStateData();
4041 * Pre-2.9: state element value is the Jmol state string
4043 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
4046 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
4048 state = readJarEntry(jprovider,
4049 getViewerJarEntryName(svattrib.getViewId()));
4052 List<String> pdbfilenames = new ArrayList<>();
4053 List<SequenceI[]> seqmaps = new ArrayList<>();
4054 List<String> pdbids = new ArrayList<>();
4055 StringBuilder newFileLoc = new StringBuilder(64);
4056 int cp = 0, ncp, ecp;
4057 Map<File, StructureData> oldFiles = svattrib.getFileData();
4058 while ((ncp = state.indexOf("load ", cp)) > -1)
4062 // look for next filename in load statement
4063 newFileLoc.append(state.substring(cp,
4064 ncp = (state.indexOf("\"", ncp + 1) + 1)));
4065 String oldfilenam = state.substring(ncp,
4066 ecp = state.indexOf("\"", ncp));
4067 // recover the new mapping data for this old filename
4068 // have to normalize filename - since Jmol and jalview do
4070 // translation differently.
4071 StructureData filedat = oldFiles.get(new File(oldfilenam));
4072 if (filedat == null)
4074 String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\");
4075 filedat = oldFiles.get(new File(reformatedOldFilename));
4077 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
4078 pdbfilenames.add(filedat.getFilePath());
4079 pdbids.add(filedat.getPdbId());
4080 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4081 newFileLoc.append("\"");
4082 cp = ecp + 1; // advance beyond last \" and set cursor so we can
4083 // look for next file statement.
4084 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
4088 // just append rest of state
4089 newFileLoc.append(state.substring(cp));
4093 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
4094 newFileLoc = new StringBuilder(state);
4095 newFileLoc.append("; load append ");
4096 for (File id : oldFiles.keySet())
4098 // add this and any other pdb files that should be present in
4100 StructureData filedat = oldFiles.get(id);
4101 newFileLoc.append(filedat.getFilePath());
4102 pdbfilenames.add(filedat.getFilePath());
4103 pdbids.add(filedat.getPdbId());
4104 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4105 newFileLoc.append(" \"");
4106 newFileLoc.append(filedat.getFilePath());
4107 newFileLoc.append("\"");
4110 newFileLoc.append(";");
4113 if (newFileLoc.length() == 0)
4117 int histbug = newFileLoc.indexOf("history = ");
4121 * change "history = [true|false];" to "history = [1|0];"
4124 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
4125 String val = (diff == -1) ? null
4126 : newFileLoc.substring(histbug, diff);
4127 if (val != null && val.length() >= 4)
4129 if (val.contains("e")) // eh? what can it be?
4131 if (val.trim().equals("true"))
4139 newFileLoc.replace(histbug, diff, val);
4144 final String[] pdbf = pdbfilenames
4145 .toArray(new String[pdbfilenames.size()]);
4146 final String[] id = pdbids.toArray(new String[pdbids.size()]);
4147 final SequenceI[][] sq = seqmaps
4148 .toArray(new SequenceI[seqmaps.size()][]);
4149 final String fileloc = newFileLoc.toString();
4150 final String sviewid = viewerData.getKey();
4151 final AlignFrame alf = af;
4152 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
4153 svattrib.getWidth(), svattrib.getHeight());
4156 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
4161 JalviewStructureDisplayI sview = null;
4164 sview = new StructureViewer(
4165 alf.alignPanel.getStructureSelectionManager())
4166 .createView(StructureViewer.ViewerType.JMOL,
4167 pdbf, id, sq, alf.alignPanel, svattrib,
4168 fileloc, rect, sviewid);
4169 addNewStructureViewer(sview);
4170 } catch (OutOfMemoryError ex)
4172 new OOMWarning("restoring structure view for PDB id " + id,
4173 (OutOfMemoryError) ex.getCause());
4174 if (sview != null && sview.isVisible())
4176 sview.closeViewer(false);
4177 sview.setVisible(false);
4183 } catch (InvocationTargetException ex)
4185 warn("Unexpected error when opening Jmol view.", ex);
4187 } catch (InterruptedException e)
4189 // e.printStackTrace();
4195 * Generates a name for the entry in the project jar file to hold state
4196 * information for a structure viewer
4201 protected String getViewerJarEntryName(String viewId)
4203 return VIEWER_PREFIX + viewId;
4207 * Returns any open frame that matches given structure viewer data. The match
4208 * is based on the unique viewId, or (for older project versions) the frame's
4214 protected StructureViewerBase findMatchingViewer(
4215 Entry<String, StructureViewerModel> viewerData)
4217 final String sviewid = viewerData.getKey();
4218 final StructureViewerModel svattrib = viewerData.getValue();
4219 StructureViewerBase comp = null;
4220 JInternalFrame[] frames = getAllFrames();
4221 for (JInternalFrame frame : frames)
4223 if (frame instanceof StructureViewerBase)
4226 * Post jalview 2.4 schema includes structure view id
4228 if (sviewid != null && ((StructureViewerBase) frame).getViewId()
4231 comp = (StructureViewerBase) frame;
4232 break; // break added in 2.9
4235 * Otherwise test for matching position and size of viewer frame
4237 else if (frame.getX() == svattrib.getX()
4238 && frame.getY() == svattrib.getY()
4239 && frame.getHeight() == svattrib.getHeight()
4240 && frame.getWidth() == svattrib.getWidth())
4242 comp = (StructureViewerBase) frame;
4243 // no break in faint hope of an exact match on viewId
4251 * Link an AlignmentPanel to an existing structure viewer.
4256 * @param useinViewerSuperpos
4257 * @param usetoColourbyseq
4258 * @param viewerColouring
4260 protected void linkStructureViewer(AlignmentPanel ap,
4261 StructureViewerBase viewer, StructureViewerModel stateData)
4263 // NOTE: if the jalview project is part of a shared session then
4264 // view synchronization should/could be done here.
4266 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4267 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4268 final boolean viewerColouring = stateData.isColourByViewer();
4269 Map<File, StructureData> oldFiles = stateData.getFileData();
4272 * Add mapping for sequences in this view to an already open viewer
4274 final AAStructureBindingModel binding = viewer.getBinding();
4275 for (File id : oldFiles.keySet())
4277 // add this and any other pdb files that should be present in the
4279 StructureData filedat = oldFiles.get(id);
4280 String pdbFile = filedat.getFilePath();
4281 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4282 binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE,
4284 binding.addSequenceForStructFile(pdbFile, seq);
4286 // and add the AlignmentPanel's reference to the view panel
4287 viewer.addAlignmentPanel(ap);
4288 if (useinViewerSuperpos)
4290 viewer.useAlignmentPanelForSuperposition(ap);
4294 viewer.excludeAlignmentPanelForSuperposition(ap);
4296 if (usetoColourbyseq)
4298 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4302 viewer.excludeAlignmentPanelForColourbyseq(ap);
4307 * Get all frames within the Desktop.
4311 protected JInternalFrame[] getAllFrames()
4313 JInternalFrame[] frames = null;
4314 // TODO is this necessary - is it safe - risk of hanging?
4319 frames = Desktop.desktop.getAllFrames();
4320 } catch (ArrayIndexOutOfBoundsException e)
4322 // occasional No such child exceptions are thrown here...
4326 } catch (InterruptedException f)
4330 } while (frames == null);
4335 * Answers true if 'version' is equal to or later than 'supported', where each
4336 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4337 * changes. Development and test values for 'version' are leniently treated
4341 * - minimum version we are comparing against
4343 * - version of data being processsed
4346 public static boolean isVersionStringLaterThan(String supported,
4349 if (supported == null || version == null
4350 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4351 || version.equalsIgnoreCase("Test")
4352 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4354 System.err.println("Assuming project file with "
4355 + (version == null ? "null" : version)
4356 + " is compatible with Jalview version " + supported);
4361 return StringUtils.compareVersions(version, supported, "b") >= 0;
4365 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4367 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4369 if (newStructureViewers != null)
4371 sview.getBinding().setFinishedLoadingFromArchive(false);
4372 newStructureViewers.add(sview);
4376 protected void setLoadingFinishedForNewStructureViewers()
4378 if (newStructureViewers != null)
4380 for (JalviewStructureDisplayI sview : newStructureViewers)
4382 sview.getBinding().setFinishedLoadingFromArchive(true);
4384 newStructureViewers.clear();
4385 newStructureViewers = null;
4389 AlignFrame loadViewport(String file, JSeq[] JSEQ,
4390 List<SequenceI> hiddenSeqs, AlignmentI al,
4391 JalviewModelSequence jms, Viewport view, String uniqueSeqSetId,
4392 String viewId, List<JvAnnotRow> autoAlan)
4394 AlignFrame af = null;
4395 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
4396 uniqueSeqSetId, viewId);
4398 af.setFileName(file, FileFormat.Jalview);
4400 for (int i = 0; i < JSEQ.length; i++)
4402 af.viewport.setSequenceColour(
4403 af.viewport.getAlignment().getSequenceAt(i),
4404 new java.awt.Color(JSEQ[i].getColour()));
4409 af.getViewport().setColourByReferenceSeq(true);
4410 af.getViewport().setDisplayReferenceSeq(true);
4413 af.viewport.setGatherViewsHere(view.getGatheredViews());
4415 if (view.getSequenceSetId() != null)
4417 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4419 af.viewport.setSequenceSetId(uniqueSeqSetId);
4422 // propagate shared settings to this new view
4423 af.viewport.setHistoryList(av.getHistoryList());
4424 af.viewport.setRedoList(av.getRedoList());
4428 viewportsAdded.put(uniqueSeqSetId, af.viewport);
4430 // TODO: check if this method can be called repeatedly without
4431 // side-effects if alignpanel already registered.
4432 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4434 // apply Hidden regions to view.
4435 if (hiddenSeqs != null)
4437 for (int s = 0; s < JSEQ.length; s++)
4439 SequenceGroup hidden = new SequenceGroup();
4440 boolean isRepresentative = false;
4441 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
4443 isRepresentative = true;
4444 SequenceI sequenceToHide = al
4445 .getSequenceAt(JSEQ[s].getHiddenSequences(r));
4446 hidden.addSequence(sequenceToHide, false);
4447 // remove from hiddenSeqs list so we don't try to hide it twice
4448 hiddenSeqs.remove(sequenceToHide);
4450 if (isRepresentative)
4452 SequenceI representativeSequence = al.getSequenceAt(s);
4453 hidden.addSequence(representativeSequence, false);
4454 af.viewport.hideRepSequences(representativeSequence, hidden);
4458 SequenceI[] hseqs = hiddenSeqs
4459 .toArray(new SequenceI[hiddenSeqs.size()]);
4460 af.viewport.hideSequence(hseqs);
4463 // recover view properties and display parameters
4465 af.viewport.setShowAnnotation(view.getShowAnnotation());
4466 af.viewport.setAbovePIDThreshold(view.getPidSelected());
4467 af.viewport.setThreshold(view.getPidThreshold());
4469 af.viewport.setColourText(view.getShowColourText());
4471 af.viewport.setConservationSelected(view.getConservationSelected());
4472 af.viewport.setIncrement(view.getConsThreshold());
4473 af.viewport.setShowJVSuffix(view.getShowFullId());
4474 af.viewport.setRightAlignIds(view.getRightAlignIds());
4475 af.viewport.setFont(new java.awt.Font(view.getFontName(),
4476 view.getFontStyle(), view.getFontSize()), true);
4477 ViewStyleI vs = af.viewport.getViewStyle();
4478 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
4479 af.viewport.setViewStyle(vs);
4480 // TODO: allow custom charWidth/Heights to be restored by updating them
4481 // after setting font - which means set above to false
4482 af.viewport.setRenderGaps(view.getRenderGaps());
4483 af.viewport.setWrapAlignment(view.getWrapAlignment());
4484 af.viewport.setShowAnnotation(view.getShowAnnotation());
4486 af.viewport.setShowBoxes(view.getShowBoxes());
4488 af.viewport.setShowText(view.getShowText());
4490 af.viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
4491 af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
4492 af.viewport.setThresholdTextColour(view.getTextColThreshold());
4493 af.viewport.setShowUnconserved(
4494 view.hasShowUnconserved() ? view.isShowUnconserved() : false);
4495 af.viewport.getRanges().setStartRes(view.getStartRes());
4497 if (view.getViewName() != null)
4499 af.viewport.viewName = view.getViewName();
4500 af.setInitialTabVisible();
4502 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
4504 // startSeq set in af.alignPanel.updateLayout below
4505 af.alignPanel.updateLayout();
4506 ColourSchemeI cs = null;
4507 // apply colourschemes
4508 if (view.getBgColour() != null)
4510 if (view.getBgColour().startsWith("ucs"))
4512 cs = getUserColourScheme(jms, view.getBgColour());
4514 else if (view.getBgColour().startsWith("Annotation"))
4516 AnnotationColours viewAnnColour = view.getAnnotationColours();
4517 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
4524 cs = ColourSchemeProperty.getColourScheme(al, view.getBgColour());
4528 af.viewport.setGlobalColourScheme(cs);
4529 af.viewport.getResidueShading().setThreshold(view.getPidThreshold(),
4530 view.getIgnoreGapsinConsensus());
4531 af.viewport.getResidueShading()
4532 .setConsensus(af.viewport.getSequenceConsensusHash());
4533 af.viewport.setColourAppliesToAllGroups(false);
4535 if (view.getConservationSelected() && cs != null)
4537 af.viewport.getResidueShading()
4538 .setConservationInc(view.getConsThreshold());
4541 af.changeColour(cs);
4543 af.viewport.setColourAppliesToAllGroups(true);
4545 af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures());
4547 if (view.hasCentreColumnLabels())
4549 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
4551 if (view.hasIgnoreGapsinConsensus())
4553 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
4556 if (view.hasFollowHighlight())
4558 af.viewport.setFollowHighlight(view.getFollowHighlight());
4560 if (view.hasFollowSelection())
4562 af.viewport.followSelection = view.getFollowSelection();
4564 if (view.hasShowConsensusHistogram())
4567 .setShowConsensusHistogram(view.getShowConsensusHistogram());
4571 af.viewport.setShowConsensusHistogram(true);
4573 if (view.hasShowSequenceLogo())
4575 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
4579 af.viewport.setShowSequenceLogo(false);
4581 if (view.hasNormaliseSequenceLogo())
4583 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
4585 if (view.hasShowDbRefTooltip())
4587 af.viewport.setShowDBRefs(view.getShowDbRefTooltip());
4589 if (view.hasShowNPfeatureTooltip())
4591 af.viewport.setShowNPFeats(view.hasShowNPfeatureTooltip());
4593 if (view.hasShowGroupConsensus())
4595 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
4599 af.viewport.setShowGroupConsensus(false);
4601 if (view.hasShowGroupConservation())
4603 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
4607 af.viewport.setShowGroupConservation(false);
4610 // recover featre settings
4611 if (jms.getFeatureSettings() != null)
4613 FeaturesDisplayed fdi;
4614 af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
4615 String[] renderOrder = new String[jms.getFeatureSettings()
4616 .getSettingCount()];
4617 Map<String, FeatureColourI> featureColours = new Hashtable<>();
4618 Map<String, Float> featureOrder = new Hashtable<>();
4620 for (int fs = 0; fs < jms.getFeatureSettings()
4621 .getSettingCount(); fs++)
4623 Setting setting = jms.getFeatureSettings().getSetting(fs);
4624 if (setting.hasMincolour())
4626 FeatureColourI gc = setting.hasMin()
4627 ? new FeatureColour(new Color(setting.getMincolour()),
4628 new Color(setting.getColour()), setting.getMin(),
4630 : new FeatureColour(new Color(setting.getMincolour()),
4631 new Color(setting.getColour()), 0, 1);
4632 if (setting.hasThreshold())
4634 gc.setThreshold(setting.getThreshold());
4635 int threshstate = setting.getThreshstate();
4636 // -1 = None, 0 = Below, 1 = Above threshold
4637 if (threshstate == 0)
4639 gc.setBelowThreshold(true);
4641 else if (threshstate == 1)
4643 gc.setAboveThreshold(true);
4646 gc.setAutoScaled(true); // default
4647 if (setting.hasAutoScale())
4649 gc.setAutoScaled(setting.getAutoScale());
4651 if (setting.hasColourByLabel())
4653 gc.setColourByLabel(setting.getColourByLabel());
4655 // and put in the feature colour table.
4656 featureColours.put(setting.getType(), gc);
4660 featureColours.put(setting.getType(),
4661 new FeatureColour(new Color(setting.getColour())));
4663 renderOrder[fs] = setting.getType();
4664 if (setting.hasOrder())
4666 featureOrder.put(setting.getType(), setting.getOrder());
4670 featureOrder.put(setting.getType(), new Float(
4671 fs / jms.getFeatureSettings().getSettingCount()));
4673 if (setting.getDisplay())
4675 fdi.setVisible(setting.getType());
4678 Map<String, Boolean> fgtable = new Hashtable<>();
4679 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
4681 Group grp = jms.getFeatureSettings().getGroup(gs);
4682 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
4684 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4685 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
4686 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
4687 FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4688 fgtable, featureColours, 1.0f, featureOrder);
4689 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
4690 .transferSettings(frs);
4694 if (view.getHiddenColumnsCount() > 0)
4696 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
4698 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(),
4699 view.getHiddenColumns(c).getEnd() // +1
4703 if (view.getCalcIdParam() != null)
4705 for (CalcIdParam calcIdParam : view.getCalcIdParam())
4707 if (calcIdParam != null)
4709 if (recoverCalcIdParam(calcIdParam, af.viewport))
4714 warn("Couldn't recover parameters for "
4715 + calcIdParam.getCalcId());
4720 af.setMenusFromViewport(af.viewport);
4721 af.setTitle(view.getTitle());
4722 // TODO: we don't need to do this if the viewport is aready visible.
4724 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
4725 * has a 'cdna/protein complement' view, in which case save it in order to
4726 * populate a SplitFrame once all views have been read in.
4728 String complementaryViewId = view.getComplementId();
4729 if (complementaryViewId == null)
4731 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
4733 // recompute any autoannotation
4734 af.alignPanel.updateAnnotation(false, true);
4735 reorderAutoannotation(af, al, autoAlan);
4736 af.alignPanel.alignmentChanged();
4740 splitFrameCandidates.put(view, af);
4746 * Reads saved data to restore Colour by Annotation settings
4748 * @param viewAnnColour
4752 * @param checkGroupAnnColour
4755 private ColourSchemeI constructAnnotationColour(
4756 AnnotationColours viewAnnColour, AlignFrame af, AlignmentI al,
4757 JalviewModelSequence jms, boolean checkGroupAnnColour)
4759 boolean propagateAnnColour = false;
4760 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
4761 if (checkGroupAnnColour && al.getGroups() != null
4762 && al.getGroups().size() > 0)
4764 // pre 2.8.1 behaviour
4765 // check to see if we should transfer annotation colours
4766 propagateAnnColour = true;
4767 for (SequenceGroup sg : al.getGroups())
4769 if (sg.getColourScheme() instanceof AnnotationColourGradient)
4771 propagateAnnColour = false;
4777 * 2.10.2- : saved annotationId is AlignmentAnnotation.annotationId
4779 String annotationId = viewAnnColour.getAnnotation();
4780 AlignmentAnnotation matchedAnnotation = annotationIds.get(annotationId);
4783 * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
4785 if (matchedAnnotation == null
4786 && annAlignment.getAlignmentAnnotation() != null)
4788 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
4791 .equals(annAlignment.getAlignmentAnnotation()[i].label))
4793 matchedAnnotation = annAlignment.getAlignmentAnnotation()[i];
4798 if (matchedAnnotation == null)
4800 System.err.println("Failed to match annotation colour scheme for "
4804 if (matchedAnnotation.getThreshold() == null)
4806 matchedAnnotation.setThreshold(new GraphLine(
4807 viewAnnColour.getThreshold(), "Threshold", Color.black));
4810 AnnotationColourGradient cs = null;
4811 if (viewAnnColour.getColourScheme().equals("None"))
4813 cs = new AnnotationColourGradient(matchedAnnotation,
4814 new Color(viewAnnColour.getMinColour()),
4815 new Color(viewAnnColour.getMaxColour()),
4816 viewAnnColour.getAboveThreshold());
4818 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
4820 cs = new AnnotationColourGradient(matchedAnnotation,
4821 getUserColourScheme(jms, viewAnnColour.getColourScheme()),
4822 viewAnnColour.getAboveThreshold());
4826 cs = new AnnotationColourGradient(matchedAnnotation,
4827 ColourSchemeProperty.getColourScheme(al,
4828 viewAnnColour.getColourScheme()),
4829 viewAnnColour.getAboveThreshold());
4832 boolean perSequenceOnly = viewAnnColour.isPerSequence();
4833 boolean useOriginalColours = viewAnnColour.isPredefinedColours();
4834 cs.setSeqAssociated(perSequenceOnly);
4835 cs.setPredefinedColours(useOriginalColours);
4837 if (propagateAnnColour && al.getGroups() != null)
4839 // Also use these settings for all the groups
4840 for (int g = 0; g < al.getGroups().size(); g++)
4842 SequenceGroup sg = al.getGroups().get(g);
4843 if (sg.getGroupColourScheme() == null)
4848 AnnotationColourGradient groupScheme = new AnnotationColourGradient(
4849 matchedAnnotation, sg.getColourScheme(),
4850 viewAnnColour.getAboveThreshold());
4851 sg.setColourScheme(groupScheme);
4852 groupScheme.setSeqAssociated(perSequenceOnly);
4853 groupScheme.setPredefinedColours(useOriginalColours);
4859 private void reorderAutoannotation(AlignFrame af, AlignmentI al,
4860 List<JvAnnotRow> autoAlan)
4862 // copy over visualization settings for autocalculated annotation in the
4864 if (al.getAlignmentAnnotation() != null)
4867 * Kludge for magic autoannotation names (see JAL-811)
4869 String[] magicNames = new String[] { "Consensus", "Quality",
4871 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
4872 Hashtable<String, JvAnnotRow> visan = new Hashtable<>();
4873 for (String nm : magicNames)
4875 visan.put(nm, nullAnnot);
4877 for (JvAnnotRow auan : autoAlan)
4879 visan.put(auan.template.label
4880 + (auan.template.getCalcId() == null ? ""
4881 : "\t" + auan.template.getCalcId()),
4884 int hSize = al.getAlignmentAnnotation().length;
4885 List<JvAnnotRow> reorder = new ArrayList<>();
4886 // work through any autoCalculated annotation already on the view
4887 // removing it if it should be placed in a different location on the
4888 // annotation panel.
4889 List<String> remains = new ArrayList<>(visan.keySet());
4890 for (int h = 0; h < hSize; h++)
4892 jalview.datamodel.AlignmentAnnotation jalan = al
4893 .getAlignmentAnnotation()[h];
4894 if (jalan.autoCalculated)
4897 JvAnnotRow valan = visan.get(k = jalan.label);
4898 if (jalan.getCalcId() != null)
4900 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
4905 // delete the auto calculated row from the alignment
4906 al.deleteAnnotation(jalan, false);
4910 if (valan != nullAnnot)
4912 if (jalan != valan.template)
4914 // newly created autoannotation row instance
4915 // so keep a reference to the visible annotation row
4916 // and copy over all relevant attributes
4917 if (valan.template.graphHeight >= 0)
4920 jalan.graphHeight = valan.template.graphHeight;
4922 jalan.visible = valan.template.visible;
4924 reorder.add(new JvAnnotRow(valan.order, jalan));
4929 // Add any (possibly stale) autocalculated rows that were not appended to
4930 // the view during construction
4931 for (String other : remains)
4933 JvAnnotRow othera = visan.get(other);
4934 if (othera != nullAnnot && othera.template.getCalcId() != null
4935 && othera.template.getCalcId().length() > 0)
4937 reorder.add(othera);
4940 // now put the automatic annotation in its correct place
4941 int s = 0, srt[] = new int[reorder.size()];
4942 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
4943 for (JvAnnotRow jvar : reorder)
4946 srt[s++] = jvar.order;
4949 jalview.util.QuickSort.sort(srt, rws);
4950 // and re-insert the annotation at its correct position
4951 for (JvAnnotRow jvar : rws)
4953 al.addAnnotation(jvar.template, jvar.order);
4955 af.alignPanel.adjustAnnotationHeight();
4959 Hashtable skipList = null;
4962 * TODO remove this method
4965 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
4966 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
4967 * throw new Error("Implementation Error. No skipList defined for this
4968 * Jalview2XML instance."); } return (AlignFrame)
4969 * skipList.get(view.getSequenceSetId()); }
4973 * Check if the Jalview view contained in object should be skipped or not.
4976 * @return true if view's sequenceSetId is a key in skipList
4978 private boolean skipViewport(JalviewModel object)
4980 if (skipList == null)
4985 if (skipList.containsKey(
4986 id = object.getJalviewModelSequence().getViewport()[0]
4987 .getSequenceSetId()))
4989 if (Cache.log != null && Cache.log.isDebugEnabled())
4991 Cache.log.debug("Skipping seuqence set id " + id);
4998 public void addToSkipList(AlignFrame af)
5000 if (skipList == null)
5002 skipList = new Hashtable();
5004 skipList.put(af.getViewport().getSequenceSetId(), af);
5007 public void clearSkipList()
5009 if (skipList != null)
5016 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
5017 boolean ignoreUnrefed)
5019 jalview.datamodel.AlignmentI ds = getDatasetFor(
5020 vamsasSet.getDatasetId());
5021 Vector dseqs = null;
5024 // create a list of new dataset sequences
5025 dseqs = new Vector();
5027 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
5029 Sequence vamsasSeq = vamsasSet.getSequence(i);
5030 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
5032 // create a new dataset
5035 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
5036 dseqs.copyInto(dsseqs);
5037 ds = new jalview.datamodel.Alignment(dsseqs);
5038 debug("Created new dataset " + vamsasSet.getDatasetId()
5039 + " for alignment " + System.identityHashCode(al));
5040 addDatasetRef(vamsasSet.getDatasetId(), ds);
5042 // set the dataset for the newly imported alignment.
5043 if (al.getDataset() == null && !ignoreUnrefed)
5052 * sequence definition to create/merge dataset sequence for
5056 * vector to add new dataset sequence to
5057 * @param ignoreUnrefed
5058 * - when true, don't create new sequences from vamsasSeq if it's id
5059 * doesn't already have an asssociated Jalview sequence.
5061 * - used to reorder the sequence in the alignment according to the
5062 * vamsasSeq array ordering, to preserve ordering of dataset
5064 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
5065 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed, int vseqpos)
5067 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
5069 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
5070 boolean reorder = false;
5071 SequenceI dsq = null;
5072 if (sq != null && sq.getDatasetSequence() != null)
5074 dsq = sq.getDatasetSequence();
5080 if (sq == null && ignoreUnrefed)
5084 String sqid = vamsasSeq.getDsseqid();
5087 // need to create or add a new dataset sequence reference to this sequence
5090 dsq = seqRefIds.get(sqid);
5095 // make a new dataset sequence
5096 dsq = sq.createDatasetSequence();
5099 // make up a new dataset reference for this sequence
5100 sqid = seqHash(dsq);
5102 dsq.setVamsasId(uniqueSetSuffix + sqid);
5103 seqRefIds.put(sqid, dsq);
5108 dseqs.addElement(dsq);
5113 ds.addSequence(dsq);
5119 { // make this dataset sequence sq's dataset sequence
5120 sq.setDatasetSequence(dsq);
5121 // and update the current dataset alignment
5126 if (!dseqs.contains(dsq))
5133 if (ds.findIndex(dsq) < 0)
5135 ds.addSequence(dsq);
5142 // TODO: refactor this as a merge dataset sequence function
5143 // now check that sq (the dataset sequence) sequence really is the union of
5144 // all references to it
5145 // boolean pre = sq.getStart() < dsq.getStart();
5146 // boolean post = sq.getEnd() > dsq.getEnd();
5150 // StringBuffer sb = new StringBuffer();
5151 String newres = jalview.analysis.AlignSeq.extractGaps(
5152 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
5153 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
5154 && newres.length() > dsq.getLength())
5156 // Update with the longer sequence.
5160 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
5161 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
5162 * sb.append(newres.substring(newres.length() - sq.getEnd() -
5163 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
5165 dsq.setSequence(newres);
5167 // TODO: merges will never happen if we 'know' we have the real dataset
5168 // sequence - this should be detected when id==dssid
5170 "DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
5171 // + (pre ? "prepended" : "") + " "
5172 // + (post ? "appended" : ""));
5177 // sequence refs are identical. We may need to update the existing dataset
5178 // alignment with this one, though.
5179 if (ds != null && dseqs == null)
5181 int opos = ds.findIndex(dsq);
5182 SequenceI tseq = null;
5183 if (opos != -1 && vseqpos != opos)
5185 // remove from old position
5186 ds.deleteSequence(dsq);
5188 if (vseqpos < ds.getHeight())
5190 if (vseqpos != opos)
5192 // save sequence at destination position
5193 tseq = ds.getSequenceAt(vseqpos);
5194 ds.replaceSequenceAt(vseqpos, dsq);
5195 ds.addSequence(tseq);
5200 ds.addSequence(dsq);
5207 * TODO use AlignmentI here and in related methods - needs
5208 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
5210 Hashtable<String, AlignmentI> datasetIds = null;
5212 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
5214 private AlignmentI getDatasetFor(String datasetId)
5216 if (datasetIds == null)
5218 datasetIds = new Hashtable<>();
5221 if (datasetIds.containsKey(datasetId))
5223 return datasetIds.get(datasetId);
5228 private void addDatasetRef(String datasetId, AlignmentI dataset)
5230 if (datasetIds == null)
5232 datasetIds = new Hashtable<>();
5234 datasetIds.put(datasetId, dataset);
5238 * make a new dataset ID for this jalview dataset alignment
5243 private String getDatasetIdRef(AlignmentI dataset)
5245 if (dataset.getDataset() != null)
5247 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
5249 String datasetId = makeHashCode(dataset, null);
5250 if (datasetId == null)
5252 // make a new datasetId and record it
5253 if (dataset2Ids == null)
5255 dataset2Ids = new IdentityHashMap<>();
5259 datasetId = dataset2Ids.get(dataset);
5261 if (datasetId == null)
5263 datasetId = "ds" + dataset2Ids.size() + 1;
5264 dataset2Ids.put(dataset, datasetId);
5270 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5272 for (int d = 0; d < sequence.getDBRefCount(); d++)
5274 DBRef dr = sequence.getDBRef(d);
5275 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
5276 sequence.getDBRef(d).getSource(),
5277 sequence.getDBRef(d).getVersion(),
5278 sequence.getDBRef(d).getAccessionId());
5279 if (dr.getMapping() != null)
5281 entry.setMap(addMapping(dr.getMapping()));
5283 datasetSequence.addDBRef(entry);
5287 private jalview.datamodel.Mapping addMapping(Mapping m)
5289 SequenceI dsto = null;
5290 // Mapping m = dr.getMapping();
5291 int fr[] = new int[m.getMapListFromCount() * 2];
5292 Enumeration f = m.enumerateMapListFrom();
5293 for (int _i = 0; f.hasMoreElements(); _i += 2)
5295 MapListFrom mf = (MapListFrom) f.nextElement();
5296 fr[_i] = mf.getStart();
5297 fr[_i + 1] = mf.getEnd();
5299 int fto[] = new int[m.getMapListToCount() * 2];
5300 f = m.enumerateMapListTo();
5301 for (int _i = 0; f.hasMoreElements(); _i += 2)
5303 MapListTo mf = (MapListTo) f.nextElement();
5304 fto[_i] = mf.getStart();
5305 fto[_i + 1] = mf.getEnd();
5307 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto, fr,
5308 fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
5309 if (m.getMappingChoice() != null)
5311 MappingChoice mc = m.getMappingChoice();
5312 if (mc.getDseqFor() != null)
5314 String dsfor = "" + mc.getDseqFor();
5315 if (seqRefIds.containsKey(dsfor))
5320 jmap.setTo(seqRefIds.get(dsfor));
5324 frefedSequence.add(newMappingRef(dsfor, jmap));
5330 * local sequence definition
5332 Sequence ms = mc.getSequence();
5333 SequenceI djs = null;
5334 String sqid = ms.getDsseqid();
5335 if (sqid != null && sqid.length() > 0)
5338 * recover dataset sequence
5340 djs = seqRefIds.get(sqid);
5345 "Warning - making up dataset sequence id for DbRef sequence map reference");
5346 sqid = ((Object) ms).toString(); // make up a new hascode for
5347 // undefined dataset sequence hash
5348 // (unlikely to happen)
5354 * make a new dataset sequence and add it to refIds hash
5356 djs = new jalview.datamodel.Sequence(ms.getName(),
5358 djs.setStart(jmap.getMap().getToLowest());
5359 djs.setEnd(jmap.getMap().getToHighest());
5360 djs.setVamsasId(uniqueSetSuffix + sqid);
5362 incompleteSeqs.put(sqid, djs);
5363 seqRefIds.put(sqid, djs);
5366 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5376 * Provides a 'copy' of an alignment view (on action New View) by 'saving' the
5377 * view as XML (but not to file), and then reloading it
5382 public AlignmentPanel copyAlignPanel(AlignmentPanel ap)
5385 JalviewModel jm = saveState(ap, null, null, null);
5387 uniqueSetSuffix = "";
5388 jm.getJalviewModelSequence().getViewport(0).setId(null);
5389 // we don't overwrite the view we just copied
5391 if (this.frefedSequence == null)
5393 frefedSequence = new Vector<>();
5396 viewportsAdded.clear();
5398 AlignFrame af = loadFromObject(jm, null, false, null);
5399 af.alignPanels.clear();
5400 af.closeMenuItem_actionPerformed(true);
5403 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5404 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5405 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5406 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5407 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5410 return af.alignPanel;
5413 private Hashtable jvids2vobj;
5415 private void warn(String msg)
5420 private void warn(String msg, Exception e)
5422 if (Cache.log != null)
5426 Cache.log.warn(msg, e);
5430 Cache.log.warn(msg);
5435 System.err.println("Warning: " + msg);
5438 e.printStackTrace();
5443 private void debug(String string)
5445 debug(string, null);
5448 private void debug(String msg, Exception e)
5450 if (Cache.log != null)
5454 Cache.log.debug(msg, e);
5458 Cache.log.debug(msg);
5463 System.err.println("Warning: " + msg);
5466 e.printStackTrace();
5472 * set the object to ID mapping tables used to write/recover objects and XML
5473 * ID strings for the jalview project. If external tables are provided then
5474 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
5475 * object goes out of scope. - also populates the datasetIds hashtable with
5476 * alignment objects containing dataset sequences
5479 * Map from ID strings to jalview datamodel
5481 * Map from jalview datamodel to ID strings
5485 public void setObjectMappingTables(Hashtable vobj2jv,
5486 IdentityHashMap jv2vobj)
5488 this.jv2vobj = jv2vobj;
5489 this.vobj2jv = vobj2jv;
5490 Iterator ds = jv2vobj.keySet().iterator();
5492 while (ds.hasNext())
5494 Object jvobj = ds.next();
5495 id = jv2vobj.get(jvobj).toString();
5496 if (jvobj instanceof jalview.datamodel.Alignment)
5498 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
5500 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
5503 else if (jvobj instanceof jalview.datamodel.Sequence)
5505 // register sequence object so the XML parser can recover it.
5506 if (seqRefIds == null)
5508 seqRefIds = new HashMap<>();
5510 if (seqsToIds == null)
5512 seqsToIds = new IdentityHashMap<>();
5514 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
5515 seqsToIds.put((SequenceI) jvobj, id);
5517 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
5520 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
5521 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
5522 if (jvann.annotationId == null)
5524 jvann.annotationId = anid;
5526 if (!jvann.annotationId.equals(anid))
5528 // TODO verify that this is the correct behaviour
5529 this.warn("Overriding Annotation ID for " + anid
5530 + " from different id : " + jvann.annotationId);
5531 jvann.annotationId = anid;
5534 else if (jvobj instanceof String)
5536 if (jvids2vobj == null)
5538 jvids2vobj = new Hashtable();
5539 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
5544 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
5550 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
5551 * objects created from the project archive. If string is null (default for
5552 * construction) then suffix will be set automatically.
5556 public void setUniqueSetSuffix(String string)
5558 uniqueSetSuffix = string;
5563 * uses skipList2 as the skipList for skipping views on sequence sets
5564 * associated with keys in the skipList
5568 public void setSkipList(Hashtable skipList2)
5570 skipList = skipList2;
5574 * Reads the jar entry of given name and returns its contents, or null if the
5575 * entry is not found.
5578 * @param jarEntryName
5581 protected String readJarEntry(jarInputStreamProvider jprovider,
5582 String jarEntryName)
5584 String result = null;
5585 BufferedReader in = null;
5590 * Reopen the jar input stream and traverse its entries to find a matching
5593 JarInputStream jin = jprovider.getJarInputStream();
5594 JarEntry entry = null;
5597 entry = jin.getNextJarEntry();
5598 } while (entry != null && !entry.getName().equals(jarEntryName));
5602 StringBuilder out = new StringBuilder(256);
5603 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
5606 while ((data = in.readLine()) != null)
5610 result = out.toString();
5614 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
5616 } catch (Exception ex)
5618 ex.printStackTrace();
5626 } catch (IOException e)
5637 * Returns an incrementing counter (0, 1, 2...)
5641 private synchronized int nextCounter()