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);
3578 if (treeFile != null)
3582 AptxInit.createInstancesFromFile(treeFile, av);
3583 } catch (IOException e)
3585 // TODO Auto-generated catch block
3586 e.printStackTrace();
3595 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
3596 * panel is restored from separate jar entries, two (gapped and trimmed) per
3597 * sequence and secondary structure.
3599 * Currently each viewer shows just one sequence and structure (gapped and
3600 * trimmed), however this method is designed to support multiple sequences or
3601 * structures in viewers if wanted in future.
3607 private void loadRnaViewers(jarInputStreamProvider jprovider,
3608 JSeq[] jseqs, AlignmentPanel ap)
3611 * scan the sequences for references to viewers; create each one the first
3612 * time it is referenced, add Rna models to existing viewers
3614 for (JSeq jseq : jseqs)
3616 for (int i = 0; i < jseq.getRnaViewerCount(); i++)
3618 RnaViewer viewer = jseq.getRnaViewer(i);
3619 AppVarna appVarna = findOrCreateVarnaViewer(viewer, uniqueSetSuffix,
3622 for (int j = 0; j < viewer.getSecondaryStructureCount(); j++)
3624 SecondaryStructure ss = viewer.getSecondaryStructure(j);
3625 SequenceI seq = seqRefIds.get(jseq.getId());
3626 AlignmentAnnotation ann = this.annotationIds
3627 .get(ss.getAnnotationId());
3630 * add the structure to the Varna display (with session state copied
3631 * from the jar to a temporary file)
3633 boolean gapped = ss.isGapped();
3634 String rnaTitle = ss.getTitle();
3635 String sessionState = ss.getViewerState();
3636 String tempStateFile = copyJarEntry(jprovider, sessionState,
3638 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
3639 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
3641 appVarna.setInitialSelection(viewer.getSelectedRna());
3647 * Locate and return an already instantiated matching AppVarna, or create one
3651 * @param viewIdSuffix
3655 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
3656 String viewIdSuffix, AlignmentPanel ap)
3659 * on each load a suffix is appended to the saved viewId, to avoid conflicts
3660 * if load is repeated
3662 String postLoadId = viewer.getViewId() + viewIdSuffix;
3663 for (JInternalFrame frame : getAllFrames())
3665 if (frame instanceof AppVarna)
3667 AppVarna varna = (AppVarna) frame;
3668 if (postLoadId.equals(varna.getViewId()))
3670 // this viewer is already instantiated
3671 // could in future here add ap as another 'parent' of the
3672 // AppVarna window; currently just 1-to-many
3679 * viewer not found - make it
3681 RnaViewerModel model = new RnaViewerModel(postLoadId, viewer.getTitle(),
3682 viewer.getXpos(), viewer.getYpos(), viewer.getWidth(),
3683 viewer.getHeight(), viewer.getDividerLocation());
3684 AppVarna varna = new AppVarna(model, ap);
3690 * Load any saved trees
3698 protected void loadTrees(JalviewModelSequence jms, Viewport view,
3699 AlignFrame af, AlignViewport av, AlignmentPanel ap)
3701 // TODO result of automated refactoring - are all these parameters needed?
3704 for (int t = 0; t < jms.getTreeCount(); t++)
3707 Tree tree = jms.getTree(t);
3708 NewickFile newick = new jalview.io.NewickFile(tree.getNewick());
3710 TreeFrameI externalViewer = AptxInit.createInstanceFromNhx(
3711 tree.getTitle(), tree.getNewick(),
3715 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
3720 tp = af.showNewickTree(
3722 tree.getTitle(), tree.getWidth(), tree.getHeight(),
3723 tree.getXpos(), tree.getYpos());
3724 if (tree.getId() != null)
3726 // perhaps bind the tree id to something ?
3731 // update local tree attributes ?
3732 // TODO: should check if tp has been manipulated by user - if so its
3733 // settings shouldn't be modified
3734 tp.setTitle(tree.getTitle());
3735 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(),
3736 tree.getWidth(), tree.getHeight()));
3737 tp.av = av; // af.viewport; // TODO: verify 'associate with all
3740 tp.treeCanvas.av = av; // af.viewport;
3741 tp.treeCanvas.ap = ap; // af.alignPanel;
3746 warn("There was a problem recovering stored Newick tree: \n"
3747 + tree.getNewick());
3751 tp.fitToWindow.setState(tree.getFitToWindow());
3752 tp.fitToWindow_actionPerformed(null);
3754 if (tree.getFontName() != null)
3756 tp.setTreeFont(new java.awt.Font(tree.getFontName(),
3757 tree.getFontStyle(), tree.getFontSize()));
3761 tp.setTreeFont(new java.awt.Font(view.getFontName(),
3762 view.getFontStyle(), tree.getFontSize()));
3765 tp.showPlaceholders(tree.getMarkUnlinked());
3766 tp.showBootstrap(tree.getShowBootstrap());
3767 tp.showDistances(tree.getShowDistances());
3769 tp.treeCanvas.threshold = tree.getThreshold();
3771 if (tree.getCurrentTree())
3773 af.viewport.setCurrentTree(tp.getTree());
3777 } catch (Exception ex)
3779 ex.printStackTrace();
3784 * Load and link any saved structure viewers.
3791 protected void loadPDBStructures(jarInputStreamProvider jprovider,
3792 JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
3795 * Run through all PDB ids on the alignment, and collect mappings between
3796 * distinct view ids and all sequences referring to that view.
3798 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<>();
3800 for (int i = 0; i < jseqs.length; i++)
3802 if (jseqs[i].getPdbidsCount() > 0)
3804 Pdbids[] ids = jseqs[i].getPdbids();
3805 for (int p = 0; p < ids.length; p++)
3807 final int structureStateCount = ids[p].getStructureStateCount();
3808 for (int s = 0; s < structureStateCount; s++)
3810 // check to see if we haven't already created this structure view
3811 final StructureState structureState = ids[p]
3812 .getStructureState(s);
3813 String sviewid = (structureState.getViewId() == null) ? null
3814 : structureState.getViewId() + uniqueSetSuffix;
3815 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
3816 // Originally : ids[p].getFile()
3817 // : TODO: verify external PDB file recovery still works in normal
3818 // jalview project load
3819 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId(),
3821 jpdb.setId(ids[p].getId());
3823 int x = structureState.getXpos();
3824 int y = structureState.getYpos();
3825 int width = structureState.getWidth();
3826 int height = structureState.getHeight();
3828 // Probably don't need to do this anymore...
3829 // Desktop.desktop.getComponentAt(x, y);
3830 // TODO: NOW: check that this recovers the PDB file correctly.
3831 String pdbFile = loadPDBFile(jprovider, ids[p].getId(),
3833 jalview.datamodel.SequenceI seq = seqRefIds
3834 .get(jseqs[i].getId() + "");
3835 if (sviewid == null)
3837 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width + ","
3840 if (!structureViewers.containsKey(sviewid))
3842 structureViewers.put(sviewid,
3843 new StructureViewerModel(x, y, width, height, false,
3844 false, true, structureState.getViewId(),
3845 structureState.getType()));
3846 // Legacy pre-2.7 conversion JAL-823 :
3847 // do not assume any view has to be linked for colour by
3851 // assemble String[] { pdb files }, String[] { id for each
3852 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3853 // seqs_file 2}, boolean[] {
3854 // linkAlignPanel,superposeWithAlignpanel}} from hash
3855 StructureViewerModel jmoldat = structureViewers.get(sviewid);
3856 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
3857 | (structureState.hasAlignwithAlignPanel()
3858 ? structureState.getAlignwithAlignPanel()
3862 * Default colour by linked panel to false if not specified (e.g.
3863 * for pre-2.7 projects)
3865 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
3866 colourWithAlignPanel |= (structureState
3867 .hasColourwithAlignPanel()
3868 ? structureState.getColourwithAlignPanel()
3870 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
3873 * Default colour by viewer to true if not specified (e.g. for
3876 boolean colourByViewer = jmoldat.isColourByViewer();
3877 colourByViewer &= structureState.hasColourByJmol()
3878 ? structureState.getColourByJmol()
3880 jmoldat.setColourByViewer(colourByViewer);
3882 if (jmoldat.getStateData().length() < structureState
3883 .getContent().length())
3886 jmoldat.setStateData(structureState.getContent());
3889 if (ids[p].getFile() != null)
3891 File mapkey = new File(ids[p].getFile());
3892 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
3893 if (seqstrmaps == null)
3895 jmoldat.getFileData().put(mapkey,
3896 seqstrmaps = jmoldat.new StructureData(pdbFile,
3899 if (!seqstrmaps.getSeqList().contains(seq))
3901 seqstrmaps.getSeqList().add(seq);
3907 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");
3914 // Instantiate the associated structure views
3915 for (Entry<String, StructureViewerModel> entry : structureViewers
3920 createOrLinkStructureViewer(entry, af, ap, jprovider);
3921 } catch (Exception e)
3924 "Error loading structure viewer: " + e.getMessage());
3925 // failed - try the next one
3937 protected void createOrLinkStructureViewer(
3938 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3939 AlignmentPanel ap, jarInputStreamProvider jprovider)
3941 final StructureViewerModel stateData = viewerData.getValue();
3944 * Search for any viewer windows already open from other alignment views
3945 * that exactly match the stored structure state
3947 StructureViewerBase comp = findMatchingViewer(viewerData);
3951 linkStructureViewer(ap, comp, stateData);
3956 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
3957 * "viewer_"+stateData.viewId
3959 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
3961 createChimeraViewer(viewerData, af, jprovider);
3966 * else Jmol (if pre-2.9, stateData contains JMOL state string)
3968 createJmolViewer(viewerData, af, jprovider);
3973 * Create a new Chimera viewer.
3979 protected void createChimeraViewer(
3980 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3981 jarInputStreamProvider jprovider)
3983 StructureViewerModel data = viewerData.getValue();
3984 String chimeraSessionFile = data.getStateData();
3987 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
3989 * NB this is the 'saved' viewId as in the project file XML, _not_ the
3990 * 'uniquified' sviewid used to reconstruct the viewer here
3992 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
3993 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
3996 Set<Entry<File, StructureData>> fileData = data.getFileData()
3998 List<PDBEntry> pdbs = new ArrayList<>();
3999 List<SequenceI[]> allseqs = new ArrayList<>();
4000 for (Entry<File, StructureData> pdb : fileData)
4002 String filePath = pdb.getValue().getFilePath();
4003 String pdbId = pdb.getValue().getPdbId();
4004 // pdbs.add(new PDBEntry(filePath, pdbId));
4005 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
4006 final List<SequenceI> seqList = pdb.getValue().getSeqList();
4007 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
4011 boolean colourByChimera = data.isColourByViewer();
4012 boolean colourBySequence = data.isColourWithAlignPanel();
4014 // TODO use StructureViewer as a factory here, see JAL-1761
4015 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
4016 final SequenceI[][] seqsArray = allseqs
4017 .toArray(new SequenceI[allseqs.size()][]);
4018 String newViewId = viewerData.getKey();
4020 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
4021 af.alignPanel, pdbArray, seqsArray, colourByChimera,
4022 colourBySequence, newViewId);
4023 cvf.setSize(data.getWidth(), data.getHeight());
4024 cvf.setLocation(data.getX(), data.getY());
4028 * Create a new Jmol window. First parse the Jmol state to translate filenames
4029 * loaded into the view, and record the order in which files are shown in the
4030 * Jmol view, so we can add the sequence mappings in same order.
4036 protected void createJmolViewer(
4037 final Entry<String, StructureViewerModel> viewerData,
4038 AlignFrame af, jarInputStreamProvider jprovider)
4040 final StructureViewerModel svattrib = viewerData.getValue();
4041 String state = svattrib.getStateData();
4044 * Pre-2.9: state element value is the Jmol state string
4046 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
4049 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
4051 state = readJarEntry(jprovider,
4052 getViewerJarEntryName(svattrib.getViewId()));
4055 List<String> pdbfilenames = new ArrayList<>();
4056 List<SequenceI[]> seqmaps = new ArrayList<>();
4057 List<String> pdbids = new ArrayList<>();
4058 StringBuilder newFileLoc = new StringBuilder(64);
4059 int cp = 0, ncp, ecp;
4060 Map<File, StructureData> oldFiles = svattrib.getFileData();
4061 while ((ncp = state.indexOf("load ", cp)) > -1)
4065 // look for next filename in load statement
4066 newFileLoc.append(state.substring(cp,
4067 ncp = (state.indexOf("\"", ncp + 1) + 1)));
4068 String oldfilenam = state.substring(ncp,
4069 ecp = state.indexOf("\"", ncp));
4070 // recover the new mapping data for this old filename
4071 // have to normalize filename - since Jmol and jalview do
4073 // translation differently.
4074 StructureData filedat = oldFiles.get(new File(oldfilenam));
4075 if (filedat == null)
4077 String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\");
4078 filedat = oldFiles.get(new File(reformatedOldFilename));
4080 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
4081 pdbfilenames.add(filedat.getFilePath());
4082 pdbids.add(filedat.getPdbId());
4083 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4084 newFileLoc.append("\"");
4085 cp = ecp + 1; // advance beyond last \" and set cursor so we can
4086 // look for next file statement.
4087 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
4091 // just append rest of state
4092 newFileLoc.append(state.substring(cp));
4096 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
4097 newFileLoc = new StringBuilder(state);
4098 newFileLoc.append("; load append ");
4099 for (File id : oldFiles.keySet())
4101 // add this and any other pdb files that should be present in
4103 StructureData filedat = oldFiles.get(id);
4104 newFileLoc.append(filedat.getFilePath());
4105 pdbfilenames.add(filedat.getFilePath());
4106 pdbids.add(filedat.getPdbId());
4107 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4108 newFileLoc.append(" \"");
4109 newFileLoc.append(filedat.getFilePath());
4110 newFileLoc.append("\"");
4113 newFileLoc.append(";");
4116 if (newFileLoc.length() == 0)
4120 int histbug = newFileLoc.indexOf("history = ");
4124 * change "history = [true|false];" to "history = [1|0];"
4127 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
4128 String val = (diff == -1) ? null
4129 : newFileLoc.substring(histbug, diff);
4130 if (val != null && val.length() >= 4)
4132 if (val.contains("e")) // eh? what can it be?
4134 if (val.trim().equals("true"))
4142 newFileLoc.replace(histbug, diff, val);
4147 final String[] pdbf = pdbfilenames
4148 .toArray(new String[pdbfilenames.size()]);
4149 final String[] id = pdbids.toArray(new String[pdbids.size()]);
4150 final SequenceI[][] sq = seqmaps
4151 .toArray(new SequenceI[seqmaps.size()][]);
4152 final String fileloc = newFileLoc.toString();
4153 final String sviewid = viewerData.getKey();
4154 final AlignFrame alf = af;
4155 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
4156 svattrib.getWidth(), svattrib.getHeight());
4159 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
4164 JalviewStructureDisplayI sview = null;
4167 sview = new StructureViewer(
4168 alf.alignPanel.getStructureSelectionManager())
4169 .createView(StructureViewer.ViewerType.JMOL,
4170 pdbf, id, sq, alf.alignPanel, svattrib,
4171 fileloc, rect, sviewid);
4172 addNewStructureViewer(sview);
4173 } catch (OutOfMemoryError ex)
4175 new OOMWarning("restoring structure view for PDB id " + id,
4176 (OutOfMemoryError) ex.getCause());
4177 if (sview != null && sview.isVisible())
4179 sview.closeViewer(false);
4180 sview.setVisible(false);
4186 } catch (InvocationTargetException ex)
4188 warn("Unexpected error when opening Jmol view.", ex);
4190 } catch (InterruptedException e)
4192 // e.printStackTrace();
4198 * Generates a name for the entry in the project jar file to hold state
4199 * information for a structure viewer
4204 protected String getViewerJarEntryName(String viewId)
4206 return VIEWER_PREFIX + viewId;
4210 * Returns any open frame that matches given structure viewer data. The match
4211 * is based on the unique viewId, or (for older project versions) the frame's
4217 protected StructureViewerBase findMatchingViewer(
4218 Entry<String, StructureViewerModel> viewerData)
4220 final String sviewid = viewerData.getKey();
4221 final StructureViewerModel svattrib = viewerData.getValue();
4222 StructureViewerBase comp = null;
4223 JInternalFrame[] frames = getAllFrames();
4224 for (JInternalFrame frame : frames)
4226 if (frame instanceof StructureViewerBase)
4229 * Post jalview 2.4 schema includes structure view id
4231 if (sviewid != null && ((StructureViewerBase) frame).getViewId()
4234 comp = (StructureViewerBase) frame;
4235 break; // break added in 2.9
4238 * Otherwise test for matching position and size of viewer frame
4240 else if (frame.getX() == svattrib.getX()
4241 && frame.getY() == svattrib.getY()
4242 && frame.getHeight() == svattrib.getHeight()
4243 && frame.getWidth() == svattrib.getWidth())
4245 comp = (StructureViewerBase) frame;
4246 // no break in faint hope of an exact match on viewId
4254 * Link an AlignmentPanel to an existing structure viewer.
4259 * @param useinViewerSuperpos
4260 * @param usetoColourbyseq
4261 * @param viewerColouring
4263 protected void linkStructureViewer(AlignmentPanel ap,
4264 StructureViewerBase viewer, StructureViewerModel stateData)
4266 // NOTE: if the jalview project is part of a shared session then
4267 // view synchronization should/could be done here.
4269 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4270 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4271 final boolean viewerColouring = stateData.isColourByViewer();
4272 Map<File, StructureData> oldFiles = stateData.getFileData();
4275 * Add mapping for sequences in this view to an already open viewer
4277 final AAStructureBindingModel binding = viewer.getBinding();
4278 for (File id : oldFiles.keySet())
4280 // add this and any other pdb files that should be present in the
4282 StructureData filedat = oldFiles.get(id);
4283 String pdbFile = filedat.getFilePath();
4284 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4285 binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE,
4287 binding.addSequenceForStructFile(pdbFile, seq);
4289 // and add the AlignmentPanel's reference to the view panel
4290 viewer.addAlignmentPanel(ap);
4291 if (useinViewerSuperpos)
4293 viewer.useAlignmentPanelForSuperposition(ap);
4297 viewer.excludeAlignmentPanelForSuperposition(ap);
4299 if (usetoColourbyseq)
4301 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4305 viewer.excludeAlignmentPanelForColourbyseq(ap);
4310 * Get all frames within the Desktop.
4314 protected JInternalFrame[] getAllFrames()
4316 JInternalFrame[] frames = null;
4317 // TODO is this necessary - is it safe - risk of hanging?
4322 frames = Desktop.desktop.getAllFrames();
4323 } catch (ArrayIndexOutOfBoundsException e)
4325 // occasional No such child exceptions are thrown here...
4329 } catch (InterruptedException f)
4333 } while (frames == null);
4338 * Answers true if 'version' is equal to or later than 'supported', where each
4339 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4340 * changes. Development and test values for 'version' are leniently treated
4344 * - minimum version we are comparing against
4346 * - version of data being processsed
4349 public static boolean isVersionStringLaterThan(String supported,
4352 if (supported == null || version == null
4353 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4354 || version.equalsIgnoreCase("Test")
4355 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4357 System.err.println("Assuming project file with "
4358 + (version == null ? "null" : version)
4359 + " is compatible with Jalview version " + supported);
4364 return StringUtils.compareVersions(version, supported, "b") >= 0;
4368 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4370 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4372 if (newStructureViewers != null)
4374 sview.getBinding().setFinishedLoadingFromArchive(false);
4375 newStructureViewers.add(sview);
4379 protected void setLoadingFinishedForNewStructureViewers()
4381 if (newStructureViewers != null)
4383 for (JalviewStructureDisplayI sview : newStructureViewers)
4385 sview.getBinding().setFinishedLoadingFromArchive(true);
4387 newStructureViewers.clear();
4388 newStructureViewers = null;
4392 AlignFrame loadViewport(String file, JSeq[] JSEQ,
4393 List<SequenceI> hiddenSeqs, AlignmentI al,
4394 JalviewModelSequence jms, Viewport view, String uniqueSeqSetId,
4395 String viewId, List<JvAnnotRow> autoAlan)
4397 AlignFrame af = null;
4398 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
4399 uniqueSeqSetId, viewId);
4401 af.setFileName(file, FileFormat.Jalview);
4403 for (int i = 0; i < JSEQ.length; i++)
4405 af.viewport.setSequenceColour(
4406 af.viewport.getAlignment().getSequenceAt(i),
4407 new java.awt.Color(JSEQ[i].getColour()));
4412 af.getViewport().setColourByReferenceSeq(true);
4413 af.getViewport().setDisplayReferenceSeq(true);
4416 af.viewport.setGatherViewsHere(view.getGatheredViews());
4418 if (view.getSequenceSetId() != null)
4420 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4422 af.viewport.setSequenceSetId(uniqueSeqSetId);
4425 // propagate shared settings to this new view
4426 af.viewport.setHistoryList(av.getHistoryList());
4427 af.viewport.setRedoList(av.getRedoList());
4431 viewportsAdded.put(uniqueSeqSetId, af.viewport);
4433 // TODO: check if this method can be called repeatedly without
4434 // side-effects if alignpanel already registered.
4435 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4437 // apply Hidden regions to view.
4438 if (hiddenSeqs != null)
4440 for (int s = 0; s < JSEQ.length; s++)
4442 SequenceGroup hidden = new SequenceGroup();
4443 boolean isRepresentative = false;
4444 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
4446 isRepresentative = true;
4447 SequenceI sequenceToHide = al
4448 .getSequenceAt(JSEQ[s].getHiddenSequences(r));
4449 hidden.addSequence(sequenceToHide, false);
4450 // remove from hiddenSeqs list so we don't try to hide it twice
4451 hiddenSeqs.remove(sequenceToHide);
4453 if (isRepresentative)
4455 SequenceI representativeSequence = al.getSequenceAt(s);
4456 hidden.addSequence(representativeSequence, false);
4457 af.viewport.hideRepSequences(representativeSequence, hidden);
4461 SequenceI[] hseqs = hiddenSeqs
4462 .toArray(new SequenceI[hiddenSeqs.size()]);
4463 af.viewport.hideSequence(hseqs);
4466 // recover view properties and display parameters
4468 af.viewport.setShowAnnotation(view.getShowAnnotation());
4469 af.viewport.setAbovePIDThreshold(view.getPidSelected());
4470 af.viewport.setThreshold(view.getPidThreshold());
4472 af.viewport.setColourText(view.getShowColourText());
4474 af.viewport.setConservationSelected(view.getConservationSelected());
4475 af.viewport.setIncrement(view.getConsThreshold());
4476 af.viewport.setShowJVSuffix(view.getShowFullId());
4477 af.viewport.setRightAlignIds(view.getRightAlignIds());
4478 af.viewport.setFont(new java.awt.Font(view.getFontName(),
4479 view.getFontStyle(), view.getFontSize()), true);
4480 ViewStyleI vs = af.viewport.getViewStyle();
4481 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
4482 af.viewport.setViewStyle(vs);
4483 // TODO: allow custom charWidth/Heights to be restored by updating them
4484 // after setting font - which means set above to false
4485 af.viewport.setRenderGaps(view.getRenderGaps());
4486 af.viewport.setWrapAlignment(view.getWrapAlignment());
4487 af.viewport.setShowAnnotation(view.getShowAnnotation());
4489 af.viewport.setShowBoxes(view.getShowBoxes());
4491 af.viewport.setShowText(view.getShowText());
4493 af.viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
4494 af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
4495 af.viewport.setThresholdTextColour(view.getTextColThreshold());
4496 af.viewport.setShowUnconserved(
4497 view.hasShowUnconserved() ? view.isShowUnconserved() : false);
4498 af.viewport.getRanges().setStartRes(view.getStartRes());
4500 if (view.getViewName() != null)
4502 af.viewport.viewName = view.getViewName();
4503 af.setInitialTabVisible();
4505 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
4507 // startSeq set in af.alignPanel.updateLayout below
4508 af.alignPanel.updateLayout();
4509 ColourSchemeI cs = null;
4510 // apply colourschemes
4511 if (view.getBgColour() != null)
4513 if (view.getBgColour().startsWith("ucs"))
4515 cs = getUserColourScheme(jms, view.getBgColour());
4517 else if (view.getBgColour().startsWith("Annotation"))
4519 AnnotationColours viewAnnColour = view.getAnnotationColours();
4520 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
4527 cs = ColourSchemeProperty.getColourScheme(al, view.getBgColour());
4531 af.viewport.setGlobalColourScheme(cs);
4532 af.viewport.getResidueShading().setThreshold(view.getPidThreshold(),
4533 view.getIgnoreGapsinConsensus());
4534 af.viewport.getResidueShading()
4535 .setConsensus(af.viewport.getSequenceConsensusHash());
4536 af.viewport.setColourAppliesToAllGroups(false);
4538 if (view.getConservationSelected() && cs != null)
4540 af.viewport.getResidueShading()
4541 .setConservationInc(view.getConsThreshold());
4544 af.changeColour(cs);
4546 af.viewport.setColourAppliesToAllGroups(true);
4548 af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures());
4550 if (view.hasCentreColumnLabels())
4552 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
4554 if (view.hasIgnoreGapsinConsensus())
4556 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
4559 if (view.hasFollowHighlight())
4561 af.viewport.setFollowHighlight(view.getFollowHighlight());
4563 if (view.hasFollowSelection())
4565 af.viewport.followSelection = view.getFollowSelection();
4567 if (view.hasShowConsensusHistogram())
4570 .setShowConsensusHistogram(view.getShowConsensusHistogram());
4574 af.viewport.setShowConsensusHistogram(true);
4576 if (view.hasShowSequenceLogo())
4578 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
4582 af.viewport.setShowSequenceLogo(false);
4584 if (view.hasNormaliseSequenceLogo())
4586 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
4588 if (view.hasShowDbRefTooltip())
4590 af.viewport.setShowDBRefs(view.getShowDbRefTooltip());
4592 if (view.hasShowNPfeatureTooltip())
4594 af.viewport.setShowNPFeats(view.hasShowNPfeatureTooltip());
4596 if (view.hasShowGroupConsensus())
4598 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
4602 af.viewport.setShowGroupConsensus(false);
4604 if (view.hasShowGroupConservation())
4606 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
4610 af.viewport.setShowGroupConservation(false);
4613 // recover featre settings
4614 if (jms.getFeatureSettings() != null)
4616 FeaturesDisplayed fdi;
4617 af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
4618 String[] renderOrder = new String[jms.getFeatureSettings()
4619 .getSettingCount()];
4620 Map<String, FeatureColourI> featureColours = new Hashtable<>();
4621 Map<String, Float> featureOrder = new Hashtable<>();
4623 for (int fs = 0; fs < jms.getFeatureSettings()
4624 .getSettingCount(); fs++)
4626 Setting setting = jms.getFeatureSettings().getSetting(fs);
4627 if (setting.hasMincolour())
4629 FeatureColourI gc = setting.hasMin()
4630 ? new FeatureColour(new Color(setting.getMincolour()),
4631 new Color(setting.getColour()), setting.getMin(),
4633 : new FeatureColour(new Color(setting.getMincolour()),
4634 new Color(setting.getColour()), 0, 1);
4635 if (setting.hasThreshold())
4637 gc.setThreshold(setting.getThreshold());
4638 int threshstate = setting.getThreshstate();
4639 // -1 = None, 0 = Below, 1 = Above threshold
4640 if (threshstate == 0)
4642 gc.setBelowThreshold(true);
4644 else if (threshstate == 1)
4646 gc.setAboveThreshold(true);
4649 gc.setAutoScaled(true); // default
4650 if (setting.hasAutoScale())
4652 gc.setAutoScaled(setting.getAutoScale());
4654 if (setting.hasColourByLabel())
4656 gc.setColourByLabel(setting.getColourByLabel());
4658 // and put in the feature colour table.
4659 featureColours.put(setting.getType(), gc);
4663 featureColours.put(setting.getType(),
4664 new FeatureColour(new Color(setting.getColour())));
4666 renderOrder[fs] = setting.getType();
4667 if (setting.hasOrder())
4669 featureOrder.put(setting.getType(), setting.getOrder());
4673 featureOrder.put(setting.getType(), new Float(
4674 fs / jms.getFeatureSettings().getSettingCount()));
4676 if (setting.getDisplay())
4678 fdi.setVisible(setting.getType());
4681 Map<String, Boolean> fgtable = new Hashtable<>();
4682 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
4684 Group grp = jms.getFeatureSettings().getGroup(gs);
4685 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
4687 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4688 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
4689 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
4690 FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4691 fgtable, featureColours, 1.0f, featureOrder);
4692 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
4693 .transferSettings(frs);
4697 if (view.getHiddenColumnsCount() > 0)
4699 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
4701 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(),
4702 view.getHiddenColumns(c).getEnd() // +1
4706 if (view.getCalcIdParam() != null)
4708 for (CalcIdParam calcIdParam : view.getCalcIdParam())
4710 if (calcIdParam != null)
4712 if (recoverCalcIdParam(calcIdParam, af.viewport))
4717 warn("Couldn't recover parameters for "
4718 + calcIdParam.getCalcId());
4723 af.setMenusFromViewport(af.viewport);
4724 af.setTitle(view.getTitle());
4725 // TODO: we don't need to do this if the viewport is aready visible.
4727 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
4728 * has a 'cdna/protein complement' view, in which case save it in order to
4729 * populate a SplitFrame once all views have been read in.
4731 String complementaryViewId = view.getComplementId();
4732 if (complementaryViewId == null)
4734 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
4736 // recompute any autoannotation
4737 af.alignPanel.updateAnnotation(false, true);
4738 reorderAutoannotation(af, al, autoAlan);
4739 af.alignPanel.alignmentChanged();
4743 splitFrameCandidates.put(view, af);
4749 * Reads saved data to restore Colour by Annotation settings
4751 * @param viewAnnColour
4755 * @param checkGroupAnnColour
4758 private ColourSchemeI constructAnnotationColour(
4759 AnnotationColours viewAnnColour, AlignFrame af, AlignmentI al,
4760 JalviewModelSequence jms, boolean checkGroupAnnColour)
4762 boolean propagateAnnColour = false;
4763 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
4764 if (checkGroupAnnColour && al.getGroups() != null
4765 && al.getGroups().size() > 0)
4767 // pre 2.8.1 behaviour
4768 // check to see if we should transfer annotation colours
4769 propagateAnnColour = true;
4770 for (SequenceGroup sg : al.getGroups())
4772 if (sg.getColourScheme() instanceof AnnotationColourGradient)
4774 propagateAnnColour = false;
4780 * 2.10.2- : saved annotationId is AlignmentAnnotation.annotationId
4782 String annotationId = viewAnnColour.getAnnotation();
4783 AlignmentAnnotation matchedAnnotation = annotationIds.get(annotationId);
4786 * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
4788 if (matchedAnnotation == null
4789 && annAlignment.getAlignmentAnnotation() != null)
4791 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
4794 .equals(annAlignment.getAlignmentAnnotation()[i].label))
4796 matchedAnnotation = annAlignment.getAlignmentAnnotation()[i];
4801 if (matchedAnnotation == null)
4803 System.err.println("Failed to match annotation colour scheme for "
4807 if (matchedAnnotation.getThreshold() == null)
4809 matchedAnnotation.setThreshold(new GraphLine(
4810 viewAnnColour.getThreshold(), "Threshold", Color.black));
4813 AnnotationColourGradient cs = null;
4814 if (viewAnnColour.getColourScheme().equals("None"))
4816 cs = new AnnotationColourGradient(matchedAnnotation,
4817 new Color(viewAnnColour.getMinColour()),
4818 new Color(viewAnnColour.getMaxColour()),
4819 viewAnnColour.getAboveThreshold());
4821 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
4823 cs = new AnnotationColourGradient(matchedAnnotation,
4824 getUserColourScheme(jms, viewAnnColour.getColourScheme()),
4825 viewAnnColour.getAboveThreshold());
4829 cs = new AnnotationColourGradient(matchedAnnotation,
4830 ColourSchemeProperty.getColourScheme(al,
4831 viewAnnColour.getColourScheme()),
4832 viewAnnColour.getAboveThreshold());
4835 boolean perSequenceOnly = viewAnnColour.isPerSequence();
4836 boolean useOriginalColours = viewAnnColour.isPredefinedColours();
4837 cs.setSeqAssociated(perSequenceOnly);
4838 cs.setPredefinedColours(useOriginalColours);
4840 if (propagateAnnColour && al.getGroups() != null)
4842 // Also use these settings for all the groups
4843 for (int g = 0; g < al.getGroups().size(); g++)
4845 SequenceGroup sg = al.getGroups().get(g);
4846 if (sg.getGroupColourScheme() == null)
4851 AnnotationColourGradient groupScheme = new AnnotationColourGradient(
4852 matchedAnnotation, sg.getColourScheme(),
4853 viewAnnColour.getAboveThreshold());
4854 sg.setColourScheme(groupScheme);
4855 groupScheme.setSeqAssociated(perSequenceOnly);
4856 groupScheme.setPredefinedColours(useOriginalColours);
4862 private void reorderAutoannotation(AlignFrame af, AlignmentI al,
4863 List<JvAnnotRow> autoAlan)
4865 // copy over visualization settings for autocalculated annotation in the
4867 if (al.getAlignmentAnnotation() != null)
4870 * Kludge for magic autoannotation names (see JAL-811)
4872 String[] magicNames = new String[] { "Consensus", "Quality",
4874 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
4875 Hashtable<String, JvAnnotRow> visan = new Hashtable<>();
4876 for (String nm : magicNames)
4878 visan.put(nm, nullAnnot);
4880 for (JvAnnotRow auan : autoAlan)
4882 visan.put(auan.template.label
4883 + (auan.template.getCalcId() == null ? ""
4884 : "\t" + auan.template.getCalcId()),
4887 int hSize = al.getAlignmentAnnotation().length;
4888 List<JvAnnotRow> reorder = new ArrayList<>();
4889 // work through any autoCalculated annotation already on the view
4890 // removing it if it should be placed in a different location on the
4891 // annotation panel.
4892 List<String> remains = new ArrayList<>(visan.keySet());
4893 for (int h = 0; h < hSize; h++)
4895 jalview.datamodel.AlignmentAnnotation jalan = al
4896 .getAlignmentAnnotation()[h];
4897 if (jalan.autoCalculated)
4900 JvAnnotRow valan = visan.get(k = jalan.label);
4901 if (jalan.getCalcId() != null)
4903 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
4908 // delete the auto calculated row from the alignment
4909 al.deleteAnnotation(jalan, false);
4913 if (valan != nullAnnot)
4915 if (jalan != valan.template)
4917 // newly created autoannotation row instance
4918 // so keep a reference to the visible annotation row
4919 // and copy over all relevant attributes
4920 if (valan.template.graphHeight >= 0)
4923 jalan.graphHeight = valan.template.graphHeight;
4925 jalan.visible = valan.template.visible;
4927 reorder.add(new JvAnnotRow(valan.order, jalan));
4932 // Add any (possibly stale) autocalculated rows that were not appended to
4933 // the view during construction
4934 for (String other : remains)
4936 JvAnnotRow othera = visan.get(other);
4937 if (othera != nullAnnot && othera.template.getCalcId() != null
4938 && othera.template.getCalcId().length() > 0)
4940 reorder.add(othera);
4943 // now put the automatic annotation in its correct place
4944 int s = 0, srt[] = new int[reorder.size()];
4945 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
4946 for (JvAnnotRow jvar : reorder)
4949 srt[s++] = jvar.order;
4952 jalview.util.QuickSort.sort(srt, rws);
4953 // and re-insert the annotation at its correct position
4954 for (JvAnnotRow jvar : rws)
4956 al.addAnnotation(jvar.template, jvar.order);
4958 af.alignPanel.adjustAnnotationHeight();
4962 Hashtable skipList = null;
4965 * TODO remove this method
4968 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
4969 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
4970 * throw new Error("Implementation Error. No skipList defined for this
4971 * Jalview2XML instance."); } return (AlignFrame)
4972 * skipList.get(view.getSequenceSetId()); }
4976 * Check if the Jalview view contained in object should be skipped or not.
4979 * @return true if view's sequenceSetId is a key in skipList
4981 private boolean skipViewport(JalviewModel object)
4983 if (skipList == null)
4988 if (skipList.containsKey(
4989 id = object.getJalviewModelSequence().getViewport()[0]
4990 .getSequenceSetId()))
4992 if (Cache.log != null && Cache.log.isDebugEnabled())
4994 Cache.log.debug("Skipping seuqence set id " + id);
5001 public void addToSkipList(AlignFrame af)
5003 if (skipList == null)
5005 skipList = new Hashtable();
5007 skipList.put(af.getViewport().getSequenceSetId(), af);
5010 public void clearSkipList()
5012 if (skipList != null)
5019 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
5020 boolean ignoreUnrefed)
5022 jalview.datamodel.AlignmentI ds = getDatasetFor(
5023 vamsasSet.getDatasetId());
5024 Vector dseqs = null;
5027 // create a list of new dataset sequences
5028 dseqs = new Vector();
5030 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
5032 Sequence vamsasSeq = vamsasSet.getSequence(i);
5033 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
5035 // create a new dataset
5038 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
5039 dseqs.copyInto(dsseqs);
5040 ds = new jalview.datamodel.Alignment(dsseqs);
5041 debug("Created new dataset " + vamsasSet.getDatasetId()
5042 + " for alignment " + System.identityHashCode(al));
5043 addDatasetRef(vamsasSet.getDatasetId(), ds);
5045 // set the dataset for the newly imported alignment.
5046 if (al.getDataset() == null && !ignoreUnrefed)
5055 * sequence definition to create/merge dataset sequence for
5059 * vector to add new dataset sequence to
5060 * @param ignoreUnrefed
5061 * - when true, don't create new sequences from vamsasSeq if it's id
5062 * doesn't already have an asssociated Jalview sequence.
5064 * - used to reorder the sequence in the alignment according to the
5065 * vamsasSeq array ordering, to preserve ordering of dataset
5067 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
5068 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed, int vseqpos)
5070 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
5072 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
5073 boolean reorder = false;
5074 SequenceI dsq = null;
5075 if (sq != null && sq.getDatasetSequence() != null)
5077 dsq = sq.getDatasetSequence();
5083 if (sq == null && ignoreUnrefed)
5087 String sqid = vamsasSeq.getDsseqid();
5090 // need to create or add a new dataset sequence reference to this sequence
5093 dsq = seqRefIds.get(sqid);
5098 // make a new dataset sequence
5099 dsq = sq.createDatasetSequence();
5102 // make up a new dataset reference for this sequence
5103 sqid = seqHash(dsq);
5105 dsq.setVamsasId(uniqueSetSuffix + sqid);
5106 seqRefIds.put(sqid, dsq);
5111 dseqs.addElement(dsq);
5116 ds.addSequence(dsq);
5122 { // make this dataset sequence sq's dataset sequence
5123 sq.setDatasetSequence(dsq);
5124 // and update the current dataset alignment
5129 if (!dseqs.contains(dsq))
5136 if (ds.findIndex(dsq) < 0)
5138 ds.addSequence(dsq);
5145 // TODO: refactor this as a merge dataset sequence function
5146 // now check that sq (the dataset sequence) sequence really is the union of
5147 // all references to it
5148 // boolean pre = sq.getStart() < dsq.getStart();
5149 // boolean post = sq.getEnd() > dsq.getEnd();
5153 // StringBuffer sb = new StringBuffer();
5154 String newres = jalview.analysis.AlignSeq.extractGaps(
5155 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
5156 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
5157 && newres.length() > dsq.getLength())
5159 // Update with the longer sequence.
5163 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
5164 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
5165 * sb.append(newres.substring(newres.length() - sq.getEnd() -
5166 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
5168 dsq.setSequence(newres);
5170 // TODO: merges will never happen if we 'know' we have the real dataset
5171 // sequence - this should be detected when id==dssid
5173 "DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
5174 // + (pre ? "prepended" : "") + " "
5175 // + (post ? "appended" : ""));
5180 // sequence refs are identical. We may need to update the existing dataset
5181 // alignment with this one, though.
5182 if (ds != null && dseqs == null)
5184 int opos = ds.findIndex(dsq);
5185 SequenceI tseq = null;
5186 if (opos != -1 && vseqpos != opos)
5188 // remove from old position
5189 ds.deleteSequence(dsq);
5191 if (vseqpos < ds.getHeight())
5193 if (vseqpos != opos)
5195 // save sequence at destination position
5196 tseq = ds.getSequenceAt(vseqpos);
5197 ds.replaceSequenceAt(vseqpos, dsq);
5198 ds.addSequence(tseq);
5203 ds.addSequence(dsq);
5210 * TODO use AlignmentI here and in related methods - needs
5211 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
5213 Hashtable<String, AlignmentI> datasetIds = null;
5215 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
5217 private AlignmentI getDatasetFor(String datasetId)
5219 if (datasetIds == null)
5221 datasetIds = new Hashtable<>();
5224 if (datasetIds.containsKey(datasetId))
5226 return datasetIds.get(datasetId);
5231 private void addDatasetRef(String datasetId, AlignmentI dataset)
5233 if (datasetIds == null)
5235 datasetIds = new Hashtable<>();
5237 datasetIds.put(datasetId, dataset);
5241 * make a new dataset ID for this jalview dataset alignment
5246 private String getDatasetIdRef(AlignmentI dataset)
5248 if (dataset.getDataset() != null)
5250 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
5252 String datasetId = makeHashCode(dataset, null);
5253 if (datasetId == null)
5255 // make a new datasetId and record it
5256 if (dataset2Ids == null)
5258 dataset2Ids = new IdentityHashMap<>();
5262 datasetId = dataset2Ids.get(dataset);
5264 if (datasetId == null)
5266 datasetId = "ds" + dataset2Ids.size() + 1;
5267 dataset2Ids.put(dataset, datasetId);
5273 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5275 for (int d = 0; d < sequence.getDBRefCount(); d++)
5277 DBRef dr = sequence.getDBRef(d);
5278 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
5279 sequence.getDBRef(d).getSource(),
5280 sequence.getDBRef(d).getVersion(),
5281 sequence.getDBRef(d).getAccessionId());
5282 if (dr.getMapping() != null)
5284 entry.setMap(addMapping(dr.getMapping()));
5286 datasetSequence.addDBRef(entry);
5290 private jalview.datamodel.Mapping addMapping(Mapping m)
5292 SequenceI dsto = null;
5293 // Mapping m = dr.getMapping();
5294 int fr[] = new int[m.getMapListFromCount() * 2];
5295 Enumeration f = m.enumerateMapListFrom();
5296 for (int _i = 0; f.hasMoreElements(); _i += 2)
5298 MapListFrom mf = (MapListFrom) f.nextElement();
5299 fr[_i] = mf.getStart();
5300 fr[_i + 1] = mf.getEnd();
5302 int fto[] = new int[m.getMapListToCount() * 2];
5303 f = m.enumerateMapListTo();
5304 for (int _i = 0; f.hasMoreElements(); _i += 2)
5306 MapListTo mf = (MapListTo) f.nextElement();
5307 fto[_i] = mf.getStart();
5308 fto[_i + 1] = mf.getEnd();
5310 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto, fr,
5311 fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
5312 if (m.getMappingChoice() != null)
5314 MappingChoice mc = m.getMappingChoice();
5315 if (mc.getDseqFor() != null)
5317 String dsfor = "" + mc.getDseqFor();
5318 if (seqRefIds.containsKey(dsfor))
5323 jmap.setTo(seqRefIds.get(dsfor));
5327 frefedSequence.add(newMappingRef(dsfor, jmap));
5333 * local sequence definition
5335 Sequence ms = mc.getSequence();
5336 SequenceI djs = null;
5337 String sqid = ms.getDsseqid();
5338 if (sqid != null && sqid.length() > 0)
5341 * recover dataset sequence
5343 djs = seqRefIds.get(sqid);
5348 "Warning - making up dataset sequence id for DbRef sequence map reference");
5349 sqid = ((Object) ms).toString(); // make up a new hascode for
5350 // undefined dataset sequence hash
5351 // (unlikely to happen)
5357 * make a new dataset sequence and add it to refIds hash
5359 djs = new jalview.datamodel.Sequence(ms.getName(),
5361 djs.setStart(jmap.getMap().getToLowest());
5362 djs.setEnd(jmap.getMap().getToHighest());
5363 djs.setVamsasId(uniqueSetSuffix + sqid);
5365 incompleteSeqs.put(sqid, djs);
5366 seqRefIds.put(sqid, djs);
5369 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5379 * Provides a 'copy' of an alignment view (on action New View) by 'saving' the
5380 * view as XML (but not to file), and then reloading it
5385 public AlignmentPanel copyAlignPanel(AlignmentPanel ap)
5388 JalviewModel jm = saveState(ap, null, null, null);
5390 uniqueSetSuffix = "";
5391 jm.getJalviewModelSequence().getViewport(0).setId(null);
5392 // we don't overwrite the view we just copied
5394 if (this.frefedSequence == null)
5396 frefedSequence = new Vector<>();
5399 viewportsAdded.clear();
5401 AlignFrame af = loadFromObject(jm, null, false, null);
5402 af.alignPanels.clear();
5403 af.closeMenuItem_actionPerformed(true);
5406 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5407 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5408 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5409 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5410 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5413 return af.alignPanel;
5416 private Hashtable jvids2vobj;
5418 private void warn(String msg)
5423 private void warn(String msg, Exception e)
5425 if (Cache.log != null)
5429 Cache.log.warn(msg, e);
5433 Cache.log.warn(msg);
5438 System.err.println("Warning: " + msg);
5441 e.printStackTrace();
5446 private void debug(String string)
5448 debug(string, null);
5451 private void debug(String msg, Exception e)
5453 if (Cache.log != null)
5457 Cache.log.debug(msg, e);
5461 Cache.log.debug(msg);
5466 System.err.println("Warning: " + msg);
5469 e.printStackTrace();
5475 * set the object to ID mapping tables used to write/recover objects and XML
5476 * ID strings for the jalview project. If external tables are provided then
5477 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
5478 * object goes out of scope. - also populates the datasetIds hashtable with
5479 * alignment objects containing dataset sequences
5482 * Map from ID strings to jalview datamodel
5484 * Map from jalview datamodel to ID strings
5488 public void setObjectMappingTables(Hashtable vobj2jv,
5489 IdentityHashMap jv2vobj)
5491 this.jv2vobj = jv2vobj;
5492 this.vobj2jv = vobj2jv;
5493 Iterator ds = jv2vobj.keySet().iterator();
5495 while (ds.hasNext())
5497 Object jvobj = ds.next();
5498 id = jv2vobj.get(jvobj).toString();
5499 if (jvobj instanceof jalview.datamodel.Alignment)
5501 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
5503 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
5506 else if (jvobj instanceof jalview.datamodel.Sequence)
5508 // register sequence object so the XML parser can recover it.
5509 if (seqRefIds == null)
5511 seqRefIds = new HashMap<>();
5513 if (seqsToIds == null)
5515 seqsToIds = new IdentityHashMap<>();
5517 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
5518 seqsToIds.put((SequenceI) jvobj, id);
5520 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
5523 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
5524 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
5525 if (jvann.annotationId == null)
5527 jvann.annotationId = anid;
5529 if (!jvann.annotationId.equals(anid))
5531 // TODO verify that this is the correct behaviour
5532 this.warn("Overriding Annotation ID for " + anid
5533 + " from different id : " + jvann.annotationId);
5534 jvann.annotationId = anid;
5537 else if (jvobj instanceof String)
5539 if (jvids2vobj == null)
5541 jvids2vobj = new Hashtable();
5542 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
5547 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
5553 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
5554 * objects created from the project archive. If string is null (default for
5555 * construction) then suffix will be set automatically.
5559 public void setUniqueSetSuffix(String string)
5561 uniqueSetSuffix = string;
5566 * uses skipList2 as the skipList for skipping views on sequence sets
5567 * associated with keys in the skipList
5571 public void setSkipList(Hashtable skipList2)
5573 skipList = skipList2;
5577 * Reads the jar entry of given name and returns its contents, or null if the
5578 * entry is not found.
5581 * @param jarEntryName
5584 protected String readJarEntry(jarInputStreamProvider jprovider,
5585 String jarEntryName)
5587 String result = null;
5588 BufferedReader in = null;
5593 * Reopen the jar input stream and traverse its entries to find a matching
5596 JarInputStream jin = jprovider.getJarInputStream();
5597 JarEntry entry = null;
5600 entry = jin.getNextJarEntry();
5601 } while (entry != null && !entry.getName().equals(jarEntryName));
5605 StringBuilder out = new StringBuilder(256);
5606 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
5609 while ((data = in.readLine()) != null)
5613 result = out.toString();
5617 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
5619 } catch (Exception ex)
5621 ex.printStackTrace();
5629 } catch (IOException e)
5640 * Returns an incrementing counter (0, 1, 2...)
5644 private synchronized int nextCounter()