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();
1115 // tree.writeToJalviewProject(outputFile);
1124 * store forward refs from an annotationRow to any groups
1126 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<>();
1129 for (SequenceI sq : jal.getSequences())
1131 // Store annotation on dataset sequences only
1132 AlignmentAnnotation[] aa = sq.getAnnotation();
1133 if (aa != null && aa.length > 0)
1135 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1142 if (jal.getAlignmentAnnotation() != null)
1144 // Store the annotation shown on the alignment.
1145 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1146 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1151 if (jal.getGroups() != null)
1153 JGroup[] groups = new JGroup[jal.getGroups().size()];
1155 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1157 JGroup jGroup = new JGroup();
1158 groups[++i] = jGroup;
1160 jGroup.setStart(sg.getStartRes());
1161 jGroup.setEnd(sg.getEndRes());
1162 jGroup.setName(sg.getName());
1163 if (groupRefs.containsKey(sg))
1165 // group has references so set its ID field
1166 jGroup.setId(groupRefs.get(sg));
1168 ColourSchemeI colourScheme = sg.getColourScheme();
1169 if (colourScheme != null)
1171 ResidueShaderI groupColourScheme = sg.getGroupColourScheme();
1172 if (groupColourScheme.conservationApplied())
1174 jGroup.setConsThreshold(groupColourScheme.getConservationInc());
1176 if (colourScheme instanceof jalview.schemes.UserColourScheme)
1179 setUserColourScheme(colourScheme, userColours, jms));
1183 jGroup.setColour(colourScheme.getSchemeName());
1186 else if (colourScheme instanceof jalview.schemes.AnnotationColourGradient)
1188 jGroup.setColour("AnnotationColourGradient");
1189 jGroup.setAnnotationColours(constructAnnotationColours(
1190 (jalview.schemes.AnnotationColourGradient) colourScheme,
1193 else if (colourScheme instanceof jalview.schemes.UserColourScheme)
1196 setUserColourScheme(colourScheme, userColours, jms));
1200 jGroup.setColour(colourScheme.getSchemeName());
1203 jGroup.setPidThreshold(groupColourScheme.getThreshold());
1206 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1207 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1208 jGroup.setDisplayText(sg.getDisplayText());
1209 jGroup.setColourText(sg.getColourText());
1210 jGroup.setTextCol1(sg.textColour.getRGB());
1211 jGroup.setTextCol2(sg.textColour2.getRGB());
1212 jGroup.setTextColThreshold(sg.thresholdTextColour);
1213 jGroup.setShowUnconserved(sg.getShowNonconserved());
1214 jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1215 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1216 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1217 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1218 for (SequenceI seq : sg.getSequences())
1220 jGroup.addSeq(seqHash(seq));
1224 jms.setJGroup(groups);
1228 // /////////SAVE VIEWPORT
1229 Viewport view = new Viewport();
1230 view.setTitle(ap.alignFrame.getTitle());
1231 view.setSequenceSetId(
1232 makeHashCode(av.getSequenceSetId(), av.getSequenceSetId()));
1233 view.setId(av.getViewId());
1234 if (av.getCodingComplement() != null)
1236 view.setComplementId(av.getCodingComplement().getViewId());
1238 view.setViewName(av.viewName);
1239 view.setGatheredViews(av.isGatherViewsHere());
1241 Rectangle size = ap.av.getExplodedGeometry();
1242 Rectangle position = size;
1245 size = ap.alignFrame.getBounds();
1246 if (av.getCodingComplement() != null)
1248 position = ((SplitFrame) ap.alignFrame.getSplitViewContainer())
1256 view.setXpos(position.x);
1257 view.setYpos(position.y);
1259 view.setWidth(size.width);
1260 view.setHeight(size.height);
1262 view.setStartRes(vpRanges.getStartRes());
1263 view.setStartSeq(vpRanges.getStartSeq());
1265 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1267 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1271 .getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1273 AnnotationColours ac = constructAnnotationColours(
1274 (jalview.schemes.AnnotationColourGradient) av
1275 .getGlobalColourScheme(),
1278 view.setAnnotationColours(ac);
1279 view.setBgColour("AnnotationColourGradient");
1283 view.setBgColour(ColourSchemeProperty
1284 .getColourName(av.getGlobalColourScheme()));
1287 ResidueShaderI vcs = av.getResidueShading();
1288 ColourSchemeI cs = av.getGlobalColourScheme();
1292 if (vcs.conservationApplied())
1294 view.setConsThreshold(vcs.getConservationInc());
1295 if (cs instanceof jalview.schemes.UserColourScheme)
1297 view.setBgColour(setUserColourScheme(cs, userColours, jms));
1300 view.setPidThreshold(vcs.getThreshold());
1303 view.setConservationSelected(av.getConservationSelected());
1304 view.setPidSelected(av.getAbovePIDThreshold());
1305 view.setFontName(av.font.getName());
1306 view.setFontSize(av.font.getSize());
1307 view.setFontStyle(av.font.getStyle());
1308 view.setScaleProteinAsCdna(av.getViewStyle().isScaleProteinAsCdna());
1309 view.setRenderGaps(av.isRenderGaps());
1310 view.setShowAnnotation(av.isShowAnnotation());
1311 view.setShowBoxes(av.getShowBoxes());
1312 view.setShowColourText(av.getColourText());
1313 view.setShowFullId(av.getShowJVSuffix());
1314 view.setRightAlignIds(av.isRightAlignIds());
1315 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1316 view.setShowText(av.getShowText());
1317 view.setShowUnconserved(av.getShowUnconserved());
1318 view.setWrapAlignment(av.getWrapAlignment());
1319 view.setTextCol1(av.getTextColour().getRGB());
1320 view.setTextCol2(av.getTextColour2().getRGB());
1321 view.setTextColThreshold(av.getThresholdTextColour());
1322 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1323 view.setShowSequenceLogo(av.isShowSequenceLogo());
1324 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1325 view.setShowGroupConsensus(av.isShowGroupConsensus());
1326 view.setShowGroupConservation(av.isShowGroupConservation());
1327 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1328 view.setShowDbRefTooltip(av.isShowDBRefs());
1329 view.setFollowHighlight(av.isFollowHighlight());
1330 view.setFollowSelection(av.followSelection);
1331 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1332 if (av.getFeaturesDisplayed() != null)
1334 jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
1336 String[] renderOrder = ap.getSeqPanel().seqCanvas
1337 .getFeatureRenderer().getRenderOrder()
1338 .toArray(new String[0]);
1340 Vector<String> settingsAdded = new Vector<>();
1341 if (renderOrder != null)
1343 for (String featureType : renderOrder)
1345 FeatureColourI fcol = ap.getSeqPanel().seqCanvas
1346 .getFeatureRenderer().getFeatureStyle(featureType);
1347 Setting setting = new Setting();
1348 setting.setType(featureType);
1349 if (!fcol.isSimpleColour())
1351 setting.setColour(fcol.getMaxColour().getRGB());
1352 setting.setMincolour(fcol.getMinColour().getRGB());
1353 setting.setMin(fcol.getMin());
1354 setting.setMax(fcol.getMax());
1355 setting.setColourByLabel(fcol.isColourByLabel());
1356 setting.setAutoScale(fcol.isAutoScaled());
1357 setting.setThreshold(fcol.getThreshold());
1358 // -1 = No threshold, 0 = Below, 1 = Above
1359 setting.setThreshstate(fcol.isAboveThreshold() ? 1
1360 : (fcol.isBelowThreshold() ? 0 : -1));
1364 setting.setColour(fcol.getColour().getRGB());
1368 av.getFeaturesDisplayed().isVisible(featureType));
1369 float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1370 .getOrder(featureType);
1373 setting.setOrder(rorder);
1375 fs.addSetting(setting);
1376 settingsAdded.addElement(featureType);
1380 // is groups actually supposed to be a map here ?
1381 Iterator<String> en = ap.getSeqPanel().seqCanvas
1382 .getFeatureRenderer().getFeatureGroups().iterator();
1383 Vector<String> groupsAdded = new Vector<>();
1384 while (en.hasNext())
1386 String grp = en.next();
1387 if (groupsAdded.contains(grp))
1391 Group g = new Group();
1393 g.setDisplay(((Boolean) ap.getSeqPanel().seqCanvas
1394 .getFeatureRenderer().checkGroupVisibility(grp, false))
1397 groupsAdded.addElement(grp);
1399 jms.setFeatureSettings(fs);
1402 if (av.hasHiddenColumns())
1404 jalview.datamodel.HiddenColumns hidden = av.getAlignment()
1405 .getHiddenColumns();
1408 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1412 ArrayList<int[]> hiddenRegions = hidden.getHiddenColumnsCopy();
1413 for (int[] region : hiddenRegions)
1415 HiddenColumns hc = new HiddenColumns();
1416 hc.setStart(region[0]);
1417 hc.setEnd(region[1]);
1418 view.addHiddenColumns(hc);
1422 if (calcIdSet.size() > 0)
1424 for (String calcId : calcIdSet)
1426 if (calcId.trim().length() > 0)
1428 CalcIdParam cidp = createCalcIdParam(calcId, av);
1429 // Some calcIds have no parameters.
1432 view.addCalcIdParam(cidp);
1438 jms.addViewport(view);
1440 object.setJalviewModelSequence(jms);
1441 object.getVamsasModel().addSequenceSet(vamsasSet);
1443 if (jout != null && fileName != null)
1445 // We may not want to write the object to disk,
1446 // eg we can copy the alignViewport to a new view object
1447 // using save and then load
1450 System.out.println("Writing jar entry " + fileName);
1451 JarEntry entry = new JarEntry(fileName);
1452 jout.putNextEntry(entry);
1453 PrintWriter pout = new PrintWriter(
1454 new OutputStreamWriter(jout, UTF_8));
1455 Marshaller marshaller = new Marshaller(pout);
1456 marshaller.marshal(object);
1459 } catch (Exception ex)
1461 // TODO: raise error in GUI if marshalling failed.
1462 ex.printStackTrace();
1469 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1470 * for each viewer, with
1472 * <li>viewer geometry (position, size, split pane divider location)</li>
1473 * <li>index of the selected structure in the viewer (currently shows gapped
1475 * <li>the id of the annotation holding RNA secondary structure</li>
1476 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1478 * Varna viewer state is also written out (in native Varna XML) to separate
1479 * project jar entries. A separate entry is written for each RNA structure
1480 * displayed, with the naming convention
1482 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
1490 * @param storeDataset
1492 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
1493 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
1494 boolean storeDataset)
1496 if (Desktop.desktop == null)
1500 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1501 for (int f = frames.length - 1; f > -1; f--)
1503 if (frames[f] instanceof AppVarna)
1505 AppVarna varna = (AppVarna) frames[f];
1507 * link the sequence to every viewer that is showing it and is linked to
1508 * its alignment panel
1510 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1512 String viewId = varna.getViewId();
1513 RnaViewer rna = new RnaViewer();
1514 rna.setViewId(viewId);
1515 rna.setTitle(varna.getTitle());
1516 rna.setXpos(varna.getX());
1517 rna.setYpos(varna.getY());
1518 rna.setWidth(varna.getWidth());
1519 rna.setHeight(varna.getHeight());
1520 rna.setDividerLocation(varna.getDividerLocation());
1521 rna.setSelectedRna(varna.getSelectedIndex());
1522 jseq.addRnaViewer(rna);
1525 * Store each Varna panel's state once in the project per sequence.
1526 * First time through only (storeDataset==false)
1528 // boolean storeSessions = false;
1529 // String sequenceViewId = viewId + seqsToIds.get(jds);
1530 // if (!storeDataset && !viewIds.contains(sequenceViewId))
1532 // viewIds.add(sequenceViewId);
1533 // storeSessions = true;
1535 for (RnaModel model : varna.getModels())
1537 if (model.seq == jds)
1540 * VARNA saves each view (sequence or alignment secondary
1541 * structure, gapped or trimmed) as a separate XML file
1543 String jarEntryName = rnaSessions.get(model);
1544 if (jarEntryName == null)
1547 String varnaStateFile = varna.getStateInfo(model.rna);
1548 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
1549 copyFileToJar(jout, varnaStateFile, jarEntryName);
1550 rnaSessions.put(model, jarEntryName);
1552 SecondaryStructure ss = new SecondaryStructure();
1553 String annotationId = varna.getAnnotation(jds).annotationId;
1554 ss.setAnnotationId(annotationId);
1555 ss.setViewerState(jarEntryName);
1556 ss.setGapped(model.gapped);
1557 ss.setTitle(model.title);
1558 rna.addSecondaryStructure(ss);
1567 * Copy the contents of a file to a new entry added to the output jar
1571 * @param jarEntryName
1573 protected void copyFileToJar(JarOutputStream jout, String infilePath,
1574 String jarEntryName)
1576 DataInputStream dis = null;
1579 File file = new File(infilePath);
1580 if (file.exists() && jout != null)
1582 dis = new DataInputStream(new FileInputStream(file));
1583 byte[] data = new byte[(int) file.length()];
1584 dis.readFully(data);
1585 writeJarEntry(jout, jarEntryName, data);
1587 } catch (Exception ex)
1589 ex.printStackTrace();
1597 } catch (IOException e)
1606 * Write the data to a new entry of given name in the output jar file
1609 * @param jarEntryName
1611 * @throws IOException
1613 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
1614 byte[] data) throws IOException
1618 System.out.println("Writing jar entry " + jarEntryName);
1619 jout.putNextEntry(new JarEntry(jarEntryName));
1620 DataOutputStream dout = new DataOutputStream(jout);
1621 dout.write(data, 0, data.length);
1628 * Save the state of a structure viewer
1633 * the archive XML element under which to save the state
1636 * @param matchedFile
1640 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
1641 Pdbids pdb, PDBEntry entry, List<String> viewIds,
1642 String matchedFile, StructureViewerBase viewFrame)
1644 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
1647 * Look for any bindings for this viewer to the PDB file of interest
1648 * (including part matches excluding chain id)
1650 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
1652 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
1653 final String pdbId = pdbentry.getId();
1654 if (!pdbId.equals(entry.getId())
1655 && !(entry.getId().length() > 4 && entry.getId().toLowerCase()
1656 .startsWith(pdbId.toLowerCase())))
1659 * not interested in a binding to a different PDB entry here
1663 if (matchedFile == null)
1665 matchedFile = pdbentry.getFile();
1667 else if (!matchedFile.equals(pdbentry.getFile()))
1670 "Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
1671 + pdbentry.getFile());
1675 // can get at it if the ID
1676 // match is ambiguous (e.g.
1679 for (int smap = 0; smap < viewFrame.getBinding()
1680 .getSequence()[peid].length; smap++)
1682 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
1683 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
1685 StructureState state = new StructureState();
1686 state.setVisible(true);
1687 state.setXpos(viewFrame.getX());
1688 state.setYpos(viewFrame.getY());
1689 state.setWidth(viewFrame.getWidth());
1690 state.setHeight(viewFrame.getHeight());
1691 final String viewId = viewFrame.getViewId();
1692 state.setViewId(viewId);
1693 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
1694 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
1695 state.setColourByJmol(viewFrame.isColouredByViewer());
1696 state.setType(viewFrame.getViewerType().toString());
1697 pdb.addStructureState(state);
1705 * Populates the AnnotationColours xml for save. This captures the settings of
1706 * the options in the 'Colour by Annotation' dialog.
1709 * @param userColours
1713 private AnnotationColours constructAnnotationColours(
1714 AnnotationColourGradient acg, List<UserColourScheme> userColours,
1715 JalviewModelSequence jms)
1717 AnnotationColours ac = new AnnotationColours();
1718 ac.setAboveThreshold(acg.getAboveThreshold());
1719 ac.setThreshold(acg.getAnnotationThreshold());
1720 // 2.10.2 save annotationId (unique) not annotation label
1721 ac.setAnnotation(acg.getAnnotation().annotationId);
1722 if (acg.getBaseColour() instanceof UserColourScheme)
1725 setUserColourScheme(acg.getBaseColour(), userColours, jms));
1730 ColourSchemeProperty.getColourName(acg.getBaseColour()));
1733 ac.setMaxColour(acg.getMaxColour().getRGB());
1734 ac.setMinColour(acg.getMinColour().getRGB());
1735 ac.setPerSequence(acg.isSeqAssociated());
1736 ac.setPredefinedColours(acg.isPredefinedColours());
1740 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
1741 IdentityHashMap<SequenceGroup, String> groupRefs,
1742 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
1743 SequenceSet vamsasSet)
1746 for (int i = 0; i < aa.length; i++)
1748 Annotation an = new Annotation();
1750 AlignmentAnnotation annotation = aa[i];
1751 if (annotation.annotationId != null)
1753 annotationIds.put(annotation.annotationId, annotation);
1756 an.setId(annotation.annotationId);
1758 an.setVisible(annotation.visible);
1760 an.setDescription(annotation.description);
1762 if (annotation.sequenceRef != null)
1764 // 2.9 JAL-1781 xref on sequence id rather than name
1765 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
1767 if (annotation.groupRef != null)
1769 String groupIdr = groupRefs.get(annotation.groupRef);
1770 if (groupIdr == null)
1772 // make a locally unique String
1773 groupRefs.put(annotation.groupRef,
1774 groupIdr = ("" + System.currentTimeMillis()
1775 + annotation.groupRef.getName()
1776 + groupRefs.size()));
1778 an.setGroupRef(groupIdr.toString());
1781 // store all visualization attributes for annotation
1782 an.setGraphHeight(annotation.graphHeight);
1783 an.setCentreColLabels(annotation.centreColLabels);
1784 an.setScaleColLabels(annotation.scaleColLabel);
1785 an.setShowAllColLabels(annotation.showAllColLabels);
1786 an.setBelowAlignment(annotation.belowAlignment);
1788 if (annotation.graph > 0)
1791 an.setGraphType(annotation.graph);
1792 an.setGraphGroup(annotation.graphGroup);
1793 if (annotation.getThreshold() != null)
1795 ThresholdLine line = new ThresholdLine();
1796 line.setLabel(annotation.getThreshold().label);
1797 line.setValue(annotation.getThreshold().value);
1798 line.setColour(annotation.getThreshold().colour.getRGB());
1799 an.setThresholdLine(line);
1807 an.setLabel(annotation.label);
1809 if (annotation == av.getAlignmentQualityAnnot()
1810 || annotation == av.getAlignmentConservationAnnotation()
1811 || annotation == av.getAlignmentConsensusAnnotation()
1812 || annotation.autoCalculated)
1814 // new way of indicating autocalculated annotation -
1815 an.setAutoCalculated(annotation.autoCalculated);
1817 if (annotation.hasScore())
1819 an.setScore(annotation.getScore());
1822 if (annotation.getCalcId() != null)
1824 calcIdSet.add(annotation.getCalcId());
1825 an.setCalcId(annotation.getCalcId());
1827 if (annotation.hasProperties())
1829 for (String pr : annotation.getProperties())
1831 Property prop = new Property();
1833 prop.setValue(annotation.getProperty(pr));
1834 an.addProperty(prop);
1838 AnnotationElement ae;
1839 if (annotation.annotations != null)
1841 an.setScoreOnly(false);
1842 for (int a = 0; a < annotation.annotations.length; a++)
1844 if ((annotation == null) || (annotation.annotations[a] == null))
1849 ae = new AnnotationElement();
1850 if (annotation.annotations[a].description != null)
1852 ae.setDescription(annotation.annotations[a].description);
1854 if (annotation.annotations[a].displayCharacter != null)
1856 ae.setDisplayCharacter(
1857 annotation.annotations[a].displayCharacter);
1860 if (!Float.isNaN(annotation.annotations[a].value))
1862 ae.setValue(annotation.annotations[a].value);
1866 if (annotation.annotations[a].secondaryStructure > ' ')
1868 ae.setSecondaryStructure(
1869 annotation.annotations[a].secondaryStructure + "");
1872 if (annotation.annotations[a].colour != null
1873 && annotation.annotations[a].colour != java.awt.Color.black)
1875 ae.setColour(annotation.annotations[a].colour.getRGB());
1878 an.addAnnotationElement(ae);
1879 if (annotation.autoCalculated)
1881 // only write one non-null entry into the annotation row -
1882 // sufficient to get the visualization attributes necessary to
1890 an.setScoreOnly(true);
1892 if (!storeDS || (storeDS && !annotation.autoCalculated))
1894 // skip autocalculated annotation - these are only provided for
1896 vamsasSet.addAnnotation(an);
1902 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
1904 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
1905 if (settings != null)
1907 CalcIdParam vCalcIdParam = new CalcIdParam();
1908 vCalcIdParam.setCalcId(calcId);
1909 vCalcIdParam.addServiceURL(settings.getServiceURI());
1910 // generic URI allowing a third party to resolve another instance of the
1911 // service used for this calculation
1912 for (String urls : settings.getServiceURLs())
1914 vCalcIdParam.addServiceURL(urls);
1916 vCalcIdParam.setVersion("1.0");
1917 if (settings.getPreset() != null)
1919 WsParamSetI setting = settings.getPreset();
1920 vCalcIdParam.setName(setting.getName());
1921 vCalcIdParam.setDescription(setting.getDescription());
1925 vCalcIdParam.setName("");
1926 vCalcIdParam.setDescription("Last used parameters");
1928 // need to be able to recover 1) settings 2) user-defined presets or
1929 // recreate settings from preset 3) predefined settings provided by
1930 // service - or settings that can be transferred (or discarded)
1931 vCalcIdParam.setParameters(
1932 settings.getWsParamFile().replace("\n", "|\\n|"));
1933 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
1934 // todo - decide if updateImmediately is needed for any projects.
1936 return vCalcIdParam;
1941 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
1944 if (calcIdParam.getVersion().equals("1.0"))
1946 Jws2Instance service = Jws2Discoverer.getDiscoverer()
1947 .getPreferredServiceFor(calcIdParam.getServiceURL());
1948 if (service != null)
1950 WsParamSetI parmSet = null;
1953 parmSet = service.getParamStore().parseServiceParameterFile(
1954 calcIdParam.getName(), calcIdParam.getDescription(),
1955 calcIdParam.getServiceURL(),
1956 calcIdParam.getParameters().replace("|\\n|", "\n"));
1957 } catch (IOException x)
1959 warn("Couldn't parse parameter data for "
1960 + calcIdParam.getCalcId(), x);
1963 List<ArgumentI> argList = null;
1964 if (calcIdParam.getName().length() > 0)
1966 parmSet = service.getParamStore()
1967 .getPreset(calcIdParam.getName());
1968 if (parmSet != null)
1970 // TODO : check we have a good match with settings in AACon -
1971 // otherwise we'll need to create a new preset
1976 argList = parmSet.getArguments();
1979 AAConSettings settings = new AAConSettings(
1980 calcIdParam.isAutoUpdate(), service, parmSet, argList);
1981 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
1982 calcIdParam.isNeedsUpdate());
1987 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
1991 throw new Error(MessageManager.formatMessage(
1992 "error.unsupported_version_calcIdparam", new Object[]
1993 { calcIdParam.toString() }));
1997 * External mapping between jalview objects and objects yielding a valid and
1998 * unique object ID string. This is null for normal Jalview project IO, but
1999 * non-null when a jalview project is being read or written as part of a
2002 IdentityHashMap jv2vobj = null;
2005 * Construct a unique ID for jvobj using either existing bindings or if none
2006 * exist, the result of the hashcode call for the object.
2009 * jalview data object
2010 * @return unique ID for referring to jvobj
2012 private String makeHashCode(Object jvobj, String altCode)
2014 if (jv2vobj != null)
2016 Object id = jv2vobj.get(jvobj);
2019 return id.toString();
2021 // check string ID mappings
2022 if (jvids2vobj != null && jvobj instanceof String)
2024 id = jvids2vobj.get(jvobj);
2028 return id.toString();
2030 // give up and warn that something has gone wrong
2031 warn("Cannot find ID for object in external mapping : " + jvobj);
2037 * return local jalview object mapped to ID, if it exists
2041 * @return null or object bound to idcode
2043 private Object retrieveExistingObj(String idcode)
2045 if (idcode != null && vobj2jv != null)
2047 return vobj2jv.get(idcode);
2053 * binding from ID strings from external mapping table to jalview data model
2056 private Hashtable vobj2jv;
2058 private Sequence createVamsasSequence(String id, SequenceI jds)
2060 return createVamsasSequence(true, id, jds, null);
2063 private Sequence createVamsasSequence(boolean recurse, String id,
2064 SequenceI jds, SequenceI parentseq)
2066 Sequence vamsasSeq = new Sequence();
2067 vamsasSeq.setId(id);
2068 vamsasSeq.setName(jds.getName());
2069 vamsasSeq.setSequence(jds.getSequenceAsString());
2070 vamsasSeq.setDescription(jds.getDescription());
2071 jalview.datamodel.DBRefEntry[] dbrefs = null;
2072 if (jds.getDatasetSequence() != null)
2074 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
2078 // seqId==dsseqid so we can tell which sequences really are
2079 // dataset sequences only
2080 vamsasSeq.setDsseqid(id);
2081 dbrefs = jds.getDBRefs();
2082 if (parentseq == null)
2089 for (int d = 0; d < dbrefs.length; d++)
2091 DBRef dbref = new DBRef();
2092 dbref.setSource(dbrefs[d].getSource());
2093 dbref.setVersion(dbrefs[d].getVersion());
2094 dbref.setAccessionId(dbrefs[d].getAccessionId());
2095 if (dbrefs[d].hasMap())
2097 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
2099 dbref.setMapping(mp);
2101 vamsasSeq.addDBRef(dbref);
2107 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
2108 SequenceI parentseq, SequenceI jds, boolean recurse)
2111 if (jmp.getMap() != null)
2115 jalview.util.MapList mlst = jmp.getMap();
2116 List<int[]> r = mlst.getFromRanges();
2117 for (int[] range : r)
2119 MapListFrom mfrom = new MapListFrom();
2120 mfrom.setStart(range[0]);
2121 mfrom.setEnd(range[1]);
2122 mp.addMapListFrom(mfrom);
2124 r = mlst.getToRanges();
2125 for (int[] range : r)
2127 MapListTo mto = new MapListTo();
2128 mto.setStart(range[0]);
2129 mto.setEnd(range[1]);
2130 mp.addMapListTo(mto);
2132 mp.setMapFromUnit(mlst.getFromRatio());
2133 mp.setMapToUnit(mlst.getToRatio());
2134 if (jmp.getTo() != null)
2136 MappingChoice mpc = new MappingChoice();
2138 // check/create ID for the sequence referenced by getTo()
2141 SequenceI ps = null;
2142 if (parentseq != jmp.getTo()
2143 && parentseq.getDatasetSequence() != jmp.getTo())
2145 // chaining dbref rather than a handshaking one
2146 jmpid = seqHash(ps = jmp.getTo());
2150 jmpid = seqHash(ps = parentseq);
2152 mpc.setDseqFor(jmpid);
2153 if (!seqRefIds.containsKey(mpc.getDseqFor()))
2155 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2156 seqRefIds.put(mpc.getDseqFor(), ps);
2160 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2163 mp.setMappingChoice(mpc);
2169 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2170 List<UserColourScheme> userColours, JalviewModelSequence jms)
2173 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2174 boolean newucs = false;
2175 if (!userColours.contains(ucs))
2177 userColours.add(ucs);
2180 id = "ucs" + userColours.indexOf(ucs);
2183 // actually create the scheme's entry in the XML model
2184 java.awt.Color[] colours = ucs.getColours();
2185 jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
2186 jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
2188 for (int i = 0; i < colours.length; i++)
2190 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2191 col.setName(ResidueProperties.aa[i]);
2192 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2193 jbucs.addColour(col);
2195 if (ucs.getLowerCaseColours() != null)
2197 colours = ucs.getLowerCaseColours();
2198 for (int i = 0; i < colours.length; i++)
2200 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2201 col.setName(ResidueProperties.aa[i].toLowerCase());
2202 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2203 jbucs.addColour(col);
2208 uc.setUserColourScheme(jbucs);
2209 jms.addUserColours(uc);
2215 jalview.schemes.UserColourScheme getUserColourScheme(
2216 JalviewModelSequence jms, String id)
2218 UserColours[] uc = jms.getUserColours();
2219 UserColours colours = null;
2221 for (int i = 0; i < uc.length; i++)
2223 if (uc[i].getId().equals(id))
2231 java.awt.Color[] newColours = new java.awt.Color[24];
2233 for (int i = 0; i < 24; i++)
2235 newColours[i] = new java.awt.Color(Integer.parseInt(
2236 colours.getUserColourScheme().getColour(i).getRGB(), 16));
2239 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2242 if (colours.getUserColourScheme().getColourCount() > 24)
2244 newColours = new java.awt.Color[23];
2245 for (int i = 0; i < 23; i++)
2247 newColours[i] = new java.awt.Color(Integer.parseInt(
2248 colours.getUserColourScheme().getColour(i + 24).getRGB(),
2251 ucs.setLowerCaseColours(newColours);
2258 * contains last error message (if any) encountered by XML loader.
2260 String errorMessage = null;
2263 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2264 * exceptions are raised during project XML parsing
2266 public boolean attemptversion1parse = true;
2269 * Load a jalview project archive from a jar file
2272 * - HTTP URL or filename
2274 public AlignFrame loadJalviewAlign(final String file)
2277 jalview.gui.AlignFrame af = null;
2281 // create list to store references for any new Jmol viewers created
2282 newStructureViewers = new Vector<>();
2283 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2284 // Workaround is to make sure caller implements the JarInputStreamProvider
2286 // so we can re-open the jar input stream for each entry.
2288 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2289 af = loadJalviewAlign(jprovider);
2290 af.setMenusForViewport();
2292 } catch (MalformedURLException e)
2294 errorMessage = "Invalid URL format for '" + file + "'";
2300 SwingUtilities.invokeAndWait(new Runnable()
2305 setLoadingFinishedForNewStructureViewers();
2308 } catch (Exception x)
2310 System.err.println("Error loading alignment: " + x.getMessage());
2316 private jarInputStreamProvider createjarInputStreamProvider(
2317 final String file) throws MalformedURLException
2320 errorMessage = null;
2321 uniqueSetSuffix = null;
2323 viewportsAdded.clear();
2324 frefedSequence = null;
2326 if (file.startsWith("http://"))
2328 url = new URL(file);
2330 final URL _url = url;
2331 return new jarInputStreamProvider()
2335 public JarInputStream getJarInputStream() throws IOException
2339 return new JarInputStream(_url.openStream());
2343 return new JarInputStream(new FileInputStream(file));
2348 public String getFilename()
2356 * Recover jalview session from a jalview project archive. Caller may
2357 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2358 * themselves. Any null fields will be initialised with default values,
2359 * non-null fields are left alone.
2364 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2366 errorMessage = null;
2367 if (uniqueSetSuffix == null)
2369 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2371 if (seqRefIds == null)
2375 AlignFrame af = null, _af = null;
2376 IdentityHashMap<AlignmentI, AlignmentI> importedDatasets = new IdentityHashMap<>();
2377 Map<String, AlignFrame> gatherToThisFrame = new HashMap<>();
2378 final String file = jprovider.getFilename();
2381 JarInputStream jin = null;
2382 JarEntry jarentry = null;
2387 jin = jprovider.getJarInputStream();
2388 for (int i = 0; i < entryCount; i++)
2390 jarentry = jin.getNextJarEntry();
2393 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2395 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2396 JalviewModel object = new JalviewModel();
2398 Unmarshaller unmar = new Unmarshaller(object);
2399 unmar.setValidation(false);
2400 object = (JalviewModel) unmar.unmarshal(in);
2401 if (true) // !skipViewport(object))
2403 _af = loadFromObject(object, file, true, jprovider);
2404 if (_af != null && object.getJalviewModelSequence()
2405 .getViewportCount() > 0)
2409 // store a reference to the first view
2412 if (_af.viewport.isGatherViewsHere())
2414 // if this is a gathered view, keep its reference since
2415 // after gathering views, only this frame will remain
2417 gatherToThisFrame.put(_af.viewport.getSequenceSetId(), _af);
2419 // Save dataset to register mappings once all resolved
2420 importedDatasets.put(af.viewport.getAlignment().getDataset(),
2421 af.viewport.getAlignment().getDataset());
2426 else if (jarentry != null)
2428 // Some other file here.
2431 } while (jarentry != null);
2432 resolveFrefedSequences();
2433 } catch (IOException ex)
2435 ex.printStackTrace();
2436 errorMessage = "Couldn't locate Jalview XML file : " + file;
2438 "Exception whilst loading jalview XML file : " + ex + "\n");
2439 } catch (Exception ex)
2441 System.err.println("Parsing as Jalview Version 2 file failed.");
2442 ex.printStackTrace(System.err);
2443 if (attemptversion1parse)
2445 // Is Version 1 Jar file?
2448 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
2449 } catch (Exception ex2)
2451 System.err.println("Exception whilst loading as jalviewXMLV1:");
2452 ex2.printStackTrace();
2456 if (Desktop.instance != null)
2458 Desktop.instance.stopLoading();
2462 System.out.println("Successfully loaded archive file");
2465 ex.printStackTrace();
2468 "Exception whilst loading jalview XML file : " + ex + "\n");
2469 } catch (OutOfMemoryError e)
2471 // Don't use the OOM Window here
2472 errorMessage = "Out of memory loading jalview XML file";
2473 System.err.println("Out of memory whilst loading jalview XML file");
2474 e.printStackTrace();
2478 * Regather multiple views (with the same sequence set id) to the frame (if
2479 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2480 * views instead of separate frames. Note this doesn't restore a state where
2481 * some expanded views in turn have tabbed views - the last "first tab" read
2482 * in will play the role of gatherer for all.
2484 for (AlignFrame fr : gatherToThisFrame.values())
2486 Desktop.instance.gatherViews(fr);
2489 restoreSplitFrames();
2490 for (AlignmentI ds : importedDatasets.keySet())
2492 if (ds.getCodonFrames() != null)
2494 StructureSelectionManager
2495 .getStructureSelectionManager(Desktop.instance)
2496 .registerMappings(ds.getCodonFrames());
2499 if (errorMessage != null)
2504 if (Desktop.instance != null)
2506 Desktop.instance.stopLoading();
2513 * Try to reconstruct and display SplitFrame windows, where each contains
2514 * complementary dna and protein alignments. Done by pairing up AlignFrame
2515 * objects (created earlier) which have complementary viewport ids associated.
2517 protected void restoreSplitFrames()
2519 List<SplitFrame> gatherTo = new ArrayList<>();
2520 List<AlignFrame> addedToSplitFrames = new ArrayList<>();
2521 Map<String, AlignFrame> dna = new HashMap<>();
2524 * Identify the DNA alignments
2526 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2529 AlignFrame af = candidate.getValue();
2530 if (af.getViewport().getAlignment().isNucleotide())
2532 dna.put(candidate.getKey().getId(), af);
2537 * Try to match up the protein complements
2539 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2542 AlignFrame af = candidate.getValue();
2543 if (!af.getViewport().getAlignment().isNucleotide())
2545 String complementId = candidate.getKey().getComplementId();
2546 // only non-null complements should be in the Map
2547 if (complementId != null && dna.containsKey(complementId))
2549 final AlignFrame dnaFrame = dna.get(complementId);
2550 SplitFrame sf = createSplitFrame(dnaFrame, af);
2551 addedToSplitFrames.add(dnaFrame);
2552 addedToSplitFrames.add(af);
2553 dnaFrame.setMenusForViewport();
2554 af.setMenusForViewport();
2555 if (af.viewport.isGatherViewsHere())
2564 * Open any that we failed to pair up (which shouldn't happen!) as
2565 * standalone AlignFrame's.
2567 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2570 AlignFrame af = candidate.getValue();
2571 if (!addedToSplitFrames.contains(af))
2573 Viewport view = candidate.getKey();
2574 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
2576 af.setMenusForViewport();
2577 System.err.println("Failed to restore view " + view.getTitle()
2578 + " to split frame");
2583 * Gather back into tabbed views as flagged.
2585 for (SplitFrame sf : gatherTo)
2587 Desktop.instance.gatherViews(sf);
2590 splitFrameCandidates.clear();
2594 * Construct and display one SplitFrame holding DNA and protein alignments.
2597 * @param proteinFrame
2600 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
2601 AlignFrame proteinFrame)
2603 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
2604 String title = MessageManager.getString("label.linked_view_title");
2605 int width = (int) dnaFrame.getBounds().getWidth();
2606 int height = (int) (dnaFrame.getBounds().getHeight()
2607 + proteinFrame.getBounds().getHeight() + 50);
2610 * SplitFrame location is saved to both enclosed frames
2612 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
2613 Desktop.addInternalFrame(splitFrame, title, width, height);
2616 * And compute cDNA consensus (couldn't do earlier with consensus as
2617 * mappings were not yet present)
2619 proteinFrame.viewport.alignmentChanged(proteinFrame.alignPanel);
2625 * check errorMessage for a valid error message and raise an error box in the
2626 * GUI or write the current errorMessage to stderr and then clear the error
2629 protected void reportErrors()
2631 reportErrors(false);
2634 protected void reportErrors(final boolean saving)
2636 if (errorMessage != null)
2638 final String finalErrorMessage = errorMessage;
2641 javax.swing.SwingUtilities.invokeLater(new Runnable()
2646 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2648 "Error " + (saving ? "saving" : "loading")
2650 JvOptionPane.WARNING_MESSAGE);
2656 System.err.println("Problem loading Jalview file: " + errorMessage);
2659 errorMessage = null;
2662 Map<String, String> alreadyLoadedPDB = new HashMap<>();
2665 * when set, local views will be updated from view stored in JalviewXML
2666 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2667 * sync if this is set to true.
2669 private final boolean updateLocalViews = false;
2672 * Returns the path to a temporary file holding the PDB file for the given PDB
2673 * id. The first time of asking, searches for a file of that name in the
2674 * Jalview project jar, and copies it to a new temporary file. Any repeat
2675 * requests just return the path to the file previously created.
2681 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId,
2684 if (alreadyLoadedPDB.containsKey(pdbId))
2686 return alreadyLoadedPDB.get(pdbId).toString();
2689 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb",
2691 if (tempFile != null)
2693 alreadyLoadedPDB.put(pdbId, tempFile);
2699 * Copies the jar entry of given name to a new temporary file and returns the
2700 * path to the file, or null if the entry is not found.
2703 * @param jarEntryName
2705 * a prefix for the temporary file name, must be at least three
2708 * null or original file - so new file can be given the same suffix
2712 protected String copyJarEntry(jarInputStreamProvider jprovider,
2713 String jarEntryName, String prefix, String origFile)
2715 BufferedReader in = null;
2716 PrintWriter out = null;
2717 String suffix = ".tmp";
2718 if (origFile == null)
2720 origFile = jarEntryName;
2722 int sfpos = origFile.lastIndexOf(".");
2723 if (sfpos > -1 && sfpos < (origFile.length() - 3))
2725 suffix = "." + origFile.substring(sfpos + 1);
2729 JarInputStream jin = jprovider.getJarInputStream();
2731 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2732 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2733 * FileInputStream(jprovider)); }
2736 JarEntry entry = null;
2739 entry = jin.getNextJarEntry();
2740 } while (entry != null && !entry.getName().equals(jarEntryName));
2743 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
2744 File outFile = File.createTempFile(prefix, suffix);
2745 outFile.deleteOnExit();
2746 out = new PrintWriter(new FileOutputStream(outFile));
2749 while ((data = in.readLine()) != null)
2754 String t = outFile.getAbsolutePath();
2759 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
2761 } catch (Exception ex)
2763 ex.printStackTrace();
2771 } catch (IOException e)
2785 private class JvAnnotRow
2787 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2794 * persisted version of annotation row from which to take vis properties
2796 public jalview.datamodel.AlignmentAnnotation template;
2799 * original position of the annotation row in the alignment
2805 * Load alignment frame from jalview XML DOM object
2810 * filename source string
2811 * @param loadTreesAndStructures
2812 * when false only create Viewport
2814 * data source provider
2815 * @return alignment frame created from view stored in DOM
2817 AlignFrame loadFromObject(JalviewModel object, String file,
2818 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
2820 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
2821 Sequence[] vamsasSeq = vamsasSet.getSequence();
2823 JalviewModelSequence jms = object.getJalviewModelSequence();
2825 Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
2828 // ////////////////////////////////
2831 List<SequenceI> hiddenSeqs = null;
2833 List<SequenceI> tmpseqs = new ArrayList<>();
2835 boolean multipleView = false;
2836 SequenceI referenceseqForView = null;
2837 JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
2838 int vi = 0; // counter in vamsasSeq array
2839 for (int i = 0; i < jseqs.length; i++)
2841 String seqId = jseqs[i].getId();
2843 SequenceI tmpSeq = seqRefIds.get(seqId);
2846 if (!incompleteSeqs.containsKey(seqId))
2848 // may not need this check, but keep it for at least 2.9,1 release
2849 if (tmpSeq.getStart() != jseqs[i].getStart()
2850 || tmpSeq.getEnd() != jseqs[i].getEnd())
2853 "Warning JAL-2154 regression: updating start/end for sequence "
2854 + tmpSeq.toString() + " to " + jseqs[i]);
2859 incompleteSeqs.remove(seqId);
2861 if (vamsasSeq.length > vi && vamsasSeq[vi].getId().equals(seqId))
2863 // most likely we are reading a dataset XML document so
2864 // update from vamsasSeq section of XML for this sequence
2865 tmpSeq.setName(vamsasSeq[vi].getName());
2866 tmpSeq.setDescription(vamsasSeq[vi].getDescription());
2867 tmpSeq.setSequence(vamsasSeq[vi].getSequence());
2872 // reading multiple views, so vamsasSeq set is a subset of JSeq
2873 multipleView = true;
2875 tmpSeq.setStart(jseqs[i].getStart());
2876 tmpSeq.setEnd(jseqs[i].getEnd());
2877 tmpseqs.add(tmpSeq);
2881 tmpSeq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
2882 vamsasSeq[vi].getSequence());
2883 tmpSeq.setDescription(vamsasSeq[vi].getDescription());
2884 tmpSeq.setStart(jseqs[i].getStart());
2885 tmpSeq.setEnd(jseqs[i].getEnd());
2886 tmpSeq.setVamsasId(uniqueSetSuffix + seqId);
2887 seqRefIds.put(vamsasSeq[vi].getId(), tmpSeq);
2888 tmpseqs.add(tmpSeq);
2892 if (jseqs[i].hasViewreference() && jseqs[i].getViewreference())
2894 referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
2897 if (jseqs[i].getHidden())
2899 if (hiddenSeqs == null)
2901 hiddenSeqs = new ArrayList<>();
2904 hiddenSeqs.add(tmpSeq);
2909 // Create the alignment object from the sequence set
2910 // ///////////////////////////////
2911 SequenceI[] orderedSeqs = tmpseqs
2912 .toArray(new SequenceI[tmpseqs.size()]);
2914 AlignmentI al = null;
2915 // so we must create or recover the dataset alignment before going further
2916 // ///////////////////////////////
2917 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
2919 // older jalview projects do not have a dataset - so creat alignment and
2921 al = new Alignment(orderedSeqs);
2922 al.setDataset(null);
2926 boolean isdsal = object.getJalviewModelSequence()
2927 .getViewportCount() == 0;
2930 // we are importing a dataset record, so
2931 // recover reference to an alignment already materialsed as dataset
2932 al = getDatasetFor(vamsasSet.getDatasetId());
2936 // materialse the alignment
2937 al = new Alignment(orderedSeqs);
2941 addDatasetRef(vamsasSet.getDatasetId(), al);
2944 // finally, verify all data in vamsasSet is actually present in al
2945 // passing on flag indicating if it is actually a stored dataset
2946 recoverDatasetFor(vamsasSet, al, isdsal);
2949 if (referenceseqForView != null)
2951 al.setSeqrep(referenceseqForView);
2953 // / Add the alignment properties
2954 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
2956 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
2957 al.setProperty(ssp.getKey(), ssp.getValue());
2960 // ///////////////////////////////
2962 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
2965 // load sequence features, database references and any associated PDB
2966 // structures for the alignment
2968 // prior to 2.10, this part would only be executed the first time a
2969 // sequence was encountered, but not afterwards.
2970 // now, for 2.10 projects, this is also done if the xml doc includes
2971 // dataset sequences not actually present in any particular view.
2973 for (int i = 0; i < vamsasSeq.length; i++)
2975 if (jseqs[i].getFeaturesCount() > 0)
2977 Features[] features = jseqs[i].getFeatures();
2978 for (int f = 0; f < features.length; f++)
2980 SequenceFeature sf = new SequenceFeature(features[f].getType(),
2981 features[f].getDescription(), features[f].getBegin(),
2982 features[f].getEnd(), features[f].getScore(),
2983 features[f].getFeatureGroup());
2984 sf.setStatus(features[f].getStatus());
2985 for (int od = 0; od < features[f].getOtherDataCount(); od++)
2987 OtherData keyValue = features[f].getOtherData(od);
2988 if (keyValue.getKey().startsWith("LINK"))
2990 sf.addLink(keyValue.getValue());
2994 sf.setValue(keyValue.getKey(), keyValue.getValue());
2998 // adds feature to datasequence's feature set (since Jalview 2.10)
2999 al.getSequenceAt(i).addSequenceFeature(sf);
3002 if (vamsasSeq[i].getDBRefCount() > 0)
3004 // adds dbrefs to datasequence's set (since Jalview 2.10)
3006 al.getSequenceAt(i).getDatasetSequence() == null
3007 ? al.getSequenceAt(i)
3008 : al.getSequenceAt(i).getDatasetSequence(),
3011 if (jseqs[i].getPdbidsCount() > 0)
3013 Pdbids[] ids = jseqs[i].getPdbids();
3014 for (int p = 0; p < ids.length; p++)
3016 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
3017 entry.setId(ids[p].getId());
3018 if (ids[p].getType() != null)
3020 if (PDBEntry.Type.getType(ids[p].getType()) != null)
3022 entry.setType(PDBEntry.Type.getType(ids[p].getType()));
3026 entry.setType(PDBEntry.Type.FILE);
3029 // jprovider is null when executing 'New View'
3030 if (ids[p].getFile() != null && jprovider != null)
3032 if (!pdbloaded.containsKey(ids[p].getFile()))
3034 entry.setFile(loadPDBFile(jprovider, ids[p].getId(),
3039 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
3042 if (ids[p].getPdbentryItem() != null)
3044 for (PdbentryItem item : ids[p].getPdbentryItem())
3046 for (Property pr : item.getProperty())
3048 entry.setProperty(pr.getName(), pr.getValue());
3052 StructureSelectionManager
3053 .getStructureSelectionManager(Desktop.instance)
3054 .registerPDBEntry(entry);
3055 // adds PDBEntry to datasequence's set (since Jalview 2.10)
3056 if (al.getSequenceAt(i).getDatasetSequence() != null)
3058 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
3062 al.getSequenceAt(i).addPDBId(entry);
3067 } // end !multipleview
3069 // ///////////////////////////////
3070 // LOAD SEQUENCE MAPPINGS
3072 if (vamsasSet.getAlcodonFrameCount() > 0)
3074 // TODO Potentially this should only be done once for all views of an
3076 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
3077 for (int i = 0; i < alc.length; i++)
3079 AlignedCodonFrame cf = new AlignedCodonFrame();
3080 if (alc[i].getAlcodMapCount() > 0)
3082 AlcodMap[] maps = alc[i].getAlcodMap();
3083 for (int m = 0; m < maps.length; m++)
3085 SequenceI dnaseq = seqRefIds.get(maps[m].getDnasq());
3087 jalview.datamodel.Mapping mapping = null;
3088 // attach to dna sequence reference.
3089 if (maps[m].getMapping() != null)
3091 mapping = addMapping(maps[m].getMapping());
3092 if (dnaseq != null && mapping.getTo() != null)
3094 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
3100 newAlcodMapRef(maps[m].getDnasq(), cf, mapping));
3104 al.addCodonFrame(cf);
3109 // ////////////////////////////////
3111 List<JvAnnotRow> autoAlan = new ArrayList<>();
3114 * store any annotations which forward reference a group's ID
3116 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<>();
3118 if (vamsasSet.getAnnotationCount() > 0)
3120 Annotation[] an = vamsasSet.getAnnotation();
3122 for (int i = 0; i < an.length; i++)
3124 Annotation annotation = an[i];
3127 * test if annotation is automatically calculated for this view only
3129 boolean autoForView = false;
3130 if (annotation.getLabel().equals("Quality")
3131 || annotation.getLabel().equals("Conservation")
3132 || annotation.getLabel().equals("Consensus"))
3134 // Kludge for pre 2.5 projects which lacked the autocalculated flag
3136 if (!annotation.hasAutoCalculated())
3138 annotation.setAutoCalculated(true);
3141 if (autoForView || (annotation.hasAutoCalculated()
3142 && annotation.isAutoCalculated()))
3144 // remove ID - we don't recover annotation from other views for
3145 // view-specific annotation
3146 annotation.setId(null);
3149 // set visiblity for other annotation in this view
3150 String annotationId = annotation.getId();
3151 if (annotationId != null && annotationIds.containsKey(annotationId))
3153 AlignmentAnnotation jda = annotationIds.get(annotationId);
3154 // in principle Visible should always be true for annotation displayed
3155 // in multiple views
3156 if (annotation.hasVisible())
3158 jda.visible = annotation.getVisible();
3161 al.addAnnotation(jda);
3165 // Construct new annotation from model.
3166 AnnotationElement[] ae = annotation.getAnnotationElement();
3167 jalview.datamodel.Annotation[] anot = null;
3168 java.awt.Color firstColour = null;
3170 if (!annotation.getScoreOnly())
3172 anot = new jalview.datamodel.Annotation[al.getWidth()];
3173 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
3175 anpos = ae[aa].getPosition();
3177 if (anpos >= anot.length)
3182 anot[anpos] = new jalview.datamodel.Annotation(
3184 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
3185 (ae[aa].getSecondaryStructure() == null
3186 || ae[aa].getSecondaryStructure().length() == 0)
3188 : ae[aa].getSecondaryStructure()
3193 // JBPNote: Consider verifying dataflow for IO of secondary
3194 // structure annotation read from Stockholm files
3195 // this was added to try to ensure that
3196 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
3198 // anot[ae[aa].getPosition()].displayCharacter = "";
3200 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
3201 if (firstColour == null)
3203 firstColour = anot[anpos].colour;
3207 jalview.datamodel.AlignmentAnnotation jaa = null;
3209 if (annotation.getGraph())
3211 float llim = 0, hlim = 0;
3212 // if (autoForView || an[i].isAutoCalculated()) {
3215 jaa = new jalview.datamodel.AlignmentAnnotation(
3216 annotation.getLabel(), annotation.getDescription(), anot,
3217 llim, hlim, annotation.getGraphType());
3219 jaa.graphGroup = annotation.getGraphGroup();
3220 jaa._linecolour = firstColour;
3221 if (annotation.getThresholdLine() != null)
3223 jaa.setThreshold(new jalview.datamodel.GraphLine(
3224 annotation.getThresholdLine().getValue(),
3225 annotation.getThresholdLine().getLabel(),
3227 annotation.getThresholdLine().getColour())));
3230 if (autoForView || annotation.isAutoCalculated())
3232 // Hardwire the symbol display line to ensure that labels for
3233 // histograms are displayed
3239 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
3240 an[i].getDescription(), anot);
3241 jaa._linecolour = firstColour;
3243 // register new annotation
3244 if (an[i].getId() != null)
3246 annotationIds.put(an[i].getId(), jaa);
3247 jaa.annotationId = an[i].getId();
3249 // recover sequence association
3250 String sequenceRef = an[i].getSequenceRef();
3251 if (sequenceRef != null)
3253 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3254 SequenceI sequence = seqRefIds.get(sequenceRef);
3255 if (sequence == null)
3257 // in pre-2.9 projects sequence ref is to sequence name
3258 sequence = al.findName(sequenceRef);
3260 if (sequence != null)
3262 jaa.createSequenceMapping(sequence, 1, true);
3263 sequence.addAlignmentAnnotation(jaa);
3266 // and make a note of any group association
3267 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
3269 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3270 .get(an[i].getGroupRef());
3273 aal = new ArrayList<>();
3274 groupAnnotRefs.put(an[i].getGroupRef(), aal);
3279 if (an[i].hasScore())
3281 jaa.setScore(an[i].getScore());
3283 if (an[i].hasVisible())
3285 jaa.visible = an[i].getVisible();
3288 if (an[i].hasCentreColLabels())
3290 jaa.centreColLabels = an[i].getCentreColLabels();
3293 if (an[i].hasScaleColLabels())
3295 jaa.scaleColLabel = an[i].getScaleColLabels();
3297 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
3299 // newer files have an 'autoCalculated' flag and store calculation
3300 // state in viewport properties
3301 jaa.autoCalculated = true; // means annotation will be marked for
3302 // update at end of load.
3304 if (an[i].hasGraphHeight())
3306 jaa.graphHeight = an[i].getGraphHeight();
3308 if (an[i].hasBelowAlignment())
3310 jaa.belowAlignment = an[i].isBelowAlignment();
3312 jaa.setCalcId(an[i].getCalcId());
3313 if (an[i].getPropertyCount() > 0)
3315 for (jalview.schemabinding.version2.Property prop : an[i]
3318 jaa.setProperty(prop.getName(), prop.getValue());
3321 if (jaa.autoCalculated)
3323 autoAlan.add(new JvAnnotRow(i, jaa));
3326 // if (!autoForView)
3328 // add autocalculated group annotation and any user created annotation
3330 al.addAnnotation(jaa);
3334 // ///////////////////////
3336 // Create alignment markup and styles for this view
3337 if (jms.getJGroupCount() > 0)
3339 JGroup[] groups = jms.getJGroup();
3340 boolean addAnnotSchemeGroup = false;
3341 for (int i = 0; i < groups.length; i++)
3343 JGroup jGroup = groups[i];
3344 ColourSchemeI cs = null;
3345 if (jGroup.getColour() != null)
3347 if (jGroup.getColour().startsWith("ucs"))
3349 cs = getUserColourScheme(jms, jGroup.getColour());
3351 else if (jGroup.getColour().equals("AnnotationColourGradient")
3352 && jGroup.getAnnotationColours() != null)
3354 addAnnotSchemeGroup = true;
3358 cs = ColourSchemeProperty.getColourScheme(al,
3359 jGroup.getColour());
3362 int pidThreshold = jGroup.getPidThreshold();
3364 Vector<SequenceI> seqs = new Vector<>();
3366 for (int s = 0; s < jGroup.getSeqCount(); s++)
3368 String seqId = jGroup.getSeq(s) + "";
3369 SequenceI ts = seqRefIds.get(seqId);
3373 seqs.addElement(ts);
3377 if (seqs.size() < 1)
3382 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3383 jGroup.getDisplayBoxes(), jGroup.getDisplayText(),
3384 jGroup.getColourText(), jGroup.getStart(), jGroup.getEnd());
3385 sg.getGroupColourScheme().setThreshold(pidThreshold, true);
3386 sg.getGroupColourScheme()
3387 .setConservationInc(jGroup.getConsThreshold());
3388 sg.setOutlineColour(new java.awt.Color(jGroup.getOutlineColour()));
3390 sg.textColour = new java.awt.Color(jGroup.getTextCol1());
3391 sg.textColour2 = new java.awt.Color(jGroup.getTextCol2());
3392 sg.setShowNonconserved(
3393 jGroup.hasShowUnconserved() ? jGroup.isShowUnconserved()
3395 sg.thresholdTextColour = jGroup.getTextColThreshold();
3396 if (jGroup.hasShowConsensusHistogram())
3398 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3401 if (jGroup.hasShowSequenceLogo())
3403 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3405 if (jGroup.hasNormaliseSequenceLogo())
3407 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3409 if (jGroup.hasIgnoreGapsinConsensus())
3411 sg.setIgnoreGapsConsensus(jGroup.getIgnoreGapsinConsensus());
3413 if (jGroup.getConsThreshold() != 0)
3415 Conservation c = new Conservation("All", sg.getSequences(null), 0,
3418 c.verdict(false, 25);
3419 sg.cs.setConservation(c);
3422 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3424 // re-instate unique group/annotation row reference
3425 List<AlignmentAnnotation> jaal = groupAnnotRefs
3426 .get(jGroup.getId());
3429 for (AlignmentAnnotation jaa : jaal)
3432 if (jaa.autoCalculated)
3434 // match up and try to set group autocalc alignment row for this
3436 if (jaa.label.startsWith("Consensus for "))
3438 sg.setConsensus(jaa);
3440 // match up and try to set group autocalc alignment row for this
3442 if (jaa.label.startsWith("Conservation for "))
3444 sg.setConservationRow(jaa);
3451 if (addAnnotSchemeGroup)
3453 // reconstruct the annotation colourscheme
3454 sg.setColourScheme(constructAnnotationColour(
3455 jGroup.getAnnotationColours(), null, al, jms, false));
3461 // only dataset in this model, so just return.
3464 // ///////////////////////////////
3467 // If we just load in the same jar file again, the sequenceSetId
3468 // will be the same, and we end up with multiple references
3469 // to the same sequenceSet. We must modify this id on load
3470 // so that each load of the file gives a unique id
3471 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3472 String viewId = (view.getId() == null ? null
3473 : view.getId() + uniqueSetSuffix);
3474 AlignFrame af = null;
3475 AlignViewport av = null;
3476 // now check to see if we really need to create a new viewport.
3477 if (multipleView && viewportsAdded.size() == 0)
3479 // We recovered an alignment for which a viewport already exists.
3480 // TODO: fix up any settings necessary for overlaying stored state onto
3481 // state recovered from another document. (may not be necessary).
3482 // we may need a binding from a viewport in memory to one recovered from
3484 // and then recover its containing af to allow the settings to be applied.
3485 // TODO: fix for vamsas demo
3487 "About to recover a viewport for existing alignment: Sequence set ID is "
3489 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3490 if (seqsetobj != null)
3492 if (seqsetobj instanceof String)
3494 uniqueSeqSetId = (String) seqsetobj;
3496 "Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
3502 "Warning : Collision between sequence set ID string and existing jalview object mapping.");
3508 * indicate that annotation colours are applied across all groups (pre
3509 * Jalview 2.8.1 behaviour)
3511 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan("2.8.1",
3512 object.getVersion());
3514 AlignmentPanel ap = null;
3515 boolean isnewview = true;
3518 // Check to see if this alignment already has a view id == viewId
3519 jalview.gui.AlignmentPanel views[] = Desktop
3520 .getAlignmentPanels(uniqueSeqSetId);
3521 if (views != null && views.length > 0)
3523 for (int v = 0; v < views.length; v++)
3525 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
3527 // recover the existing alignpanel, alignframe, viewport
3528 af = views[v].alignFrame;
3531 // TODO: could even skip resetting view settings if we don't want to
3532 // change the local settings from other jalview processes
3541 af = loadViewport(file, jseqs, hiddenSeqs, al, jms, view,
3542 uniqueSeqSetId, viewId, autoAlan);
3548 * Load any trees, PDB structures and viewers
3550 * Not done if flag is false (when this method is used for New View)
3552 if (loadTreesAndStructures)
3554 loadTrees(jms, view, af, av, ap);
3555 loadPDBStructures(jprovider, jseqs, af, ap);
3556 loadRnaViewers(jprovider, jseqs, ap);
3558 // and finally return.
3563 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
3564 * panel is restored from separate jar entries, two (gapped and trimmed) per
3565 * sequence and secondary structure.
3567 * Currently each viewer shows just one sequence and structure (gapped and
3568 * trimmed), however this method is designed to support multiple sequences or
3569 * structures in viewers if wanted in future.
3575 private void loadRnaViewers(jarInputStreamProvider jprovider,
3576 JSeq[] jseqs, AlignmentPanel ap)
3579 * scan the sequences for references to viewers; create each one the first
3580 * time it is referenced, add Rna models to existing viewers
3582 for (JSeq jseq : jseqs)
3584 for (int i = 0; i < jseq.getRnaViewerCount(); i++)
3586 RnaViewer viewer = jseq.getRnaViewer(i);
3587 AppVarna appVarna = findOrCreateVarnaViewer(viewer, uniqueSetSuffix,
3590 for (int j = 0; j < viewer.getSecondaryStructureCount(); j++)
3592 SecondaryStructure ss = viewer.getSecondaryStructure(j);
3593 SequenceI seq = seqRefIds.get(jseq.getId());
3594 AlignmentAnnotation ann = this.annotationIds
3595 .get(ss.getAnnotationId());
3598 * add the structure to the Varna display (with session state copied
3599 * from the jar to a temporary file)
3601 boolean gapped = ss.isGapped();
3602 String rnaTitle = ss.getTitle();
3603 String sessionState = ss.getViewerState();
3604 String tempStateFile = copyJarEntry(jprovider, sessionState,
3606 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
3607 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
3609 appVarna.setInitialSelection(viewer.getSelectedRna());
3615 * Locate and return an already instantiated matching AppVarna, or create one
3619 * @param viewIdSuffix
3623 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
3624 String viewIdSuffix, AlignmentPanel ap)
3627 * on each load a suffix is appended to the saved viewId, to avoid conflicts
3628 * if load is repeated
3630 String postLoadId = viewer.getViewId() + viewIdSuffix;
3631 for (JInternalFrame frame : getAllFrames())
3633 if (frame instanceof AppVarna)
3635 AppVarna varna = (AppVarna) frame;
3636 if (postLoadId.equals(varna.getViewId()))
3638 // this viewer is already instantiated
3639 // could in future here add ap as another 'parent' of the
3640 // AppVarna window; currently just 1-to-many
3647 * viewer not found - make it
3649 RnaViewerModel model = new RnaViewerModel(postLoadId, viewer.getTitle(),
3650 viewer.getXpos(), viewer.getYpos(), viewer.getWidth(),
3651 viewer.getHeight(), viewer.getDividerLocation());
3652 AppVarna varna = new AppVarna(model, ap);
3658 * Load any saved trees
3666 protected void loadTrees(JalviewModelSequence jms, Viewport view,
3667 AlignFrame af, AlignViewport av, AlignmentPanel ap)
3669 // TODO result of automated refactoring - are all these parameters needed?
3672 for (int t = 0; t < jms.getTreeCount(); t++)
3675 Tree tree = jms.getTree(t);
3676 NewickFile newick = new jalview.io.NewickFile(tree.getNewick());
3678 TreeFrameI externalViewer = AptxInit.createInstanceFromNhx(
3679 tree.getTitle(), tree.getNewick(),
3683 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
3688 tp = af.showNewickTree(
3690 tree.getTitle(), tree.getWidth(), tree.getHeight(),
3691 tree.getXpos(), tree.getYpos());
3692 if (tree.getId() != null)
3694 // perhaps bind the tree id to something ?
3699 // update local tree attributes ?
3700 // TODO: should check if tp has been manipulated by user - if so its
3701 // settings shouldn't be modified
3702 tp.setTitle(tree.getTitle());
3703 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(),
3704 tree.getWidth(), tree.getHeight()));
3705 tp.av = av; // af.viewport; // TODO: verify 'associate with all
3708 tp.treeCanvas.av = av; // af.viewport;
3709 tp.treeCanvas.ap = ap; // af.alignPanel;
3714 warn("There was a problem recovering stored Newick tree: \n"
3715 + tree.getNewick());
3719 tp.fitToWindow.setState(tree.getFitToWindow());
3720 tp.fitToWindow_actionPerformed(null);
3722 if (tree.getFontName() != null)
3724 tp.setTreeFont(new java.awt.Font(tree.getFontName(),
3725 tree.getFontStyle(), tree.getFontSize()));
3729 tp.setTreeFont(new java.awt.Font(view.getFontName(),
3730 view.getFontStyle(), tree.getFontSize()));
3733 tp.showPlaceholders(tree.getMarkUnlinked());
3734 tp.showBootstrap(tree.getShowBootstrap());
3735 tp.showDistances(tree.getShowDistances());
3737 tp.treeCanvas.threshold = tree.getThreshold();
3739 if (tree.getCurrentTree())
3741 af.viewport.setCurrentTree(tp.getTree());
3745 } catch (Exception ex)
3747 ex.printStackTrace();
3752 * Load and link any saved structure viewers.
3759 protected void loadPDBStructures(jarInputStreamProvider jprovider,
3760 JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
3763 * Run through all PDB ids on the alignment, and collect mappings between
3764 * distinct view ids and all sequences referring to that view.
3766 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<>();
3768 for (int i = 0; i < jseqs.length; i++)
3770 if (jseqs[i].getPdbidsCount() > 0)
3772 Pdbids[] ids = jseqs[i].getPdbids();
3773 for (int p = 0; p < ids.length; p++)
3775 final int structureStateCount = ids[p].getStructureStateCount();
3776 for (int s = 0; s < structureStateCount; s++)
3778 // check to see if we haven't already created this structure view
3779 final StructureState structureState = ids[p]
3780 .getStructureState(s);
3781 String sviewid = (structureState.getViewId() == null) ? null
3782 : structureState.getViewId() + uniqueSetSuffix;
3783 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
3784 // Originally : ids[p].getFile()
3785 // : TODO: verify external PDB file recovery still works in normal
3786 // jalview project load
3787 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId(),
3789 jpdb.setId(ids[p].getId());
3791 int x = structureState.getXpos();
3792 int y = structureState.getYpos();
3793 int width = structureState.getWidth();
3794 int height = structureState.getHeight();
3796 // Probably don't need to do this anymore...
3797 // Desktop.desktop.getComponentAt(x, y);
3798 // TODO: NOW: check that this recovers the PDB file correctly.
3799 String pdbFile = loadPDBFile(jprovider, ids[p].getId(),
3801 jalview.datamodel.SequenceI seq = seqRefIds
3802 .get(jseqs[i].getId() + "");
3803 if (sviewid == null)
3805 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width + ","
3808 if (!structureViewers.containsKey(sviewid))
3810 structureViewers.put(sviewid,
3811 new StructureViewerModel(x, y, width, height, false,
3812 false, true, structureState.getViewId(),
3813 structureState.getType()));
3814 // Legacy pre-2.7 conversion JAL-823 :
3815 // do not assume any view has to be linked for colour by
3819 // assemble String[] { pdb files }, String[] { id for each
3820 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3821 // seqs_file 2}, boolean[] {
3822 // linkAlignPanel,superposeWithAlignpanel}} from hash
3823 StructureViewerModel jmoldat = structureViewers.get(sviewid);
3824 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
3825 | (structureState.hasAlignwithAlignPanel()
3826 ? structureState.getAlignwithAlignPanel()
3830 * Default colour by linked panel to false if not specified (e.g.
3831 * for pre-2.7 projects)
3833 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
3834 colourWithAlignPanel |= (structureState
3835 .hasColourwithAlignPanel()
3836 ? structureState.getColourwithAlignPanel()
3838 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
3841 * Default colour by viewer to true if not specified (e.g. for
3844 boolean colourByViewer = jmoldat.isColourByViewer();
3845 colourByViewer &= structureState.hasColourByJmol()
3846 ? structureState.getColourByJmol()
3848 jmoldat.setColourByViewer(colourByViewer);
3850 if (jmoldat.getStateData().length() < structureState
3851 .getContent().length())
3854 jmoldat.setStateData(structureState.getContent());
3857 if (ids[p].getFile() != null)
3859 File mapkey = new File(ids[p].getFile());
3860 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
3861 if (seqstrmaps == null)
3863 jmoldat.getFileData().put(mapkey,
3864 seqstrmaps = jmoldat.new StructureData(pdbFile,
3867 if (!seqstrmaps.getSeqList().contains(seq))
3869 seqstrmaps.getSeqList().add(seq);
3875 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");
3882 // Instantiate the associated structure views
3883 for (Entry<String, StructureViewerModel> entry : structureViewers
3888 createOrLinkStructureViewer(entry, af, ap, jprovider);
3889 } catch (Exception e)
3892 "Error loading structure viewer: " + e.getMessage());
3893 // failed - try the next one
3905 protected void createOrLinkStructureViewer(
3906 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3907 AlignmentPanel ap, jarInputStreamProvider jprovider)
3909 final StructureViewerModel stateData = viewerData.getValue();
3912 * Search for any viewer windows already open from other alignment views
3913 * that exactly match the stored structure state
3915 StructureViewerBase comp = findMatchingViewer(viewerData);
3919 linkStructureViewer(ap, comp, stateData);
3924 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
3925 * "viewer_"+stateData.viewId
3927 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
3929 createChimeraViewer(viewerData, af, jprovider);
3934 * else Jmol (if pre-2.9, stateData contains JMOL state string)
3936 createJmolViewer(viewerData, af, jprovider);
3941 * Create a new Chimera viewer.
3947 protected void createChimeraViewer(
3948 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3949 jarInputStreamProvider jprovider)
3951 StructureViewerModel data = viewerData.getValue();
3952 String chimeraSessionFile = data.getStateData();
3955 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
3957 * NB this is the 'saved' viewId as in the project file XML, _not_ the
3958 * 'uniquified' sviewid used to reconstruct the viewer here
3960 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
3961 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
3964 Set<Entry<File, StructureData>> fileData = data.getFileData()
3966 List<PDBEntry> pdbs = new ArrayList<>();
3967 List<SequenceI[]> allseqs = new ArrayList<>();
3968 for (Entry<File, StructureData> pdb : fileData)
3970 String filePath = pdb.getValue().getFilePath();
3971 String pdbId = pdb.getValue().getPdbId();
3972 // pdbs.add(new PDBEntry(filePath, pdbId));
3973 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
3974 final List<SequenceI> seqList = pdb.getValue().getSeqList();
3975 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
3979 boolean colourByChimera = data.isColourByViewer();
3980 boolean colourBySequence = data.isColourWithAlignPanel();
3982 // TODO use StructureViewer as a factory here, see JAL-1761
3983 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
3984 final SequenceI[][] seqsArray = allseqs
3985 .toArray(new SequenceI[allseqs.size()][]);
3986 String newViewId = viewerData.getKey();
3988 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
3989 af.alignPanel, pdbArray, seqsArray, colourByChimera,
3990 colourBySequence, newViewId);
3991 cvf.setSize(data.getWidth(), data.getHeight());
3992 cvf.setLocation(data.getX(), data.getY());
3996 * Create a new Jmol window. First parse the Jmol state to translate filenames
3997 * loaded into the view, and record the order in which files are shown in the
3998 * Jmol view, so we can add the sequence mappings in same order.
4004 protected void createJmolViewer(
4005 final Entry<String, StructureViewerModel> viewerData,
4006 AlignFrame af, jarInputStreamProvider jprovider)
4008 final StructureViewerModel svattrib = viewerData.getValue();
4009 String state = svattrib.getStateData();
4012 * Pre-2.9: state element value is the Jmol state string
4014 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
4017 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
4019 state = readJarEntry(jprovider,
4020 getViewerJarEntryName(svattrib.getViewId()));
4023 List<String> pdbfilenames = new ArrayList<>();
4024 List<SequenceI[]> seqmaps = new ArrayList<>();
4025 List<String> pdbids = new ArrayList<>();
4026 StringBuilder newFileLoc = new StringBuilder(64);
4027 int cp = 0, ncp, ecp;
4028 Map<File, StructureData> oldFiles = svattrib.getFileData();
4029 while ((ncp = state.indexOf("load ", cp)) > -1)
4033 // look for next filename in load statement
4034 newFileLoc.append(state.substring(cp,
4035 ncp = (state.indexOf("\"", ncp + 1) + 1)));
4036 String oldfilenam = state.substring(ncp,
4037 ecp = state.indexOf("\"", ncp));
4038 // recover the new mapping data for this old filename
4039 // have to normalize filename - since Jmol and jalview do
4041 // translation differently.
4042 StructureData filedat = oldFiles.get(new File(oldfilenam));
4043 if (filedat == null)
4045 String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\");
4046 filedat = oldFiles.get(new File(reformatedOldFilename));
4048 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
4049 pdbfilenames.add(filedat.getFilePath());
4050 pdbids.add(filedat.getPdbId());
4051 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4052 newFileLoc.append("\"");
4053 cp = ecp + 1; // advance beyond last \" and set cursor so we can
4054 // look for next file statement.
4055 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
4059 // just append rest of state
4060 newFileLoc.append(state.substring(cp));
4064 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
4065 newFileLoc = new StringBuilder(state);
4066 newFileLoc.append("; load append ");
4067 for (File id : oldFiles.keySet())
4069 // add this and any other pdb files that should be present in
4071 StructureData filedat = oldFiles.get(id);
4072 newFileLoc.append(filedat.getFilePath());
4073 pdbfilenames.add(filedat.getFilePath());
4074 pdbids.add(filedat.getPdbId());
4075 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4076 newFileLoc.append(" \"");
4077 newFileLoc.append(filedat.getFilePath());
4078 newFileLoc.append("\"");
4081 newFileLoc.append(";");
4084 if (newFileLoc.length() == 0)
4088 int histbug = newFileLoc.indexOf("history = ");
4092 * change "history = [true|false];" to "history = [1|0];"
4095 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
4096 String val = (diff == -1) ? null
4097 : newFileLoc.substring(histbug, diff);
4098 if (val != null && val.length() >= 4)
4100 if (val.contains("e")) // eh? what can it be?
4102 if (val.trim().equals("true"))
4110 newFileLoc.replace(histbug, diff, val);
4115 final String[] pdbf = pdbfilenames
4116 .toArray(new String[pdbfilenames.size()]);
4117 final String[] id = pdbids.toArray(new String[pdbids.size()]);
4118 final SequenceI[][] sq = seqmaps
4119 .toArray(new SequenceI[seqmaps.size()][]);
4120 final String fileloc = newFileLoc.toString();
4121 final String sviewid = viewerData.getKey();
4122 final AlignFrame alf = af;
4123 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
4124 svattrib.getWidth(), svattrib.getHeight());
4127 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
4132 JalviewStructureDisplayI sview = null;
4135 sview = new StructureViewer(
4136 alf.alignPanel.getStructureSelectionManager())
4137 .createView(StructureViewer.ViewerType.JMOL,
4138 pdbf, id, sq, alf.alignPanel, svattrib,
4139 fileloc, rect, sviewid);
4140 addNewStructureViewer(sview);
4141 } catch (OutOfMemoryError ex)
4143 new OOMWarning("restoring structure view for PDB id " + id,
4144 (OutOfMemoryError) ex.getCause());
4145 if (sview != null && sview.isVisible())
4147 sview.closeViewer(false);
4148 sview.setVisible(false);
4154 } catch (InvocationTargetException ex)
4156 warn("Unexpected error when opening Jmol view.", ex);
4158 } catch (InterruptedException e)
4160 // e.printStackTrace();
4166 * Generates a name for the entry in the project jar file to hold state
4167 * information for a structure viewer
4172 protected String getViewerJarEntryName(String viewId)
4174 return VIEWER_PREFIX + viewId;
4178 * Returns any open frame that matches given structure viewer data. The match
4179 * is based on the unique viewId, or (for older project versions) the frame's
4185 protected StructureViewerBase findMatchingViewer(
4186 Entry<String, StructureViewerModel> viewerData)
4188 final String sviewid = viewerData.getKey();
4189 final StructureViewerModel svattrib = viewerData.getValue();
4190 StructureViewerBase comp = null;
4191 JInternalFrame[] frames = getAllFrames();
4192 for (JInternalFrame frame : frames)
4194 if (frame instanceof StructureViewerBase)
4197 * Post jalview 2.4 schema includes structure view id
4199 if (sviewid != null && ((StructureViewerBase) frame).getViewId()
4202 comp = (StructureViewerBase) frame;
4203 break; // break added in 2.9
4206 * Otherwise test for matching position and size of viewer frame
4208 else if (frame.getX() == svattrib.getX()
4209 && frame.getY() == svattrib.getY()
4210 && frame.getHeight() == svattrib.getHeight()
4211 && frame.getWidth() == svattrib.getWidth())
4213 comp = (StructureViewerBase) frame;
4214 // no break in faint hope of an exact match on viewId
4222 * Link an AlignmentPanel to an existing structure viewer.
4227 * @param useinViewerSuperpos
4228 * @param usetoColourbyseq
4229 * @param viewerColouring
4231 protected void linkStructureViewer(AlignmentPanel ap,
4232 StructureViewerBase viewer, StructureViewerModel stateData)
4234 // NOTE: if the jalview project is part of a shared session then
4235 // view synchronization should/could be done here.
4237 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4238 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4239 final boolean viewerColouring = stateData.isColourByViewer();
4240 Map<File, StructureData> oldFiles = stateData.getFileData();
4243 * Add mapping for sequences in this view to an already open viewer
4245 final AAStructureBindingModel binding = viewer.getBinding();
4246 for (File id : oldFiles.keySet())
4248 // add this and any other pdb files that should be present in the
4250 StructureData filedat = oldFiles.get(id);
4251 String pdbFile = filedat.getFilePath();
4252 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4253 binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE,
4255 binding.addSequenceForStructFile(pdbFile, seq);
4257 // and add the AlignmentPanel's reference to the view panel
4258 viewer.addAlignmentPanel(ap);
4259 if (useinViewerSuperpos)
4261 viewer.useAlignmentPanelForSuperposition(ap);
4265 viewer.excludeAlignmentPanelForSuperposition(ap);
4267 if (usetoColourbyseq)
4269 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4273 viewer.excludeAlignmentPanelForColourbyseq(ap);
4278 * Get all frames within the Desktop.
4282 protected JInternalFrame[] getAllFrames()
4284 JInternalFrame[] frames = null;
4285 // TODO is this necessary - is it safe - risk of hanging?
4290 frames = Desktop.desktop.getAllFrames();
4291 } catch (ArrayIndexOutOfBoundsException e)
4293 // occasional No such child exceptions are thrown here...
4297 } catch (InterruptedException f)
4301 } while (frames == null);
4306 * Answers true if 'version' is equal to or later than 'supported', where each
4307 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4308 * changes. Development and test values for 'version' are leniently treated
4312 * - minimum version we are comparing against
4314 * - version of data being processsed
4317 public static boolean isVersionStringLaterThan(String supported,
4320 if (supported == null || version == null
4321 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4322 || version.equalsIgnoreCase("Test")
4323 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4325 System.err.println("Assuming project file with "
4326 + (version == null ? "null" : version)
4327 + " is compatible with Jalview version " + supported);
4332 return StringUtils.compareVersions(version, supported, "b") >= 0;
4336 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4338 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4340 if (newStructureViewers != null)
4342 sview.getBinding().setFinishedLoadingFromArchive(false);
4343 newStructureViewers.add(sview);
4347 protected void setLoadingFinishedForNewStructureViewers()
4349 if (newStructureViewers != null)
4351 for (JalviewStructureDisplayI sview : newStructureViewers)
4353 sview.getBinding().setFinishedLoadingFromArchive(true);
4355 newStructureViewers.clear();
4356 newStructureViewers = null;
4360 AlignFrame loadViewport(String file, JSeq[] JSEQ,
4361 List<SequenceI> hiddenSeqs, AlignmentI al,
4362 JalviewModelSequence jms, Viewport view, String uniqueSeqSetId,
4363 String viewId, List<JvAnnotRow> autoAlan)
4365 AlignFrame af = null;
4366 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
4367 uniqueSeqSetId, viewId);
4369 af.setFileName(file, FileFormat.Jalview);
4371 for (int i = 0; i < JSEQ.length; i++)
4373 af.viewport.setSequenceColour(
4374 af.viewport.getAlignment().getSequenceAt(i),
4375 new java.awt.Color(JSEQ[i].getColour()));
4380 af.getViewport().setColourByReferenceSeq(true);
4381 af.getViewport().setDisplayReferenceSeq(true);
4384 af.viewport.setGatherViewsHere(view.getGatheredViews());
4386 if (view.getSequenceSetId() != null)
4388 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4390 af.viewport.setSequenceSetId(uniqueSeqSetId);
4393 // propagate shared settings to this new view
4394 af.viewport.setHistoryList(av.getHistoryList());
4395 af.viewport.setRedoList(av.getRedoList());
4399 viewportsAdded.put(uniqueSeqSetId, af.viewport);
4401 // TODO: check if this method can be called repeatedly without
4402 // side-effects if alignpanel already registered.
4403 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4405 // apply Hidden regions to view.
4406 if (hiddenSeqs != null)
4408 for (int s = 0; s < JSEQ.length; s++)
4410 SequenceGroup hidden = new SequenceGroup();
4411 boolean isRepresentative = false;
4412 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
4414 isRepresentative = true;
4415 SequenceI sequenceToHide = al
4416 .getSequenceAt(JSEQ[s].getHiddenSequences(r));
4417 hidden.addSequence(sequenceToHide, false);
4418 // remove from hiddenSeqs list so we don't try to hide it twice
4419 hiddenSeqs.remove(sequenceToHide);
4421 if (isRepresentative)
4423 SequenceI representativeSequence = al.getSequenceAt(s);
4424 hidden.addSequence(representativeSequence, false);
4425 af.viewport.hideRepSequences(representativeSequence, hidden);
4429 SequenceI[] hseqs = hiddenSeqs
4430 .toArray(new SequenceI[hiddenSeqs.size()]);
4431 af.viewport.hideSequence(hseqs);
4434 // recover view properties and display parameters
4436 af.viewport.setShowAnnotation(view.getShowAnnotation());
4437 af.viewport.setAbovePIDThreshold(view.getPidSelected());
4438 af.viewport.setThreshold(view.getPidThreshold());
4440 af.viewport.setColourText(view.getShowColourText());
4442 af.viewport.setConservationSelected(view.getConservationSelected());
4443 af.viewport.setIncrement(view.getConsThreshold());
4444 af.viewport.setShowJVSuffix(view.getShowFullId());
4445 af.viewport.setRightAlignIds(view.getRightAlignIds());
4446 af.viewport.setFont(new java.awt.Font(view.getFontName(),
4447 view.getFontStyle(), view.getFontSize()), true);
4448 ViewStyleI vs = af.viewport.getViewStyle();
4449 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
4450 af.viewport.setViewStyle(vs);
4451 // TODO: allow custom charWidth/Heights to be restored by updating them
4452 // after setting font - which means set above to false
4453 af.viewport.setRenderGaps(view.getRenderGaps());
4454 af.viewport.setWrapAlignment(view.getWrapAlignment());
4455 af.viewport.setShowAnnotation(view.getShowAnnotation());
4457 af.viewport.setShowBoxes(view.getShowBoxes());
4459 af.viewport.setShowText(view.getShowText());
4461 af.viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
4462 af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
4463 af.viewport.setThresholdTextColour(view.getTextColThreshold());
4464 af.viewport.setShowUnconserved(
4465 view.hasShowUnconserved() ? view.isShowUnconserved() : false);
4466 af.viewport.getRanges().setStartRes(view.getStartRes());
4468 if (view.getViewName() != null)
4470 af.viewport.viewName = view.getViewName();
4471 af.setInitialTabVisible();
4473 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
4475 // startSeq set in af.alignPanel.updateLayout below
4476 af.alignPanel.updateLayout();
4477 ColourSchemeI cs = null;
4478 // apply colourschemes
4479 if (view.getBgColour() != null)
4481 if (view.getBgColour().startsWith("ucs"))
4483 cs = getUserColourScheme(jms, view.getBgColour());
4485 else if (view.getBgColour().startsWith("Annotation"))
4487 AnnotationColours viewAnnColour = view.getAnnotationColours();
4488 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
4495 cs = ColourSchemeProperty.getColourScheme(al, view.getBgColour());
4499 af.viewport.setGlobalColourScheme(cs);
4500 af.viewport.getResidueShading().setThreshold(view.getPidThreshold(),
4501 view.getIgnoreGapsinConsensus());
4502 af.viewport.getResidueShading()
4503 .setConsensus(af.viewport.getSequenceConsensusHash());
4504 af.viewport.setColourAppliesToAllGroups(false);
4506 if (view.getConservationSelected() && cs != null)
4508 af.viewport.getResidueShading()
4509 .setConservationInc(view.getConsThreshold());
4512 af.changeColour(cs);
4514 af.viewport.setColourAppliesToAllGroups(true);
4516 af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures());
4518 if (view.hasCentreColumnLabels())
4520 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
4522 if (view.hasIgnoreGapsinConsensus())
4524 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
4527 if (view.hasFollowHighlight())
4529 af.viewport.setFollowHighlight(view.getFollowHighlight());
4531 if (view.hasFollowSelection())
4533 af.viewport.followSelection = view.getFollowSelection();
4535 if (view.hasShowConsensusHistogram())
4538 .setShowConsensusHistogram(view.getShowConsensusHistogram());
4542 af.viewport.setShowConsensusHistogram(true);
4544 if (view.hasShowSequenceLogo())
4546 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
4550 af.viewport.setShowSequenceLogo(false);
4552 if (view.hasNormaliseSequenceLogo())
4554 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
4556 if (view.hasShowDbRefTooltip())
4558 af.viewport.setShowDBRefs(view.getShowDbRefTooltip());
4560 if (view.hasShowNPfeatureTooltip())
4562 af.viewport.setShowNPFeats(view.hasShowNPfeatureTooltip());
4564 if (view.hasShowGroupConsensus())
4566 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
4570 af.viewport.setShowGroupConsensus(false);
4572 if (view.hasShowGroupConservation())
4574 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
4578 af.viewport.setShowGroupConservation(false);
4581 // recover featre settings
4582 if (jms.getFeatureSettings() != null)
4584 FeaturesDisplayed fdi;
4585 af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
4586 String[] renderOrder = new String[jms.getFeatureSettings()
4587 .getSettingCount()];
4588 Map<String, FeatureColourI> featureColours = new Hashtable<>();
4589 Map<String, Float> featureOrder = new Hashtable<>();
4591 for (int fs = 0; fs < jms.getFeatureSettings()
4592 .getSettingCount(); fs++)
4594 Setting setting = jms.getFeatureSettings().getSetting(fs);
4595 if (setting.hasMincolour())
4597 FeatureColourI gc = setting.hasMin()
4598 ? new FeatureColour(new Color(setting.getMincolour()),
4599 new Color(setting.getColour()), setting.getMin(),
4601 : new FeatureColour(new Color(setting.getMincolour()),
4602 new Color(setting.getColour()), 0, 1);
4603 if (setting.hasThreshold())
4605 gc.setThreshold(setting.getThreshold());
4606 int threshstate = setting.getThreshstate();
4607 // -1 = None, 0 = Below, 1 = Above threshold
4608 if (threshstate == 0)
4610 gc.setBelowThreshold(true);
4612 else if (threshstate == 1)
4614 gc.setAboveThreshold(true);
4617 gc.setAutoScaled(true); // default
4618 if (setting.hasAutoScale())
4620 gc.setAutoScaled(setting.getAutoScale());
4622 if (setting.hasColourByLabel())
4624 gc.setColourByLabel(setting.getColourByLabel());
4626 // and put in the feature colour table.
4627 featureColours.put(setting.getType(), gc);
4631 featureColours.put(setting.getType(),
4632 new FeatureColour(new Color(setting.getColour())));
4634 renderOrder[fs] = setting.getType();
4635 if (setting.hasOrder())
4637 featureOrder.put(setting.getType(), setting.getOrder());
4641 featureOrder.put(setting.getType(), new Float(
4642 fs / jms.getFeatureSettings().getSettingCount()));
4644 if (setting.getDisplay())
4646 fdi.setVisible(setting.getType());
4649 Map<String, Boolean> fgtable = new Hashtable<>();
4650 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
4652 Group grp = jms.getFeatureSettings().getGroup(gs);
4653 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
4655 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4656 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
4657 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
4658 FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4659 fgtable, featureColours, 1.0f, featureOrder);
4660 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
4661 .transferSettings(frs);
4665 if (view.getHiddenColumnsCount() > 0)
4667 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
4669 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(),
4670 view.getHiddenColumns(c).getEnd() // +1
4674 if (view.getCalcIdParam() != null)
4676 for (CalcIdParam calcIdParam : view.getCalcIdParam())
4678 if (calcIdParam != null)
4680 if (recoverCalcIdParam(calcIdParam, af.viewport))
4685 warn("Couldn't recover parameters for "
4686 + calcIdParam.getCalcId());
4691 af.setMenusFromViewport(af.viewport);
4692 af.setTitle(view.getTitle());
4693 // TODO: we don't need to do this if the viewport is aready visible.
4695 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
4696 * has a 'cdna/protein complement' view, in which case save it in order to
4697 * populate a SplitFrame once all views have been read in.
4699 String complementaryViewId = view.getComplementId();
4700 if (complementaryViewId == null)
4702 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
4704 // recompute any autoannotation
4705 af.alignPanel.updateAnnotation(false, true);
4706 reorderAutoannotation(af, al, autoAlan);
4707 af.alignPanel.alignmentChanged();
4711 splitFrameCandidates.put(view, af);
4717 * Reads saved data to restore Colour by Annotation settings
4719 * @param viewAnnColour
4723 * @param checkGroupAnnColour
4726 private ColourSchemeI constructAnnotationColour(
4727 AnnotationColours viewAnnColour, AlignFrame af, AlignmentI al,
4728 JalviewModelSequence jms, boolean checkGroupAnnColour)
4730 boolean propagateAnnColour = false;
4731 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
4732 if (checkGroupAnnColour && al.getGroups() != null
4733 && al.getGroups().size() > 0)
4735 // pre 2.8.1 behaviour
4736 // check to see if we should transfer annotation colours
4737 propagateAnnColour = true;
4738 for (SequenceGroup sg : al.getGroups())
4740 if (sg.getColourScheme() instanceof AnnotationColourGradient)
4742 propagateAnnColour = false;
4748 * 2.10.2- : saved annotationId is AlignmentAnnotation.annotationId
4750 String annotationId = viewAnnColour.getAnnotation();
4751 AlignmentAnnotation matchedAnnotation = annotationIds.get(annotationId);
4754 * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
4756 if (matchedAnnotation == null
4757 && annAlignment.getAlignmentAnnotation() != null)
4759 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
4762 .equals(annAlignment.getAlignmentAnnotation()[i].label))
4764 matchedAnnotation = annAlignment.getAlignmentAnnotation()[i];
4769 if (matchedAnnotation == null)
4771 System.err.println("Failed to match annotation colour scheme for "
4775 if (matchedAnnotation.getThreshold() == null)
4777 matchedAnnotation.setThreshold(new GraphLine(
4778 viewAnnColour.getThreshold(), "Threshold", Color.black));
4781 AnnotationColourGradient cs = null;
4782 if (viewAnnColour.getColourScheme().equals("None"))
4784 cs = new AnnotationColourGradient(matchedAnnotation,
4785 new Color(viewAnnColour.getMinColour()),
4786 new Color(viewAnnColour.getMaxColour()),
4787 viewAnnColour.getAboveThreshold());
4789 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
4791 cs = new AnnotationColourGradient(matchedAnnotation,
4792 getUserColourScheme(jms, viewAnnColour.getColourScheme()),
4793 viewAnnColour.getAboveThreshold());
4797 cs = new AnnotationColourGradient(matchedAnnotation,
4798 ColourSchemeProperty.getColourScheme(al,
4799 viewAnnColour.getColourScheme()),
4800 viewAnnColour.getAboveThreshold());
4803 boolean perSequenceOnly = viewAnnColour.isPerSequence();
4804 boolean useOriginalColours = viewAnnColour.isPredefinedColours();
4805 cs.setSeqAssociated(perSequenceOnly);
4806 cs.setPredefinedColours(useOriginalColours);
4808 if (propagateAnnColour && al.getGroups() != null)
4810 // Also use these settings for all the groups
4811 for (int g = 0; g < al.getGroups().size(); g++)
4813 SequenceGroup sg = al.getGroups().get(g);
4814 if (sg.getGroupColourScheme() == null)
4819 AnnotationColourGradient groupScheme = new AnnotationColourGradient(
4820 matchedAnnotation, sg.getColourScheme(),
4821 viewAnnColour.getAboveThreshold());
4822 sg.setColourScheme(groupScheme);
4823 groupScheme.setSeqAssociated(perSequenceOnly);
4824 groupScheme.setPredefinedColours(useOriginalColours);
4830 private void reorderAutoannotation(AlignFrame af, AlignmentI al,
4831 List<JvAnnotRow> autoAlan)
4833 // copy over visualization settings for autocalculated annotation in the
4835 if (al.getAlignmentAnnotation() != null)
4838 * Kludge for magic autoannotation names (see JAL-811)
4840 String[] magicNames = new String[] { "Consensus", "Quality",
4842 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
4843 Hashtable<String, JvAnnotRow> visan = new Hashtable<>();
4844 for (String nm : magicNames)
4846 visan.put(nm, nullAnnot);
4848 for (JvAnnotRow auan : autoAlan)
4850 visan.put(auan.template.label
4851 + (auan.template.getCalcId() == null ? ""
4852 : "\t" + auan.template.getCalcId()),
4855 int hSize = al.getAlignmentAnnotation().length;
4856 List<JvAnnotRow> reorder = new ArrayList<>();
4857 // work through any autoCalculated annotation already on the view
4858 // removing it if it should be placed in a different location on the
4859 // annotation panel.
4860 List<String> remains = new ArrayList<>(visan.keySet());
4861 for (int h = 0; h < hSize; h++)
4863 jalview.datamodel.AlignmentAnnotation jalan = al
4864 .getAlignmentAnnotation()[h];
4865 if (jalan.autoCalculated)
4868 JvAnnotRow valan = visan.get(k = jalan.label);
4869 if (jalan.getCalcId() != null)
4871 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
4876 // delete the auto calculated row from the alignment
4877 al.deleteAnnotation(jalan, false);
4881 if (valan != nullAnnot)
4883 if (jalan != valan.template)
4885 // newly created autoannotation row instance
4886 // so keep a reference to the visible annotation row
4887 // and copy over all relevant attributes
4888 if (valan.template.graphHeight >= 0)
4891 jalan.graphHeight = valan.template.graphHeight;
4893 jalan.visible = valan.template.visible;
4895 reorder.add(new JvAnnotRow(valan.order, jalan));
4900 // Add any (possibly stale) autocalculated rows that were not appended to
4901 // the view during construction
4902 for (String other : remains)
4904 JvAnnotRow othera = visan.get(other);
4905 if (othera != nullAnnot && othera.template.getCalcId() != null
4906 && othera.template.getCalcId().length() > 0)
4908 reorder.add(othera);
4911 // now put the automatic annotation in its correct place
4912 int s = 0, srt[] = new int[reorder.size()];
4913 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
4914 for (JvAnnotRow jvar : reorder)
4917 srt[s++] = jvar.order;
4920 jalview.util.QuickSort.sort(srt, rws);
4921 // and re-insert the annotation at its correct position
4922 for (JvAnnotRow jvar : rws)
4924 al.addAnnotation(jvar.template, jvar.order);
4926 af.alignPanel.adjustAnnotationHeight();
4930 Hashtable skipList = null;
4933 * TODO remove this method
4936 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
4937 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
4938 * throw new Error("Implementation Error. No skipList defined for this
4939 * Jalview2XML instance."); } return (AlignFrame)
4940 * skipList.get(view.getSequenceSetId()); }
4944 * Check if the Jalview view contained in object should be skipped or not.
4947 * @return true if view's sequenceSetId is a key in skipList
4949 private boolean skipViewport(JalviewModel object)
4951 if (skipList == null)
4956 if (skipList.containsKey(
4957 id = object.getJalviewModelSequence().getViewport()[0]
4958 .getSequenceSetId()))
4960 if (Cache.log != null && Cache.log.isDebugEnabled())
4962 Cache.log.debug("Skipping seuqence set id " + id);
4969 public void addToSkipList(AlignFrame af)
4971 if (skipList == null)
4973 skipList = new Hashtable();
4975 skipList.put(af.getViewport().getSequenceSetId(), af);
4978 public void clearSkipList()
4980 if (skipList != null)
4987 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
4988 boolean ignoreUnrefed)
4990 jalview.datamodel.AlignmentI ds = getDatasetFor(
4991 vamsasSet.getDatasetId());
4992 Vector dseqs = null;
4995 // create a list of new dataset sequences
4996 dseqs = new Vector();
4998 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
5000 Sequence vamsasSeq = vamsasSet.getSequence(i);
5001 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
5003 // create a new dataset
5006 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
5007 dseqs.copyInto(dsseqs);
5008 ds = new jalview.datamodel.Alignment(dsseqs);
5009 debug("Created new dataset " + vamsasSet.getDatasetId()
5010 + " for alignment " + System.identityHashCode(al));
5011 addDatasetRef(vamsasSet.getDatasetId(), ds);
5013 // set the dataset for the newly imported alignment.
5014 if (al.getDataset() == null && !ignoreUnrefed)
5023 * sequence definition to create/merge dataset sequence for
5027 * vector to add new dataset sequence to
5028 * @param ignoreUnrefed
5029 * - when true, don't create new sequences from vamsasSeq if it's id
5030 * doesn't already have an asssociated Jalview sequence.
5032 * - used to reorder the sequence in the alignment according to the
5033 * vamsasSeq array ordering, to preserve ordering of dataset
5035 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
5036 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed, int vseqpos)
5038 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
5040 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
5041 boolean reorder = false;
5042 SequenceI dsq = null;
5043 if (sq != null && sq.getDatasetSequence() != null)
5045 dsq = sq.getDatasetSequence();
5051 if (sq == null && ignoreUnrefed)
5055 String sqid = vamsasSeq.getDsseqid();
5058 // need to create or add a new dataset sequence reference to this sequence
5061 dsq = seqRefIds.get(sqid);
5066 // make a new dataset sequence
5067 dsq = sq.createDatasetSequence();
5070 // make up a new dataset reference for this sequence
5071 sqid = seqHash(dsq);
5073 dsq.setVamsasId(uniqueSetSuffix + sqid);
5074 seqRefIds.put(sqid, dsq);
5079 dseqs.addElement(dsq);
5084 ds.addSequence(dsq);
5090 { // make this dataset sequence sq's dataset sequence
5091 sq.setDatasetSequence(dsq);
5092 // and update the current dataset alignment
5097 if (!dseqs.contains(dsq))
5104 if (ds.findIndex(dsq) < 0)
5106 ds.addSequence(dsq);
5113 // TODO: refactor this as a merge dataset sequence function
5114 // now check that sq (the dataset sequence) sequence really is the union of
5115 // all references to it
5116 // boolean pre = sq.getStart() < dsq.getStart();
5117 // boolean post = sq.getEnd() > dsq.getEnd();
5121 // StringBuffer sb = new StringBuffer();
5122 String newres = jalview.analysis.AlignSeq.extractGaps(
5123 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
5124 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
5125 && newres.length() > dsq.getLength())
5127 // Update with the longer sequence.
5131 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
5132 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
5133 * sb.append(newres.substring(newres.length() - sq.getEnd() -
5134 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
5136 dsq.setSequence(newres);
5138 // TODO: merges will never happen if we 'know' we have the real dataset
5139 // sequence - this should be detected when id==dssid
5141 "DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
5142 // + (pre ? "prepended" : "") + " "
5143 // + (post ? "appended" : ""));
5148 // sequence refs are identical. We may need to update the existing dataset
5149 // alignment with this one, though.
5150 if (ds != null && dseqs == null)
5152 int opos = ds.findIndex(dsq);
5153 SequenceI tseq = null;
5154 if (opos != -1 && vseqpos != opos)
5156 // remove from old position
5157 ds.deleteSequence(dsq);
5159 if (vseqpos < ds.getHeight())
5161 if (vseqpos != opos)
5163 // save sequence at destination position
5164 tseq = ds.getSequenceAt(vseqpos);
5165 ds.replaceSequenceAt(vseqpos, dsq);
5166 ds.addSequence(tseq);
5171 ds.addSequence(dsq);
5178 * TODO use AlignmentI here and in related methods - needs
5179 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
5181 Hashtable<String, AlignmentI> datasetIds = null;
5183 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
5185 private AlignmentI getDatasetFor(String datasetId)
5187 if (datasetIds == null)
5189 datasetIds = new Hashtable<>();
5192 if (datasetIds.containsKey(datasetId))
5194 return datasetIds.get(datasetId);
5199 private void addDatasetRef(String datasetId, AlignmentI dataset)
5201 if (datasetIds == null)
5203 datasetIds = new Hashtable<>();
5205 datasetIds.put(datasetId, dataset);
5209 * make a new dataset ID for this jalview dataset alignment
5214 private String getDatasetIdRef(AlignmentI dataset)
5216 if (dataset.getDataset() != null)
5218 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
5220 String datasetId = makeHashCode(dataset, null);
5221 if (datasetId == null)
5223 // make a new datasetId and record it
5224 if (dataset2Ids == null)
5226 dataset2Ids = new IdentityHashMap<>();
5230 datasetId = dataset2Ids.get(dataset);
5232 if (datasetId == null)
5234 datasetId = "ds" + dataset2Ids.size() + 1;
5235 dataset2Ids.put(dataset, datasetId);
5241 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5243 for (int d = 0; d < sequence.getDBRefCount(); d++)
5245 DBRef dr = sequence.getDBRef(d);
5246 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
5247 sequence.getDBRef(d).getSource(),
5248 sequence.getDBRef(d).getVersion(),
5249 sequence.getDBRef(d).getAccessionId());
5250 if (dr.getMapping() != null)
5252 entry.setMap(addMapping(dr.getMapping()));
5254 datasetSequence.addDBRef(entry);
5258 private jalview.datamodel.Mapping addMapping(Mapping m)
5260 SequenceI dsto = null;
5261 // Mapping m = dr.getMapping();
5262 int fr[] = new int[m.getMapListFromCount() * 2];
5263 Enumeration f = m.enumerateMapListFrom();
5264 for (int _i = 0; f.hasMoreElements(); _i += 2)
5266 MapListFrom mf = (MapListFrom) f.nextElement();
5267 fr[_i] = mf.getStart();
5268 fr[_i + 1] = mf.getEnd();
5270 int fto[] = new int[m.getMapListToCount() * 2];
5271 f = m.enumerateMapListTo();
5272 for (int _i = 0; f.hasMoreElements(); _i += 2)
5274 MapListTo mf = (MapListTo) f.nextElement();
5275 fto[_i] = mf.getStart();
5276 fto[_i + 1] = mf.getEnd();
5278 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto, fr,
5279 fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
5280 if (m.getMappingChoice() != null)
5282 MappingChoice mc = m.getMappingChoice();
5283 if (mc.getDseqFor() != null)
5285 String dsfor = "" + mc.getDseqFor();
5286 if (seqRefIds.containsKey(dsfor))
5291 jmap.setTo(seqRefIds.get(dsfor));
5295 frefedSequence.add(newMappingRef(dsfor, jmap));
5301 * local sequence definition
5303 Sequence ms = mc.getSequence();
5304 SequenceI djs = null;
5305 String sqid = ms.getDsseqid();
5306 if (sqid != null && sqid.length() > 0)
5309 * recover dataset sequence
5311 djs = seqRefIds.get(sqid);
5316 "Warning - making up dataset sequence id for DbRef sequence map reference");
5317 sqid = ((Object) ms).toString(); // make up a new hascode for
5318 // undefined dataset sequence hash
5319 // (unlikely to happen)
5325 * make a new dataset sequence and add it to refIds hash
5327 djs = new jalview.datamodel.Sequence(ms.getName(),
5329 djs.setStart(jmap.getMap().getToLowest());
5330 djs.setEnd(jmap.getMap().getToHighest());
5331 djs.setVamsasId(uniqueSetSuffix + sqid);
5333 incompleteSeqs.put(sqid, djs);
5334 seqRefIds.put(sqid, djs);
5337 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5347 * Provides a 'copy' of an alignment view (on action New View) by 'saving' the
5348 * view as XML (but not to file), and then reloading it
5353 public AlignmentPanel copyAlignPanel(AlignmentPanel ap)
5356 JalviewModel jm = saveState(ap, null, null, null);
5358 uniqueSetSuffix = "";
5359 jm.getJalviewModelSequence().getViewport(0).setId(null);
5360 // we don't overwrite the view we just copied
5362 if (this.frefedSequence == null)
5364 frefedSequence = new Vector<>();
5367 viewportsAdded.clear();
5369 AlignFrame af = loadFromObject(jm, null, false, null);
5370 af.alignPanels.clear();
5371 af.closeMenuItem_actionPerformed(true);
5374 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5375 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5376 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5377 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5378 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5381 return af.alignPanel;
5384 private Hashtable jvids2vobj;
5386 private void warn(String msg)
5391 private void warn(String msg, Exception e)
5393 if (Cache.log != null)
5397 Cache.log.warn(msg, e);
5401 Cache.log.warn(msg);
5406 System.err.println("Warning: " + msg);
5409 e.printStackTrace();
5414 private void debug(String string)
5416 debug(string, null);
5419 private void debug(String msg, Exception e)
5421 if (Cache.log != null)
5425 Cache.log.debug(msg, e);
5429 Cache.log.debug(msg);
5434 System.err.println("Warning: " + msg);
5437 e.printStackTrace();
5443 * set the object to ID mapping tables used to write/recover objects and XML
5444 * ID strings for the jalview project. If external tables are provided then
5445 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
5446 * object goes out of scope. - also populates the datasetIds hashtable with
5447 * alignment objects containing dataset sequences
5450 * Map from ID strings to jalview datamodel
5452 * Map from jalview datamodel to ID strings
5456 public void setObjectMappingTables(Hashtable vobj2jv,
5457 IdentityHashMap jv2vobj)
5459 this.jv2vobj = jv2vobj;
5460 this.vobj2jv = vobj2jv;
5461 Iterator ds = jv2vobj.keySet().iterator();
5463 while (ds.hasNext())
5465 Object jvobj = ds.next();
5466 id = jv2vobj.get(jvobj).toString();
5467 if (jvobj instanceof jalview.datamodel.Alignment)
5469 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
5471 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
5474 else if (jvobj instanceof jalview.datamodel.Sequence)
5476 // register sequence object so the XML parser can recover it.
5477 if (seqRefIds == null)
5479 seqRefIds = new HashMap<>();
5481 if (seqsToIds == null)
5483 seqsToIds = new IdentityHashMap<>();
5485 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
5486 seqsToIds.put((SequenceI) jvobj, id);
5488 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
5491 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
5492 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
5493 if (jvann.annotationId == null)
5495 jvann.annotationId = anid;
5497 if (!jvann.annotationId.equals(anid))
5499 // TODO verify that this is the correct behaviour
5500 this.warn("Overriding Annotation ID for " + anid
5501 + " from different id : " + jvann.annotationId);
5502 jvann.annotationId = anid;
5505 else if (jvobj instanceof String)
5507 if (jvids2vobj == null)
5509 jvids2vobj = new Hashtable();
5510 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
5515 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
5521 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
5522 * objects created from the project archive. If string is null (default for
5523 * construction) then suffix will be set automatically.
5527 public void setUniqueSetSuffix(String string)
5529 uniqueSetSuffix = string;
5534 * uses skipList2 as the skipList for skipping views on sequence sets
5535 * associated with keys in the skipList
5539 public void setSkipList(Hashtable skipList2)
5541 skipList = skipList2;
5545 * Reads the jar entry of given name and returns its contents, or null if the
5546 * entry is not found.
5549 * @param jarEntryName
5552 protected String readJarEntry(jarInputStreamProvider jprovider,
5553 String jarEntryName)
5555 String result = null;
5556 BufferedReader in = null;
5561 * Reopen the jar input stream and traverse its entries to find a matching
5564 JarInputStream jin = jprovider.getJarInputStream();
5565 JarEntry entry = null;
5568 entry = jin.getNextJarEntry();
5569 } while (entry != null && !entry.getName().equals(jarEntryName));
5573 StringBuilder out = new StringBuilder(256);
5574 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
5577 while ((data = in.readLine()) != null)
5581 result = out.toString();
5585 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
5587 } catch (Exception ex)
5589 ex.printStackTrace();
5597 } catch (IOException e)
5608 * Returns an incrementing counter (0, 1, 2...)
5612 private synchronized int nextCounter()