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.SequenceGroup;
36 import jalview.datamodel.SequenceI;
37 import jalview.datamodel.StructureViewerModel;
38 import jalview.datamodel.StructureViewerModel.StructureData;
39 import jalview.ext.varna.RnaModel;
40 import jalview.gui.StructureViewer.ViewerType;
41 import jalview.io.DataSourceType;
42 import jalview.io.FileFormat;
43 import jalview.renderer.ResidueShaderI;
44 import jalview.schemabinding.version2.AlcodMap;
45 import jalview.schemabinding.version2.AlcodonFrame;
46 import jalview.schemabinding.version2.Annotation;
47 import jalview.schemabinding.version2.AnnotationColours;
48 import jalview.schemabinding.version2.AnnotationElement;
49 import jalview.schemabinding.version2.CalcIdParam;
50 import jalview.schemabinding.version2.DBRef;
51 import jalview.schemabinding.version2.Features;
52 import jalview.schemabinding.version2.Group;
53 import jalview.schemabinding.version2.HiddenColumns;
54 import jalview.schemabinding.version2.JGroup;
55 import jalview.schemabinding.version2.JSeq;
56 import jalview.schemabinding.version2.JalviewModel;
57 import jalview.schemabinding.version2.JalviewModelSequence;
58 import jalview.schemabinding.version2.MapListFrom;
59 import jalview.schemabinding.version2.MapListTo;
60 import jalview.schemabinding.version2.Mapping;
61 import jalview.schemabinding.version2.MappingChoice;
62 import jalview.schemabinding.version2.OtherData;
63 import jalview.schemabinding.version2.PdbentryItem;
64 import jalview.schemabinding.version2.Pdbids;
65 import jalview.schemabinding.version2.Property;
66 import jalview.schemabinding.version2.RnaViewer;
67 import jalview.schemabinding.version2.SecondaryStructure;
68 import jalview.schemabinding.version2.Sequence;
69 import jalview.schemabinding.version2.SequenceSet;
70 import jalview.schemabinding.version2.SequenceSetProperties;
71 import jalview.schemabinding.version2.Setting;
72 import jalview.schemabinding.version2.StructureState;
73 import jalview.schemabinding.version2.ThresholdLine;
74 import jalview.schemabinding.version2.Tree;
75 import jalview.schemabinding.version2.UserColours;
76 import jalview.schemabinding.version2.Viewport;
77 import jalview.schemes.AnnotationColourGradient;
78 import jalview.schemes.ColourSchemeI;
79 import jalview.schemes.ColourSchemeProperty;
80 import jalview.schemes.FeatureColour;
81 import jalview.schemes.ResidueProperties;
82 import jalview.schemes.UserColourScheme;
83 import jalview.structure.StructureSelectionManager;
84 import jalview.structures.models.AAStructureBindingModel;
85 import jalview.util.MessageManager;
86 import jalview.util.Platform;
87 import jalview.util.StringUtils;
88 import jalview.util.jarInputStreamProvider;
89 import jalview.viewmodel.AlignmentViewport;
90 import jalview.viewmodel.ViewportRanges;
91 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
92 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
93 import jalview.ws.jws2.Jws2Discoverer;
94 import jalview.ws.jws2.dm.AAConSettings;
95 import jalview.ws.jws2.jabaws2.Jws2Instance;
96 import jalview.ws.params.ArgumentI;
97 import jalview.ws.params.AutoCalcSetting;
98 import jalview.ws.params.WsParamSetI;
100 import java.awt.Color;
101 import java.awt.Rectangle;
102 import java.io.BufferedReader;
103 import java.io.DataInputStream;
104 import java.io.DataOutputStream;
106 import java.io.FileInputStream;
107 import java.io.FileOutputStream;
108 import java.io.IOException;
109 import java.io.InputStreamReader;
110 import java.io.OutputStreamWriter;
111 import java.io.PrintWriter;
112 import java.lang.reflect.InvocationTargetException;
113 import java.net.MalformedURLException;
115 import java.util.ArrayList;
116 import java.util.Arrays;
117 import java.util.Enumeration;
118 import java.util.HashMap;
119 import java.util.HashSet;
120 import java.util.Hashtable;
121 import java.util.IdentityHashMap;
122 import java.util.Iterator;
123 import java.util.LinkedHashMap;
124 import java.util.List;
125 import java.util.Map;
126 import java.util.Map.Entry;
127 import java.util.Set;
128 import java.util.Vector;
129 import java.util.jar.JarEntry;
130 import java.util.jar.JarInputStream;
131 import java.util.jar.JarOutputStream;
133 import javax.swing.JInternalFrame;
134 import javax.swing.SwingUtilities;
136 import org.exolab.castor.xml.Marshaller;
137 import org.exolab.castor.xml.Unmarshaller;
140 * Write out the current jalview desktop state as a Jalview XML stream.
142 * Note: the vamsas objects referred to here are primitive versions of the
143 * VAMSAS project schema elements - they are not the same and most likely never
147 * @version $Revision: 1.134 $
149 public class Jalview2XML
151 private static final String VIEWER_PREFIX = "viewer_";
153 private static final String RNA_PREFIX = "rna_";
155 private static final String UTF_8 = "UTF-8";
157 // use this with nextCounter() to make unique names for entities
158 private int counter = 0;
161 * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
162 * of sequence objects are created.
164 IdentityHashMap<SequenceI, String> seqsToIds = null;
167 * jalview XML Sequence ID to jalview sequence object reference (both dataset
168 * and alignment sequences. Populated as XML reps of sequence objects are
171 Map<String, SequenceI> seqRefIds = null;
173 Map<String, SequenceI> incompleteSeqs = null;
175 List<SeqFref> frefedSequence = null;
177 boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
180 * Map of reconstructed AlignFrame objects that appear to have come from
181 * SplitFrame objects (have a dna/protein complement view).
183 private Map<Viewport, AlignFrame> splitFrameCandidates = new HashMap<>();
186 * Map from displayed rna structure models to their saved session state jar
189 private Map<RnaModel, String> rnaSessions = new HashMap<>();
192 * create/return unique hash string for sq
195 * @return new or existing unique string for sq
197 String seqHash(SequenceI sq)
199 if (seqsToIds == null)
203 if (seqsToIds.containsKey(sq))
205 return seqsToIds.get(sq);
209 // create sequential key
210 String key = "sq" + (seqsToIds.size() + 1);
211 key = makeHashCode(sq, key); // check we don't have an external reference
213 seqsToIds.put(sq, key);
222 if (seqRefIds != null)
226 if (seqsToIds != null)
230 if (incompleteSeqs != null)
232 incompleteSeqs.clear();
240 warn("clearSeqRefs called when _cleartables was not set. Doing nothing.");
241 // seqRefIds = new Hashtable();
242 // seqsToIds = new IdentityHashMap();
248 if (seqsToIds == null)
250 seqsToIds = new IdentityHashMap<>();
252 if (seqRefIds == null)
254 seqRefIds = new HashMap<>();
256 if (incompleteSeqs == null)
258 incompleteSeqs = new HashMap<>();
260 if (frefedSequence == null)
262 frefedSequence = new ArrayList<>();
270 public Jalview2XML(boolean raiseGUI)
272 this.raiseGUI = raiseGUI;
276 * base class for resolving forward references to sequences by their ID
281 abstract class SeqFref
287 public SeqFref(String _sref, String type)
293 public String getSref()
298 public SequenceI getSrefSeq()
300 return seqRefIds.get(sref);
303 public boolean isResolvable()
305 return seqRefIds.get(sref) != null;
308 public SequenceI getSrefDatasetSeq()
310 SequenceI sq = seqRefIds.get(sref);
313 while (sq.getDatasetSequence() != null)
315 sq = sq.getDatasetSequence();
322 * @return true if the forward reference was fully resolved
324 abstract boolean resolve();
327 public String toString()
329 return type + " reference to " + sref;
334 * create forward reference for a mapping
340 public SeqFref newMappingRef(final String sref,
341 final jalview.datamodel.Mapping _jmap)
343 SeqFref fref = new SeqFref(sref, "Mapping")
345 public jalview.datamodel.Mapping jmap = _jmap;
350 SequenceI seq = getSrefDatasetSeq();
362 public SeqFref newAlcodMapRef(final String sref,
363 final AlignedCodonFrame _cf,
364 final jalview.datamodel.Mapping _jmap)
367 SeqFref fref = new SeqFref(sref, "Codon Frame")
369 AlignedCodonFrame cf = _cf;
371 public jalview.datamodel.Mapping mp = _jmap;
374 public boolean isResolvable()
376 return super.isResolvable() && mp.getTo() != null;
382 SequenceI seq = getSrefDatasetSeq();
387 cf.addMap(seq, mp.getTo(), mp.getMap());
394 public void resolveFrefedSequences()
396 Iterator<SeqFref> nextFref = frefedSequence.iterator();
397 int toresolve = frefedSequence.size();
398 int unresolved = 0, failedtoresolve = 0;
399 while (nextFref.hasNext())
401 SeqFref ref = nextFref.next();
402 if (ref.isResolvable())
414 } catch (Exception x)
417 "IMPLEMENTATION ERROR: Failed to resolve forward reference for sequence "
430 System.err.println("Jalview Project Import: There were " + unresolved
431 + " forward references left unresolved on the stack.");
433 if (failedtoresolve > 0)
435 System.err.println("SERIOUS! " + failedtoresolve
436 + " resolvable forward references failed to resolve.");
438 if (incompleteSeqs != null && incompleteSeqs.size() > 0)
441 "Jalview Project Import: There are " + incompleteSeqs.size()
442 + " sequences which may have incomplete metadata.");
443 if (incompleteSeqs.size() < 10)
445 for (SequenceI s : incompleteSeqs.values())
447 System.err.println(s.toString());
453 "Too many to report. Skipping output of incomplete sequences.");
459 * This maintains a map of viewports, the key being the seqSetId. Important to
460 * set historyItem and redoList for multiple views
462 Map<String, AlignViewport> viewportsAdded = new HashMap<>();
464 Map<String, AlignmentAnnotation> annotationIds = new HashMap<>();
466 String uniqueSetSuffix = "";
469 * List of pdbfiles added to Jar
471 List<String> pdbfiles = null;
473 // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
474 public void saveState(File statefile)
476 FileOutputStream fos = null;
479 fos = new FileOutputStream(statefile);
480 JarOutputStream jout = new JarOutputStream(fos);
483 } catch (Exception e)
485 // TODO: inform user of the problem - they need to know if their data was
487 if (errorMessage == null)
489 errorMessage = "Couldn't write Jalview Archive to output file '"
490 + statefile + "' - See console error log for details";
494 errorMessage += "(output file was '" + statefile + "')";
504 } catch (IOException e)
514 * Writes a jalview project archive to the given Jar output stream.
518 public void saveState(JarOutputStream jout)
520 AlignFrame[] frames = Desktop.getAlignFrames();
526 saveAllFrames(Arrays.asList(frames), jout);
530 * core method for storing state for a set of AlignFrames.
533 * - frames involving all data to be exported (including containing
536 * - project output stream
538 private void saveAllFrames(List<AlignFrame> frames, JarOutputStream jout)
540 Hashtable<String, AlignFrame> dsses = new Hashtable<>();
543 * ensure cached data is clear before starting
545 // todo tidy up seqRefIds, seqsToIds initialisation / reset
547 splitFrameCandidates.clear();
552 // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
553 // //////////////////////////////////////////////////
555 List<String> shortNames = new ArrayList<>();
556 List<String> viewIds = new ArrayList<>();
559 for (int i = frames.size() - 1; i > -1; i--)
561 AlignFrame af = frames.get(i);
563 if (skipList != null && skipList
564 .containsKey(af.getViewport().getSequenceSetId()))
569 String shortName = makeFilename(af, shortNames);
571 int ap, apSize = af.alignPanels.size();
573 for (ap = 0; ap < apSize; ap++)
575 AlignmentPanel apanel = af.alignPanels.get(ap);
576 String fileName = apSize == 1 ? shortName : ap + shortName;
577 if (!fileName.endsWith(".xml"))
579 fileName = fileName + ".xml";
582 saveState(apanel, fileName, jout, viewIds);
584 String dssid = getDatasetIdRef(
585 af.getViewport().getAlignment().getDataset());
586 if (!dsses.containsKey(dssid))
588 dsses.put(dssid, af);
593 writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix,
599 } catch (Exception foo)
604 } catch (Exception ex)
606 // TODO: inform user of the problem - they need to know if their data was
608 if (errorMessage == null)
610 errorMessage = "Couldn't write Jalview Archive - see error output for details";
612 ex.printStackTrace();
617 * Generates a distinct file name, based on the title of the AlignFrame, by
618 * appending _n for increasing n until an unused name is generated. The new
619 * name (without its extension) is added to the list.
623 * @return the generated name, with .xml extension
625 protected String makeFilename(AlignFrame af, List<String> namesUsed)
627 String shortName = af.getTitle();
629 if (shortName.indexOf(File.separatorChar) > -1)
631 shortName = shortName
632 .substring(shortName.lastIndexOf(File.separatorChar) + 1);
637 while (namesUsed.contains(shortName))
639 if (shortName.endsWith("_" + (count - 1)))
641 shortName = shortName.substring(0, shortName.lastIndexOf("_"));
644 shortName = shortName.concat("_" + count);
648 namesUsed.add(shortName);
650 if (!shortName.endsWith(".xml"))
652 shortName = shortName + ".xml";
657 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
658 public boolean saveAlignment(AlignFrame af, String jarFile,
663 FileOutputStream fos = new FileOutputStream(jarFile);
664 JarOutputStream jout = new JarOutputStream(fos);
665 List<AlignFrame> frames = new ArrayList<>();
667 // resolve splitframes
668 if (af.getViewport().getCodingComplement() != null)
670 frames = ((SplitFrame) af.getSplitViewContainer()).getAlignFrames();
676 saveAllFrames(frames, jout);
680 } catch (Exception foo)
686 } catch (Exception ex)
688 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
689 ex.printStackTrace();
694 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
695 String fileName, JarOutputStream jout)
698 for (String dssids : dsses.keySet())
700 AlignFrame _af = dsses.get(dssids);
701 String jfileName = fileName + " Dataset for " + _af.getTitle();
702 if (!jfileName.endsWith(".xml"))
704 jfileName = jfileName + ".xml";
706 saveState(_af.alignPanel, jfileName, true, jout, null);
711 * create a JalviewModel from an alignment view and marshall it to a
715 * panel to create jalview model for
717 * name of alignment panel written to output stream
724 public JalviewModel saveState(AlignmentPanel ap, String fileName,
725 JarOutputStream jout, List<String> viewIds)
727 return saveState(ap, fileName, false, jout, viewIds);
731 * create a JalviewModel from an alignment view and marshall it to a
735 * panel to create jalview model for
737 * name of alignment panel written to output stream
739 * when true, only write the dataset for the alignment, not the data
740 * associated with the view.
746 public JalviewModel saveState(AlignmentPanel ap, String fileName,
747 boolean storeDS, JarOutputStream jout, List<String> viewIds)
751 viewIds = new ArrayList<>();
756 List<UserColourScheme> userColours = new ArrayList<>();
758 AlignViewport av = ap.av;
759 ViewportRanges vpRanges = av.getRanges();
761 JalviewModel object = new JalviewModel();
762 object.setVamsasModel(new jalview.schemabinding.version2.VamsasModel());
764 object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
766 jalview.bin.Cache.getDefault("VERSION", "Development Build"));
769 * rjal is full height alignment, jal is actual alignment with full metadata
770 * but excludes hidden sequences.
772 jalview.datamodel.AlignmentI rjal = av.getAlignment(), jal = rjal;
774 if (av.hasHiddenRows())
776 rjal = jal.getHiddenSequences().getFullAlignment();
779 SequenceSet vamsasSet = new SequenceSet();
781 JalviewModelSequence jms = new JalviewModelSequence();
783 vamsasSet.setGapChar(jal.getGapCharacter() + "");
785 if (jal.getDataset() != null)
787 // dataset id is the dataset's hashcode
788 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
791 // switch jal and the dataset
792 jal = jal.getDataset();
796 if (jal.getProperties() != null)
798 Enumeration en = jal.getProperties().keys();
799 while (en.hasMoreElements())
801 String key = en.nextElement().toString();
802 SequenceSetProperties ssp = new SequenceSetProperties();
804 ssp.setValue(jal.getProperties().get(key).toString());
805 vamsasSet.addSequenceSetProperties(ssp);
810 Set<String> calcIdSet = new HashSet<>();
811 // record the set of vamsas sequence XML POJO we create.
812 HashMap<String, Sequence> vamsasSetIds = new HashMap<>();
814 for (final SequenceI jds : rjal.getSequences())
816 final SequenceI jdatasq = jds.getDatasetSequence() == null ? jds
817 : jds.getDatasetSequence();
818 String id = seqHash(jds);
819 if (vamsasSetIds.get(id) == null)
821 if (seqRefIds.get(id) != null && !storeDS)
823 // This happens for two reasons: 1. multiple views are being
825 // 2. the hashCode has collided with another sequence's code. This
827 // HAPPEN! (PF00072.15.stk does this)
828 // JBPNote: Uncomment to debug writing out of files that do not read
829 // back in due to ArrayOutOfBoundExceptions.
830 // System.err.println("vamsasSeq backref: "+id+"");
831 // System.err.println(jds.getName()+"
832 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
833 // System.err.println("Hashcode: "+seqHash(jds));
834 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
835 // System.err.println(rsq.getName()+"
836 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
837 // System.err.println("Hashcode: "+seqHash(rsq));
841 vamsasSeq = createVamsasSequence(id, jds);
842 vamsasSet.addSequence(vamsasSeq);
843 vamsasSetIds.put(id, vamsasSeq);
844 seqRefIds.put(id, jds);
848 jseq.setStart(jds.getStart());
849 jseq.setEnd(jds.getEnd());
850 jseq.setColour(av.getSequenceColour(jds).getRGB());
852 jseq.setId(id); // jseq id should be a string not a number
855 // Store any sequences this sequence represents
856 if (av.hasHiddenRows())
858 // use rjal, contains the full height alignment
860 av.getAlignment().getHiddenSequences().isHidden(jds));
862 if (av.isHiddenRepSequence(jds))
864 jalview.datamodel.SequenceI[] reps = av
865 .getRepresentedSequences(jds).getSequencesInOrder(rjal);
867 for (int h = 0; h < reps.length; h++)
871 jseq.addHiddenSequences(rjal.findIndex(reps[h]));
876 // mark sequence as reference - if it is the reference for this view
879 jseq.setViewreference(jds == jal.getSeqrep());
883 // TODO: omit sequence features from each alignment view's XML dump if we
884 // are storing dataset
885 if (jds.getSequenceFeatures() != null)
887 jalview.datamodel.SequenceFeature[] sf = jds.getSequenceFeatures();
889 while (index < sf.length)
891 Features features = new Features();
893 features.setBegin(sf[index].getBegin());
894 features.setEnd(sf[index].getEnd());
895 features.setDescription(sf[index].getDescription());
896 features.setType(sf[index].getType());
897 features.setFeatureGroup(sf[index].getFeatureGroup());
898 features.setScore(sf[index].getScore());
899 if (sf[index].links != null)
901 for (int l = 0; l < sf[index].links.size(); l++)
903 OtherData keyValue = new OtherData();
904 keyValue.setKey("LINK_" + l);
905 keyValue.setValue(sf[index].links.elementAt(l).toString());
906 features.addOtherData(keyValue);
909 if (sf[index].otherDetails != null)
912 Iterator<String> keys = sf[index].otherDetails.keySet()
914 while (keys.hasNext())
917 OtherData keyValue = new OtherData();
918 keyValue.setKey(key);
919 keyValue.setValue(sf[index].otherDetails.get(key).toString());
920 features.addOtherData(keyValue);
924 jseq.addFeatures(features);
929 if (jdatasq.getAllPDBEntries() != null)
931 Enumeration en = jdatasq.getAllPDBEntries().elements();
932 while (en.hasMoreElements())
934 Pdbids pdb = new Pdbids();
935 jalview.datamodel.PDBEntry entry = (jalview.datamodel.PDBEntry) en
938 String pdbId = entry.getId();
940 pdb.setType(entry.getType());
943 * Store any structure views associated with this sequence. This
944 * section copes with duplicate entries in the project, so a dataset
945 * only view *should* be coped with sensibly.
947 // This must have been loaded, is it still visible?
948 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
949 String matchedFile = null;
950 for (int f = frames.length - 1; f > -1; f--)
952 if (frames[f] instanceof StructureViewerBase)
954 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
955 matchedFile = saveStructureState(ap, jds, pdb, entry, viewIds,
956 matchedFile, viewFrame);
958 * Only store each structure viewer's state once in the project
959 * jar. First time through only (storeDS==false)
961 String viewId = viewFrame.getViewId();
962 if (!storeDS && !viewIds.contains(viewId))
967 String viewerState = viewFrame.getStateInfo();
968 writeJarEntry(jout, getViewerJarEntryName(viewId),
969 viewerState.getBytes());
970 } catch (IOException e)
973 "Error saving viewer state: " + e.getMessage());
979 if (matchedFile != null || entry.getFile() != null)
981 if (entry.getFile() != null)
984 matchedFile = entry.getFile();
986 pdb.setFile(matchedFile); // entry.getFile());
987 if (pdbfiles == null)
989 pdbfiles = new ArrayList<>();
992 if (!pdbfiles.contains(pdbId))
995 copyFileToJar(jout, matchedFile, pdbId);
999 Enumeration<String> props = entry.getProperties();
1000 if (props.hasMoreElements())
1002 PdbentryItem item = new PdbentryItem();
1003 while (props.hasMoreElements())
1005 Property prop = new Property();
1006 String key = props.nextElement();
1008 prop.setValue(entry.getProperty(key).toString());
1009 item.addProperty(prop);
1011 pdb.addPdbentryItem(item);
1014 jseq.addPdbids(pdb);
1018 saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
1023 if (!storeDS && av.hasHiddenRows())
1025 jal = av.getAlignment();
1029 if (storeDS && jal.getCodonFrames() != null)
1031 List<AlignedCodonFrame> jac = jal.getCodonFrames();
1032 for (AlignedCodonFrame acf : jac)
1034 AlcodonFrame alc = new AlcodonFrame();
1035 if (acf.getProtMappings() != null
1036 && acf.getProtMappings().length > 0)
1038 boolean hasMap = false;
1039 SequenceI[] dnas = acf.getdnaSeqs();
1040 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1041 for (int m = 0; m < pmaps.length; m++)
1043 AlcodMap alcmap = new AlcodMap();
1044 alcmap.setDnasq(seqHash(dnas[m]));
1046 createVamsasMapping(pmaps[m], dnas[m], null, false));
1047 alc.addAlcodMap(alcmap);
1052 vamsasSet.addAlcodonFrame(alc);
1055 // TODO: delete this ? dead code from 2.8.3->2.9 ?
1057 // AlcodonFrame alc = new AlcodonFrame();
1058 // vamsasSet.addAlcodonFrame(alc);
1059 // for (int p = 0; p < acf.aaWidth; p++)
1061 // Alcodon cmap = new Alcodon();
1062 // if (acf.codons[p] != null)
1064 // // Null codons indicate a gapped column in the translated peptide
1066 // cmap.setPos1(acf.codons[p][0]);
1067 // cmap.setPos2(acf.codons[p][1]);
1068 // cmap.setPos3(acf.codons[p][2]);
1070 // alc.addAlcodon(cmap);
1072 // if (acf.getProtMappings() != null
1073 // && acf.getProtMappings().length > 0)
1075 // SequenceI[] dnas = acf.getdnaSeqs();
1076 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1077 // for (int m = 0; m < pmaps.length; m++)
1079 // AlcodMap alcmap = new AlcodMap();
1080 // alcmap.setDnasq(seqHash(dnas[m]));
1081 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
1083 // alc.addAlcodMap(alcmap);
1090 // /////////////////////////////////
1091 if (!storeDS && av.currentTree != null)
1093 // FIND ANY ASSOCIATED TREES
1094 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
1095 if (Desktop.desktop != null)
1097 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1099 for (int t = 0; t < frames.length; t++)
1101 if (frames[t] instanceof TreePanel)
1103 TreePanel tp = (TreePanel) frames[t];
1105 if (tp.treeCanvas.av.getAlignment() == jal)
1107 Tree tree = new Tree();
1108 tree.setTitle(tp.getTitle());
1109 tree.setCurrentTree((av.currentTree == tp.getTree()));
1110 tree.setNewick(tp.getTree().print());
1111 tree.setThreshold(tp.treeCanvas.threshold);
1113 tree.setFitToWindow(tp.fitToWindow.getState());
1114 tree.setFontName(tp.getTreeFont().getName());
1115 tree.setFontSize(tp.getTreeFont().getSize());
1116 tree.setFontStyle(tp.getTreeFont().getStyle());
1117 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
1119 tree.setShowBootstrap(tp.bootstrapMenu.getState());
1120 tree.setShowDistances(tp.distanceMenu.getState());
1122 tree.setHeight(tp.getHeight());
1123 tree.setWidth(tp.getWidth());
1124 tree.setXpos(tp.getX());
1125 tree.setYpos(tp.getY());
1126 tree.setId(makeHashCode(tp, null));
1136 * store forward refs from an annotationRow to any groups
1138 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<>();
1141 for (SequenceI sq : jal.getSequences())
1143 // Store annotation on dataset sequences only
1144 AlignmentAnnotation[] aa = sq.getAnnotation();
1145 if (aa != null && aa.length > 0)
1147 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1154 if (jal.getAlignmentAnnotation() != null)
1156 // Store the annotation shown on the alignment.
1157 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1158 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1163 if (jal.getGroups() != null)
1165 JGroup[] groups = new JGroup[jal.getGroups().size()];
1167 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1169 JGroup jGroup = new JGroup();
1170 groups[++i] = jGroup;
1172 jGroup.setStart(sg.getStartRes());
1173 jGroup.setEnd(sg.getEndRes());
1174 jGroup.setName(sg.getName());
1175 if (groupRefs.containsKey(sg))
1177 // group has references so set its ID field
1178 jGroup.setId(groupRefs.get(sg));
1180 ColourSchemeI colourScheme = sg.getColourScheme();
1181 if (colourScheme != null)
1183 ResidueShaderI groupColourScheme = sg.getGroupColourScheme();
1184 if (groupColourScheme.conservationApplied())
1186 jGroup.setConsThreshold(groupColourScheme.getConservationInc());
1188 if (colourScheme instanceof jalview.schemes.UserColourScheme)
1191 setUserColourScheme(colourScheme, userColours, jms));
1195 jGroup.setColour(colourScheme.getSchemeName());
1198 else if (colourScheme instanceof jalview.schemes.AnnotationColourGradient)
1200 jGroup.setColour("AnnotationColourGradient");
1201 jGroup.setAnnotationColours(constructAnnotationColours(
1202 (jalview.schemes.AnnotationColourGradient) colourScheme,
1205 else if (colourScheme instanceof jalview.schemes.UserColourScheme)
1208 setUserColourScheme(colourScheme, userColours, jms));
1212 jGroup.setColour(colourScheme.getSchemeName());
1215 jGroup.setPidThreshold(groupColourScheme.getThreshold());
1218 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1219 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1220 jGroup.setDisplayText(sg.getDisplayText());
1221 jGroup.setColourText(sg.getColourText());
1222 jGroup.setTextCol1(sg.textColour.getRGB());
1223 jGroup.setTextCol2(sg.textColour2.getRGB());
1224 jGroup.setTextColThreshold(sg.thresholdTextColour);
1225 jGroup.setShowUnconserved(sg.getShowNonconserved());
1226 jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1227 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1228 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1229 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1230 for (SequenceI seq : sg.getSequences())
1232 jGroup.addSeq(seqHash(seq));
1236 jms.setJGroup(groups);
1240 // /////////SAVE VIEWPORT
1241 Viewport view = new Viewport();
1242 view.setTitle(ap.alignFrame.getTitle());
1243 view.setSequenceSetId(
1244 makeHashCode(av.getSequenceSetId(), av.getSequenceSetId()));
1245 view.setId(av.getViewId());
1246 if (av.getCodingComplement() != null)
1248 view.setComplementId(av.getCodingComplement().getViewId());
1250 view.setViewName(av.viewName);
1251 view.setGatheredViews(av.isGatherViewsHere());
1253 Rectangle size = ap.av.getExplodedGeometry();
1254 Rectangle position = size;
1257 size = ap.alignFrame.getBounds();
1258 if (av.getCodingComplement() != null)
1260 position = ((SplitFrame) ap.alignFrame.getSplitViewContainer())
1268 view.setXpos(position.x);
1269 view.setYpos(position.y);
1271 view.setWidth(size.width);
1272 view.setHeight(size.height);
1274 view.setStartRes(vpRanges.getStartRes());
1275 view.setStartSeq(vpRanges.getStartSeq());
1277 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1279 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1283 .getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1285 AnnotationColours ac = constructAnnotationColours(
1286 (jalview.schemes.AnnotationColourGradient) av
1287 .getGlobalColourScheme(),
1290 view.setAnnotationColours(ac);
1291 view.setBgColour("AnnotationColourGradient");
1295 view.setBgColour(ColourSchemeProperty
1296 .getColourName(av.getGlobalColourScheme()));
1299 ResidueShaderI vcs = av.getResidueShading();
1300 ColourSchemeI cs = av.getGlobalColourScheme();
1304 if (vcs.conservationApplied())
1306 view.setConsThreshold(vcs.getConservationInc());
1307 if (cs instanceof jalview.schemes.UserColourScheme)
1309 view.setBgColour(setUserColourScheme(cs, userColours, jms));
1312 view.setPidThreshold(vcs.getThreshold());
1315 view.setConservationSelected(av.getConservationSelected());
1316 view.setPidSelected(av.getAbovePIDThreshold());
1317 view.setFontName(av.font.getName());
1318 view.setFontSize(av.font.getSize());
1319 view.setFontStyle(av.font.getStyle());
1320 view.setScaleProteinAsCdna(av.getViewStyle().isScaleProteinAsCdna());
1321 view.setRenderGaps(av.isRenderGaps());
1322 view.setShowAnnotation(av.isShowAnnotation());
1323 view.setShowBoxes(av.getShowBoxes());
1324 view.setShowColourText(av.getColourText());
1325 view.setShowFullId(av.getShowJVSuffix());
1326 view.setRightAlignIds(av.isRightAlignIds());
1327 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1328 view.setShowText(av.getShowText());
1329 view.setShowUnconserved(av.getShowUnconserved());
1330 view.setWrapAlignment(av.getWrapAlignment());
1331 view.setTextCol1(av.getTextColour().getRGB());
1332 view.setTextCol2(av.getTextColour2().getRGB());
1333 view.setTextColThreshold(av.getThresholdTextColour());
1334 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1335 view.setShowSequenceLogo(av.isShowSequenceLogo());
1336 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1337 view.setShowGroupConsensus(av.isShowGroupConsensus());
1338 view.setShowGroupConservation(av.isShowGroupConservation());
1339 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1340 view.setShowDbRefTooltip(av.isShowDBRefs());
1341 view.setFollowHighlight(av.isFollowHighlight());
1342 view.setFollowSelection(av.followSelection);
1343 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1344 if (av.getFeaturesDisplayed() != null)
1346 jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
1348 String[] renderOrder = ap.getSeqPanel().seqCanvas
1349 .getFeatureRenderer().getRenderOrder()
1350 .toArray(new String[0]);
1352 Vector<String> settingsAdded = new Vector<>();
1353 if (renderOrder != null)
1355 for (String featureType : renderOrder)
1357 FeatureColourI fcol = ap.getSeqPanel().seqCanvas
1358 .getFeatureRenderer().getFeatureStyle(featureType);
1359 Setting setting = new Setting();
1360 setting.setType(featureType);
1361 if (!fcol.isSimpleColour())
1363 setting.setColour(fcol.getMaxColour().getRGB());
1364 setting.setMincolour(fcol.getMinColour().getRGB());
1365 setting.setMin(fcol.getMin());
1366 setting.setMax(fcol.getMax());
1367 setting.setColourByLabel(fcol.isColourByLabel());
1368 setting.setAutoScale(fcol.isAutoScaled());
1369 setting.setThreshold(fcol.getThreshold());
1370 // -1 = No threshold, 0 = Below, 1 = Above
1371 setting.setThreshstate(fcol.isAboveThreshold() ? 1
1372 : (fcol.isBelowThreshold() ? 0 : -1));
1376 setting.setColour(fcol.getColour().getRGB());
1380 av.getFeaturesDisplayed().isVisible(featureType));
1381 float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1382 .getOrder(featureType);
1385 setting.setOrder(rorder);
1387 fs.addSetting(setting);
1388 settingsAdded.addElement(featureType);
1392 // is groups actually supposed to be a map here ?
1393 Iterator<String> en = ap.getSeqPanel().seqCanvas
1394 .getFeatureRenderer().getFeatureGroups().iterator();
1395 Vector<String> groupsAdded = new Vector<>();
1396 while (en.hasNext())
1398 String grp = en.next();
1399 if (groupsAdded.contains(grp))
1403 Group g = new Group();
1405 g.setDisplay(((Boolean) ap.getSeqPanel().seqCanvas
1406 .getFeatureRenderer().checkGroupVisibility(grp, false))
1409 groupsAdded.addElement(grp);
1411 jms.setFeatureSettings(fs);
1414 if (av.hasHiddenColumns())
1416 jalview.datamodel.HiddenColumns hidden = av.getAlignment()
1417 .getHiddenColumns();
1420 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1424 ArrayList<int[]> hiddenRegions = hidden.getHiddenColumnsCopy();
1425 for (int[] region : hiddenRegions)
1427 HiddenColumns hc = new HiddenColumns();
1428 hc.setStart(region[0]);
1429 hc.setEnd(region[1]);
1430 view.addHiddenColumns(hc);
1434 if (calcIdSet.size() > 0)
1436 for (String calcId : calcIdSet)
1438 if (calcId.trim().length() > 0)
1440 CalcIdParam cidp = createCalcIdParam(calcId, av);
1441 // Some calcIds have no parameters.
1444 view.addCalcIdParam(cidp);
1450 jms.addViewport(view);
1452 object.setJalviewModelSequence(jms);
1453 object.getVamsasModel().addSequenceSet(vamsasSet);
1455 if (jout != null && fileName != null)
1457 // We may not want to write the object to disk,
1458 // eg we can copy the alignViewport to a new view object
1459 // using save and then load
1462 System.out.println("Writing jar entry " + fileName);
1463 JarEntry entry = new JarEntry(fileName);
1464 jout.putNextEntry(entry);
1465 PrintWriter pout = new PrintWriter(
1466 new OutputStreamWriter(jout, UTF_8));
1467 Marshaller marshaller = new Marshaller(pout);
1468 marshaller.marshal(object);
1471 } catch (Exception ex)
1473 // TODO: raise error in GUI if marshalling failed.
1474 ex.printStackTrace();
1481 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1482 * for each viewer, with
1484 * <li>viewer geometry (position, size, split pane divider location)</li>
1485 * <li>index of the selected structure in the viewer (currently shows gapped
1487 * <li>the id of the annotation holding RNA secondary structure</li>
1488 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1490 * Varna viewer state is also written out (in native Varna XML) to separate
1491 * project jar entries. A separate entry is written for each RNA structure
1492 * displayed, with the naming convention
1494 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
1502 * @param storeDataset
1504 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
1505 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
1506 boolean storeDataset)
1508 if (Desktop.desktop == null)
1512 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1513 for (int f = frames.length - 1; f > -1; f--)
1515 if (frames[f] instanceof AppVarna)
1517 AppVarna varna = (AppVarna) frames[f];
1519 * link the sequence to every viewer that is showing it and is linked to
1520 * its alignment panel
1522 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1524 String viewId = varna.getViewId();
1525 RnaViewer rna = new RnaViewer();
1526 rna.setViewId(viewId);
1527 rna.setTitle(varna.getTitle());
1528 rna.setXpos(varna.getX());
1529 rna.setYpos(varna.getY());
1530 rna.setWidth(varna.getWidth());
1531 rna.setHeight(varna.getHeight());
1532 rna.setDividerLocation(varna.getDividerLocation());
1533 rna.setSelectedRna(varna.getSelectedIndex());
1534 jseq.addRnaViewer(rna);
1537 * Store each Varna panel's state once in the project per sequence.
1538 * First time through only (storeDataset==false)
1540 // boolean storeSessions = false;
1541 // String sequenceViewId = viewId + seqsToIds.get(jds);
1542 // if (!storeDataset && !viewIds.contains(sequenceViewId))
1544 // viewIds.add(sequenceViewId);
1545 // storeSessions = true;
1547 for (RnaModel model : varna.getModels())
1549 if (model.seq == jds)
1552 * VARNA saves each view (sequence or alignment secondary
1553 * structure, gapped or trimmed) as a separate XML file
1555 String jarEntryName = rnaSessions.get(model);
1556 if (jarEntryName == null)
1559 String varnaStateFile = varna.getStateInfo(model.rna);
1560 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
1561 copyFileToJar(jout, varnaStateFile, jarEntryName);
1562 rnaSessions.put(model, jarEntryName);
1564 SecondaryStructure ss = new SecondaryStructure();
1565 String annotationId = varna.getAnnotation(jds).annotationId;
1566 ss.setAnnotationId(annotationId);
1567 ss.setViewerState(jarEntryName);
1568 ss.setGapped(model.gapped);
1569 ss.setTitle(model.title);
1570 rna.addSecondaryStructure(ss);
1579 * Copy the contents of a file to a new entry added to the output jar
1583 * @param jarEntryName
1585 protected void copyFileToJar(JarOutputStream jout, String infilePath,
1586 String jarEntryName)
1588 DataInputStream dis = null;
1591 File file = new File(infilePath);
1592 if (file.exists() && jout != null)
1594 dis = new DataInputStream(new FileInputStream(file));
1595 byte[] data = new byte[(int) file.length()];
1596 dis.readFully(data);
1597 writeJarEntry(jout, jarEntryName, data);
1599 } catch (Exception ex)
1601 ex.printStackTrace();
1609 } catch (IOException e)
1618 * Write the data to a new entry of given name in the output jar file
1621 * @param jarEntryName
1623 * @throws IOException
1625 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
1626 byte[] data) throws IOException
1630 System.out.println("Writing jar entry " + jarEntryName);
1631 jout.putNextEntry(new JarEntry(jarEntryName));
1632 DataOutputStream dout = new DataOutputStream(jout);
1633 dout.write(data, 0, data.length);
1640 * Save the state of a structure viewer
1645 * the archive XML element under which to save the state
1648 * @param matchedFile
1652 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
1653 Pdbids pdb, PDBEntry entry, List<String> viewIds,
1654 String matchedFile, StructureViewerBase viewFrame)
1656 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
1659 * Look for any bindings for this viewer to the PDB file of interest
1660 * (including part matches excluding chain id)
1662 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
1664 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
1665 final String pdbId = pdbentry.getId();
1666 if (!pdbId.equals(entry.getId())
1667 && !(entry.getId().length() > 4 && entry.getId().toLowerCase()
1668 .startsWith(pdbId.toLowerCase())))
1671 * not interested in a binding to a different PDB entry here
1675 if (matchedFile == null)
1677 matchedFile = pdbentry.getFile();
1679 else if (!matchedFile.equals(pdbentry.getFile()))
1682 "Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
1683 + pdbentry.getFile());
1687 // can get at it if the ID
1688 // match is ambiguous (e.g.
1691 for (int smap = 0; smap < viewFrame.getBinding()
1692 .getSequence()[peid].length; smap++)
1694 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
1695 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
1697 StructureState state = new StructureState();
1698 state.setVisible(true);
1699 state.setXpos(viewFrame.getX());
1700 state.setYpos(viewFrame.getY());
1701 state.setWidth(viewFrame.getWidth());
1702 state.setHeight(viewFrame.getHeight());
1703 final String viewId = viewFrame.getViewId();
1704 state.setViewId(viewId);
1705 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
1706 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
1707 state.setColourByJmol(viewFrame.isColouredByViewer());
1708 state.setType(viewFrame.getViewerType().toString());
1709 pdb.addStructureState(state);
1717 * Populates the AnnotationColours xml for save. This captures the settings of
1718 * the options in the 'Colour by Annotation' dialog.
1721 * @param userColours
1725 private AnnotationColours constructAnnotationColours(
1726 AnnotationColourGradient acg, List<UserColourScheme> userColours,
1727 JalviewModelSequence jms)
1729 AnnotationColours ac = new AnnotationColours();
1730 ac.setAboveThreshold(acg.getAboveThreshold());
1731 ac.setThreshold(acg.getAnnotationThreshold());
1732 // 2.10.2 save annotationId (unique) not annotation label
1733 ac.setAnnotation(acg.getAnnotation().annotationId);
1734 if (acg.getBaseColour() instanceof UserColourScheme)
1737 setUserColourScheme(acg.getBaseColour(), userColours, jms));
1742 ColourSchemeProperty.getColourName(acg.getBaseColour()));
1745 ac.setMaxColour(acg.getMaxColour().getRGB());
1746 ac.setMinColour(acg.getMinColour().getRGB());
1747 ac.setPerSequence(acg.isSeqAssociated());
1748 ac.setPredefinedColours(acg.isPredefinedColours());
1752 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
1753 IdentityHashMap<SequenceGroup, String> groupRefs,
1754 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
1755 SequenceSet vamsasSet)
1758 for (int i = 0; i < aa.length; i++)
1760 Annotation an = new Annotation();
1762 AlignmentAnnotation annotation = aa[i];
1763 if (annotation.annotationId != null)
1765 annotationIds.put(annotation.annotationId, annotation);
1768 an.setId(annotation.annotationId);
1770 an.setVisible(annotation.visible);
1772 an.setDescription(annotation.description);
1774 if (annotation.sequenceRef != null)
1776 // 2.9 JAL-1781 xref on sequence id rather than name
1777 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
1779 if (annotation.groupRef != null)
1781 String groupIdr = groupRefs.get(annotation.groupRef);
1782 if (groupIdr == null)
1784 // make a locally unique String
1785 groupRefs.put(annotation.groupRef,
1786 groupIdr = ("" + System.currentTimeMillis()
1787 + annotation.groupRef.getName()
1788 + groupRefs.size()));
1790 an.setGroupRef(groupIdr.toString());
1793 // store all visualization attributes for annotation
1794 an.setGraphHeight(annotation.graphHeight);
1795 an.setCentreColLabels(annotation.centreColLabels);
1796 an.setScaleColLabels(annotation.scaleColLabel);
1797 an.setShowAllColLabels(annotation.showAllColLabels);
1798 an.setBelowAlignment(annotation.belowAlignment);
1800 if (annotation.graph > 0)
1803 an.setGraphType(annotation.graph);
1804 an.setGraphGroup(annotation.graphGroup);
1805 if (annotation.getThreshold() != null)
1807 ThresholdLine line = new ThresholdLine();
1808 line.setLabel(annotation.getThreshold().label);
1809 line.setValue(annotation.getThreshold().value);
1810 line.setColour(annotation.getThreshold().colour.getRGB());
1811 an.setThresholdLine(line);
1819 an.setLabel(annotation.label);
1821 if (annotation == av.getAlignmentQualityAnnot()
1822 || annotation == av.getAlignmentConservationAnnotation()
1823 || annotation == av.getAlignmentConsensusAnnotation()
1824 || annotation.autoCalculated)
1826 // new way of indicating autocalculated annotation -
1827 an.setAutoCalculated(annotation.autoCalculated);
1829 if (annotation.hasScore())
1831 an.setScore(annotation.getScore());
1834 if (annotation.getCalcId() != null)
1836 calcIdSet.add(annotation.getCalcId());
1837 an.setCalcId(annotation.getCalcId());
1839 if (annotation.hasProperties())
1841 for (String pr : annotation.getProperties())
1843 Property prop = new Property();
1845 prop.setValue(annotation.getProperty(pr));
1846 an.addProperty(prop);
1850 AnnotationElement ae;
1851 if (annotation.annotations != null)
1853 an.setScoreOnly(false);
1854 for (int a = 0; a < annotation.annotations.length; a++)
1856 if ((annotation == null) || (annotation.annotations[a] == null))
1861 ae = new AnnotationElement();
1862 if (annotation.annotations[a].description != null)
1864 ae.setDescription(annotation.annotations[a].description);
1866 if (annotation.annotations[a].displayCharacter != null)
1868 ae.setDisplayCharacter(
1869 annotation.annotations[a].displayCharacter);
1872 if (!Float.isNaN(annotation.annotations[a].value))
1874 ae.setValue(annotation.annotations[a].value);
1878 if (annotation.annotations[a].secondaryStructure > ' ')
1880 ae.setSecondaryStructure(
1881 annotation.annotations[a].secondaryStructure + "");
1884 if (annotation.annotations[a].colour != null
1885 && annotation.annotations[a].colour != java.awt.Color.black)
1887 ae.setColour(annotation.annotations[a].colour.getRGB());
1890 an.addAnnotationElement(ae);
1891 if (annotation.autoCalculated)
1893 // only write one non-null entry into the annotation row -
1894 // sufficient to get the visualization attributes necessary to
1902 an.setScoreOnly(true);
1904 if (!storeDS || (storeDS && !annotation.autoCalculated))
1906 // skip autocalculated annotation - these are only provided for
1908 vamsasSet.addAnnotation(an);
1914 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
1916 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
1917 if (settings != null)
1919 CalcIdParam vCalcIdParam = new CalcIdParam();
1920 vCalcIdParam.setCalcId(calcId);
1921 vCalcIdParam.addServiceURL(settings.getServiceURI());
1922 // generic URI allowing a third party to resolve another instance of the
1923 // service used for this calculation
1924 for (String urls : settings.getServiceURLs())
1926 vCalcIdParam.addServiceURL(urls);
1928 vCalcIdParam.setVersion("1.0");
1929 if (settings.getPreset() != null)
1931 WsParamSetI setting = settings.getPreset();
1932 vCalcIdParam.setName(setting.getName());
1933 vCalcIdParam.setDescription(setting.getDescription());
1937 vCalcIdParam.setName("");
1938 vCalcIdParam.setDescription("Last used parameters");
1940 // need to be able to recover 1) settings 2) user-defined presets or
1941 // recreate settings from preset 3) predefined settings provided by
1942 // service - or settings that can be transferred (or discarded)
1943 vCalcIdParam.setParameters(
1944 settings.getWsParamFile().replace("\n", "|\\n|"));
1945 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
1946 // todo - decide if updateImmediately is needed for any projects.
1948 return vCalcIdParam;
1953 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
1956 if (calcIdParam.getVersion().equals("1.0"))
1958 Jws2Instance service = Jws2Discoverer.getDiscoverer()
1959 .getPreferredServiceFor(calcIdParam.getServiceURL());
1960 if (service != null)
1962 WsParamSetI parmSet = null;
1965 parmSet = service.getParamStore().parseServiceParameterFile(
1966 calcIdParam.getName(), calcIdParam.getDescription(),
1967 calcIdParam.getServiceURL(),
1968 calcIdParam.getParameters().replace("|\\n|", "\n"));
1969 } catch (IOException x)
1971 warn("Couldn't parse parameter data for "
1972 + calcIdParam.getCalcId(), x);
1975 List<ArgumentI> argList = null;
1976 if (calcIdParam.getName().length() > 0)
1978 parmSet = service.getParamStore()
1979 .getPreset(calcIdParam.getName());
1980 if (parmSet != null)
1982 // TODO : check we have a good match with settings in AACon -
1983 // otherwise we'll need to create a new preset
1988 argList = parmSet.getArguments();
1991 AAConSettings settings = new AAConSettings(
1992 calcIdParam.isAutoUpdate(), service, parmSet, argList);
1993 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
1994 calcIdParam.isNeedsUpdate());
1999 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
2003 throw new Error(MessageManager.formatMessage(
2004 "error.unsupported_version_calcIdparam", new Object[]
2005 { calcIdParam.toString() }));
2009 * External mapping between jalview objects and objects yielding a valid and
2010 * unique object ID string. This is null for normal Jalview project IO, but
2011 * non-null when a jalview project is being read or written as part of a
2014 IdentityHashMap jv2vobj = null;
2017 * Construct a unique ID for jvobj using either existing bindings or if none
2018 * exist, the result of the hashcode call for the object.
2021 * jalview data object
2022 * @return unique ID for referring to jvobj
2024 private String makeHashCode(Object jvobj, String altCode)
2026 if (jv2vobj != null)
2028 Object id = jv2vobj.get(jvobj);
2031 return id.toString();
2033 // check string ID mappings
2034 if (jvids2vobj != null && jvobj instanceof String)
2036 id = jvids2vobj.get(jvobj);
2040 return id.toString();
2042 // give up and warn that something has gone wrong
2043 warn("Cannot find ID for object in external mapping : " + jvobj);
2049 * return local jalview object mapped to ID, if it exists
2053 * @return null or object bound to idcode
2055 private Object retrieveExistingObj(String idcode)
2057 if (idcode != null && vobj2jv != null)
2059 return vobj2jv.get(idcode);
2065 * binding from ID strings from external mapping table to jalview data model
2068 private Hashtable vobj2jv;
2070 private Sequence createVamsasSequence(String id, SequenceI jds)
2072 return createVamsasSequence(true, id, jds, null);
2075 private Sequence createVamsasSequence(boolean recurse, String id,
2076 SequenceI jds, SequenceI parentseq)
2078 Sequence vamsasSeq = new Sequence();
2079 vamsasSeq.setId(id);
2080 vamsasSeq.setName(jds.getName());
2081 vamsasSeq.setSequence(jds.getSequenceAsString());
2082 vamsasSeq.setDescription(jds.getDescription());
2083 jalview.datamodel.DBRefEntry[] dbrefs = null;
2084 if (jds.getDatasetSequence() != null)
2086 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
2090 // seqId==dsseqid so we can tell which sequences really are
2091 // dataset sequences only
2092 vamsasSeq.setDsseqid(id);
2093 dbrefs = jds.getDBRefs();
2094 if (parentseq == null)
2101 for (int d = 0; d < dbrefs.length; d++)
2103 DBRef dbref = new DBRef();
2104 dbref.setSource(dbrefs[d].getSource());
2105 dbref.setVersion(dbrefs[d].getVersion());
2106 dbref.setAccessionId(dbrefs[d].getAccessionId());
2107 if (dbrefs[d].hasMap())
2109 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
2111 dbref.setMapping(mp);
2113 vamsasSeq.addDBRef(dbref);
2119 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
2120 SequenceI parentseq, SequenceI jds, boolean recurse)
2123 if (jmp.getMap() != null)
2127 jalview.util.MapList mlst = jmp.getMap();
2128 List<int[]> r = mlst.getFromRanges();
2129 for (int[] range : r)
2131 MapListFrom mfrom = new MapListFrom();
2132 mfrom.setStart(range[0]);
2133 mfrom.setEnd(range[1]);
2134 mp.addMapListFrom(mfrom);
2136 r = mlst.getToRanges();
2137 for (int[] range : r)
2139 MapListTo mto = new MapListTo();
2140 mto.setStart(range[0]);
2141 mto.setEnd(range[1]);
2142 mp.addMapListTo(mto);
2144 mp.setMapFromUnit(mlst.getFromRatio());
2145 mp.setMapToUnit(mlst.getToRatio());
2146 if (jmp.getTo() != null)
2148 MappingChoice mpc = new MappingChoice();
2150 // check/create ID for the sequence referenced by getTo()
2153 SequenceI ps = null;
2154 if (parentseq != jmp.getTo()
2155 && parentseq.getDatasetSequence() != jmp.getTo())
2157 // chaining dbref rather than a handshaking one
2158 jmpid = seqHash(ps = jmp.getTo());
2162 jmpid = seqHash(ps = parentseq);
2164 mpc.setDseqFor(jmpid);
2165 if (!seqRefIds.containsKey(mpc.getDseqFor()))
2167 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2168 seqRefIds.put(mpc.getDseqFor(), ps);
2172 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2175 mp.setMappingChoice(mpc);
2181 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2182 List<UserColourScheme> userColours, JalviewModelSequence jms)
2185 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2186 boolean newucs = false;
2187 if (!userColours.contains(ucs))
2189 userColours.add(ucs);
2192 id = "ucs" + userColours.indexOf(ucs);
2195 // actually create the scheme's entry in the XML model
2196 java.awt.Color[] colours = ucs.getColours();
2197 jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
2198 jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
2200 for (int i = 0; i < colours.length; i++)
2202 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2203 col.setName(ResidueProperties.aa[i]);
2204 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2205 jbucs.addColour(col);
2207 if (ucs.getLowerCaseColours() != null)
2209 colours = ucs.getLowerCaseColours();
2210 for (int i = 0; i < colours.length; i++)
2212 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2213 col.setName(ResidueProperties.aa[i].toLowerCase());
2214 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2215 jbucs.addColour(col);
2220 uc.setUserColourScheme(jbucs);
2221 jms.addUserColours(uc);
2227 jalview.schemes.UserColourScheme getUserColourScheme(
2228 JalviewModelSequence jms, String id)
2230 UserColours[] uc = jms.getUserColours();
2231 UserColours colours = null;
2233 for (int i = 0; i < uc.length; i++)
2235 if (uc[i].getId().equals(id))
2243 java.awt.Color[] newColours = new java.awt.Color[24];
2245 for (int i = 0; i < 24; i++)
2247 newColours[i] = new java.awt.Color(Integer.parseInt(
2248 colours.getUserColourScheme().getColour(i).getRGB(), 16));
2251 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2254 if (colours.getUserColourScheme().getColourCount() > 24)
2256 newColours = new java.awt.Color[23];
2257 for (int i = 0; i < 23; i++)
2259 newColours[i] = new java.awt.Color(Integer.parseInt(
2260 colours.getUserColourScheme().getColour(i + 24).getRGB(),
2263 ucs.setLowerCaseColours(newColours);
2270 * contains last error message (if any) encountered by XML loader.
2272 String errorMessage = null;
2275 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2276 * exceptions are raised during project XML parsing
2278 public boolean attemptversion1parse = true;
2281 * Load a jalview project archive from a jar file
2284 * - HTTP URL or filename
2286 public AlignFrame loadJalviewAlign(final String file)
2289 jalview.gui.AlignFrame af = null;
2293 // create list to store references for any new Jmol viewers created
2294 newStructureViewers = new Vector<>();
2295 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2296 // Workaround is to make sure caller implements the JarInputStreamProvider
2298 // so we can re-open the jar input stream for each entry.
2300 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2301 af = loadJalviewAlign(jprovider);
2303 } catch (MalformedURLException e)
2305 errorMessage = "Invalid URL format for '" + file + "'";
2311 SwingUtilities.invokeAndWait(new Runnable()
2316 setLoadingFinishedForNewStructureViewers();
2319 } catch (Exception x)
2321 System.err.println("Error loading alignment: " + x.getMessage());
2327 private jarInputStreamProvider createjarInputStreamProvider(
2328 final String file) throws MalformedURLException
2331 errorMessage = null;
2332 uniqueSetSuffix = null;
2334 viewportsAdded.clear();
2335 frefedSequence = null;
2337 if (file.startsWith("http://"))
2339 url = new URL(file);
2341 final URL _url = url;
2342 return new jarInputStreamProvider()
2346 public JarInputStream getJarInputStream() throws IOException
2350 return new JarInputStream(_url.openStream());
2354 return new JarInputStream(new FileInputStream(file));
2359 public String getFilename()
2367 * Recover jalview session from a jalview project archive. Caller may
2368 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2369 * themselves. Any null fields will be initialised with default values,
2370 * non-null fields are left alone.
2375 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2377 errorMessage = null;
2378 if (uniqueSetSuffix == null)
2380 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2382 if (seqRefIds == null)
2386 AlignFrame af = null, _af = null;
2387 IdentityHashMap<AlignmentI, AlignmentI> importedDatasets = new IdentityHashMap<>();
2388 Map<String, AlignFrame> gatherToThisFrame = new HashMap<>();
2389 final String file = jprovider.getFilename();
2392 JarInputStream jin = null;
2393 JarEntry jarentry = null;
2398 jin = jprovider.getJarInputStream();
2399 for (int i = 0; i < entryCount; i++)
2401 jarentry = jin.getNextJarEntry();
2404 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2406 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2407 JalviewModel object = new JalviewModel();
2409 Unmarshaller unmar = new Unmarshaller(object);
2410 unmar.setValidation(false);
2411 object = (JalviewModel) unmar.unmarshal(in);
2412 if (true) // !skipViewport(object))
2414 _af = loadFromObject(object, file, true, jprovider);
2415 if (_af != null && object.getJalviewModelSequence()
2416 .getViewportCount() > 0)
2420 // store a reference to the first view
2423 if (_af.viewport.isGatherViewsHere())
2425 // if this is a gathered view, keep its reference since
2426 // after gathering views, only this frame will remain
2428 gatherToThisFrame.put(_af.viewport.getSequenceSetId(), _af);
2430 // Save dataset to register mappings once all resolved
2431 importedDatasets.put(af.viewport.getAlignment().getDataset(),
2432 af.viewport.getAlignment().getDataset());
2437 else if (jarentry != null)
2439 // Some other file here.
2442 } while (jarentry != null);
2443 resolveFrefedSequences();
2444 } catch (IOException ex)
2446 ex.printStackTrace();
2447 errorMessage = "Couldn't locate Jalview XML file : " + file;
2449 "Exception whilst loading jalview XML file : " + ex + "\n");
2450 } catch (Exception ex)
2452 System.err.println("Parsing as Jalview Version 2 file failed.");
2453 ex.printStackTrace(System.err);
2454 if (attemptversion1parse)
2456 // Is Version 1 Jar file?
2459 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
2460 } catch (Exception ex2)
2462 System.err.println("Exception whilst loading as jalviewXMLV1:");
2463 ex2.printStackTrace();
2467 if (Desktop.instance != null)
2469 Desktop.instance.stopLoading();
2473 System.out.println("Successfully loaded archive file");
2476 ex.printStackTrace();
2479 "Exception whilst loading jalview XML file : " + ex + "\n");
2480 } catch (OutOfMemoryError e)
2482 // Don't use the OOM Window here
2483 errorMessage = "Out of memory loading jalview XML file";
2484 System.err.println("Out of memory whilst loading jalview XML file");
2485 e.printStackTrace();
2489 * Regather multiple views (with the same sequence set id) to the frame (if
2490 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2491 * views instead of separate frames. Note this doesn't restore a state where
2492 * some expanded views in turn have tabbed views - the last "first tab" read
2493 * in will play the role of gatherer for all.
2495 for (AlignFrame fr : gatherToThisFrame.values())
2497 Desktop.instance.gatherViews(fr);
2500 restoreSplitFrames();
2501 for (AlignmentI ds : importedDatasets.keySet())
2503 if (ds.getCodonFrames() != null)
2505 StructureSelectionManager
2506 .getStructureSelectionManager(Desktop.instance)
2507 .registerMappings(ds.getCodonFrames());
2510 if (errorMessage != null)
2515 if (Desktop.instance != null)
2517 Desktop.instance.stopLoading();
2524 * Try to reconstruct and display SplitFrame windows, where each contains
2525 * complementary dna and protein alignments. Done by pairing up AlignFrame
2526 * objects (created earlier) which have complementary viewport ids associated.
2528 protected void restoreSplitFrames()
2530 List<SplitFrame> gatherTo = new ArrayList<>();
2531 List<AlignFrame> addedToSplitFrames = new ArrayList<>();
2532 Map<String, AlignFrame> dna = new HashMap<>();
2535 * Identify the DNA alignments
2537 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2540 AlignFrame af = candidate.getValue();
2541 if (af.getViewport().getAlignment().isNucleotide())
2543 dna.put(candidate.getKey().getId(), af);
2548 * Try to match up the protein complements
2550 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2553 AlignFrame af = candidate.getValue();
2554 if (!af.getViewport().getAlignment().isNucleotide())
2556 String complementId = candidate.getKey().getComplementId();
2557 // only non-null complements should be in the Map
2558 if (complementId != null && dna.containsKey(complementId))
2560 final AlignFrame dnaFrame = dna.get(complementId);
2561 SplitFrame sf = createSplitFrame(dnaFrame, af);
2562 addedToSplitFrames.add(dnaFrame);
2563 addedToSplitFrames.add(af);
2564 dnaFrame.setMenusForViewport();
2565 af.setMenusForViewport();
2566 if (af.viewport.isGatherViewsHere())
2575 * Open any that we failed to pair up (which shouldn't happen!) as
2576 * standalone AlignFrame's.
2578 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2581 AlignFrame af = candidate.getValue();
2582 if (!addedToSplitFrames.contains(af))
2584 Viewport view = candidate.getKey();
2585 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
2587 af.setMenusForViewport();
2588 System.err.println("Failed to restore view " + view.getTitle()
2589 + " to split frame");
2594 * Gather back into tabbed views as flagged.
2596 for (SplitFrame sf : gatherTo)
2598 Desktop.instance.gatherViews(sf);
2601 splitFrameCandidates.clear();
2605 * Construct and display one SplitFrame holding DNA and protein alignments.
2608 * @param proteinFrame
2611 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
2612 AlignFrame proteinFrame)
2614 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
2615 String title = MessageManager.getString("label.linked_view_title");
2616 int width = (int) dnaFrame.getBounds().getWidth();
2617 int height = (int) (dnaFrame.getBounds().getHeight()
2618 + proteinFrame.getBounds().getHeight() + 50);
2621 * SplitFrame location is saved to both enclosed frames
2623 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
2624 Desktop.addInternalFrame(splitFrame, title, width, height);
2627 * And compute cDNA consensus (couldn't do earlier with consensus as
2628 * mappings were not yet present)
2630 proteinFrame.viewport.alignmentChanged(proteinFrame.alignPanel);
2636 * check errorMessage for a valid error message and raise an error box in the
2637 * GUI or write the current errorMessage to stderr and then clear the error
2640 protected void reportErrors()
2642 reportErrors(false);
2645 protected void reportErrors(final boolean saving)
2647 if (errorMessage != null)
2649 final String finalErrorMessage = errorMessage;
2652 javax.swing.SwingUtilities.invokeLater(new Runnable()
2657 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
2659 "Error " + (saving ? "saving" : "loading")
2661 JvOptionPane.WARNING_MESSAGE);
2667 System.err.println("Problem loading Jalview file: " + errorMessage);
2670 errorMessage = null;
2673 Map<String, String> alreadyLoadedPDB = new HashMap<>();
2676 * when set, local views will be updated from view stored in JalviewXML
2677 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2678 * sync if this is set to true.
2680 private final boolean updateLocalViews = false;
2683 * Returns the path to a temporary file holding the PDB file for the given PDB
2684 * id. The first time of asking, searches for a file of that name in the
2685 * Jalview project jar, and copies it to a new temporary file. Any repeat
2686 * requests just return the path to the file previously created.
2692 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId,
2695 if (alreadyLoadedPDB.containsKey(pdbId))
2697 return alreadyLoadedPDB.get(pdbId).toString();
2700 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb",
2702 if (tempFile != null)
2704 alreadyLoadedPDB.put(pdbId, tempFile);
2710 * Copies the jar entry of given name to a new temporary file and returns the
2711 * path to the file, or null if the entry is not found.
2714 * @param jarEntryName
2716 * a prefix for the temporary file name, must be at least three
2719 * null or original file - so new file can be given the same suffix
2723 protected String copyJarEntry(jarInputStreamProvider jprovider,
2724 String jarEntryName, String prefix, String origFile)
2726 BufferedReader in = null;
2727 PrintWriter out = null;
2728 String suffix = ".tmp";
2729 if (origFile == null)
2731 origFile = jarEntryName;
2733 int sfpos = origFile.lastIndexOf(".");
2734 if (sfpos > -1 && sfpos < (origFile.length() - 3))
2736 suffix = "." + origFile.substring(sfpos + 1);
2740 JarInputStream jin = jprovider.getJarInputStream();
2742 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2743 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2744 * FileInputStream(jprovider)); }
2747 JarEntry entry = null;
2750 entry = jin.getNextJarEntry();
2751 } while (entry != null && !entry.getName().equals(jarEntryName));
2754 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
2755 File outFile = File.createTempFile(prefix, suffix);
2756 outFile.deleteOnExit();
2757 out = new PrintWriter(new FileOutputStream(outFile));
2760 while ((data = in.readLine()) != null)
2765 String t = outFile.getAbsolutePath();
2770 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
2772 } catch (Exception ex)
2774 ex.printStackTrace();
2782 } catch (IOException e)
2796 private class JvAnnotRow
2798 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2805 * persisted version of annotation row from which to take vis properties
2807 public jalview.datamodel.AlignmentAnnotation template;
2810 * original position of the annotation row in the alignment
2816 * Load alignment frame from jalview XML DOM object
2821 * filename source string
2822 * @param loadTreesAndStructures
2823 * when false only create Viewport
2825 * data source provider
2826 * @return alignment frame created from view stored in DOM
2828 AlignFrame loadFromObject(JalviewModel object, String file,
2829 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
2831 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
2832 Sequence[] vamsasSeq = vamsasSet.getSequence();
2834 JalviewModelSequence jms = object.getJalviewModelSequence();
2836 Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
2839 // ////////////////////////////////
2842 List<SequenceI> hiddenSeqs = null;
2844 List<SequenceI> tmpseqs = new ArrayList<>();
2846 boolean multipleView = false;
2847 SequenceI referenceseqForView = null;
2848 JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
2849 int vi = 0; // counter in vamsasSeq array
2850 for (int i = 0; i < jseqs.length; i++)
2852 String seqId = jseqs[i].getId();
2854 SequenceI tmpSeq = seqRefIds.get(seqId);
2857 if (!incompleteSeqs.containsKey(seqId))
2859 // may not need this check, but keep it for at least 2.9,1 release
2860 if (tmpSeq.getStart() != jseqs[i].getStart()
2861 || tmpSeq.getEnd() != jseqs[i].getEnd())
2864 "Warning JAL-2154 regression: updating start/end for sequence "
2865 + tmpSeq.toString() + " to " + jseqs[i]);
2870 incompleteSeqs.remove(seqId);
2872 if (vamsasSeq.length > vi && vamsasSeq[vi].getId().equals(seqId))
2874 // most likely we are reading a dataset XML document so
2875 // update from vamsasSeq section of XML for this sequence
2876 tmpSeq.setName(vamsasSeq[vi].getName());
2877 tmpSeq.setDescription(vamsasSeq[vi].getDescription());
2878 tmpSeq.setSequence(vamsasSeq[vi].getSequence());
2883 // reading multiple views, so vamsasSeq set is a subset of JSeq
2884 multipleView = true;
2886 tmpSeq.setStart(jseqs[i].getStart());
2887 tmpSeq.setEnd(jseqs[i].getEnd());
2888 tmpseqs.add(tmpSeq);
2892 tmpSeq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
2893 vamsasSeq[vi].getSequence());
2894 tmpSeq.setDescription(vamsasSeq[vi].getDescription());
2895 tmpSeq.setStart(jseqs[i].getStart());
2896 tmpSeq.setEnd(jseqs[i].getEnd());
2897 tmpSeq.setVamsasId(uniqueSetSuffix + seqId);
2898 seqRefIds.put(vamsasSeq[vi].getId(), tmpSeq);
2899 tmpseqs.add(tmpSeq);
2903 if (jseqs[i].hasViewreference() && jseqs[i].getViewreference())
2905 referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
2908 if (jseqs[i].getHidden())
2910 if (hiddenSeqs == null)
2912 hiddenSeqs = new ArrayList<>();
2915 hiddenSeqs.add(tmpSeq);
2920 // Create the alignment object from the sequence set
2921 // ///////////////////////////////
2922 SequenceI[] orderedSeqs = tmpseqs
2923 .toArray(new SequenceI[tmpseqs.size()]);
2925 AlignmentI al = null;
2926 // so we must create or recover the dataset alignment before going further
2927 // ///////////////////////////////
2928 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
2930 // older jalview projects do not have a dataset - so creat alignment and
2932 al = new Alignment(orderedSeqs);
2933 al.setDataset(null);
2937 boolean isdsal = object.getJalviewModelSequence()
2938 .getViewportCount() == 0;
2941 // we are importing a dataset record, so
2942 // recover reference to an alignment already materialsed as dataset
2943 al = getDatasetFor(vamsasSet.getDatasetId());
2947 // materialse the alignment
2948 al = new Alignment(orderedSeqs);
2952 addDatasetRef(vamsasSet.getDatasetId(), al);
2955 // finally, verify all data in vamsasSet is actually present in al
2956 // passing on flag indicating if it is actually a stored dataset
2957 recoverDatasetFor(vamsasSet, al, isdsal);
2960 if (referenceseqForView != null)
2962 al.setSeqrep(referenceseqForView);
2964 // / Add the alignment properties
2965 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
2967 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
2968 al.setProperty(ssp.getKey(), ssp.getValue());
2971 // ///////////////////////////////
2973 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
2976 // load sequence features, database references and any associated PDB
2977 // structures for the alignment
2979 // prior to 2.10, this part would only be executed the first time a
2980 // sequence was encountered, but not afterwards.
2981 // now, for 2.10 projects, this is also done if the xml doc includes
2982 // dataset sequences not actually present in any particular view.
2984 for (int i = 0; i < vamsasSeq.length; i++)
2986 if (jseqs[i].getFeaturesCount() > 0)
2988 Features[] features = jseqs[i].getFeatures();
2989 for (int f = 0; f < features.length; f++)
2991 jalview.datamodel.SequenceFeature sf = new jalview.datamodel.SequenceFeature(
2992 features[f].getType(), features[f].getDescription(),
2993 features[f].getStatus(), features[f].getBegin(),
2994 features[f].getEnd(), features[f].getFeatureGroup());
2996 sf.setScore(features[f].getScore());
2997 for (int od = 0; od < features[f].getOtherDataCount(); od++)
2999 OtherData keyValue = features[f].getOtherData(od);
3000 if (keyValue.getKey().startsWith("LINK"))
3002 sf.addLink(keyValue.getValue());
3006 sf.setValue(keyValue.getKey(), keyValue.getValue());
3010 // adds feature to datasequence's feature set (since Jalview 2.10)
3011 al.getSequenceAt(i).addSequenceFeature(sf);
3014 if (vamsasSeq[i].getDBRefCount() > 0)
3016 // adds dbrefs to datasequence's set (since Jalview 2.10)
3018 al.getSequenceAt(i).getDatasetSequence() == null
3019 ? al.getSequenceAt(i)
3020 : al.getSequenceAt(i).getDatasetSequence(),
3023 if (jseqs[i].getPdbidsCount() > 0)
3025 Pdbids[] ids = jseqs[i].getPdbids();
3026 for (int p = 0; p < ids.length; p++)
3028 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
3029 entry.setId(ids[p].getId());
3030 if (ids[p].getType() != null)
3032 if (PDBEntry.Type.getType(ids[p].getType()) != null)
3034 entry.setType(PDBEntry.Type.getType(ids[p].getType()));
3038 entry.setType(PDBEntry.Type.FILE);
3041 // jprovider is null when executing 'New View'
3042 if (ids[p].getFile() != null && jprovider != null)
3044 if (!pdbloaded.containsKey(ids[p].getFile()))
3046 entry.setFile(loadPDBFile(jprovider, ids[p].getId(),
3051 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
3054 if (ids[p].getPdbentryItem() != null)
3056 for (PdbentryItem item : ids[p].getPdbentryItem())
3058 for (Property pr : item.getProperty())
3060 entry.setProperty(pr.getName(), pr.getValue());
3064 StructureSelectionManager
3065 .getStructureSelectionManager(Desktop.instance)
3066 .registerPDBEntry(entry);
3067 // adds PDBEntry to datasequence's set (since Jalview 2.10)
3068 if (al.getSequenceAt(i).getDatasetSequence() != null)
3070 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
3074 al.getSequenceAt(i).addPDBId(entry);
3079 } // end !multipleview
3081 // ///////////////////////////////
3082 // LOAD SEQUENCE MAPPINGS
3084 if (vamsasSet.getAlcodonFrameCount() > 0)
3086 // TODO Potentially this should only be done once for all views of an
3088 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
3089 for (int i = 0; i < alc.length; i++)
3091 AlignedCodonFrame cf = new AlignedCodonFrame();
3092 if (alc[i].getAlcodMapCount() > 0)
3094 AlcodMap[] maps = alc[i].getAlcodMap();
3095 for (int m = 0; m < maps.length; m++)
3097 SequenceI dnaseq = seqRefIds.get(maps[m].getDnasq());
3099 jalview.datamodel.Mapping mapping = null;
3100 // attach to dna sequence reference.
3101 if (maps[m].getMapping() != null)
3103 mapping = addMapping(maps[m].getMapping());
3104 if (dnaseq != null && mapping.getTo() != null)
3106 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
3112 newAlcodMapRef(maps[m].getDnasq(), cf, mapping));
3116 al.addCodonFrame(cf);
3121 // ////////////////////////////////
3123 List<JvAnnotRow> autoAlan = new ArrayList<>();
3126 * store any annotations which forward reference a group's ID
3128 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<>();
3130 if (vamsasSet.getAnnotationCount() > 0)
3132 Annotation[] an = vamsasSet.getAnnotation();
3134 for (int i = 0; i < an.length; i++)
3136 Annotation annotation = an[i];
3139 * test if annotation is automatically calculated for this view only
3141 boolean autoForView = false;
3142 if (annotation.getLabel().equals("Quality")
3143 || annotation.getLabel().equals("Conservation")
3144 || annotation.getLabel().equals("Consensus"))
3146 // Kludge for pre 2.5 projects which lacked the autocalculated flag
3148 if (!annotation.hasAutoCalculated())
3150 annotation.setAutoCalculated(true);
3153 if (autoForView || (annotation.hasAutoCalculated()
3154 && annotation.isAutoCalculated()))
3156 // remove ID - we don't recover annotation from other views for
3157 // view-specific annotation
3158 annotation.setId(null);
3161 // set visiblity for other annotation in this view
3162 String annotationId = annotation.getId();
3163 if (annotationId != null && annotationIds.containsKey(annotationId))
3165 AlignmentAnnotation jda = annotationIds.get(annotationId);
3166 // in principle Visible should always be true for annotation displayed
3167 // in multiple views
3168 if (annotation.hasVisible())
3170 jda.visible = annotation.getVisible();
3173 al.addAnnotation(jda);
3177 // Construct new annotation from model.
3178 AnnotationElement[] ae = annotation.getAnnotationElement();
3179 jalview.datamodel.Annotation[] anot = null;
3180 java.awt.Color firstColour = null;
3182 if (!annotation.getScoreOnly())
3184 anot = new jalview.datamodel.Annotation[al.getWidth()];
3185 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
3187 anpos = ae[aa].getPosition();
3189 if (anpos >= anot.length)
3194 anot[anpos] = new jalview.datamodel.Annotation(
3196 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
3197 (ae[aa].getSecondaryStructure() == null
3198 || ae[aa].getSecondaryStructure().length() == 0)
3200 : ae[aa].getSecondaryStructure()
3205 // JBPNote: Consider verifying dataflow for IO of secondary
3206 // structure annotation read from Stockholm files
3207 // this was added to try to ensure that
3208 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
3210 // anot[ae[aa].getPosition()].displayCharacter = "";
3212 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
3213 if (firstColour == null)
3215 firstColour = anot[anpos].colour;
3219 jalview.datamodel.AlignmentAnnotation jaa = null;
3221 if (annotation.getGraph())
3223 float llim = 0, hlim = 0;
3224 // if (autoForView || an[i].isAutoCalculated()) {
3227 jaa = new jalview.datamodel.AlignmentAnnotation(
3228 annotation.getLabel(), annotation.getDescription(), anot,
3229 llim, hlim, annotation.getGraphType());
3231 jaa.graphGroup = annotation.getGraphGroup();
3232 jaa._linecolour = firstColour;
3233 if (annotation.getThresholdLine() != null)
3235 jaa.setThreshold(new jalview.datamodel.GraphLine(
3236 annotation.getThresholdLine().getValue(),
3237 annotation.getThresholdLine().getLabel(),
3239 annotation.getThresholdLine().getColour())));
3242 if (autoForView || annotation.isAutoCalculated())
3244 // Hardwire the symbol display line to ensure that labels for
3245 // histograms are displayed
3251 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
3252 an[i].getDescription(), anot);
3253 jaa._linecolour = firstColour;
3255 // register new annotation
3256 if (an[i].getId() != null)
3258 annotationIds.put(an[i].getId(), jaa);
3259 jaa.annotationId = an[i].getId();
3261 // recover sequence association
3262 String sequenceRef = an[i].getSequenceRef();
3263 if (sequenceRef != null)
3265 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3266 SequenceI sequence = seqRefIds.get(sequenceRef);
3267 if (sequence == null)
3269 // in pre-2.9 projects sequence ref is to sequence name
3270 sequence = al.findName(sequenceRef);
3272 if (sequence != null)
3274 jaa.createSequenceMapping(sequence, 1, true);
3275 sequence.addAlignmentAnnotation(jaa);
3278 // and make a note of any group association
3279 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
3281 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3282 .get(an[i].getGroupRef());
3285 aal = new ArrayList<>();
3286 groupAnnotRefs.put(an[i].getGroupRef(), aal);
3291 if (an[i].hasScore())
3293 jaa.setScore(an[i].getScore());
3295 if (an[i].hasVisible())
3297 jaa.visible = an[i].getVisible();
3300 if (an[i].hasCentreColLabels())
3302 jaa.centreColLabels = an[i].getCentreColLabels();
3305 if (an[i].hasScaleColLabels())
3307 jaa.scaleColLabel = an[i].getScaleColLabels();
3309 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
3311 // newer files have an 'autoCalculated' flag and store calculation
3312 // state in viewport properties
3313 jaa.autoCalculated = true; // means annotation will be marked for
3314 // update at end of load.
3316 if (an[i].hasGraphHeight())
3318 jaa.graphHeight = an[i].getGraphHeight();
3320 if (an[i].hasBelowAlignment())
3322 jaa.belowAlignment = an[i].isBelowAlignment();
3324 jaa.setCalcId(an[i].getCalcId());
3325 if (an[i].getPropertyCount() > 0)
3327 for (jalview.schemabinding.version2.Property prop : an[i]
3330 jaa.setProperty(prop.getName(), prop.getValue());
3333 if (jaa.autoCalculated)
3335 autoAlan.add(new JvAnnotRow(i, jaa));
3338 // if (!autoForView)
3340 // add autocalculated group annotation and any user created annotation
3342 al.addAnnotation(jaa);
3346 // ///////////////////////
3348 // Create alignment markup and styles for this view
3349 if (jms.getJGroupCount() > 0)
3351 JGroup[] groups = jms.getJGroup();
3352 boolean addAnnotSchemeGroup = false;
3353 for (int i = 0; i < groups.length; i++)
3355 JGroup jGroup = groups[i];
3356 ColourSchemeI cs = null;
3357 if (jGroup.getColour() != null)
3359 if (jGroup.getColour().startsWith("ucs"))
3361 cs = getUserColourScheme(jms, jGroup.getColour());
3363 else if (jGroup.getColour().equals("AnnotationColourGradient")
3364 && jGroup.getAnnotationColours() != null)
3366 addAnnotSchemeGroup = true;
3370 cs = ColourSchemeProperty.getColourScheme(al,
3371 jGroup.getColour());
3374 int pidThreshold = jGroup.getPidThreshold();
3376 Vector<SequenceI> seqs = new Vector<>();
3378 for (int s = 0; s < jGroup.getSeqCount(); s++)
3380 String seqId = jGroup.getSeq(s) + "";
3381 SequenceI ts = seqRefIds.get(seqId);
3385 seqs.addElement(ts);
3389 if (seqs.size() < 1)
3394 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3395 jGroup.getDisplayBoxes(), jGroup.getDisplayText(),
3396 jGroup.getColourText(), jGroup.getStart(), jGroup.getEnd());
3397 sg.getGroupColourScheme().setThreshold(pidThreshold, true);
3398 sg.getGroupColourScheme()
3399 .setConservationInc(jGroup.getConsThreshold());
3400 sg.setOutlineColour(new java.awt.Color(jGroup.getOutlineColour()));
3402 sg.textColour = new java.awt.Color(jGroup.getTextCol1());
3403 sg.textColour2 = new java.awt.Color(jGroup.getTextCol2());
3404 sg.setShowNonconserved(
3405 jGroup.hasShowUnconserved() ? jGroup.isShowUnconserved()
3407 sg.thresholdTextColour = jGroup.getTextColThreshold();
3408 if (jGroup.hasShowConsensusHistogram())
3410 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3413 if (jGroup.hasShowSequenceLogo())
3415 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3417 if (jGroup.hasNormaliseSequenceLogo())
3419 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3421 if (jGroup.hasIgnoreGapsinConsensus())
3423 sg.setIgnoreGapsConsensus(jGroup.getIgnoreGapsinConsensus());
3425 if (jGroup.getConsThreshold() != 0)
3427 Conservation c = new Conservation("All", sg.getSequences(null), 0,
3430 c.verdict(false, 25);
3431 sg.cs.setConservation(c);
3434 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3436 // re-instate unique group/annotation row reference
3437 List<AlignmentAnnotation> jaal = groupAnnotRefs
3438 .get(jGroup.getId());
3441 for (AlignmentAnnotation jaa : jaal)
3444 if (jaa.autoCalculated)
3446 // match up and try to set group autocalc alignment row for this
3448 if (jaa.label.startsWith("Consensus for "))
3450 sg.setConsensus(jaa);
3452 // match up and try to set group autocalc alignment row for this
3454 if (jaa.label.startsWith("Conservation for "))
3456 sg.setConservationRow(jaa);
3463 if (addAnnotSchemeGroup)
3465 // reconstruct the annotation colourscheme
3466 sg.setColourScheme(constructAnnotationColour(
3467 jGroup.getAnnotationColours(), null, al, jms, false));
3473 // only dataset in this model, so just return.
3476 // ///////////////////////////////
3479 // If we just load in the same jar file again, the sequenceSetId
3480 // will be the same, and we end up with multiple references
3481 // to the same sequenceSet. We must modify this id on load
3482 // so that each load of the file gives a unique id
3483 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3484 String viewId = (view.getId() == null ? null
3485 : view.getId() + uniqueSetSuffix);
3486 AlignFrame af = null;
3487 AlignViewport av = null;
3488 // now check to see if we really need to create a new viewport.
3489 if (multipleView && viewportsAdded.size() == 0)
3491 // We recovered an alignment for which a viewport already exists.
3492 // TODO: fix up any settings necessary for overlaying stored state onto
3493 // state recovered from another document. (may not be necessary).
3494 // we may need a binding from a viewport in memory to one recovered from
3496 // and then recover its containing af to allow the settings to be applied.
3497 // TODO: fix for vamsas demo
3499 "About to recover a viewport for existing alignment: Sequence set ID is "
3501 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3502 if (seqsetobj != null)
3504 if (seqsetobj instanceof String)
3506 uniqueSeqSetId = (String) seqsetobj;
3508 "Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
3514 "Warning : Collision between sequence set ID string and existing jalview object mapping.");
3520 * indicate that annotation colours are applied across all groups (pre
3521 * Jalview 2.8.1 behaviour)
3523 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan("2.8.1",
3524 object.getVersion());
3526 AlignmentPanel ap = null;
3527 boolean isnewview = true;
3530 // Check to see if this alignment already has a view id == viewId
3531 jalview.gui.AlignmentPanel views[] = Desktop
3532 .getAlignmentPanels(uniqueSeqSetId);
3533 if (views != null && views.length > 0)
3535 for (int v = 0; v < views.length; v++)
3537 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
3539 // recover the existing alignpanel, alignframe, viewport
3540 af = views[v].alignFrame;
3543 // TODO: could even skip resetting view settings if we don't want to
3544 // change the local settings from other jalview processes
3553 af = loadViewport(file, jseqs, hiddenSeqs, al, jms, view,
3554 uniqueSeqSetId, viewId, autoAlan);
3560 * Load any trees, PDB structures and viewers
3562 * Not done if flag is false (when this method is used for New View)
3564 if (loadTreesAndStructures)
3566 loadTrees(jms, view, af, av, ap);
3567 loadPDBStructures(jprovider, jseqs, af, ap);
3568 loadRnaViewers(jprovider, jseqs, ap);
3570 // and finally return.
3575 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
3576 * panel is restored from separate jar entries, two (gapped and trimmed) per
3577 * sequence and secondary structure.
3579 * Currently each viewer shows just one sequence and structure (gapped and
3580 * trimmed), however this method is designed to support multiple sequences or
3581 * structures in viewers if wanted in future.
3587 private void loadRnaViewers(jarInputStreamProvider jprovider,
3588 JSeq[] jseqs, AlignmentPanel ap)
3591 * scan the sequences for references to viewers; create each one the first
3592 * time it is referenced, add Rna models to existing viewers
3594 for (JSeq jseq : jseqs)
3596 for (int i = 0; i < jseq.getRnaViewerCount(); i++)
3598 RnaViewer viewer = jseq.getRnaViewer(i);
3599 AppVarna appVarna = findOrCreateVarnaViewer(viewer, uniqueSetSuffix,
3602 for (int j = 0; j < viewer.getSecondaryStructureCount(); j++)
3604 SecondaryStructure ss = viewer.getSecondaryStructure(j);
3605 SequenceI seq = seqRefIds.get(jseq.getId());
3606 AlignmentAnnotation ann = this.annotationIds
3607 .get(ss.getAnnotationId());
3610 * add the structure to the Varna display (with session state copied
3611 * from the jar to a temporary file)
3613 boolean gapped = ss.isGapped();
3614 String rnaTitle = ss.getTitle();
3615 String sessionState = ss.getViewerState();
3616 String tempStateFile = copyJarEntry(jprovider, sessionState,
3618 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
3619 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
3621 appVarna.setInitialSelection(viewer.getSelectedRna());
3627 * Locate and return an already instantiated matching AppVarna, or create one
3631 * @param viewIdSuffix
3635 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
3636 String viewIdSuffix, AlignmentPanel ap)
3639 * on each load a suffix is appended to the saved viewId, to avoid conflicts
3640 * if load is repeated
3642 String postLoadId = viewer.getViewId() + viewIdSuffix;
3643 for (JInternalFrame frame : getAllFrames())
3645 if (frame instanceof AppVarna)
3647 AppVarna varna = (AppVarna) frame;
3648 if (postLoadId.equals(varna.getViewId()))
3650 // this viewer is already instantiated
3651 // could in future here add ap as another 'parent' of the
3652 // AppVarna window; currently just 1-to-many
3659 * viewer not found - make it
3661 RnaViewerModel model = new RnaViewerModel(postLoadId, viewer.getTitle(),
3662 viewer.getXpos(), viewer.getYpos(), viewer.getWidth(),
3663 viewer.getHeight(), viewer.getDividerLocation());
3664 AppVarna varna = new AppVarna(model, ap);
3670 * Load any saved trees
3678 protected void loadTrees(JalviewModelSequence jms, Viewport view,
3679 AlignFrame af, AlignViewport av, AlignmentPanel ap)
3681 // TODO result of automated refactoring - are all these parameters needed?
3684 for (int t = 0; t < jms.getTreeCount(); t++)
3687 Tree tree = jms.getTree(t);
3689 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
3692 tp = af.showNewickTree(
3693 new jalview.io.NewickFile(tree.getNewick()),
3694 tree.getTitle(), tree.getWidth(), tree.getHeight(),
3695 tree.getXpos(), tree.getYpos());
3696 if (tree.getId() != null)
3698 // perhaps bind the tree id to something ?
3703 // update local tree attributes ?
3704 // TODO: should check if tp has been manipulated by user - if so its
3705 // settings shouldn't be modified
3706 tp.setTitle(tree.getTitle());
3707 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(),
3708 tree.getWidth(), tree.getHeight()));
3709 tp.av = av; // af.viewport; // TODO: verify 'associate with all
3712 tp.treeCanvas.av = av; // af.viewport;
3713 tp.treeCanvas.ap = ap; // af.alignPanel;
3718 warn("There was a problem recovering stored Newick tree: \n"
3719 + tree.getNewick());
3723 tp.fitToWindow.setState(tree.getFitToWindow());
3724 tp.fitToWindow_actionPerformed(null);
3726 if (tree.getFontName() != null)
3728 tp.setTreeFont(new java.awt.Font(tree.getFontName(),
3729 tree.getFontStyle(), tree.getFontSize()));
3733 tp.setTreeFont(new java.awt.Font(view.getFontName(),
3734 view.getFontStyle(), tree.getFontSize()));
3737 tp.showPlaceholders(tree.getMarkUnlinked());
3738 tp.showBootstrap(tree.getShowBootstrap());
3739 tp.showDistances(tree.getShowDistances());
3741 tp.treeCanvas.threshold = tree.getThreshold();
3743 if (tree.getCurrentTree())
3745 af.viewport.setCurrentTree(tp.getTree());
3749 } catch (Exception ex)
3751 ex.printStackTrace();
3756 * Load and link any saved structure viewers.
3763 protected void loadPDBStructures(jarInputStreamProvider jprovider,
3764 JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
3767 * Run through all PDB ids on the alignment, and collect mappings between
3768 * distinct view ids and all sequences referring to that view.
3770 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<>();
3772 for (int i = 0; i < jseqs.length; i++)
3774 if (jseqs[i].getPdbidsCount() > 0)
3776 Pdbids[] ids = jseqs[i].getPdbids();
3777 for (int p = 0; p < ids.length; p++)
3779 final int structureStateCount = ids[p].getStructureStateCount();
3780 for (int s = 0; s < structureStateCount; s++)
3782 // check to see if we haven't already created this structure view
3783 final StructureState structureState = ids[p]
3784 .getStructureState(s);
3785 String sviewid = (structureState.getViewId() == null) ? null
3786 : structureState.getViewId() + uniqueSetSuffix;
3787 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
3788 // Originally : ids[p].getFile()
3789 // : TODO: verify external PDB file recovery still works in normal
3790 // jalview project load
3791 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId(),
3793 jpdb.setId(ids[p].getId());
3795 int x = structureState.getXpos();
3796 int y = structureState.getYpos();
3797 int width = structureState.getWidth();
3798 int height = structureState.getHeight();
3800 // Probably don't need to do this anymore...
3801 // Desktop.desktop.getComponentAt(x, y);
3802 // TODO: NOW: check that this recovers the PDB file correctly.
3803 String pdbFile = loadPDBFile(jprovider, ids[p].getId(),
3805 jalview.datamodel.SequenceI seq = seqRefIds
3806 .get(jseqs[i].getId() + "");
3807 if (sviewid == null)
3809 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width + ","
3812 if (!structureViewers.containsKey(sviewid))
3814 structureViewers.put(sviewid,
3815 new StructureViewerModel(x, y, width, height, false,
3816 false, true, structureState.getViewId(),
3817 structureState.getType()));
3818 // Legacy pre-2.7 conversion JAL-823 :
3819 // do not assume any view has to be linked for colour by
3823 // assemble String[] { pdb files }, String[] { id for each
3824 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3825 // seqs_file 2}, boolean[] {
3826 // linkAlignPanel,superposeWithAlignpanel}} from hash
3827 StructureViewerModel jmoldat = structureViewers.get(sviewid);
3828 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
3829 | (structureState.hasAlignwithAlignPanel()
3830 ? structureState.getAlignwithAlignPanel()
3834 * Default colour by linked panel to false if not specified (e.g.
3835 * for pre-2.7 projects)
3837 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
3838 colourWithAlignPanel |= (structureState
3839 .hasColourwithAlignPanel()
3840 ? structureState.getColourwithAlignPanel()
3842 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
3845 * Default colour by viewer to true if not specified (e.g. for
3848 boolean colourByViewer = jmoldat.isColourByViewer();
3849 colourByViewer &= structureState.hasColourByJmol()
3850 ? structureState.getColourByJmol()
3852 jmoldat.setColourByViewer(colourByViewer);
3854 if (jmoldat.getStateData().length() < structureState
3855 .getContent().length())
3858 jmoldat.setStateData(structureState.getContent());
3861 if (ids[p].getFile() != null)
3863 File mapkey = new File(ids[p].getFile());
3864 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
3865 if (seqstrmaps == null)
3867 jmoldat.getFileData().put(mapkey,
3868 seqstrmaps = jmoldat.new StructureData(pdbFile,
3871 if (!seqstrmaps.getSeqList().contains(seq))
3873 seqstrmaps.getSeqList().add(seq);
3879 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");
3886 // Instantiate the associated structure views
3887 for (Entry<String, StructureViewerModel> entry : structureViewers
3892 createOrLinkStructureViewer(entry, af, ap, jprovider);
3893 } catch (Exception e)
3896 "Error loading structure viewer: " + e.getMessage());
3897 // failed - try the next one
3909 protected void createOrLinkStructureViewer(
3910 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3911 AlignmentPanel ap, jarInputStreamProvider jprovider)
3913 final StructureViewerModel stateData = viewerData.getValue();
3916 * Search for any viewer windows already open from other alignment views
3917 * that exactly match the stored structure state
3919 StructureViewerBase comp = findMatchingViewer(viewerData);
3923 linkStructureViewer(ap, comp, stateData);
3928 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
3929 * "viewer_"+stateData.viewId
3931 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
3933 createChimeraViewer(viewerData, af, jprovider);
3938 * else Jmol (if pre-2.9, stateData contains JMOL state string)
3940 createJmolViewer(viewerData, af, jprovider);
3945 * Create a new Chimera viewer.
3951 protected void createChimeraViewer(
3952 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3953 jarInputStreamProvider jprovider)
3955 StructureViewerModel data = viewerData.getValue();
3956 String chimeraSessionFile = data.getStateData();
3959 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
3961 * NB this is the 'saved' viewId as in the project file XML, _not_ the
3962 * 'uniquified' sviewid used to reconstruct the viewer here
3964 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
3965 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
3968 Set<Entry<File, StructureData>> fileData = data.getFileData()
3970 List<PDBEntry> pdbs = new ArrayList<>();
3971 List<SequenceI[]> allseqs = new ArrayList<>();
3972 for (Entry<File, StructureData> pdb : fileData)
3974 String filePath = pdb.getValue().getFilePath();
3975 String pdbId = pdb.getValue().getPdbId();
3976 // pdbs.add(new PDBEntry(filePath, pdbId));
3977 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
3978 final List<SequenceI> seqList = pdb.getValue().getSeqList();
3979 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
3983 boolean colourByChimera = data.isColourByViewer();
3984 boolean colourBySequence = data.isColourWithAlignPanel();
3986 // TODO use StructureViewer as a factory here, see JAL-1761
3987 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
3988 final SequenceI[][] seqsArray = allseqs
3989 .toArray(new SequenceI[allseqs.size()][]);
3990 String newViewId = viewerData.getKey();
3992 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
3993 af.alignPanel, pdbArray, seqsArray, colourByChimera,
3994 colourBySequence, newViewId);
3995 cvf.setSize(data.getWidth(), data.getHeight());
3996 cvf.setLocation(data.getX(), data.getY());
4000 * Create a new Jmol window. First parse the Jmol state to translate filenames
4001 * loaded into the view, and record the order in which files are shown in the
4002 * Jmol view, so we can add the sequence mappings in same order.
4008 protected void createJmolViewer(
4009 final Entry<String, StructureViewerModel> viewerData,
4010 AlignFrame af, jarInputStreamProvider jprovider)
4012 final StructureViewerModel svattrib = viewerData.getValue();
4013 String state = svattrib.getStateData();
4016 * Pre-2.9: state element value is the Jmol state string
4018 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
4021 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
4023 state = readJarEntry(jprovider,
4024 getViewerJarEntryName(svattrib.getViewId()));
4027 List<String> pdbfilenames = new ArrayList<>();
4028 List<SequenceI[]> seqmaps = new ArrayList<>();
4029 List<String> pdbids = new ArrayList<>();
4030 StringBuilder newFileLoc = new StringBuilder(64);
4031 int cp = 0, ncp, ecp;
4032 Map<File, StructureData> oldFiles = svattrib.getFileData();
4033 while ((ncp = state.indexOf("load ", cp)) > -1)
4037 // look for next filename in load statement
4038 newFileLoc.append(state.substring(cp,
4039 ncp = (state.indexOf("\"", ncp + 1) + 1)));
4040 String oldfilenam = state.substring(ncp,
4041 ecp = state.indexOf("\"", ncp));
4042 // recover the new mapping data for this old filename
4043 // have to normalize filename - since Jmol and jalview do
4045 // translation differently.
4046 StructureData filedat = oldFiles.get(new File(oldfilenam));
4047 if (filedat == null)
4049 String reformatedOldFilename = oldfilenam.replaceAll("/", "\\\\");
4050 filedat = oldFiles.get(new File(reformatedOldFilename));
4052 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
4053 pdbfilenames.add(filedat.getFilePath());
4054 pdbids.add(filedat.getPdbId());
4055 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4056 newFileLoc.append("\"");
4057 cp = ecp + 1; // advance beyond last \" and set cursor so we can
4058 // look for next file statement.
4059 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
4063 // just append rest of state
4064 newFileLoc.append(state.substring(cp));
4068 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
4069 newFileLoc = new StringBuilder(state);
4070 newFileLoc.append("; load append ");
4071 for (File id : oldFiles.keySet())
4073 // add this and any other pdb files that should be present in
4075 StructureData filedat = oldFiles.get(id);
4076 newFileLoc.append(filedat.getFilePath());
4077 pdbfilenames.add(filedat.getFilePath());
4078 pdbids.add(filedat.getPdbId());
4079 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
4080 newFileLoc.append(" \"");
4081 newFileLoc.append(filedat.getFilePath());
4082 newFileLoc.append("\"");
4085 newFileLoc.append(";");
4088 if (newFileLoc.length() == 0)
4092 int histbug = newFileLoc.indexOf("history = ");
4096 * change "history = [true|false];" to "history = [1|0];"
4099 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
4100 String val = (diff == -1) ? null
4101 : newFileLoc.substring(histbug, diff);
4102 if (val != null && val.length() >= 4)
4104 if (val.contains("e")) // eh? what can it be?
4106 if (val.trim().equals("true"))
4114 newFileLoc.replace(histbug, diff, val);
4119 final String[] pdbf = pdbfilenames
4120 .toArray(new String[pdbfilenames.size()]);
4121 final String[] id = pdbids.toArray(new String[pdbids.size()]);
4122 final SequenceI[][] sq = seqmaps
4123 .toArray(new SequenceI[seqmaps.size()][]);
4124 final String fileloc = newFileLoc.toString();
4125 final String sviewid = viewerData.getKey();
4126 final AlignFrame alf = af;
4127 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
4128 svattrib.getWidth(), svattrib.getHeight());
4131 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
4136 JalviewStructureDisplayI sview = null;
4139 sview = new StructureViewer(
4140 alf.alignPanel.getStructureSelectionManager())
4141 .createView(StructureViewer.ViewerType.JMOL,
4142 pdbf, id, sq, alf.alignPanel, svattrib,
4143 fileloc, rect, sviewid);
4144 addNewStructureViewer(sview);
4145 } catch (OutOfMemoryError ex)
4147 new OOMWarning("restoring structure view for PDB id " + id,
4148 (OutOfMemoryError) ex.getCause());
4149 if (sview != null && sview.isVisible())
4151 sview.closeViewer(false);
4152 sview.setVisible(false);
4158 } catch (InvocationTargetException ex)
4160 warn("Unexpected error when opening Jmol view.", ex);
4162 } catch (InterruptedException e)
4164 // e.printStackTrace();
4170 * Generates a name for the entry in the project jar file to hold state
4171 * information for a structure viewer
4176 protected String getViewerJarEntryName(String viewId)
4178 return VIEWER_PREFIX + viewId;
4182 * Returns any open frame that matches given structure viewer data. The match
4183 * is based on the unique viewId, or (for older project versions) the frame's
4189 protected StructureViewerBase findMatchingViewer(
4190 Entry<String, StructureViewerModel> viewerData)
4192 final String sviewid = viewerData.getKey();
4193 final StructureViewerModel svattrib = viewerData.getValue();
4194 StructureViewerBase comp = null;
4195 JInternalFrame[] frames = getAllFrames();
4196 for (JInternalFrame frame : frames)
4198 if (frame instanceof StructureViewerBase)
4201 * Post jalview 2.4 schema includes structure view id
4203 if (sviewid != null && ((StructureViewerBase) frame).getViewId()
4206 comp = (StructureViewerBase) frame;
4207 break; // break added in 2.9
4210 * Otherwise test for matching position and size of viewer frame
4212 else if (frame.getX() == svattrib.getX()
4213 && frame.getY() == svattrib.getY()
4214 && frame.getHeight() == svattrib.getHeight()
4215 && frame.getWidth() == svattrib.getWidth())
4217 comp = (StructureViewerBase) frame;
4218 // no break in faint hope of an exact match on viewId
4226 * Link an AlignmentPanel to an existing structure viewer.
4231 * @param useinViewerSuperpos
4232 * @param usetoColourbyseq
4233 * @param viewerColouring
4235 protected void linkStructureViewer(AlignmentPanel ap,
4236 StructureViewerBase viewer, StructureViewerModel stateData)
4238 // NOTE: if the jalview project is part of a shared session then
4239 // view synchronization should/could be done here.
4241 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4242 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4243 final boolean viewerColouring = stateData.isColourByViewer();
4244 Map<File, StructureData> oldFiles = stateData.getFileData();
4247 * Add mapping for sequences in this view to an already open viewer
4249 final AAStructureBindingModel binding = viewer.getBinding();
4250 for (File id : oldFiles.keySet())
4252 // add this and any other pdb files that should be present in the
4254 StructureData filedat = oldFiles.get(id);
4255 String pdbFile = filedat.getFilePath();
4256 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4257 binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE);
4258 binding.addSequenceForStructFile(pdbFile, seq);
4260 // and add the AlignmentPanel's reference to the view panel
4261 viewer.addAlignmentPanel(ap);
4262 if (useinViewerSuperpos)
4264 viewer.useAlignmentPanelForSuperposition(ap);
4268 viewer.excludeAlignmentPanelForSuperposition(ap);
4270 if (usetoColourbyseq)
4272 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4276 viewer.excludeAlignmentPanelForColourbyseq(ap);
4281 * Get all frames within the Desktop.
4285 protected JInternalFrame[] getAllFrames()
4287 JInternalFrame[] frames = null;
4288 // TODO is this necessary - is it safe - risk of hanging?
4293 frames = Desktop.desktop.getAllFrames();
4294 } catch (ArrayIndexOutOfBoundsException e)
4296 // occasional No such child exceptions are thrown here...
4300 } catch (InterruptedException f)
4304 } while (frames == null);
4309 * Answers true if 'version' is equal to or later than 'supported', where each
4310 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4311 * changes. Development and test values for 'version' are leniently treated
4315 * - minimum version we are comparing against
4317 * - version of data being processsed
4320 public static boolean isVersionStringLaterThan(String supported,
4323 if (supported == null || version == null
4324 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4325 || version.equalsIgnoreCase("Test")
4326 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4328 System.err.println("Assuming project file with "
4329 + (version == null ? "null" : version)
4330 + " is compatible with Jalview version " + supported);
4335 return StringUtils.compareVersions(version, supported, "b") >= 0;
4339 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4341 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4343 if (newStructureViewers != null)
4345 sview.getBinding().setFinishedLoadingFromArchive(false);
4346 newStructureViewers.add(sview);
4350 protected void setLoadingFinishedForNewStructureViewers()
4352 if (newStructureViewers != null)
4354 for (JalviewStructureDisplayI sview : newStructureViewers)
4356 sview.getBinding().setFinishedLoadingFromArchive(true);
4358 newStructureViewers.clear();
4359 newStructureViewers = null;
4363 AlignFrame loadViewport(String file, JSeq[] JSEQ,
4364 List<SequenceI> hiddenSeqs, AlignmentI al,
4365 JalviewModelSequence jms, Viewport view, String uniqueSeqSetId,
4366 String viewId, List<JvAnnotRow> autoAlan)
4368 AlignFrame af = null;
4369 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
4370 uniqueSeqSetId, viewId);
4372 af.setFileName(file, FileFormat.Jalview);
4374 for (int i = 0; i < JSEQ.length; i++)
4376 af.viewport.setSequenceColour(
4377 af.viewport.getAlignment().getSequenceAt(i),
4378 new java.awt.Color(JSEQ[i].getColour()));
4383 af.getViewport().setColourByReferenceSeq(true);
4384 af.getViewport().setDisplayReferenceSeq(true);
4387 af.viewport.setGatherViewsHere(view.getGatheredViews());
4389 if (view.getSequenceSetId() != null)
4391 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4393 af.viewport.setSequenceSetId(uniqueSeqSetId);
4396 // propagate shared settings to this new view
4397 af.viewport.setHistoryList(av.getHistoryList());
4398 af.viewport.setRedoList(av.getRedoList());
4402 viewportsAdded.put(uniqueSeqSetId, af.viewport);
4404 // TODO: check if this method can be called repeatedly without
4405 // side-effects if alignpanel already registered.
4406 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4408 // apply Hidden regions to view.
4409 if (hiddenSeqs != null)
4411 for (int s = 0; s < JSEQ.length; s++)
4413 SequenceGroup hidden = new SequenceGroup();
4414 boolean isRepresentative = false;
4415 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
4417 isRepresentative = true;
4418 SequenceI sequenceToHide = al
4419 .getSequenceAt(JSEQ[s].getHiddenSequences(r));
4420 hidden.addSequence(sequenceToHide, false);
4421 // remove from hiddenSeqs list so we don't try to hide it twice
4422 hiddenSeqs.remove(sequenceToHide);
4424 if (isRepresentative)
4426 SequenceI representativeSequence = al.getSequenceAt(s);
4427 hidden.addSequence(representativeSequence, false);
4428 af.viewport.hideRepSequences(representativeSequence, hidden);
4432 SequenceI[] hseqs = hiddenSeqs
4433 .toArray(new SequenceI[hiddenSeqs.size()]);
4434 af.viewport.hideSequence(hseqs);
4437 // recover view properties and display parameters
4439 af.viewport.setShowAnnotation(view.getShowAnnotation());
4440 af.viewport.setAbovePIDThreshold(view.getPidSelected());
4441 af.viewport.setThreshold(view.getPidThreshold());
4443 af.viewport.setColourText(view.getShowColourText());
4445 af.viewport.setConservationSelected(view.getConservationSelected());
4446 af.viewport.setIncrement(view.getConsThreshold());
4447 af.viewport.setShowJVSuffix(view.getShowFullId());
4448 af.viewport.setRightAlignIds(view.getRightAlignIds());
4449 af.viewport.setFont(new java.awt.Font(view.getFontName(),
4450 view.getFontStyle(), view.getFontSize()), true);
4451 ViewStyleI vs = af.viewport.getViewStyle();
4452 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
4453 af.viewport.setViewStyle(vs);
4454 // TODO: allow custom charWidth/Heights to be restored by updating them
4455 // after setting font - which means set above to false
4456 af.viewport.setRenderGaps(view.getRenderGaps());
4457 af.viewport.setWrapAlignment(view.getWrapAlignment());
4458 af.viewport.setShowAnnotation(view.getShowAnnotation());
4460 af.viewport.setShowBoxes(view.getShowBoxes());
4462 af.viewport.setShowText(view.getShowText());
4464 af.viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
4465 af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
4466 af.viewport.setThresholdTextColour(view.getTextColThreshold());
4467 af.viewport.setShowUnconserved(
4468 view.hasShowUnconserved() ? view.isShowUnconserved() : false);
4469 af.viewport.getRanges().setStartRes(view.getStartRes());
4471 if (view.getViewName() != null)
4473 af.viewport.viewName = view.getViewName();
4474 af.setInitialTabVisible();
4476 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
4478 // startSeq set in af.alignPanel.updateLayout below
4479 af.alignPanel.updateLayout();
4480 ColourSchemeI cs = null;
4481 // apply colourschemes
4482 if (view.getBgColour() != null)
4484 if (view.getBgColour().startsWith("ucs"))
4486 cs = getUserColourScheme(jms, view.getBgColour());
4488 else if (view.getBgColour().startsWith("Annotation"))
4490 AnnotationColours viewAnnColour = view.getAnnotationColours();
4491 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
4498 cs = ColourSchemeProperty.getColourScheme(al, view.getBgColour());
4502 af.viewport.setGlobalColourScheme(cs);
4503 af.viewport.getResidueShading().setThreshold(view.getPidThreshold(),
4504 view.getIgnoreGapsinConsensus());
4505 af.viewport.getResidueShading()
4506 .setConsensus(af.viewport.getSequenceConsensusHash());
4507 af.viewport.setColourAppliesToAllGroups(false);
4509 if (view.getConservationSelected() && cs != null)
4511 af.viewport.getResidueShading()
4512 .setConservationInc(view.getConsThreshold());
4515 af.changeColour(cs);
4517 af.viewport.setColourAppliesToAllGroups(true);
4519 af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures());
4521 if (view.hasCentreColumnLabels())
4523 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
4525 if (view.hasIgnoreGapsinConsensus())
4527 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
4530 if (view.hasFollowHighlight())
4532 af.viewport.setFollowHighlight(view.getFollowHighlight());
4534 if (view.hasFollowSelection())
4536 af.viewport.followSelection = view.getFollowSelection();
4538 if (view.hasShowConsensusHistogram())
4541 .setShowConsensusHistogram(view.getShowConsensusHistogram());
4545 af.viewport.setShowConsensusHistogram(true);
4547 if (view.hasShowSequenceLogo())
4549 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
4553 af.viewport.setShowSequenceLogo(false);
4555 if (view.hasNormaliseSequenceLogo())
4557 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
4559 if (view.hasShowDbRefTooltip())
4561 af.viewport.setShowDBRefs(view.getShowDbRefTooltip());
4563 if (view.hasShowNPfeatureTooltip())
4565 af.viewport.setShowNPFeats(view.hasShowNPfeatureTooltip());
4567 if (view.hasShowGroupConsensus())
4569 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
4573 af.viewport.setShowGroupConsensus(false);
4575 if (view.hasShowGroupConservation())
4577 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
4581 af.viewport.setShowGroupConservation(false);
4584 // recover featre settings
4585 if (jms.getFeatureSettings() != null)
4587 FeaturesDisplayed fdi;
4588 af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
4589 String[] renderOrder = new String[jms.getFeatureSettings()
4590 .getSettingCount()];
4591 Map<String, FeatureColourI> featureColours = new Hashtable<>();
4592 Map<String, Float> featureOrder = new Hashtable<>();
4594 for (int fs = 0; fs < jms.getFeatureSettings()
4595 .getSettingCount(); fs++)
4597 Setting setting = jms.getFeatureSettings().getSetting(fs);
4598 if (setting.hasMincolour())
4600 FeatureColourI gc = setting.hasMin()
4601 ? new FeatureColour(new Color(setting.getMincolour()),
4602 new Color(setting.getColour()), setting.getMin(),
4604 : new FeatureColour(new Color(setting.getMincolour()),
4605 new Color(setting.getColour()), 0, 1);
4606 if (setting.hasThreshold())
4608 gc.setThreshold(setting.getThreshold());
4609 int threshstate = setting.getThreshstate();
4610 // -1 = None, 0 = Below, 1 = Above threshold
4611 if (threshstate == 0)
4613 gc.setBelowThreshold(true);
4615 else if (threshstate == 1)
4617 gc.setAboveThreshold(true);
4620 gc.setAutoScaled(true); // default
4621 if (setting.hasAutoScale())
4623 gc.setAutoScaled(setting.getAutoScale());
4625 if (setting.hasColourByLabel())
4627 gc.setColourByLabel(setting.getColourByLabel());
4629 // and put in the feature colour table.
4630 featureColours.put(setting.getType(), gc);
4634 featureColours.put(setting.getType(),
4635 new FeatureColour(new Color(setting.getColour())));
4637 renderOrder[fs] = setting.getType();
4638 if (setting.hasOrder())
4640 featureOrder.put(setting.getType(), setting.getOrder());
4644 featureOrder.put(setting.getType(), new Float(
4645 fs / jms.getFeatureSettings().getSettingCount()));
4647 if (setting.getDisplay())
4649 fdi.setVisible(setting.getType());
4652 Map<String, Boolean> fgtable = new Hashtable<>();
4653 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
4655 Group grp = jms.getFeatureSettings().getGroup(gs);
4656 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
4658 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4659 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
4660 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
4661 FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4662 fgtable, featureColours, 1.0f, featureOrder);
4663 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
4664 .transferSettings(frs);
4668 if (view.getHiddenColumnsCount() > 0)
4670 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
4672 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(),
4673 view.getHiddenColumns(c).getEnd() // +1
4677 if (view.getCalcIdParam() != null)
4679 for (CalcIdParam calcIdParam : view.getCalcIdParam())
4681 if (calcIdParam != null)
4683 if (recoverCalcIdParam(calcIdParam, af.viewport))
4688 warn("Couldn't recover parameters for "
4689 + calcIdParam.getCalcId());
4694 af.setMenusFromViewport(af.viewport);
4695 af.setTitle(view.getTitle());
4696 // TODO: we don't need to do this if the viewport is aready visible.
4698 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
4699 * has a 'cdna/protein complement' view, in which case save it in order to
4700 * populate a SplitFrame once all views have been read in.
4702 String complementaryViewId = view.getComplementId();
4703 if (complementaryViewId == null)
4705 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
4707 // recompute any autoannotation
4708 af.alignPanel.updateAnnotation(false, true);
4709 reorderAutoannotation(af, al, autoAlan);
4710 af.alignPanel.alignmentChanged();
4714 splitFrameCandidates.put(view, af);
4720 * Reads saved data to restore Colour by Annotation settings
4722 * @param viewAnnColour
4726 * @param checkGroupAnnColour
4729 private ColourSchemeI constructAnnotationColour(
4730 AnnotationColours viewAnnColour, AlignFrame af, AlignmentI al,
4731 JalviewModelSequence jms, boolean checkGroupAnnColour)
4733 boolean propagateAnnColour = false;
4734 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
4735 if (checkGroupAnnColour && al.getGroups() != null
4736 && al.getGroups().size() > 0)
4738 // pre 2.8.1 behaviour
4739 // check to see if we should transfer annotation colours
4740 propagateAnnColour = true;
4741 for (SequenceGroup sg : al.getGroups())
4743 if (sg.getColourScheme() instanceof AnnotationColourGradient)
4745 propagateAnnColour = false;
4751 * 2.10.2- : saved annotationId is AlignmentAnnotation.annotationId
4753 String annotationId = viewAnnColour.getAnnotation();
4754 AlignmentAnnotation matchedAnnotation = annotationIds.get(annotationId);
4757 * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
4759 if (matchedAnnotation == null
4760 && annAlignment.getAlignmentAnnotation() != null)
4762 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
4765 .equals(annAlignment.getAlignmentAnnotation()[i].label))
4767 matchedAnnotation = annAlignment.getAlignmentAnnotation()[i];
4772 if (matchedAnnotation == null)
4774 System.err.println("Failed to match annotation colour scheme for "
4778 if (matchedAnnotation.getThreshold() == null)
4780 matchedAnnotation.setThreshold(new GraphLine(
4781 viewAnnColour.getThreshold(), "Threshold", Color.black));
4784 AnnotationColourGradient cs = null;
4785 if (viewAnnColour.getColourScheme().equals("None"))
4787 cs = new AnnotationColourGradient(matchedAnnotation,
4788 new Color(viewAnnColour.getMinColour()),
4789 new Color(viewAnnColour.getMaxColour()),
4790 viewAnnColour.getAboveThreshold());
4792 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
4794 cs = new AnnotationColourGradient(matchedAnnotation,
4795 getUserColourScheme(jms, viewAnnColour.getColourScheme()),
4796 viewAnnColour.getAboveThreshold());
4800 cs = new AnnotationColourGradient(matchedAnnotation,
4801 ColourSchemeProperty.getColourScheme(al,
4802 viewAnnColour.getColourScheme()),
4803 viewAnnColour.getAboveThreshold());
4806 boolean perSequenceOnly = viewAnnColour.isPerSequence();
4807 boolean useOriginalColours = viewAnnColour.isPredefinedColours();
4808 cs.setSeqAssociated(perSequenceOnly);
4809 cs.setPredefinedColours(useOriginalColours);
4811 if (propagateAnnColour && al.getGroups() != null)
4813 // Also use these settings for all the groups
4814 for (int g = 0; g < al.getGroups().size(); g++)
4816 SequenceGroup sg = al.getGroups().get(g);
4817 if (sg.getGroupColourScheme() == null)
4822 AnnotationColourGradient groupScheme = new AnnotationColourGradient(
4823 matchedAnnotation, sg.getColourScheme(),
4824 viewAnnColour.getAboveThreshold());
4825 sg.setColourScheme(groupScheme);
4826 groupScheme.setSeqAssociated(perSequenceOnly);
4827 groupScheme.setPredefinedColours(useOriginalColours);
4833 private void reorderAutoannotation(AlignFrame af, AlignmentI al,
4834 List<JvAnnotRow> autoAlan)
4836 // copy over visualization settings for autocalculated annotation in the
4838 if (al.getAlignmentAnnotation() != null)
4841 * Kludge for magic autoannotation names (see JAL-811)
4843 String[] magicNames = new String[] { "Consensus", "Quality",
4845 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
4846 Hashtable<String, JvAnnotRow> visan = new Hashtable<>();
4847 for (String nm : magicNames)
4849 visan.put(nm, nullAnnot);
4851 for (JvAnnotRow auan : autoAlan)
4853 visan.put(auan.template.label
4854 + (auan.template.getCalcId() == null ? ""
4855 : "\t" + auan.template.getCalcId()),
4858 int hSize = al.getAlignmentAnnotation().length;
4859 List<JvAnnotRow> reorder = new ArrayList<>();
4860 // work through any autoCalculated annotation already on the view
4861 // removing it if it should be placed in a different location on the
4862 // annotation panel.
4863 List<String> remains = new ArrayList<>(visan.keySet());
4864 for (int h = 0; h < hSize; h++)
4866 jalview.datamodel.AlignmentAnnotation jalan = al
4867 .getAlignmentAnnotation()[h];
4868 if (jalan.autoCalculated)
4871 JvAnnotRow valan = visan.get(k = jalan.label);
4872 if (jalan.getCalcId() != null)
4874 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
4879 // delete the auto calculated row from the alignment
4880 al.deleteAnnotation(jalan, false);
4884 if (valan != nullAnnot)
4886 if (jalan != valan.template)
4888 // newly created autoannotation row instance
4889 // so keep a reference to the visible annotation row
4890 // and copy over all relevant attributes
4891 if (valan.template.graphHeight >= 0)
4894 jalan.graphHeight = valan.template.graphHeight;
4896 jalan.visible = valan.template.visible;
4898 reorder.add(new JvAnnotRow(valan.order, jalan));
4903 // Add any (possibly stale) autocalculated rows that were not appended to
4904 // the view during construction
4905 for (String other : remains)
4907 JvAnnotRow othera = visan.get(other);
4908 if (othera != nullAnnot && othera.template.getCalcId() != null
4909 && othera.template.getCalcId().length() > 0)
4911 reorder.add(othera);
4914 // now put the automatic annotation in its correct place
4915 int s = 0, srt[] = new int[reorder.size()];
4916 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
4917 for (JvAnnotRow jvar : reorder)
4920 srt[s++] = jvar.order;
4923 jalview.util.QuickSort.sort(srt, rws);
4924 // and re-insert the annotation at its correct position
4925 for (JvAnnotRow jvar : rws)
4927 al.addAnnotation(jvar.template, jvar.order);
4929 af.alignPanel.adjustAnnotationHeight();
4933 Hashtable skipList = null;
4936 * TODO remove this method
4939 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
4940 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
4941 * throw new Error("Implementation Error. No skipList defined for this
4942 * Jalview2XML instance."); } return (AlignFrame)
4943 * skipList.get(view.getSequenceSetId()); }
4947 * Check if the Jalview view contained in object should be skipped or not.
4950 * @return true if view's sequenceSetId is a key in skipList
4952 private boolean skipViewport(JalviewModel object)
4954 if (skipList == null)
4959 if (skipList.containsKey(
4960 id = object.getJalviewModelSequence().getViewport()[0]
4961 .getSequenceSetId()))
4963 if (Cache.log != null && Cache.log.isDebugEnabled())
4965 Cache.log.debug("Skipping seuqence set id " + id);
4972 public void addToSkipList(AlignFrame af)
4974 if (skipList == null)
4976 skipList = new Hashtable();
4978 skipList.put(af.getViewport().getSequenceSetId(), af);
4981 public void clearSkipList()
4983 if (skipList != null)
4990 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
4991 boolean ignoreUnrefed)
4993 jalview.datamodel.AlignmentI ds = getDatasetFor(
4994 vamsasSet.getDatasetId());
4995 Vector dseqs = null;
4998 // create a list of new dataset sequences
4999 dseqs = new Vector();
5001 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
5003 Sequence vamsasSeq = vamsasSet.getSequence(i);
5004 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
5006 // create a new dataset
5009 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
5010 dseqs.copyInto(dsseqs);
5011 ds = new jalview.datamodel.Alignment(dsseqs);
5012 debug("Created new dataset " + vamsasSet.getDatasetId()
5013 + " for alignment " + System.identityHashCode(al));
5014 addDatasetRef(vamsasSet.getDatasetId(), ds);
5016 // set the dataset for the newly imported alignment.
5017 if (al.getDataset() == null && !ignoreUnrefed)
5026 * sequence definition to create/merge dataset sequence for
5030 * vector to add new dataset sequence to
5031 * @param ignoreUnrefed
5032 * - when true, don't create new sequences from vamsasSeq if it's id
5033 * doesn't already have an asssociated Jalview sequence.
5035 * - used to reorder the sequence in the alignment according to the
5036 * vamsasSeq array ordering, to preserve ordering of dataset
5038 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
5039 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed, int vseqpos)
5041 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
5043 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
5044 boolean reorder = false;
5045 SequenceI dsq = null;
5046 if (sq != null && sq.getDatasetSequence() != null)
5048 dsq = sq.getDatasetSequence();
5054 if (sq == null && ignoreUnrefed)
5058 String sqid = vamsasSeq.getDsseqid();
5061 // need to create or add a new dataset sequence reference to this sequence
5064 dsq = seqRefIds.get(sqid);
5069 // make a new dataset sequence
5070 dsq = sq.createDatasetSequence();
5073 // make up a new dataset reference for this sequence
5074 sqid = seqHash(dsq);
5076 dsq.setVamsasId(uniqueSetSuffix + sqid);
5077 seqRefIds.put(sqid, dsq);
5082 dseqs.addElement(dsq);
5087 ds.addSequence(dsq);
5093 { // make this dataset sequence sq's dataset sequence
5094 sq.setDatasetSequence(dsq);
5095 // and update the current dataset alignment
5100 if (!dseqs.contains(dsq))
5107 if (ds.findIndex(dsq) < 0)
5109 ds.addSequence(dsq);
5116 // TODO: refactor this as a merge dataset sequence function
5117 // now check that sq (the dataset sequence) sequence really is the union of
5118 // all references to it
5119 // boolean pre = sq.getStart() < dsq.getStart();
5120 // boolean post = sq.getEnd() > dsq.getEnd();
5124 // StringBuffer sb = new StringBuffer();
5125 String newres = jalview.analysis.AlignSeq.extractGaps(
5126 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
5127 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
5128 && newres.length() > dsq.getLength())
5130 // Update with the longer sequence.
5134 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
5135 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
5136 * sb.append(newres.substring(newres.length() - sq.getEnd() -
5137 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
5139 dsq.setSequence(newres);
5141 // TODO: merges will never happen if we 'know' we have the real dataset
5142 // sequence - this should be detected when id==dssid
5144 "DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
5145 // + (pre ? "prepended" : "") + " "
5146 // + (post ? "appended" : ""));
5151 // sequence refs are identical. We may need to update the existing dataset
5152 // alignment with this one, though.
5153 if (ds != null && dseqs == null)
5155 int opos = ds.findIndex(dsq);
5156 SequenceI tseq = null;
5157 if (opos != -1 && vseqpos != opos)
5159 // remove from old position
5160 ds.deleteSequence(dsq);
5162 if (vseqpos < ds.getHeight())
5164 if (vseqpos != opos)
5166 // save sequence at destination position
5167 tseq = ds.getSequenceAt(vseqpos);
5168 ds.replaceSequenceAt(vseqpos, dsq);
5169 ds.addSequence(tseq);
5174 ds.addSequence(dsq);
5181 * TODO use AlignmentI here and in related methods - needs
5182 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
5184 Hashtable<String, AlignmentI> datasetIds = null;
5186 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
5188 private AlignmentI getDatasetFor(String datasetId)
5190 if (datasetIds == null)
5192 datasetIds = new Hashtable<>();
5195 if (datasetIds.containsKey(datasetId))
5197 return datasetIds.get(datasetId);
5202 private void addDatasetRef(String datasetId, AlignmentI dataset)
5204 if (datasetIds == null)
5206 datasetIds = new Hashtable<>();
5208 datasetIds.put(datasetId, dataset);
5212 * make a new dataset ID for this jalview dataset alignment
5217 private String getDatasetIdRef(AlignmentI dataset)
5219 if (dataset.getDataset() != null)
5221 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
5223 String datasetId = makeHashCode(dataset, null);
5224 if (datasetId == null)
5226 // make a new datasetId and record it
5227 if (dataset2Ids == null)
5229 dataset2Ids = new IdentityHashMap<>();
5233 datasetId = dataset2Ids.get(dataset);
5235 if (datasetId == null)
5237 datasetId = "ds" + dataset2Ids.size() + 1;
5238 dataset2Ids.put(dataset, datasetId);
5244 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5246 for (int d = 0; d < sequence.getDBRefCount(); d++)
5248 DBRef dr = sequence.getDBRef(d);
5249 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
5250 sequence.getDBRef(d).getSource(),
5251 sequence.getDBRef(d).getVersion(),
5252 sequence.getDBRef(d).getAccessionId());
5253 if (dr.getMapping() != null)
5255 entry.setMap(addMapping(dr.getMapping()));
5257 datasetSequence.addDBRef(entry);
5261 private jalview.datamodel.Mapping addMapping(Mapping m)
5263 SequenceI dsto = null;
5264 // Mapping m = dr.getMapping();
5265 int fr[] = new int[m.getMapListFromCount() * 2];
5266 Enumeration f = m.enumerateMapListFrom();
5267 for (int _i = 0; f.hasMoreElements(); _i += 2)
5269 MapListFrom mf = (MapListFrom) f.nextElement();
5270 fr[_i] = mf.getStart();
5271 fr[_i + 1] = mf.getEnd();
5273 int fto[] = new int[m.getMapListToCount() * 2];
5274 f = m.enumerateMapListTo();
5275 for (int _i = 0; f.hasMoreElements(); _i += 2)
5277 MapListTo mf = (MapListTo) f.nextElement();
5278 fto[_i] = mf.getStart();
5279 fto[_i + 1] = mf.getEnd();
5281 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto, fr,
5282 fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
5283 if (m.getMappingChoice() != null)
5285 MappingChoice mc = m.getMappingChoice();
5286 if (mc.getDseqFor() != null)
5288 String dsfor = "" + mc.getDseqFor();
5289 if (seqRefIds.containsKey(dsfor))
5294 jmap.setTo(seqRefIds.get(dsfor));
5298 frefedSequence.add(newMappingRef(dsfor, jmap));
5304 * local sequence definition
5306 Sequence ms = mc.getSequence();
5307 SequenceI djs = null;
5308 String sqid = ms.getDsseqid();
5309 if (sqid != null && sqid.length() > 0)
5312 * recover dataset sequence
5314 djs = seqRefIds.get(sqid);
5319 "Warning - making up dataset sequence id for DbRef sequence map reference");
5320 sqid = ((Object) ms).toString(); // make up a new hascode for
5321 // undefined dataset sequence hash
5322 // (unlikely to happen)
5328 * make a new dataset sequence and add it to refIds hash
5330 djs = new jalview.datamodel.Sequence(ms.getName(),
5332 djs.setStart(jmap.getMap().getToLowest());
5333 djs.setEnd(jmap.getMap().getToHighest());
5334 djs.setVamsasId(uniqueSetSuffix + sqid);
5336 incompleteSeqs.put(sqid, djs);
5337 seqRefIds.put(sqid, djs);
5340 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5349 public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
5350 boolean keepSeqRefs)
5353 JalviewModel jm = saveState(ap, null, null, null);
5358 jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
5362 uniqueSetSuffix = "";
5363 jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
5368 if (this.frefedSequence == null)
5370 frefedSequence = new Vector();
5373 viewportsAdded.clear();
5375 AlignFrame af = loadFromObject(jm, null, false, null);
5376 af.alignPanels.clear();
5377 af.closeMenuItem_actionPerformed(true);
5380 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5381 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5382 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5383 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5384 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5387 return af.alignPanel;
5391 * flag indicating if hashtables should be cleared on finalization TODO this
5392 * flag may not be necessary
5394 private final boolean _cleartables = true;
5396 private Hashtable jvids2vobj;
5401 * @see java.lang.Object#finalize()
5404 protected void finalize() throws Throwable
5406 // really make sure we have no buried refs left.
5411 this.seqRefIds = null;
5412 this.seqsToIds = null;
5416 private void warn(String msg)
5421 private void warn(String msg, Exception e)
5423 if (Cache.log != null)
5427 Cache.log.warn(msg, e);
5431 Cache.log.warn(msg);
5436 System.err.println("Warning: " + msg);
5439 e.printStackTrace();
5444 private void debug(String string)
5446 debug(string, null);
5449 private void debug(String msg, Exception e)
5451 if (Cache.log != null)
5455 Cache.log.debug(msg, e);
5459 Cache.log.debug(msg);
5464 System.err.println("Warning: " + msg);
5467 e.printStackTrace();
5473 * set the object to ID mapping tables used to write/recover objects and XML
5474 * ID strings for the jalview project. If external tables are provided then
5475 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
5476 * object goes out of scope. - also populates the datasetIds hashtable with
5477 * alignment objects containing dataset sequences
5480 * Map from ID strings to jalview datamodel
5482 * Map from jalview datamodel to ID strings
5486 public void setObjectMappingTables(Hashtable vobj2jv,
5487 IdentityHashMap jv2vobj)
5489 this.jv2vobj = jv2vobj;
5490 this.vobj2jv = vobj2jv;
5491 Iterator ds = jv2vobj.keySet().iterator();
5493 while (ds.hasNext())
5495 Object jvobj = ds.next();
5496 id = jv2vobj.get(jvobj).toString();
5497 if (jvobj instanceof jalview.datamodel.Alignment)
5499 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
5501 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
5504 else if (jvobj instanceof jalview.datamodel.Sequence)
5506 // register sequence object so the XML parser can recover it.
5507 if (seqRefIds == null)
5509 seqRefIds = new HashMap<>();
5511 if (seqsToIds == null)
5513 seqsToIds = new IdentityHashMap<>();
5515 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
5516 seqsToIds.put((SequenceI) jvobj, id);
5518 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
5521 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
5522 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
5523 if (jvann.annotationId == null)
5525 jvann.annotationId = anid;
5527 if (!jvann.annotationId.equals(anid))
5529 // TODO verify that this is the correct behaviour
5530 this.warn("Overriding Annotation ID for " + anid
5531 + " from different id : " + jvann.annotationId);
5532 jvann.annotationId = anid;
5535 else if (jvobj instanceof String)
5537 if (jvids2vobj == null)
5539 jvids2vobj = new Hashtable();
5540 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
5545 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
5551 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
5552 * objects created from the project archive. If string is null (default for
5553 * construction) then suffix will be set automatically.
5557 public void setUniqueSetSuffix(String string)
5559 uniqueSetSuffix = string;
5564 * uses skipList2 as the skipList for skipping views on sequence sets
5565 * associated with keys in the skipList
5569 public void setSkipList(Hashtable skipList2)
5571 skipList = skipList2;
5575 * Reads the jar entry of given name and returns its contents, or null if the
5576 * entry is not found.
5579 * @param jarEntryName
5582 protected String readJarEntry(jarInputStreamProvider jprovider,
5583 String jarEntryName)
5585 String result = null;
5586 BufferedReader in = null;
5591 * Reopen the jar input stream and traverse its entries to find a matching
5594 JarInputStream jin = jprovider.getJarInputStream();
5595 JarEntry entry = null;
5598 entry = jin.getNextJarEntry();
5599 } while (entry != null && !entry.getName().equals(jarEntryName));
5603 StringBuilder out = new StringBuilder(256);
5604 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
5607 while ((data = in.readLine()) != null)
5611 result = out.toString();
5615 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
5617 } catch (Exception ex)
5619 ex.printStackTrace();
5627 } catch (IOException e)
5638 * Returns an incrementing counter (0, 1, 2...)
5642 private synchronized int nextCounter()