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.api.FeatureColourI;
24 import jalview.api.ViewStyleI;
25 import jalview.api.structures.JalviewStructureDisplayI;
26 import jalview.bin.Cache;
27 import jalview.datamodel.AlignedCodonFrame;
28 import jalview.datamodel.Alignment;
29 import jalview.datamodel.AlignmentAnnotation;
30 import jalview.datamodel.AlignmentI;
31 import jalview.datamodel.PDBEntry;
32 import jalview.datamodel.RnaViewerModel;
33 import jalview.datamodel.SequenceGroup;
34 import jalview.datamodel.SequenceI;
35 import jalview.datamodel.StructureViewerModel;
36 import jalview.datamodel.StructureViewerModel.StructureData;
37 import jalview.ext.varna.RnaModel;
38 import jalview.gui.StructureViewer.ViewerType;
39 import jalview.schemabinding.version2.AlcodMap;
40 import jalview.schemabinding.version2.AlcodonFrame;
41 import jalview.schemabinding.version2.Annotation;
42 import jalview.schemabinding.version2.AnnotationColours;
43 import jalview.schemabinding.version2.AnnotationElement;
44 import jalview.schemabinding.version2.CalcIdParam;
45 import jalview.schemabinding.version2.DBRef;
46 import jalview.schemabinding.version2.Features;
47 import jalview.schemabinding.version2.Group;
48 import jalview.schemabinding.version2.HiddenColumns;
49 import jalview.schemabinding.version2.JGroup;
50 import jalview.schemabinding.version2.JSeq;
51 import jalview.schemabinding.version2.JalviewModel;
52 import jalview.schemabinding.version2.JalviewModelSequence;
53 import jalview.schemabinding.version2.MapListFrom;
54 import jalview.schemabinding.version2.MapListTo;
55 import jalview.schemabinding.version2.Mapping;
56 import jalview.schemabinding.version2.MappingChoice;
57 import jalview.schemabinding.version2.OtherData;
58 import jalview.schemabinding.version2.PdbentryItem;
59 import jalview.schemabinding.version2.Pdbids;
60 import jalview.schemabinding.version2.Property;
61 import jalview.schemabinding.version2.RnaViewer;
62 import jalview.schemabinding.version2.SecondaryStructure;
63 import jalview.schemabinding.version2.Sequence;
64 import jalview.schemabinding.version2.SequenceSet;
65 import jalview.schemabinding.version2.SequenceSetProperties;
66 import jalview.schemabinding.version2.Setting;
67 import jalview.schemabinding.version2.StructureState;
68 import jalview.schemabinding.version2.ThresholdLine;
69 import jalview.schemabinding.version2.Tree;
70 import jalview.schemabinding.version2.UserColours;
71 import jalview.schemabinding.version2.Viewport;
72 import jalview.schemes.AnnotationColourGradient;
73 import jalview.schemes.ColourSchemeI;
74 import jalview.schemes.ColourSchemeProperty;
75 import jalview.schemes.FeatureColour;
76 import jalview.schemes.ResidueColourScheme;
77 import jalview.schemes.ResidueProperties;
78 import jalview.schemes.UserColourScheme;
79 import jalview.structure.StructureSelectionManager;
80 import jalview.structures.models.AAStructureBindingModel;
81 import jalview.util.MessageManager;
82 import jalview.util.Platform;
83 import jalview.util.StringUtils;
84 import jalview.util.jarInputStreamProvider;
85 import jalview.viewmodel.AlignmentViewport;
86 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
87 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
88 import jalview.ws.jws2.Jws2Discoverer;
89 import jalview.ws.jws2.dm.AAConSettings;
90 import jalview.ws.jws2.jabaws2.Jws2Instance;
91 import jalview.ws.params.ArgumentI;
92 import jalview.ws.params.AutoCalcSetting;
93 import jalview.ws.params.WsParamSetI;
95 import java.awt.Color;
96 import java.awt.Rectangle;
97 import java.io.BufferedReader;
98 import java.io.DataInputStream;
99 import java.io.DataOutputStream;
101 import java.io.FileInputStream;
102 import java.io.FileOutputStream;
103 import java.io.IOException;
104 import java.io.InputStreamReader;
105 import java.io.OutputStreamWriter;
106 import java.io.PrintWriter;
107 import java.lang.reflect.InvocationTargetException;
108 import java.net.MalformedURLException;
110 import java.util.ArrayList;
111 import java.util.Enumeration;
112 import java.util.HashMap;
113 import java.util.HashSet;
114 import java.util.Hashtable;
115 import java.util.IdentityHashMap;
116 import java.util.Iterator;
117 import java.util.LinkedHashMap;
118 import java.util.List;
119 import java.util.Map;
120 import java.util.Map.Entry;
121 import java.util.Set;
122 import java.util.Vector;
123 import java.util.jar.JarEntry;
124 import java.util.jar.JarInputStream;
125 import java.util.jar.JarOutputStream;
127 import javax.swing.JInternalFrame;
128 import javax.swing.JOptionPane;
129 import javax.swing.SwingUtilities;
131 import org.exolab.castor.xml.Marshaller;
132 import org.exolab.castor.xml.Unmarshaller;
135 * Write out the current jalview desktop state as a Jalview XML stream.
137 * Note: the vamsas objects referred to here are primitive versions of the
138 * VAMSAS project schema elements - they are not the same and most likely never
142 * @version $Revision: 1.134 $
144 public class Jalview2XML
146 private static final String VIEWER_PREFIX = "viewer_";
148 private static final String RNA_PREFIX = "rna_";
150 private static final String UTF_8 = "UTF-8";
152 // use this with nextCounter() to make unique names for entities
153 private int counter = 0;
156 * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
157 * of sequence objects are created.
159 IdentityHashMap<SequenceI, String> seqsToIds = null;
162 * jalview XML Sequence ID to jalview sequence object reference (both dataset
163 * and alignment sequences. Populated as XML reps of sequence objects are
166 Map<String, SequenceI> seqRefIds = null;
168 List<SeqFref> frefedSequence = null;
170 boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
173 * Map of reconstructed AlignFrame objects that appear to have come from
174 * SplitFrame objects (have a dna/protein complement view).
176 private Map<Viewport, AlignFrame> splitFrameCandidates = new HashMap<Viewport, AlignFrame>();
179 * Map from displayed rna structure models to their saved session state jar
182 private Map<RnaModel, String> rnaSessions = new HashMap<RnaModel, String>();
185 * create/return unique hash string for sq
188 * @return new or existing unique string for sq
190 String seqHash(SequenceI sq)
192 if (seqsToIds == null)
196 if (seqsToIds.containsKey(sq))
198 return seqsToIds.get(sq);
202 // create sequential key
203 String key = "sq" + (seqsToIds.size() + 1);
204 key = makeHashCode(sq, key); // check we don't have an external reference
206 seqsToIds.put(sq, key);
215 if (seqRefIds != null)
219 if (seqsToIds != null)
229 warn("clearSeqRefs called when _cleartables was not set. Doing nothing.");
230 // seqRefIds = new Hashtable();
231 // seqsToIds = new IdentityHashMap();
237 if (seqsToIds == null)
239 seqsToIds = new IdentityHashMap<SequenceI, String>();
241 if (seqRefIds == null)
243 seqRefIds = new HashMap<String, SequenceI>();
245 if (frefedSequence == null)
247 frefedSequence = new ArrayList<SeqFref>();
255 public Jalview2XML(boolean raiseGUI)
257 this.raiseGUI = raiseGUI;
261 * base class for resolving forward references to sequences by their ID
266 abstract class SeqFref
270 public SeqFref(String _sref)
275 public String getSref()
280 public SequenceI getSrefSeq()
282 return seqRefIds.get(sref);
285 public boolean isResolvable()
287 return seqRefIds.get(sref) != null;
290 public SequenceI getSrefDatasetSeq()
292 SequenceI sq = seqRefIds.get(sref);
295 while (sq.getDatasetSequence() != null)
297 sq = sq.getDatasetSequence();
303 * @return true if the forward reference was fully resolved
305 abstract boolean resolve();
309 * create forward reference for a mapping
315 public SeqFref newMappingRef(final String sref,
316 final jalview.datamodel.Mapping _jmap)
318 SeqFref fref = new SeqFref(sref)
320 public jalview.datamodel.Mapping jmap = _jmap;
325 SequenceI seq = getSrefDatasetSeq();
337 public SeqFref newAlcodMapRef(final String sref,
338 final AlignedCodonFrame _cf, final jalview.datamodel.Mapping _jmap)
341 SeqFref fref = new SeqFref(sref)
343 AlignedCodonFrame cf = _cf;
345 public jalview.datamodel.Mapping mp = _jmap;
350 SequenceI seq = getSrefDatasetSeq();
355 cf.addMap(seq, mp.getTo(), mp.getMap());
362 public void resolveFrefedSequences()
364 Iterator<SeqFref> nextFref=frefedSequence.iterator();
365 int toresolve=frefedSequence.size();
366 int unresolved=0,failedtoresolve=0;
367 while (nextFref.hasNext()) {
368 SeqFref ref = nextFref.next();
369 if (ref.isResolvable())
378 } catch (Exception x) {
379 System.err.println("IMPLEMENTATION ERROR: Failed to resolve forward reference for sequence "+ref.getSref());
389 System.err.println("There were "+unresolved+" forward references left unresolved on the stack.");
391 if (failedtoresolve>0)
393 System.err.println("SERIOUS! " + failedtoresolve
394 + " resolvable forward references failed to resolve.");
399 * This maintains a map of viewports, the key being the seqSetId. Important to
400 * set historyItem and redoList for multiple views
402 Map<String, AlignViewport> viewportsAdded = new HashMap<String, AlignViewport>();
404 Map<String, AlignmentAnnotation> annotationIds = new HashMap<String, AlignmentAnnotation>();
406 String uniqueSetSuffix = "";
409 * List of pdbfiles added to Jar
411 List<String> pdbfiles = null;
413 // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
414 public void saveState(File statefile)
416 FileOutputStream fos = null;
419 fos = new FileOutputStream(statefile);
420 JarOutputStream jout = new JarOutputStream(fos);
423 } catch (Exception e)
425 // TODO: inform user of the problem - they need to know if their data was
427 if (errorMessage == null)
429 errorMessage = "Couldn't write Jalview Archive to output file '"
430 + statefile + "' - See console error log for details";
434 errorMessage += "(output file was '" + statefile + "')";
444 } catch (IOException e)
454 * Writes a jalview project archive to the given Jar output stream.
458 public void saveState(JarOutputStream jout)
460 AlignFrame[] frames = Desktop.getAlignFrames();
467 Hashtable<String, AlignFrame> dsses = new Hashtable<String, AlignFrame>();
470 * ensure cached data is clear before starting
472 // todo tidy up seqRefIds, seqsToIds initialisation / reset
474 splitFrameCandidates.clear();
479 // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
480 // //////////////////////////////////////////////////
482 List<String> shortNames = new ArrayList<String>();
483 List<String> viewIds = new ArrayList<String>();
486 for (int i = frames.length - 1; i > -1; i--)
488 AlignFrame af = frames[i];
492 .containsKey(af.getViewport().getSequenceSetId()))
497 String shortName = makeFilename(af, shortNames);
499 int ap, apSize = af.alignPanels.size();
501 for (ap = 0; ap < apSize; ap++)
503 AlignmentPanel apanel = af.alignPanels.get(ap);
504 String fileName = apSize == 1 ? shortName : ap + shortName;
505 if (!fileName.endsWith(".xml"))
507 fileName = fileName + ".xml";
510 saveState(apanel, fileName, jout, viewIds);
512 String dssid = getDatasetIdRef(af.getViewport().getAlignment()
514 if (!dsses.containsKey(dssid))
516 dsses.put(dssid, af);
521 writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix,
527 } catch (Exception foo)
532 } catch (Exception ex)
534 // TODO: inform user of the problem - they need to know if their data was
536 if (errorMessage == null)
538 errorMessage = "Couldn't write Jalview Archive - see error output for details";
540 ex.printStackTrace();
545 * Generates a distinct file name, based on the title of the AlignFrame, by
546 * appending _n for increasing n until an unused name is generated. The new
547 * name (without its extension) is added to the list.
551 * @return the generated name, with .xml extension
553 protected String makeFilename(AlignFrame af, List<String> namesUsed)
555 String shortName = af.getTitle();
557 if (shortName.indexOf(File.separatorChar) > -1)
559 shortName = shortName.substring(shortName
560 .lastIndexOf(File.separatorChar) + 1);
565 while (namesUsed.contains(shortName))
567 if (shortName.endsWith("_" + (count - 1)))
569 shortName = shortName.substring(0, shortName.lastIndexOf("_"));
572 shortName = shortName.concat("_" + count);
576 namesUsed.add(shortName);
578 if (!shortName.endsWith(".xml"))
580 shortName = shortName + ".xml";
585 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
586 public boolean saveAlignment(AlignFrame af, String jarFile,
592 int apSize = af.alignPanels.size();
593 FileOutputStream fos = new FileOutputStream(jarFile);
594 JarOutputStream jout = new JarOutputStream(fos);
595 Hashtable<String, AlignFrame> dsses = new Hashtable<String, AlignFrame>();
596 List<String> viewIds = new ArrayList<String>();
598 for (AlignmentPanel apanel : af.alignPanels)
600 String jfileName = apSize == 1 ? fileName : fileName + ap;
602 if (!jfileName.endsWith(".xml"))
604 jfileName = jfileName + ".xml";
606 saveState(apanel, jfileName, jout, viewIds);
607 String dssid = getDatasetIdRef(af.getViewport().getAlignment()
609 if (!dsses.containsKey(dssid))
611 dsses.put(dssid, af);
614 writeDatasetFor(dsses, fileName, jout);
618 } catch (Exception foo)
624 } catch (Exception ex)
626 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
627 ex.printStackTrace();
632 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
633 String fileName, JarOutputStream jout)
636 for (String dssids : dsses.keySet())
638 AlignFrame _af = dsses.get(dssids);
639 String jfileName = fileName + " Dataset for " + _af.getTitle();
640 if (!jfileName.endsWith(".xml"))
642 jfileName = jfileName + ".xml";
644 saveState(_af.alignPanel, jfileName, true, jout, null);
649 * create a JalviewModel from an alignment view and marshall it to a
653 * panel to create jalview model for
655 * name of alignment panel written to output stream
662 public JalviewModel saveState(AlignmentPanel ap, String fileName,
663 JarOutputStream jout, List<String> viewIds)
665 return saveState(ap, fileName, false, jout, viewIds);
669 * create a JalviewModel from an alignment view and marshall it to a
673 * panel to create jalview model for
675 * name of alignment panel written to output stream
677 * when true, only write the dataset for the alignment, not the data
678 * associated with the view.
684 public JalviewModel saveState(AlignmentPanel ap, String fileName,
685 boolean storeDS, JarOutputStream jout, List<String> viewIds)
689 viewIds = new ArrayList<String>();
694 List<UserColourScheme> userColours = new ArrayList<UserColourScheme>();
696 AlignViewport av = ap.av;
698 JalviewModel object = new JalviewModel();
699 object.setVamsasModel(new jalview.schemabinding.version2.VamsasModel());
701 object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
702 object.setVersion(jalview.bin.Cache.getDefault("VERSION",
703 "Development Build"));
706 * rjal is full height alignment, jal is actual alignment with full metadata
707 * but excludes hidden sequences.
709 jalview.datamodel.AlignmentI rjal = av.getAlignment(), jal = rjal;
711 if (av.hasHiddenRows())
713 rjal = jal.getHiddenSequences().getFullAlignment();
716 SequenceSet vamsasSet = new SequenceSet();
718 JalviewModelSequence jms = new JalviewModelSequence();
720 vamsasSet.setGapChar(jal.getGapCharacter() + "");
722 if (jal.getDataset() != null)
724 // dataset id is the dataset's hashcode
725 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
728 // switch jal and the dataset
729 jal = jal.getDataset();
733 if (jal.getProperties() != null)
735 Enumeration en = jal.getProperties().keys();
736 while (en.hasMoreElements())
738 String key = en.nextElement().toString();
739 SequenceSetProperties ssp = new SequenceSetProperties();
741 ssp.setValue(jal.getProperties().get(key).toString());
742 vamsasSet.addSequenceSetProperties(ssp);
747 Set<String> calcIdSet = new HashSet<String>();
750 for (final SequenceI jds : rjal.getSequences())
752 final SequenceI jdatasq = jds.getDatasetSequence() == null ? jds
753 : jds.getDatasetSequence();
754 String id = seqHash(jds);
756 if (seqRefIds.get(id) != null)
758 // This happens for two reasons: 1. multiple views are being serialised.
759 // 2. the hashCode has collided with another sequence's code. This DOES
760 // HAPPEN! (PF00072.15.stk does this)
761 // JBPNote: Uncomment to debug writing out of files that do not read
762 // back in due to ArrayOutOfBoundExceptions.
763 // System.err.println("vamsasSeq backref: "+id+"");
764 // System.err.println(jds.getName()+"
765 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
766 // System.err.println("Hashcode: "+seqHash(jds));
767 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
768 // System.err.println(rsq.getName()+"
769 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
770 // System.err.println("Hashcode: "+seqHash(rsq));
774 vamsasSeq = createVamsasSequence(id, jds);
775 vamsasSet.addSequence(vamsasSeq);
776 seqRefIds.put(id, jds);
780 jseq.setStart(jds.getStart());
781 jseq.setEnd(jds.getEnd());
782 jseq.setColour(av.getSequenceColour(jds).getRGB());
784 jseq.setId(id); // jseq id should be a string not a number
787 // Store any sequences this sequence represents
788 if (av.hasHiddenRows())
790 // use rjal, contains the full height alignment
791 jseq.setHidden(av.getAlignment().getHiddenSequences()
794 if (av.isHiddenRepSequence(jds))
796 jalview.datamodel.SequenceI[] reps = av
797 .getRepresentedSequences(jds)
798 .getSequencesInOrder(rjal);
800 for (int h = 0; h < reps.length; h++)
804 jseq.addHiddenSequences(rjal.findIndex(reps[h]));
809 // mark sequence as reference - if it is the reference for this view
812 jseq.setViewreference(jds == jal.getSeqrep());
816 // TODO: omit sequence features from each alignment view's XML dump if we
817 // are storing dataset
818 if (jds.getSequenceFeatures() != null)
820 jalview.datamodel.SequenceFeature[] sf = jds.getSequenceFeatures();
822 while (index < sf.length)
824 Features features = new Features();
826 features.setBegin(sf[index].getBegin());
827 features.setEnd(sf[index].getEnd());
828 features.setDescription(sf[index].getDescription());
829 features.setType(sf[index].getType());
830 features.setFeatureGroup(sf[index].getFeatureGroup());
831 features.setScore(sf[index].getScore());
832 if (sf[index].links != null)
834 for (int l = 0; l < sf[index].links.size(); l++)
836 OtherData keyValue = new OtherData();
837 keyValue.setKey("LINK_" + l);
838 keyValue.setValue(sf[index].links.elementAt(l).toString());
839 features.addOtherData(keyValue);
842 if (sf[index].otherDetails != null)
845 Iterator<String> keys = sf[index].otherDetails.keySet()
847 while (keys.hasNext())
850 OtherData keyValue = new OtherData();
851 keyValue.setKey(key);
852 keyValue.setValue(sf[index].otherDetails.get(key).toString());
853 features.addOtherData(keyValue);
857 jseq.addFeatures(features);
862 if (jdatasq.getAllPDBEntries() != null)
864 Enumeration en = jdatasq.getAllPDBEntries().elements();
865 while (en.hasMoreElements())
867 Pdbids pdb = new Pdbids();
868 jalview.datamodel.PDBEntry entry = (jalview.datamodel.PDBEntry) en
871 String pdbId = entry.getId();
873 pdb.setType(entry.getType());
876 * Store any structure views associated with this sequence. This
877 * section copes with duplicate entries in the project, so a dataset
878 * only view *should* be coped with sensibly.
880 // This must have been loaded, is it still visible?
881 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
882 String matchedFile = null;
883 for (int f = frames.length - 1; f > -1; f--)
885 if (frames[f] instanceof StructureViewerBase)
887 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
888 matchedFile = saveStructureState(ap, jds, pdb, entry,
889 viewIds, matchedFile, viewFrame);
891 * Only store each structure viewer's state once in the project
892 * jar. First time through only (storeDS==false)
894 String viewId = viewFrame.getViewId();
895 if (!storeDS && !viewIds.contains(viewId))
900 String viewerState = viewFrame.getStateInfo();
901 writeJarEntry(jout, getViewerJarEntryName(viewId),
902 viewerState.getBytes());
903 } catch (IOException e)
905 System.err.println("Error saving viewer state: "
912 if (matchedFile != null || entry.getFile() != null)
914 if (entry.getFile() != null)
917 matchedFile = entry.getFile();
919 pdb.setFile(matchedFile); // entry.getFile());
920 if (pdbfiles == null)
922 pdbfiles = new ArrayList<String>();
925 if (!pdbfiles.contains(pdbId))
928 copyFileToJar(jout, matchedFile, pdbId);
932 if (entry.getProperty() != null && !entry.getProperty().isEmpty())
934 PdbentryItem item = new PdbentryItem();
935 Hashtable properties = entry.getProperty();
936 Enumeration en2 = properties.keys();
937 while (en2.hasMoreElements())
939 Property prop = new Property();
940 String key = en2.nextElement().toString();
942 prop.setValue(properties.get(key).toString());
943 item.addProperty(prop);
945 pdb.addPdbentryItem(item);
952 saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
957 if (!storeDS && av.hasHiddenRows())
959 jal = av.getAlignment();
962 if (jal.getCodonFrames() != null)
964 List<AlignedCodonFrame> jac = jal.getCodonFrames();
965 for (AlignedCodonFrame acf : jac)
967 AlcodonFrame alc = new AlcodonFrame();
968 if (acf.getProtMappings() != null
969 && acf.getProtMappings().length > 0)
971 boolean hasMap = false;
972 SequenceI[] dnas = acf.getdnaSeqs();
973 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
974 for (int m = 0; m < pmaps.length; m++)
976 AlcodMap alcmap = new AlcodMap();
977 alcmap.setDnasq(seqHash(dnas[m]));
978 alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
980 alc.addAlcodMap(alcmap);
985 vamsasSet.addAlcodonFrame(alc);
988 // TODO: delete this ? dead code from 2.8.3->2.9 ?
990 // AlcodonFrame alc = new AlcodonFrame();
991 // vamsasSet.addAlcodonFrame(alc);
992 // for (int p = 0; p < acf.aaWidth; p++)
994 // Alcodon cmap = new Alcodon();
995 // if (acf.codons[p] != null)
997 // // Null codons indicate a gapped column in the translated peptide
999 // cmap.setPos1(acf.codons[p][0]);
1000 // cmap.setPos2(acf.codons[p][1]);
1001 // cmap.setPos3(acf.codons[p][2]);
1003 // alc.addAlcodon(cmap);
1005 // if (acf.getProtMappings() != null
1006 // && acf.getProtMappings().length > 0)
1008 // SequenceI[] dnas = acf.getdnaSeqs();
1009 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
1010 // for (int m = 0; m < pmaps.length; m++)
1012 // AlcodMap alcmap = new AlcodMap();
1013 // alcmap.setDnasq(seqHash(dnas[m]));
1014 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
1016 // alc.addAlcodMap(alcmap);
1023 // /////////////////////////////////
1024 if (!storeDS && av.currentTree != null)
1026 // FIND ANY ASSOCIATED TREES
1027 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
1028 if (Desktop.desktop != null)
1030 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1032 for (int t = 0; t < frames.length; t++)
1034 if (frames[t] instanceof TreePanel)
1036 TreePanel tp = (TreePanel) frames[t];
1038 if (tp.treeCanvas.av.getAlignment() == jal)
1040 Tree tree = new Tree();
1041 tree.setTitle(tp.getTitle());
1042 tree.setCurrentTree((av.currentTree == tp.getTree()));
1043 tree.setNewick(tp.getTree().toString());
1044 tree.setThreshold(tp.treeCanvas.threshold);
1046 tree.setFitToWindow(tp.fitToWindow.getState());
1047 tree.setFontName(tp.getTreeFont().getName());
1048 tree.setFontSize(tp.getTreeFont().getSize());
1049 tree.setFontStyle(tp.getTreeFont().getStyle());
1050 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
1052 tree.setShowBootstrap(tp.bootstrapMenu.getState());
1053 tree.setShowDistances(tp.distanceMenu.getState());
1055 tree.setHeight(tp.getHeight());
1056 tree.setWidth(tp.getWidth());
1057 tree.setXpos(tp.getX());
1058 tree.setYpos(tp.getY());
1059 tree.setId(makeHashCode(tp, null));
1069 * store forward refs from an annotationRow to any groups
1071 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<SequenceGroup, String>();
1074 for (SequenceI sq : jal.getSequences())
1076 // Store annotation on dataset sequences only
1077 AlignmentAnnotation[] aa = sq.getAnnotation();
1078 if (aa != null && aa.length > 0)
1080 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1087 if (jal.getAlignmentAnnotation() != null)
1089 // Store the annotation shown on the alignment.
1090 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1091 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1096 if (jal.getGroups() != null)
1098 JGroup[] groups = new JGroup[jal.getGroups().size()];
1100 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1102 JGroup jGroup = new JGroup();
1103 groups[++i] = jGroup;
1105 jGroup.setStart(sg.getStartRes());
1106 jGroup.setEnd(sg.getEndRes());
1107 jGroup.setName(sg.getName());
1108 if (groupRefs.containsKey(sg))
1110 // group has references so set its ID field
1111 jGroup.setId(groupRefs.get(sg));
1115 if (sg.cs.conservationApplied())
1117 jGroup.setConsThreshold(sg.cs.getConservationInc());
1119 if (sg.cs instanceof jalview.schemes.UserColourScheme)
1121 jGroup.setColour(setUserColourScheme(sg.cs, userColours, jms));
1125 jGroup.setColour(ColourSchemeProperty.getColourName(sg.cs));
1128 else if (sg.cs instanceof jalview.schemes.AnnotationColourGradient)
1130 jGroup.setColour("AnnotationColourGradient");
1131 jGroup.setAnnotationColours(constructAnnotationColours(
1132 (jalview.schemes.AnnotationColourGradient) sg.cs,
1135 else if (sg.cs instanceof jalview.schemes.UserColourScheme)
1137 jGroup.setColour(setUserColourScheme(sg.cs, userColours, jms));
1141 jGroup.setColour(ColourSchemeProperty.getColourName(sg.cs));
1144 jGroup.setPidThreshold(sg.cs.getThreshold());
1147 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1148 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1149 jGroup.setDisplayText(sg.getDisplayText());
1150 jGroup.setColourText(sg.getColourText());
1151 jGroup.setTextCol1(sg.textColour.getRGB());
1152 jGroup.setTextCol2(sg.textColour2.getRGB());
1153 jGroup.setTextColThreshold(sg.thresholdTextColour);
1154 jGroup.setShowUnconserved(sg.getShowNonconserved());
1155 jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1156 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1157 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1158 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1159 for (SequenceI seq : sg.getSequences())
1161 jGroup.addSeq(seqHash(seq));
1165 jms.setJGroup(groups);
1169 // /////////SAVE VIEWPORT
1170 Viewport view = new Viewport();
1171 view.setTitle(ap.alignFrame.getTitle());
1172 view.setSequenceSetId(makeHashCode(av.getSequenceSetId(),
1173 av.getSequenceSetId()));
1174 view.setId(av.getViewId());
1175 if (av.getCodingComplement() != null)
1177 view.setComplementId(av.getCodingComplement().getViewId());
1179 view.setViewName(av.viewName);
1180 view.setGatheredViews(av.isGatherViewsHere());
1182 Rectangle size = ap.av.getExplodedGeometry();
1183 Rectangle position = size;
1186 size = ap.alignFrame.getBounds();
1187 if (av.getCodingComplement() != null)
1189 position = ((SplitFrame) ap.alignFrame.getSplitViewContainer())
1197 view.setXpos(position.x);
1198 view.setYpos(position.y);
1200 view.setWidth(size.width);
1201 view.setHeight(size.height);
1203 view.setStartRes(av.startRes);
1204 view.setStartSeq(av.startSeq);
1206 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1208 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1211 else if (av.getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1213 AnnotationColours ac = constructAnnotationColours(
1214 (jalview.schemes.AnnotationColourGradient) av
1215 .getGlobalColourScheme(),
1218 view.setAnnotationColours(ac);
1219 view.setBgColour("AnnotationColourGradient");
1223 view.setBgColour(ColourSchemeProperty.getColourName(av
1224 .getGlobalColourScheme()));
1227 ColourSchemeI cs = av.getGlobalColourScheme();
1231 if (cs.conservationApplied())
1233 view.setConsThreshold(cs.getConservationInc());
1234 if (cs instanceof jalview.schemes.UserColourScheme)
1236 view.setBgColour(setUserColourScheme(cs, userColours, jms));
1240 if (cs instanceof ResidueColourScheme)
1242 view.setPidThreshold(cs.getThreshold());
1246 view.setConservationSelected(av.getConservationSelected());
1247 view.setPidSelected(av.getAbovePIDThreshold());
1248 view.setFontName(av.font.getName());
1249 view.setFontSize(av.font.getSize());
1250 view.setFontStyle(av.font.getStyle());
1251 view.setScaleProteinAsCdna(av.getViewStyle().isScaleProteinAsCdna());
1252 view.setRenderGaps(av.isRenderGaps());
1253 view.setShowAnnotation(av.isShowAnnotation());
1254 view.setShowBoxes(av.getShowBoxes());
1255 view.setShowColourText(av.getColourText());
1256 view.setShowFullId(av.getShowJVSuffix());
1257 view.setRightAlignIds(av.isRightAlignIds());
1258 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1259 view.setShowText(av.getShowText());
1260 view.setShowUnconserved(av.getShowUnconserved());
1261 view.setWrapAlignment(av.getWrapAlignment());
1262 view.setTextCol1(av.getTextColour().getRGB());
1263 view.setTextCol2(av.getTextColour2().getRGB());
1264 view.setTextColThreshold(av.getThresholdTextColour());
1265 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1266 view.setShowSequenceLogo(av.isShowSequenceLogo());
1267 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1268 view.setShowGroupConsensus(av.isShowGroupConsensus());
1269 view.setShowGroupConservation(av.isShowGroupConservation());
1270 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1271 view.setShowDbRefTooltip(av.isShowDBRefs());
1272 view.setFollowHighlight(av.isFollowHighlight());
1273 view.setFollowSelection(av.followSelection);
1274 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1275 if (av.getFeaturesDisplayed() != null)
1277 jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
1279 String[] renderOrder = ap.getSeqPanel().seqCanvas
1280 .getFeatureRenderer().getRenderOrder()
1281 .toArray(new String[0]);
1283 Vector<String> settingsAdded = new Vector<String>();
1284 if (renderOrder != null)
1286 for (String featureType : renderOrder)
1288 FeatureColourI fcol = ap.getSeqPanel().seqCanvas
1289 .getFeatureRenderer()
1290 .getFeatureStyle(featureType);
1291 Setting setting = new Setting();
1292 setting.setType(featureType);
1293 if (!fcol.isSimpleColour())
1295 setting.setColour(fcol.getMaxColour().getRGB());
1296 setting.setMincolour(fcol.getMinColour().getRGB());
1297 setting.setMin(fcol.getMin());
1298 setting.setMax(fcol.getMax());
1299 setting.setColourByLabel(fcol.isColourByLabel());
1300 setting.setAutoScale(fcol.isAutoScaled());
1301 setting.setThreshold(fcol.getThreshold());
1302 // -1 = No threshold, 0 = Below, 1 = Above
1303 setting.setThreshstate(fcol.isAboveThreshold() ? 1
1304 : (fcol.isBelowThreshold() ? 0 : -1));
1308 setting.setColour(fcol.getColour().getRGB());
1311 setting.setDisplay(av.getFeaturesDisplayed().isVisible(
1313 float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1314 .getOrder(featureType);
1317 setting.setOrder(rorder);
1319 fs.addSetting(setting);
1320 settingsAdded.addElement(featureType);
1324 // is groups actually supposed to be a map here ?
1325 Iterator<String> en = ap.getSeqPanel().seqCanvas
1326 .getFeatureRenderer()
1327 .getFeatureGroups().iterator();
1328 Vector<String> groupsAdded = new Vector<String>();
1329 while (en.hasNext())
1331 String grp = en.next();
1332 if (groupsAdded.contains(grp))
1336 Group g = new Group();
1338 g.setDisplay(((Boolean) ap.getSeqPanel().seqCanvas
1339 .getFeatureRenderer().checkGroupVisibility(grp, false))
1342 groupsAdded.addElement(grp);
1344 jms.setFeatureSettings(fs);
1347 if (av.hasHiddenColumns())
1349 if (av.getColumnSelection() == null
1350 || av.getColumnSelection().getHiddenColumns() == null)
1352 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1356 for (int c = 0; c < av.getColumnSelection().getHiddenColumns()
1359 int[] region = av.getColumnSelection().getHiddenColumns()
1361 HiddenColumns hc = new HiddenColumns();
1362 hc.setStart(region[0]);
1363 hc.setEnd(region[1]);
1364 view.addHiddenColumns(hc);
1368 if (calcIdSet.size() > 0)
1370 for (String calcId : calcIdSet)
1372 if (calcId.trim().length() > 0)
1374 CalcIdParam cidp = createCalcIdParam(calcId, av);
1375 // Some calcIds have no parameters.
1378 view.addCalcIdParam(cidp);
1384 jms.addViewport(view);
1386 object.setJalviewModelSequence(jms);
1387 object.getVamsasModel().addSequenceSet(vamsasSet);
1389 if (jout != null && fileName != null)
1391 // We may not want to write the object to disk,
1392 // eg we can copy the alignViewport to a new view object
1393 // using save and then load
1396 System.out.println("Writing jar entry " + fileName);
1397 JarEntry entry = new JarEntry(fileName);
1398 jout.putNextEntry(entry);
1399 PrintWriter pout = new PrintWriter(new OutputStreamWriter(jout,
1401 Marshaller marshaller = new Marshaller(pout);
1402 marshaller.marshal(object);
1405 } catch (Exception ex)
1407 // TODO: raise error in GUI if marshalling failed.
1408 ex.printStackTrace();
1415 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1416 * for each viewer, with
1418 * <li>viewer geometry (position, size, split pane divider location)</li>
1419 * <li>index of the selected structure in the viewer (currently shows gapped
1421 * <li>the id of the annotation holding RNA secondary structure</li>
1422 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1424 * Varna viewer state is also written out (in native Varna XML) to separate
1425 * project jar entries. A separate entry is written for each RNA structure
1426 * displayed, with the naming convention
1428 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
1436 * @param storeDataset
1438 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
1439 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
1440 boolean storeDataset)
1442 if (Desktop.desktop == null)
1446 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1447 for (int f = frames.length - 1; f > -1; f--)
1449 if (frames[f] instanceof AppVarna)
1451 AppVarna varna = (AppVarna) frames[f];
1453 * link the sequence to every viewer that is showing it and is linked to
1454 * its alignment panel
1456 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1458 String viewId = varna.getViewId();
1459 RnaViewer rna = new RnaViewer();
1460 rna.setViewId(viewId);
1461 rna.setTitle(varna.getTitle());
1462 rna.setXpos(varna.getX());
1463 rna.setYpos(varna.getY());
1464 rna.setWidth(varna.getWidth());
1465 rna.setHeight(varna.getHeight());
1466 rna.setDividerLocation(varna.getDividerLocation());
1467 rna.setSelectedRna(varna.getSelectedIndex());
1468 jseq.addRnaViewer(rna);
1471 * Store each Varna panel's state once in the project per sequence.
1472 * First time through only (storeDataset==false)
1474 // boolean storeSessions = false;
1475 // String sequenceViewId = viewId + seqsToIds.get(jds);
1476 // if (!storeDataset && !viewIds.contains(sequenceViewId))
1478 // viewIds.add(sequenceViewId);
1479 // storeSessions = true;
1481 for (RnaModel model : varna.getModels())
1483 if (model.seq == jds)
1486 * VARNA saves each view (sequence or alignment secondary
1487 * structure, gapped or trimmed) as a separate XML file
1489 String jarEntryName = rnaSessions.get(model);
1490 if (jarEntryName == null)
1493 String varnaStateFile = varna.getStateInfo(model.rna);
1494 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
1495 copyFileToJar(jout, varnaStateFile, jarEntryName);
1496 rnaSessions.put(model, jarEntryName);
1498 SecondaryStructure ss = new SecondaryStructure();
1499 String annotationId = varna.getAnnotation(jds).annotationId;
1500 ss.setAnnotationId(annotationId);
1501 ss.setViewerState(jarEntryName);
1502 ss.setGapped(model.gapped);
1503 ss.setTitle(model.title);
1504 rna.addSecondaryStructure(ss);
1513 * Copy the contents of a file to a new entry added to the output jar
1517 * @param jarEntryName
1519 protected void copyFileToJar(JarOutputStream jout, String infilePath,
1520 String jarEntryName)
1522 DataInputStream dis = null;
1525 File file = new File(infilePath);
1526 if (file.exists() && jout != null)
1528 dis = new DataInputStream(new FileInputStream(file));
1529 byte[] data = new byte[(int) file.length()];
1530 dis.readFully(data);
1531 writeJarEntry(jout, jarEntryName, data);
1533 } catch (Exception ex)
1535 ex.printStackTrace();
1543 } catch (IOException e)
1552 * Write the data to a new entry of given name in the output jar file
1555 * @param jarEntryName
1557 * @throws IOException
1559 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
1560 byte[] data) throws IOException
1564 System.out.println("Writing jar entry " + jarEntryName);
1565 jout.putNextEntry(new JarEntry(jarEntryName));
1566 DataOutputStream dout = new DataOutputStream(jout);
1567 dout.write(data, 0, data.length);
1574 * Save the state of a structure viewer
1579 * the archive XML element under which to save the state
1582 * @param matchedFile
1586 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
1587 Pdbids pdb, PDBEntry entry, List<String> viewIds,
1588 String matchedFile, StructureViewerBase viewFrame)
1590 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
1593 * Look for any bindings for this viewer to the PDB file of interest
1594 * (including part matches excluding chain id)
1596 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
1598 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
1599 final String pdbId = pdbentry.getId();
1600 if (!pdbId.equals(entry.getId())
1601 && !(entry.getId().length() > 4 && entry.getId()
1602 .toLowerCase().startsWith(pdbId.toLowerCase())))
1605 * not interested in a binding to a different PDB entry here
1609 if (matchedFile == null)
1611 matchedFile = pdbentry.getFile();
1613 else if (!matchedFile.equals(pdbentry.getFile()))
1616 .warn("Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
1617 + pdbentry.getFile());
1621 // can get at it if the ID
1622 // match is ambiguous (e.g.
1625 for (int smap = 0; smap < viewFrame.getBinding().getSequence()[peid].length; smap++)
1627 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
1628 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
1630 StructureState state = new StructureState();
1631 state.setVisible(true);
1632 state.setXpos(viewFrame.getX());
1633 state.setYpos(viewFrame.getY());
1634 state.setWidth(viewFrame.getWidth());
1635 state.setHeight(viewFrame.getHeight());
1636 final String viewId = viewFrame.getViewId();
1637 state.setViewId(viewId);
1638 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
1639 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
1640 state.setColourByJmol(viewFrame.isColouredByViewer());
1641 state.setType(viewFrame.getViewerType().toString());
1642 pdb.addStructureState(state);
1649 private AnnotationColours constructAnnotationColours(
1650 AnnotationColourGradient acg, List<UserColourScheme> userColours,
1651 JalviewModelSequence jms)
1653 AnnotationColours ac = new AnnotationColours();
1654 ac.setAboveThreshold(acg.getAboveThreshold());
1655 ac.setThreshold(acg.getAnnotationThreshold());
1656 ac.setAnnotation(acg.getAnnotation());
1657 if (acg.getBaseColour() instanceof jalview.schemes.UserColourScheme)
1659 ac.setColourScheme(setUserColourScheme(acg.getBaseColour(),
1664 ac.setColourScheme(ColourSchemeProperty.getColourName(acg
1668 ac.setMaxColour(acg.getMaxColour().getRGB());
1669 ac.setMinColour(acg.getMinColour().getRGB());
1670 ac.setPerSequence(acg.isSeqAssociated());
1671 ac.setPredefinedColours(acg.isPredefinedColours());
1675 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
1676 IdentityHashMap<SequenceGroup, String> groupRefs,
1677 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
1678 SequenceSet vamsasSet)
1681 for (int i = 0; i < aa.length; i++)
1683 Annotation an = new Annotation();
1685 AlignmentAnnotation annotation = aa[i];
1686 if (annotation.annotationId != null)
1688 annotationIds.put(annotation.annotationId, annotation);
1691 an.setId(annotation.annotationId);
1693 an.setVisible(annotation.visible);
1695 an.setDescription(annotation.description);
1697 if (annotation.sequenceRef != null)
1699 // 2.9 JAL-1781 xref on sequence id rather than name
1700 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
1702 if (annotation.groupRef != null)
1704 String groupIdr = groupRefs.get(annotation.groupRef);
1705 if (groupIdr == null)
1707 // make a locally unique String
1709 annotation.groupRef,
1710 groupIdr = ("" + System.currentTimeMillis()
1711 + annotation.groupRef.getName() + groupRefs
1714 an.setGroupRef(groupIdr.toString());
1717 // store all visualization attributes for annotation
1718 an.setGraphHeight(annotation.graphHeight);
1719 an.setCentreColLabels(annotation.centreColLabels);
1720 an.setScaleColLabels(annotation.scaleColLabel);
1721 an.setShowAllColLabels(annotation.showAllColLabels);
1722 an.setBelowAlignment(annotation.belowAlignment);
1724 if (annotation.graph > 0)
1727 an.setGraphType(annotation.graph);
1728 an.setGraphGroup(annotation.graphGroup);
1729 if (annotation.getThreshold() != null)
1731 ThresholdLine line = new ThresholdLine();
1732 line.setLabel(annotation.getThreshold().label);
1733 line.setValue(annotation.getThreshold().value);
1734 line.setColour(annotation.getThreshold().colour.getRGB());
1735 an.setThresholdLine(line);
1743 an.setLabel(annotation.label);
1745 if (annotation == av.getAlignmentQualityAnnot()
1746 || annotation == av.getAlignmentConservationAnnotation()
1747 || annotation == av.getAlignmentConsensusAnnotation()
1748 || annotation.autoCalculated)
1750 // new way of indicating autocalculated annotation -
1751 an.setAutoCalculated(annotation.autoCalculated);
1753 if (annotation.hasScore())
1755 an.setScore(annotation.getScore());
1758 if (annotation.getCalcId() != null)
1760 calcIdSet.add(annotation.getCalcId());
1761 an.setCalcId(annotation.getCalcId());
1763 if (annotation.hasProperties())
1765 for (String pr : annotation.getProperties())
1767 Property prop = new Property();
1769 prop.setValue(annotation.getProperty(pr));
1770 an.addProperty(prop);
1774 AnnotationElement ae;
1775 if (annotation.annotations != null)
1777 an.setScoreOnly(false);
1778 for (int a = 0; a < annotation.annotations.length; a++)
1780 if ((annotation == null) || (annotation.annotations[a] == null))
1785 ae = new AnnotationElement();
1786 if (annotation.annotations[a].description != null)
1788 ae.setDescription(annotation.annotations[a].description);
1790 if (annotation.annotations[a].displayCharacter != null)
1792 ae.setDisplayCharacter(annotation.annotations[a].displayCharacter);
1795 if (!Float.isNaN(annotation.annotations[a].value))
1797 ae.setValue(annotation.annotations[a].value);
1801 if (annotation.annotations[a].secondaryStructure > ' ')
1803 ae.setSecondaryStructure(annotation.annotations[a].secondaryStructure
1807 if (annotation.annotations[a].colour != null
1808 && annotation.annotations[a].colour != java.awt.Color.black)
1810 ae.setColour(annotation.annotations[a].colour.getRGB());
1813 an.addAnnotationElement(ae);
1814 if (annotation.autoCalculated)
1816 // only write one non-null entry into the annotation row -
1817 // sufficient to get the visualization attributes necessary to
1825 an.setScoreOnly(true);
1827 if (!storeDS || (storeDS && !annotation.autoCalculated))
1829 // skip autocalculated annotation - these are only provided for
1831 vamsasSet.addAnnotation(an);
1837 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
1839 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
1840 if (settings != null)
1842 CalcIdParam vCalcIdParam = new CalcIdParam();
1843 vCalcIdParam.setCalcId(calcId);
1844 vCalcIdParam.addServiceURL(settings.getServiceURI());
1845 // generic URI allowing a third party to resolve another instance of the
1846 // service used for this calculation
1847 for (String urls : settings.getServiceURLs())
1849 vCalcIdParam.addServiceURL(urls);
1851 vCalcIdParam.setVersion("1.0");
1852 if (settings.getPreset() != null)
1854 WsParamSetI setting = settings.getPreset();
1855 vCalcIdParam.setName(setting.getName());
1856 vCalcIdParam.setDescription(setting.getDescription());
1860 vCalcIdParam.setName("");
1861 vCalcIdParam.setDescription("Last used parameters");
1863 // need to be able to recover 1) settings 2) user-defined presets or
1864 // recreate settings from preset 3) predefined settings provided by
1865 // service - or settings that can be transferred (or discarded)
1866 vCalcIdParam.setParameters(settings.getWsParamFile().replace("\n",
1868 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
1869 // todo - decide if updateImmediately is needed for any projects.
1871 return vCalcIdParam;
1876 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
1879 if (calcIdParam.getVersion().equals("1.0"))
1881 Jws2Instance service = Jws2Discoverer.getDiscoverer()
1882 .getPreferredServiceFor(calcIdParam.getServiceURL());
1883 if (service != null)
1885 WsParamSetI parmSet = null;
1888 parmSet = service.getParamStore().parseServiceParameterFile(
1889 calcIdParam.getName(), calcIdParam.getDescription(),
1890 calcIdParam.getServiceURL(),
1891 calcIdParam.getParameters().replace("|\\n|", "\n"));
1892 } catch (IOException x)
1894 warn("Couldn't parse parameter data for "
1895 + calcIdParam.getCalcId(), x);
1898 List<ArgumentI> argList = null;
1899 if (calcIdParam.getName().length() > 0)
1901 parmSet = service.getParamStore()
1902 .getPreset(calcIdParam.getName());
1903 if (parmSet != null)
1905 // TODO : check we have a good match with settings in AACon -
1906 // otherwise we'll need to create a new preset
1911 argList = parmSet.getArguments();
1914 AAConSettings settings = new AAConSettings(
1915 calcIdParam.isAutoUpdate(), service, parmSet, argList);
1916 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
1917 calcIdParam.isNeedsUpdate());
1922 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
1926 throw new Error(MessageManager.formatMessage(
1927 "error.unsupported_version_calcIdparam",
1928 new Object[] { calcIdParam.toString() }));
1932 * External mapping between jalview objects and objects yielding a valid and
1933 * unique object ID string. This is null for normal Jalview project IO, but
1934 * non-null when a jalview project is being read or written as part of a
1937 IdentityHashMap jv2vobj = null;
1940 * Construct a unique ID for jvobj using either existing bindings or if none
1941 * exist, the result of the hashcode call for the object.
1944 * jalview data object
1945 * @return unique ID for referring to jvobj
1947 private String makeHashCode(Object jvobj, String altCode)
1949 if (jv2vobj != null)
1951 Object id = jv2vobj.get(jvobj);
1954 return id.toString();
1956 // check string ID mappings
1957 if (jvids2vobj != null && jvobj instanceof String)
1959 id = jvids2vobj.get(jvobj);
1963 return id.toString();
1965 // give up and warn that something has gone wrong
1966 warn("Cannot find ID for object in external mapping : " + jvobj);
1972 * return local jalview object mapped to ID, if it exists
1976 * @return null or object bound to idcode
1978 private Object retrieveExistingObj(String idcode)
1980 if (idcode != null && vobj2jv != null)
1982 return vobj2jv.get(idcode);
1988 * binding from ID strings from external mapping table to jalview data model
1991 private Hashtable vobj2jv;
1993 private Sequence createVamsasSequence(String id, SequenceI jds)
1995 return createVamsasSequence(true, id, jds, null);
1998 private Sequence createVamsasSequence(boolean recurse, String id,
1999 SequenceI jds, SequenceI parentseq)
2001 Sequence vamsasSeq = new Sequence();
2002 vamsasSeq.setId(id);
2003 vamsasSeq.setName(jds.getName());
2004 vamsasSeq.setSequence(jds.getSequenceAsString());
2005 vamsasSeq.setDescription(jds.getDescription());
2006 jalview.datamodel.DBRefEntry[] dbrefs = null;
2007 if (jds.getDatasetSequence() != null)
2009 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
2010 if (jds.getDatasetSequence().getDBRefs() != null)
2012 dbrefs = jds.getDatasetSequence().getDBRefs();
2017 vamsasSeq.setDsseqid(id); // so we can tell which sequences really are
2018 // dataset sequences only
2019 dbrefs = jds.getDBRefs();
2023 for (int d = 0; d < dbrefs.length; d++)
2025 DBRef dbref = new DBRef();
2026 dbref.setSource(dbrefs[d].getSource());
2027 dbref.setVersion(dbrefs[d].getVersion());
2028 dbref.setAccessionId(dbrefs[d].getAccessionId());
2029 if (dbrefs[d].hasMap())
2031 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
2033 dbref.setMapping(mp);
2035 vamsasSeq.addDBRef(dbref);
2041 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
2042 SequenceI parentseq, SequenceI jds, boolean recurse)
2045 if (jmp.getMap() != null)
2049 jalview.util.MapList mlst = jmp.getMap();
2050 List<int[]> r = mlst.getFromRanges();
2051 for (int[] range : r)
2053 MapListFrom mfrom = new MapListFrom();
2054 mfrom.setStart(range[0]);
2055 mfrom.setEnd(range[1]);
2056 mp.addMapListFrom(mfrom);
2058 r = mlst.getToRanges();
2059 for (int[] range : r)
2061 MapListTo mto = new MapListTo();
2062 mto.setStart(range[0]);
2063 mto.setEnd(range[1]);
2064 mp.addMapListTo(mto);
2066 mp.setMapFromUnit(mlst.getFromRatio());
2067 mp.setMapToUnit(mlst.getToRatio());
2068 if (jmp.getTo() != null)
2070 MappingChoice mpc = new MappingChoice();
2072 && (parentseq != jmp.getTo() || parentseq
2073 .getDatasetSequence() != jmp.getTo()))
2075 mpc.setSequence(createVamsasSequence(false, seqHash(jmp.getTo()),
2081 SequenceI ps = null;
2082 if (parentseq != jmp.getTo()
2083 && parentseq.getDatasetSequence() != jmp.getTo())
2085 // chaining dbref rather than a handshaking one
2086 jmpid = seqHash(ps = jmp.getTo());
2090 jmpid = seqHash(ps = parentseq);
2092 mpc.setDseqFor(jmpid);
2093 if (!seqRefIds.containsKey(mpc.getDseqFor()))
2095 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2096 seqRefIds.put(mpc.getDseqFor(), ps);
2100 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2103 mp.setMappingChoice(mpc);
2109 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2110 List<UserColourScheme> userColours, JalviewModelSequence jms)
2113 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2114 boolean newucs = false;
2115 if (!userColours.contains(ucs))
2117 userColours.add(ucs);
2120 id = "ucs" + userColours.indexOf(ucs);
2123 // actually create the scheme's entry in the XML model
2124 java.awt.Color[] colours = ucs.getColours();
2125 jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
2126 jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
2128 for (int i = 0; i < colours.length; i++)
2130 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2131 col.setName(ResidueProperties.aa[i]);
2132 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2133 jbucs.addColour(col);
2135 if (ucs.getLowerCaseColours() != null)
2137 colours = ucs.getLowerCaseColours();
2138 for (int i = 0; i < colours.length; i++)
2140 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2141 col.setName(ResidueProperties.aa[i].toLowerCase());
2142 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2143 jbucs.addColour(col);
2148 uc.setUserColourScheme(jbucs);
2149 jms.addUserColours(uc);
2155 jalview.schemes.UserColourScheme getUserColourScheme(
2156 JalviewModelSequence jms, String id)
2158 UserColours[] uc = jms.getUserColours();
2159 UserColours colours = null;
2161 for (int i = 0; i < uc.length; i++)
2163 if (uc[i].getId().equals(id))
2171 java.awt.Color[] newColours = new java.awt.Color[24];
2173 for (int i = 0; i < 24; i++)
2175 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2176 .getUserColourScheme().getColour(i).getRGB(), 16));
2179 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2182 if (colours.getUserColourScheme().getColourCount() > 24)
2184 newColours = new java.awt.Color[23];
2185 for (int i = 0; i < 23; i++)
2187 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2188 .getUserColourScheme().getColour(i + 24).getRGB(), 16));
2190 ucs.setLowerCaseColours(newColours);
2197 * contains last error message (if any) encountered by XML loader.
2199 String errorMessage = null;
2202 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2203 * exceptions are raised during project XML parsing
2205 public boolean attemptversion1parse = true;
2208 * Load a jalview project archive from a jar file
2211 * - HTTP URL or filename
2213 public AlignFrame loadJalviewAlign(final String file)
2216 jalview.gui.AlignFrame af = null;
2220 // create list to store references for any new Jmol viewers created
2221 newStructureViewers = new Vector<JalviewStructureDisplayI>();
2222 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2223 // Workaround is to make sure caller implements the JarInputStreamProvider
2225 // so we can re-open the jar input stream for each entry.
2227 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2228 af = loadJalviewAlign(jprovider);
2230 } catch (MalformedURLException e)
2232 errorMessage = "Invalid URL format for '" + file + "'";
2238 SwingUtilities.invokeAndWait(new Runnable()
2243 setLoadingFinishedForNewStructureViewers();
2246 } catch (Exception x)
2248 System.err.println("Error loading alignment: " + x.getMessage());
2254 private jarInputStreamProvider createjarInputStreamProvider(
2255 final String file) throws MalformedURLException
2258 errorMessage = null;
2259 uniqueSetSuffix = null;
2261 viewportsAdded.clear();
2262 frefedSequence = null;
2264 if (file.startsWith("http://"))
2266 url = new URL(file);
2268 final URL _url = url;
2269 return new jarInputStreamProvider()
2273 public JarInputStream getJarInputStream() throws IOException
2277 return new JarInputStream(_url.openStream());
2281 return new JarInputStream(new FileInputStream(file));
2286 public String getFilename()
2294 * Recover jalview session from a jalview project archive. Caller may
2295 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2296 * themselves. Any null fields will be initialised with default values,
2297 * non-null fields are left alone.
2302 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2304 errorMessage = null;
2305 if (uniqueSetSuffix == null)
2307 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2309 if (seqRefIds == null)
2313 AlignFrame af = null, _af = null;
2314 Map<String, AlignFrame> gatherToThisFrame = new HashMap<String, AlignFrame>();
2315 final String file = jprovider.getFilename();
2318 JarInputStream jin = null;
2319 JarEntry jarentry = null;
2324 jin = jprovider.getJarInputStream();
2325 for (int i = 0; i < entryCount; i++)
2327 jarentry = jin.getNextJarEntry();
2330 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2332 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2333 JalviewModel object = new JalviewModel();
2335 Unmarshaller unmar = new Unmarshaller(object);
2336 unmar.setValidation(false);
2337 object = (JalviewModel) unmar.unmarshal(in);
2338 if (true) // !skipViewport(object))
2340 _af = loadFromObject(object, file, true, jprovider);
2341 if (object.getJalviewModelSequence().getViewportCount() > 0)
2344 if (af.viewport.isGatherViewsHere())
2346 gatherToThisFrame.put(af.viewport.getSequenceSetId(), af);
2352 else if (jarentry != null)
2354 // Some other file here.
2357 } while (jarentry != null);
2358 resolveFrefedSequences();
2359 } catch (IOException ex)
2361 ex.printStackTrace();
2362 errorMessage = "Couldn't locate Jalview XML file : " + file;
2363 System.err.println("Exception whilst loading jalview XML file : "
2365 } catch (Exception ex)
2367 System.err.println("Parsing as Jalview Version 2 file failed.");
2368 ex.printStackTrace(System.err);
2369 if (attemptversion1parse)
2371 // Is Version 1 Jar file?
2374 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
2375 } catch (Exception ex2)
2377 System.err.println("Exception whilst loading as jalviewXMLV1:");
2378 ex2.printStackTrace();
2382 if (Desktop.instance != null)
2384 Desktop.instance.stopLoading();
2388 System.out.println("Successfully loaded archive file");
2391 ex.printStackTrace();
2393 System.err.println("Exception whilst loading jalview XML file : "
2395 } catch (OutOfMemoryError e)
2397 // Don't use the OOM Window here
2398 errorMessage = "Out of memory loading jalview XML file";
2399 System.err.println("Out of memory whilst loading jalview XML file");
2400 e.printStackTrace();
2403 if (Desktop.instance != null)
2405 Desktop.instance.stopLoading();
2409 * Regather multiple views (with the same sequence set id) to the frame (if
2410 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2411 * views instead of separate frames. Note this doesn't restore a state where
2412 * some expanded views in turn have tabbed views - the last "first tab" read
2413 * in will play the role of gatherer for all.
2415 for (AlignFrame fr : gatherToThisFrame.values())
2417 Desktop.instance.gatherViews(fr);
2420 restoreSplitFrames();
2422 if (errorMessage != null)
2430 * Try to reconstruct and display SplitFrame windows, where each contains
2431 * complementary dna and protein alignments. Done by pairing up AlignFrame
2432 * objects (created earlier) which have complementary viewport ids associated.
2434 protected void restoreSplitFrames()
2436 List<SplitFrame> gatherTo = new ArrayList<SplitFrame>();
2437 List<AlignFrame> addedToSplitFrames = new ArrayList<AlignFrame>();
2438 Map<String, AlignFrame> dna = new HashMap<String, AlignFrame>();
2441 * Identify the DNA alignments
2443 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2446 AlignFrame af = candidate.getValue();
2447 if (af.getViewport().getAlignment().isNucleotide())
2449 dna.put(candidate.getKey().getId(), af);
2454 * Try to match up the protein complements
2456 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2459 AlignFrame af = candidate.getValue();
2460 if (!af.getViewport().getAlignment().isNucleotide())
2462 String complementId = candidate.getKey().getComplementId();
2463 // only non-null complements should be in the Map
2464 if (complementId != null && dna.containsKey(complementId))
2466 final AlignFrame dnaFrame = dna.get(complementId);
2467 SplitFrame sf = createSplitFrame(dnaFrame, af);
2468 addedToSplitFrames.add(dnaFrame);
2469 addedToSplitFrames.add(af);
2470 if (af.viewport.isGatherViewsHere())
2479 * Open any that we failed to pair up (which shouldn't happen!) as
2480 * standalone AlignFrame's.
2482 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2485 AlignFrame af = candidate.getValue();
2486 if (!addedToSplitFrames.contains(af))
2488 Viewport view = candidate.getKey();
2489 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
2491 System.err.println("Failed to restore view " + view.getTitle()
2492 + " to split frame");
2497 * Gather back into tabbed views as flagged.
2499 for (SplitFrame sf : gatherTo)
2501 Desktop.instance.gatherViews(sf);
2504 splitFrameCandidates.clear();
2508 * Construct and display one SplitFrame holding DNA and protein alignments.
2511 * @param proteinFrame
2514 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
2515 AlignFrame proteinFrame)
2517 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
2518 String title = MessageManager.getString("label.linked_view_title");
2519 int width = (int) dnaFrame.getBounds().getWidth();
2520 int height = (int) (dnaFrame.getBounds().getHeight()
2521 + proteinFrame.getBounds().getHeight() + 50);
2524 * SplitFrame location is saved to both enclosed frames
2526 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
2527 Desktop.addInternalFrame(splitFrame, title, width, height);
2530 * And compute cDNA consensus (couldn't do earlier with consensus as
2531 * mappings were not yet present)
2533 proteinFrame.viewport.alignmentChanged(proteinFrame.alignPanel);
2539 * check errorMessage for a valid error message and raise an error box in the
2540 * GUI or write the current errorMessage to stderr and then clear the error
2543 protected void reportErrors()
2545 reportErrors(false);
2548 protected void reportErrors(final boolean saving)
2550 if (errorMessage != null)
2552 final String finalErrorMessage = errorMessage;
2555 javax.swing.SwingUtilities.invokeLater(new Runnable()
2560 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2561 finalErrorMessage, "Error "
2562 + (saving ? "saving" : "loading")
2563 + " Jalview file", JOptionPane.WARNING_MESSAGE);
2569 System.err.println("Problem loading Jalview file: " + errorMessage);
2572 errorMessage = null;
2575 Map<String, String> alreadyLoadedPDB = new HashMap<String, String>();
2578 * when set, local views will be updated from view stored in JalviewXML
2579 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2580 * sync if this is set to true.
2582 private final boolean updateLocalViews = false;
2585 * Returns the path to a temporary file holding the PDB file for the given PDB
2586 * id. The first time of asking, searches for a file of that name in the
2587 * Jalview project jar, and copies it to a new temporary file. Any repeat
2588 * requests just return the path to the file previously created.
2594 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId)
2596 if (alreadyLoadedPDB.containsKey(pdbId))
2598 return alreadyLoadedPDB.get(pdbId).toString();
2601 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb");
2602 if (tempFile != null)
2604 alreadyLoadedPDB.put(pdbId, tempFile);
2610 * Copies the jar entry of given name to a new temporary file and returns the
2611 * path to the file, or null if the entry is not found.
2614 * @param jarEntryName
2616 * a prefix for the temporary file name, must be at least three
2620 protected String copyJarEntry(jarInputStreamProvider jprovider,
2621 String jarEntryName, String prefix)
2623 BufferedReader in = null;
2624 PrintWriter out = null;
2628 JarInputStream jin = jprovider.getJarInputStream();
2630 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2631 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2632 * FileInputStream(jprovider)); }
2635 JarEntry entry = null;
2638 entry = jin.getNextJarEntry();
2639 } while (entry != null && !entry.getName().equals(jarEntryName));
2642 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
2643 File outFile = File.createTempFile(prefix, ".tmp");
2644 outFile.deleteOnExit();
2645 out = new PrintWriter(new FileOutputStream(outFile));
2648 while ((data = in.readLine()) != null)
2653 String t = outFile.getAbsolutePath();
2658 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
2660 } catch (Exception ex)
2662 ex.printStackTrace();
2670 } catch (IOException e)
2684 private class JvAnnotRow
2686 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2693 * persisted version of annotation row from which to take vis properties
2695 public jalview.datamodel.AlignmentAnnotation template;
2698 * original position of the annotation row in the alignment
2704 * Load alignment frame from jalview XML DOM object
2709 * filename source string
2710 * @param loadTreesAndStructures
2711 * when false only create Viewport
2713 * data source provider
2714 * @return alignment frame created from view stored in DOM
2716 AlignFrame loadFromObject(JalviewModel object, String file,
2717 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
2719 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
2720 Sequence[] vamsasSeq = vamsasSet.getSequence();
2722 JalviewModelSequence jms = object.getJalviewModelSequence();
2724 Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
2727 // ////////////////////////////////
2730 List<SequenceI> hiddenSeqs = null;
2733 List<SequenceI> tmpseqs = new ArrayList<SequenceI>();
2735 boolean multipleView = false;
2736 SequenceI referenceseqForView = null;
2737 JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
2738 int vi = 0; // counter in vamsasSeq array
2739 for (int i = 0; i < jseqs.length; i++)
2741 String seqId = jseqs[i].getId();
2743 SequenceI tmpSeq = seqRefIds.get(seqId);
2746 tmpSeq.setStart(jseqs[i].getStart());
2747 tmpSeq.setEnd(jseqs[i].getEnd());
2748 tmpseqs.add(tmpSeq);
2749 multipleView = true;
2753 tmpSeq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
2754 vamsasSeq[vi].getSequence());
2755 tmpSeq.setDescription(vamsasSeq[vi].getDescription());
2756 tmpSeq.setStart(jseqs[i].getStart());
2757 tmpSeq.setEnd(jseqs[i].getEnd());
2758 tmpSeq.setVamsasId(uniqueSetSuffix + seqId);
2759 seqRefIds.put(vamsasSeq[vi].getId(), tmpSeq);
2760 tmpseqs.add(tmpSeq);
2764 if (jseqs[i].hasViewreference() && jseqs[i].getViewreference())
2766 referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
2769 if (jseqs[i].getHidden())
2771 if (hiddenSeqs == null)
2773 hiddenSeqs = new ArrayList<SequenceI>();
2776 hiddenSeqs.add(tmpSeq);
2781 // Create the alignment object from the sequence set
2782 // ///////////////////////////////
2783 SequenceI[] orderedSeqs = tmpseqs
2784 .toArray(new SequenceI[tmpseqs.size()]);
2786 AlignmentI al = new Alignment(orderedSeqs);
2788 if (referenceseqForView != null)
2790 al.setSeqrep(referenceseqForView);
2792 // / Add the alignment properties
2793 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
2795 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
2796 al.setProperty(ssp.getKey(), ssp.getValue());
2800 // SequenceFeatures are added to the DatasetSequence,
2801 // so we must create or recover the dataset before loading features
2802 // ///////////////////////////////
2803 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
2805 // older jalview projects do not have a dataset id.
2806 al.setDataset(null);
2810 // recover dataset - passing on flag indicating if this a 'viewless'
2811 // sequence set (a.k.a. a stored dataset for the project)
2812 recoverDatasetFor(vamsasSet, al, object.getJalviewModelSequence()
2813 .getViewportCount() == 0);
2815 // ///////////////////////////////
2817 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
2820 // load sequence features, database references and any associated PDB
2821 // structures for the alignment
2822 for (int i = 0; i < vamsasSeq.length; i++)
2824 if (jseqs[i].getFeaturesCount() > 0)
2826 Features[] features = jseqs[i].getFeatures();
2827 for (int f = 0; f < features.length; f++)
2829 jalview.datamodel.SequenceFeature sf = new jalview.datamodel.SequenceFeature(
2830 features[f].getType(), features[f].getDescription(),
2831 features[f].getStatus(), features[f].getBegin(),
2832 features[f].getEnd(), features[f].getFeatureGroup());
2834 sf.setScore(features[f].getScore());
2835 for (int od = 0; od < features[f].getOtherDataCount(); od++)
2837 OtherData keyValue = features[f].getOtherData(od);
2838 if (keyValue.getKey().startsWith("LINK"))
2840 sf.addLink(keyValue.getValue());
2844 sf.setValue(keyValue.getKey(), keyValue.getValue());
2849 al.getSequenceAt(i).getDatasetSequence().addSequenceFeature(sf);
2852 if (vamsasSeq[i].getDBRefCount() > 0)
2854 addDBRefs(al.getSequenceAt(i).getDatasetSequence(), vamsasSeq[i]);
2856 if (jseqs[i].getPdbidsCount() > 0)
2858 Pdbids[] ids = jseqs[i].getPdbids();
2859 for (int p = 0; p < ids.length; p++)
2861 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
2862 entry.setId(ids[p].getId());
2863 if (ids[p].getType() != null)
2865 if (ids[p].getType().equalsIgnoreCase("PDB"))
2867 entry.setType(PDBEntry.Type.PDB);
2871 entry.setType(PDBEntry.Type.FILE);
2874 if (ids[p].getFile() != null)
2876 if (!pdbloaded.containsKey(ids[p].getFile()))
2878 entry.setFile(loadPDBFile(jprovider, ids[p].getId()));
2882 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
2885 StructureSelectionManager.getStructureSelectionManager(
2886 Desktop.instance).registerPDBEntry(entry);
2887 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
2891 } // end !multipleview
2893 // ///////////////////////////////
2894 // LOAD SEQUENCE MAPPINGS
2896 if (vamsasSet.getAlcodonFrameCount() > 0)
2898 // TODO Potentially this should only be done once for all views of an
2900 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
2901 for (int i = 0; i < alc.length; i++)
2903 AlignedCodonFrame cf = new AlignedCodonFrame();
2904 if (alc[i].getAlcodMapCount() > 0)
2906 AlcodMap[] maps = alc[i].getAlcodMap();
2907 for (int m = 0; m < maps.length; m++)
2909 SequenceI dnaseq = seqRefIds.get(maps[m].getDnasq());
2911 jalview.datamodel.Mapping mapping = null;
2912 // attach to dna sequence reference.
2913 if (maps[m].getMapping() != null)
2915 mapping = addMapping(maps[m].getMapping());
2917 if (dnaseq != null && mapping.getTo() != null)
2919 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
2924 frefedSequence.add(newAlcodMapRef(maps[m].getDnasq(), cf,
2928 al.addCodonFrame(cf);
2933 // ////////////////////////////////
2935 List<JvAnnotRow> autoAlan = new ArrayList<JvAnnotRow>();
2938 * store any annotations which forward reference a group's ID
2940 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<String, List<AlignmentAnnotation>>();
2942 if (vamsasSet.getAnnotationCount() > 0)
2944 Annotation[] an = vamsasSet.getAnnotation();
2946 for (int i = 0; i < an.length; i++)
2948 Annotation annotation = an[i];
2951 * test if annotation is automatically calculated for this view only
2953 boolean autoForView = false;
2954 if (annotation.getLabel().equals("Quality")
2955 || annotation.getLabel().equals("Conservation")
2956 || annotation.getLabel().equals("Consensus"))
2958 // Kludge for pre 2.5 projects which lacked the autocalculated flag
2960 if (!annotation.hasAutoCalculated())
2962 annotation.setAutoCalculated(true);
2966 || (annotation.hasAutoCalculated() && annotation
2967 .isAutoCalculated()))
2969 // remove ID - we don't recover annotation from other views for
2970 // view-specific annotation
2971 annotation.setId(null);
2974 // set visiblity for other annotation in this view
2975 String annotationId = annotation.getId();
2976 if (annotationId != null && annotationIds.containsKey(annotationId))
2978 AlignmentAnnotation jda = annotationIds.get(annotationId);
2979 // in principle Visible should always be true for annotation displayed
2980 // in multiple views
2981 if (annotation.hasVisible())
2983 jda.visible = annotation.getVisible();
2986 al.addAnnotation(jda);
2990 // Construct new annotation from model.
2991 AnnotationElement[] ae = annotation.getAnnotationElement();
2992 jalview.datamodel.Annotation[] anot = null;
2993 java.awt.Color firstColour = null;
2995 if (!annotation.getScoreOnly())
2997 anot = new jalview.datamodel.Annotation[al.getWidth()];
2998 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
3000 anpos = ae[aa].getPosition();
3002 if (anpos >= anot.length)
3007 anot[anpos] = new jalview.datamodel.Annotation(
3009 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
3010 (ae[aa].getSecondaryStructure() == null || ae[aa]
3011 .getSecondaryStructure().length() == 0) ? ' '
3012 : ae[aa].getSecondaryStructure().charAt(0),
3016 // JBPNote: Consider verifying dataflow for IO of secondary
3017 // structure annotation read from Stockholm files
3018 // this was added to try to ensure that
3019 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
3021 // anot[ae[aa].getPosition()].displayCharacter = "";
3023 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
3024 if (firstColour == null)
3026 firstColour = anot[anpos].colour;
3030 jalview.datamodel.AlignmentAnnotation jaa = null;
3032 if (annotation.getGraph())
3034 float llim = 0, hlim = 0;
3035 // if (autoForView || an[i].isAutoCalculated()) {
3038 jaa = new jalview.datamodel.AlignmentAnnotation(
3039 annotation.getLabel(), annotation.getDescription(), anot,
3040 llim, hlim, annotation.getGraphType());
3042 jaa.graphGroup = annotation.getGraphGroup();
3043 jaa._linecolour = firstColour;
3044 if (annotation.getThresholdLine() != null)
3046 jaa.setThreshold(new jalview.datamodel.GraphLine(annotation
3047 .getThresholdLine().getValue(), annotation
3048 .getThresholdLine().getLabel(), new java.awt.Color(
3049 annotation.getThresholdLine().getColour())));
3052 if (autoForView || annotation.isAutoCalculated())
3054 // Hardwire the symbol display line to ensure that labels for
3055 // histograms are displayed
3061 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
3062 an[i].getDescription(), anot);
3063 jaa._linecolour = firstColour;
3065 // register new annotation
3066 if (an[i].getId() != null)
3068 annotationIds.put(an[i].getId(), jaa);
3069 jaa.annotationId = an[i].getId();
3071 // recover sequence association
3072 String sequenceRef = an[i].getSequenceRef();
3073 if (sequenceRef != null)
3075 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3076 SequenceI sequence = seqRefIds.get(sequenceRef);
3077 if (sequence == null)
3079 // in pre-2.9 projects sequence ref is to sequence name
3080 sequence = al.findName(sequenceRef);
3082 if (sequence != null)
3084 jaa.createSequenceMapping(sequence, 1, true);
3085 sequence.addAlignmentAnnotation(jaa);
3088 // and make a note of any group association
3089 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
3091 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3092 .get(an[i].getGroupRef());
3095 aal = new ArrayList<jalview.datamodel.AlignmentAnnotation>();
3096 groupAnnotRefs.put(an[i].getGroupRef(), aal);
3101 if (an[i].hasScore())
3103 jaa.setScore(an[i].getScore());
3105 if (an[i].hasVisible())
3107 jaa.visible = an[i].getVisible();
3110 if (an[i].hasCentreColLabels())
3112 jaa.centreColLabels = an[i].getCentreColLabels();
3115 if (an[i].hasScaleColLabels())
3117 jaa.scaleColLabel = an[i].getScaleColLabels();
3119 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
3121 // newer files have an 'autoCalculated' flag and store calculation
3122 // state in viewport properties
3123 jaa.autoCalculated = true; // means annotation will be marked for
3124 // update at end of load.
3126 if (an[i].hasGraphHeight())
3128 jaa.graphHeight = an[i].getGraphHeight();
3130 if (an[i].hasBelowAlignment())
3132 jaa.belowAlignment = an[i].isBelowAlignment();
3134 jaa.setCalcId(an[i].getCalcId());
3135 if (an[i].getPropertyCount() > 0)
3137 for (jalview.schemabinding.version2.Property prop : an[i]
3140 jaa.setProperty(prop.getName(), prop.getValue());
3143 if (jaa.autoCalculated)
3145 autoAlan.add(new JvAnnotRow(i, jaa));
3148 // if (!autoForView)
3150 // add autocalculated group annotation and any user created annotation
3152 al.addAnnotation(jaa);
3156 // ///////////////////////
3158 // Create alignment markup and styles for this view
3159 if (jms.getJGroupCount() > 0)
3161 JGroup[] groups = jms.getJGroup();
3162 boolean addAnnotSchemeGroup = false;
3163 for (int i = 0; i < groups.length; i++)
3165 JGroup jGroup = groups[i];
3166 ColourSchemeI cs = null;
3167 if (jGroup.getColour() != null)
3169 if (jGroup.getColour().startsWith("ucs"))
3171 cs = getUserColourScheme(jms, jGroup.getColour());
3173 else if (jGroup.getColour().equals("AnnotationColourGradient")
3174 && jGroup.getAnnotationColours() != null)
3176 addAnnotSchemeGroup = true;
3181 cs = ColourSchemeProperty.getColour(al, jGroup.getColour());
3186 cs.setThreshold(jGroup.getPidThreshold(), true);
3190 Vector<SequenceI> seqs = new Vector<SequenceI>();
3192 for (int s = 0; s < jGroup.getSeqCount(); s++)
3194 String seqId = jGroup.getSeq(s) + "";
3195 SequenceI ts = seqRefIds.get(seqId);
3199 seqs.addElement(ts);
3203 if (seqs.size() < 1)
3208 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3209 jGroup.getDisplayBoxes(), jGroup.getDisplayText(),
3210 jGroup.getColourText(), jGroup.getStart(), jGroup.getEnd());
3212 sg.setOutlineColour(new java.awt.Color(jGroup.getOutlineColour()));
3214 sg.textColour = new java.awt.Color(jGroup.getTextCol1());
3215 sg.textColour2 = new java.awt.Color(jGroup.getTextCol2());
3216 sg.setShowNonconserved(jGroup.hasShowUnconserved() ? jGroup
3217 .isShowUnconserved() : false);
3218 sg.thresholdTextColour = jGroup.getTextColThreshold();
3219 if (jGroup.hasShowConsensusHistogram())
3221 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3224 if (jGroup.hasShowSequenceLogo())
3226 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3228 if (jGroup.hasNormaliseSequenceLogo())
3230 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3232 if (jGroup.hasIgnoreGapsinConsensus())
3234 sg.setIgnoreGapsConsensus(jGroup.getIgnoreGapsinConsensus());
3236 if (jGroup.getConsThreshold() != 0)
3238 jalview.analysis.Conservation c = new jalview.analysis.Conservation(
3239 "All", ResidueProperties.propHash, 3,
3240 sg.getSequences(null), 0, sg.getWidth() - 1);
3242 c.verdict(false, 25);
3243 sg.cs.setConservation(c);
3246 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3248 // re-instate unique group/annotation row reference
3249 List<AlignmentAnnotation> jaal = groupAnnotRefs.get(jGroup
3253 for (AlignmentAnnotation jaa : jaal)
3256 if (jaa.autoCalculated)
3258 // match up and try to set group autocalc alignment row for this
3260 if (jaa.label.startsWith("Consensus for "))
3262 sg.setConsensus(jaa);
3264 // match up and try to set group autocalc alignment row for this
3266 if (jaa.label.startsWith("Conservation for "))
3268 sg.setConservationRow(jaa);
3275 if (addAnnotSchemeGroup)
3277 // reconstruct the annotation colourscheme
3278 sg.cs = constructAnnotationColour(jGroup.getAnnotationColours(),
3279 null, al, jms, false);
3285 // only dataset in this model, so just return.
3288 // ///////////////////////////////
3291 // If we just load in the same jar file again, the sequenceSetId
3292 // will be the same, and we end up with multiple references
3293 // to the same sequenceSet. We must modify this id on load
3294 // so that each load of the file gives a unique id
3295 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3296 String viewId = (view.getId() == null ? null : view.getId()
3298 AlignFrame af = null;
3299 AlignViewport av = null;
3300 // now check to see if we really need to create a new viewport.
3301 if (multipleView && viewportsAdded.size() == 0)
3303 // We recovered an alignment for which a viewport already exists.
3304 // TODO: fix up any settings necessary for overlaying stored state onto
3305 // state recovered from another document. (may not be necessary).
3306 // we may need a binding from a viewport in memory to one recovered from
3308 // and then recover its containing af to allow the settings to be applied.
3309 // TODO: fix for vamsas demo
3311 .println("About to recover a viewport for existing alignment: Sequence set ID is "
3313 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3314 if (seqsetobj != null)
3316 if (seqsetobj instanceof String)
3318 uniqueSeqSetId = (String) seqsetobj;
3320 .println("Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
3326 .println("Warning : Collision between sequence set ID string and existing jalview object mapping.");
3332 * indicate that annotation colours are applied across all groups (pre
3333 * Jalview 2.8.1 behaviour)
3335 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan(
3336 "2.8.1", object.getVersion());
3338 AlignmentPanel ap = null;
3339 boolean isnewview = true;
3342 // Check to see if this alignment already has a view id == viewId
3343 jalview.gui.AlignmentPanel views[] = Desktop
3344 .getAlignmentPanels(uniqueSeqSetId);
3345 if (views != null && views.length > 0)
3347 for (int v = 0; v < views.length; v++)
3349 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
3351 // recover the existing alignpanel, alignframe, viewport
3352 af = views[v].alignFrame;
3355 // TODO: could even skip resetting view settings if we don't want to
3356 // change the local settings from other jalview processes
3365 af = loadViewport(file, jseqs, hiddenSeqs, al, jms, view,
3366 uniqueSeqSetId, viewId, autoAlan);
3372 * Load any trees, PDB structures and viewers
3374 * Not done if flag is false (when this method is used for New View)
3376 if (loadTreesAndStructures)
3378 loadTrees(jms, view, af, av, ap);
3379 loadPDBStructures(jprovider, jseqs, af, ap);
3380 loadRnaViewers(jprovider, jseqs, ap);
3382 // and finally return.
3387 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
3388 * panel is restored from separate jar entries, two (gapped and trimmed) per
3389 * sequence and secondary structure.
3391 * Currently each viewer shows just one sequence and structure (gapped and
3392 * trimmed), however this method is designed to support multiple sequences or
3393 * structures in viewers if wanted in future.
3399 private void loadRnaViewers(jarInputStreamProvider jprovider,
3400 JSeq[] jseqs, AlignmentPanel ap)
3403 * scan the sequences for references to viewers; create each one the first
3404 * time it is referenced, add Rna models to existing viewers
3406 for (JSeq jseq : jseqs)
3408 for (int i = 0; i < jseq.getRnaViewerCount(); i++)
3410 RnaViewer viewer = jseq.getRnaViewer(i);
3411 AppVarna appVarna = findOrCreateVarnaViewer(viewer,
3412 uniqueSetSuffix, ap);
3414 for (int j = 0; j < viewer.getSecondaryStructureCount(); j++)
3416 SecondaryStructure ss = viewer.getSecondaryStructure(j);
3417 SequenceI seq = seqRefIds.get(jseq.getId());
3418 AlignmentAnnotation ann = this.annotationIds.get(ss
3419 .getAnnotationId());
3422 * add the structure to the Varna display (with session state copied
3423 * from the jar to a temporary file)
3425 boolean gapped = ss.isGapped();
3426 String rnaTitle = ss.getTitle();
3427 String sessionState = ss.getViewerState();
3428 String tempStateFile = copyJarEntry(jprovider, sessionState,
3430 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
3431 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
3433 appVarna.setInitialSelection(viewer.getSelectedRna());
3439 * Locate and return an already instantiated matching AppVarna, or create one
3443 * @param viewIdSuffix
3447 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
3448 String viewIdSuffix, AlignmentPanel ap)
3451 * on each load a suffix is appended to the saved viewId, to avoid conflicts
3452 * if load is repeated
3454 String postLoadId = viewer.getViewId() + viewIdSuffix;
3455 for (JInternalFrame frame : getAllFrames())
3457 if (frame instanceof AppVarna)
3459 AppVarna varna = (AppVarna) frame;
3460 if (postLoadId.equals(varna.getViewId()))
3462 // this viewer is already instantiated
3463 // could in future here add ap as another 'parent' of the
3464 // AppVarna window; currently just 1-to-many
3471 * viewer not found - make it
3473 RnaViewerModel model = new RnaViewerModel(postLoadId,
3474 viewer.getTitle(), viewer.getXpos(), viewer.getYpos(),
3475 viewer.getWidth(), viewer.getHeight(),
3476 viewer.getDividerLocation());
3477 AppVarna varna = new AppVarna(model, ap);
3483 * Load any saved trees
3491 protected void loadTrees(JalviewModelSequence jms, Viewport view,
3492 AlignFrame af, AlignViewport av, AlignmentPanel ap)
3494 // TODO result of automated refactoring - are all these parameters needed?
3497 for (int t = 0; t < jms.getTreeCount(); t++)
3500 Tree tree = jms.getTree(t);
3502 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
3505 tp = af.ShowNewickTree(
3506 new jalview.io.NewickFile(tree.getNewick()),
3507 tree.getTitle(), tree.getWidth(), tree.getHeight(),
3508 tree.getXpos(), tree.getYpos());
3509 if (tree.getId() != null)
3511 // perhaps bind the tree id to something ?
3516 // update local tree attributes ?
3517 // TODO: should check if tp has been manipulated by user - if so its
3518 // settings shouldn't be modified
3519 tp.setTitle(tree.getTitle());
3520 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(), tree
3521 .getWidth(), tree.getHeight()));
3522 tp.av = av; // af.viewport; // TODO: verify 'associate with all
3525 tp.treeCanvas.av = av; // af.viewport;
3526 tp.treeCanvas.ap = ap; // af.alignPanel;
3531 warn("There was a problem recovering stored Newick tree: \n"
3532 + tree.getNewick());
3536 tp.fitToWindow.setState(tree.getFitToWindow());
3537 tp.fitToWindow_actionPerformed(null);
3539 if (tree.getFontName() != null)
3541 tp.setTreeFont(new java.awt.Font(tree.getFontName(), tree
3542 .getFontStyle(), tree.getFontSize()));
3546 tp.setTreeFont(new java.awt.Font(view.getFontName(), view
3547 .getFontStyle(), tree.getFontSize()));
3550 tp.showPlaceholders(tree.getMarkUnlinked());
3551 tp.showBootstrap(tree.getShowBootstrap());
3552 tp.showDistances(tree.getShowDistances());
3554 tp.treeCanvas.threshold = tree.getThreshold();
3556 if (tree.getCurrentTree())
3558 af.viewport.setCurrentTree(tp.getTree());
3562 } catch (Exception ex)
3564 ex.printStackTrace();
3569 * Load and link any saved structure viewers.
3576 protected void loadPDBStructures(jarInputStreamProvider jprovider,
3577 JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
3580 * Run through all PDB ids on the alignment, and collect mappings between
3581 * distinct view ids and all sequences referring to that view.
3583 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<String, StructureViewerModel>();
3585 for (int i = 0; i < jseqs.length; i++)
3587 if (jseqs[i].getPdbidsCount() > 0)
3589 Pdbids[] ids = jseqs[i].getPdbids();
3590 for (int p = 0; p < ids.length; p++)
3592 final int structureStateCount = ids[p].getStructureStateCount();
3593 for (int s = 0; s < structureStateCount; s++)
3595 // check to see if we haven't already created this structure view
3596 final StructureState structureState = ids[p]
3597 .getStructureState(s);
3598 String sviewid = (structureState.getViewId() == null) ? null
3599 : structureState.getViewId() + uniqueSetSuffix;
3600 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
3601 // Originally : ids[p].getFile()
3602 // : TODO: verify external PDB file recovery still works in normal
3603 // jalview project load
3604 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId()));
3605 jpdb.setId(ids[p].getId());
3607 int x = structureState.getXpos();
3608 int y = structureState.getYpos();
3609 int width = structureState.getWidth();
3610 int height = structureState.getHeight();
3612 // Probably don't need to do this anymore...
3613 // Desktop.desktop.getComponentAt(x, y);
3614 // TODO: NOW: check that this recovers the PDB file correctly.
3615 String pdbFile = loadPDBFile(jprovider, ids[p].getId());
3616 jalview.datamodel.SequenceI seq = seqRefIds.get(jseqs[i]
3618 if (sviewid == null)
3620 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width
3623 if (!structureViewers.containsKey(sviewid))
3625 structureViewers.put(sviewid,
3626 new StructureViewerModel(x, y, width, height, false,
3627 false, true, structureState.getViewId(),
3628 structureState.getType()));
3629 // Legacy pre-2.7 conversion JAL-823 :
3630 // do not assume any view has to be linked for colour by
3634 // assemble String[] { pdb files }, String[] { id for each
3635 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3636 // seqs_file 2}, boolean[] {
3637 // linkAlignPanel,superposeWithAlignpanel}} from hash
3638 StructureViewerModel jmoldat = structureViewers.get(sviewid);
3639 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
3640 | (structureState.hasAlignwithAlignPanel() ? structureState
3641 .getAlignwithAlignPanel() : false));
3644 * Default colour by linked panel to false if not specified (e.g.
3645 * for pre-2.7 projects)
3647 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
3648 colourWithAlignPanel |= (structureState
3649 .hasColourwithAlignPanel() ? structureState
3650 .getColourwithAlignPanel() : false);
3651 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
3654 * Default colour by viewer to true if not specified (e.g. for
3657 boolean colourByViewer = jmoldat.isColourByViewer();
3658 colourByViewer &= structureState.hasColourByJmol() ? structureState
3659 .getColourByJmol() : true;
3660 jmoldat.setColourByViewer(colourByViewer);
3662 if (jmoldat.getStateData().length() < structureState
3663 .getContent().length())
3666 jmoldat.setStateData(structureState.getContent());
3669 if (ids[p].getFile() != null)
3671 File mapkey = new File(ids[p].getFile());
3672 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
3673 if (seqstrmaps == null)
3675 jmoldat.getFileData().put(
3677 seqstrmaps = jmoldat.new StructureData(pdbFile,
3680 if (!seqstrmaps.getSeqList().contains(seq))
3682 seqstrmaps.getSeqList().add(seq);
3688 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");
3695 // Instantiate the associated structure views
3696 for (Entry<String, StructureViewerModel> entry : structureViewers
3701 createOrLinkStructureViewer(entry, af, ap, jprovider);
3702 } catch (Exception e)
3704 System.err.println("Error loading structure viewer: "
3706 // failed - try the next one
3718 protected void createOrLinkStructureViewer(
3719 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3720 AlignmentPanel ap, jarInputStreamProvider jprovider)
3722 final StructureViewerModel stateData = viewerData.getValue();
3725 * Search for any viewer windows already open from other alignment views
3726 * that exactly match the stored structure state
3728 StructureViewerBase comp = findMatchingViewer(viewerData);
3732 linkStructureViewer(ap, comp, stateData);
3737 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
3738 * "viewer_"+stateData.viewId
3740 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
3742 createChimeraViewer(viewerData, af, jprovider);
3747 * else Jmol (if pre-2.9, stateData contains JMOL state string)
3749 createJmolViewer(viewerData, af, jprovider);
3754 * Create a new Chimera viewer.
3760 protected void createChimeraViewer(
3761 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3762 jarInputStreamProvider jprovider)
3764 StructureViewerModel data = viewerData.getValue();
3765 String chimeraSessionFile = data.getStateData();
3768 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
3770 * NB this is the 'saved' viewId as in the project file XML, _not_ the
3771 * 'uniquified' sviewid used to reconstruct the viewer here
3773 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
3774 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
3777 Set<Entry<File, StructureData>> fileData = data.getFileData()
3779 List<PDBEntry> pdbs = new ArrayList<PDBEntry>();
3780 List<SequenceI[]> allseqs = new ArrayList<SequenceI[]>();
3781 for (Entry<File, StructureData> pdb : fileData)
3783 String filePath = pdb.getValue().getFilePath();
3784 String pdbId = pdb.getValue().getPdbId();
3785 // pdbs.add(new PDBEntry(filePath, pdbId));
3786 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
3787 final List<SequenceI> seqList = pdb.getValue().getSeqList();
3788 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
3792 boolean colourByChimera = data.isColourByViewer();
3793 boolean colourBySequence = data.isColourWithAlignPanel();
3795 // TODO use StructureViewer as a factory here, see JAL-1761
3796 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
3797 final SequenceI[][] seqsArray = allseqs.toArray(new SequenceI[allseqs
3799 String newViewId = viewerData.getKey();
3801 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
3802 af.alignPanel, pdbArray, seqsArray, colourByChimera,
3803 colourBySequence, newViewId);
3804 cvf.setSize(data.getWidth(), data.getHeight());
3805 cvf.setLocation(data.getX(), data.getY());
3809 * Create a new Jmol window. First parse the Jmol state to translate filenames
3810 * loaded into the view, and record the order in which files are shown in the
3811 * Jmol view, so we can add the sequence mappings in same order.
3817 protected void createJmolViewer(
3818 final Entry<String, StructureViewerModel> viewerData,
3819 AlignFrame af, jarInputStreamProvider jprovider)
3821 final StructureViewerModel svattrib = viewerData.getValue();
3822 String state = svattrib.getStateData();
3825 * Pre-2.9: state element value is the Jmol state string
3827 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
3830 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
3832 state = readJarEntry(jprovider,
3833 getViewerJarEntryName(svattrib.getViewId()));
3836 List<String> pdbfilenames = new ArrayList<String>();
3837 List<SequenceI[]> seqmaps = new ArrayList<SequenceI[]>();
3838 List<String> pdbids = new ArrayList<String>();
3839 StringBuilder newFileLoc = new StringBuilder(64);
3840 int cp = 0, ncp, ecp;
3841 Map<File, StructureData> oldFiles = svattrib.getFileData();
3842 while ((ncp = state.indexOf("load ", cp)) > -1)
3846 // look for next filename in load statement
3847 newFileLoc.append(state.substring(cp,
3848 ncp = (state.indexOf("\"", ncp + 1) + 1)));
3849 String oldfilenam = state.substring(ncp,
3850 ecp = state.indexOf("\"", ncp));
3851 // recover the new mapping data for this old filename
3852 // have to normalize filename - since Jmol and jalview do
3854 // translation differently.
3855 StructureData filedat = oldFiles.get(new File(oldfilenam));
3856 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
3857 pdbfilenames.add(filedat.getFilePath());
3858 pdbids.add(filedat.getPdbId());
3859 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
3860 newFileLoc.append("\"");
3861 cp = ecp + 1; // advance beyond last \" and set cursor so we can
3862 // look for next file statement.
3863 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
3867 // just append rest of state
3868 newFileLoc.append(state.substring(cp));
3872 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
3873 newFileLoc = new StringBuilder(state);
3874 newFileLoc.append("; load append ");
3875 for (File id : oldFiles.keySet())
3877 // add this and any other pdb files that should be present in
3879 StructureData filedat = oldFiles.get(id);
3880 newFileLoc.append(filedat.getFilePath());
3881 pdbfilenames.add(filedat.getFilePath());
3882 pdbids.add(filedat.getPdbId());
3883 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
3884 newFileLoc.append(" \"");
3885 newFileLoc.append(filedat.getFilePath());
3886 newFileLoc.append("\"");
3889 newFileLoc.append(";");
3892 if (newFileLoc.length() == 0)
3896 int histbug = newFileLoc.indexOf("history = ");
3900 * change "history = [true|false];" to "history = [1|0];"
3903 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
3904 String val = (diff == -1) ? null : newFileLoc
3905 .substring(histbug, diff);
3906 if (val != null && val.length() >= 4)
3908 if (val.contains("e")) // eh? what can it be?
3910 if (val.trim().equals("true"))
3918 newFileLoc.replace(histbug, diff, val);
3923 final String[] pdbf = pdbfilenames.toArray(new String[pdbfilenames
3925 final String[] id = pdbids.toArray(new String[pdbids.size()]);
3926 final SequenceI[][] sq = seqmaps
3927 .toArray(new SequenceI[seqmaps.size()][]);
3928 final String fileloc = newFileLoc.toString();
3929 final String sviewid = viewerData.getKey();
3930 final AlignFrame alf = af;
3931 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
3932 svattrib.getWidth(), svattrib.getHeight());
3935 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
3940 JalviewStructureDisplayI sview = null;
3943 sview = new StructureViewer(alf.alignPanel
3944 .getStructureSelectionManager()).createView(
3945 StructureViewer.ViewerType.JMOL, pdbf, id, sq,
3946 alf.alignPanel, svattrib, fileloc, rect, sviewid);
3947 addNewStructureViewer(sview);
3948 } catch (OutOfMemoryError ex)
3950 new OOMWarning("restoring structure view for PDB id " + id,
3951 (OutOfMemoryError) ex.getCause());
3952 if (sview != null && sview.isVisible())
3954 sview.closeViewer(false);
3955 sview.setVisible(false);
3961 } catch (InvocationTargetException ex)
3963 warn("Unexpected error when opening Jmol view.", ex);
3965 } catch (InterruptedException e)
3967 // e.printStackTrace();
3973 * Generates a name for the entry in the project jar file to hold state
3974 * information for a structure viewer
3979 protected String getViewerJarEntryName(String viewId)
3981 return VIEWER_PREFIX + viewId;
3985 * Returns any open frame that matches given structure viewer data. The match
3986 * is based on the unique viewId, or (for older project versions) the frame's
3992 protected StructureViewerBase findMatchingViewer(
3993 Entry<String, StructureViewerModel> viewerData)
3995 final String sviewid = viewerData.getKey();
3996 final StructureViewerModel svattrib = viewerData.getValue();
3997 StructureViewerBase comp = null;
3998 JInternalFrame[] frames = getAllFrames();
3999 for (JInternalFrame frame : frames)
4001 if (frame instanceof StructureViewerBase)
4004 * Post jalview 2.4 schema includes structure view id
4007 && ((StructureViewerBase) frame).getViewId()
4010 comp = (StructureViewerBase) frame;
4011 break; // break added in 2.9
4014 * Otherwise test for matching position and size of viewer frame
4016 else if (frame.getX() == svattrib.getX()
4017 && frame.getY() == svattrib.getY()
4018 && frame.getHeight() == svattrib.getHeight()
4019 && frame.getWidth() == svattrib.getWidth())
4021 comp = (StructureViewerBase) frame;
4022 // no break in faint hope of an exact match on viewId
4030 * Link an AlignmentPanel to an existing structure viewer.
4035 * @param useinViewerSuperpos
4036 * @param usetoColourbyseq
4037 * @param viewerColouring
4039 protected void linkStructureViewer(AlignmentPanel ap,
4040 StructureViewerBase viewer, StructureViewerModel stateData)
4042 // NOTE: if the jalview project is part of a shared session then
4043 // view synchronization should/could be done here.
4045 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
4046 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
4047 final boolean viewerColouring = stateData.isColourByViewer();
4048 Map<File, StructureData> oldFiles = stateData.getFileData();
4051 * Add mapping for sequences in this view to an already open viewer
4053 final AAStructureBindingModel binding = viewer.getBinding();
4054 for (File id : oldFiles.keySet())
4056 // add this and any other pdb files that should be present in the
4058 StructureData filedat = oldFiles.get(id);
4059 String pdbFile = filedat.getFilePath();
4060 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
4061 binding.getSsm().setMapping(seq, null, pdbFile,
4062 jalview.io.AppletFormatAdapter.FILE);
4063 binding.addSequenceForStructFile(pdbFile, seq);
4065 // and add the AlignmentPanel's reference to the view panel
4066 viewer.addAlignmentPanel(ap);
4067 if (useinViewerSuperpos)
4069 viewer.useAlignmentPanelForSuperposition(ap);
4073 viewer.excludeAlignmentPanelForSuperposition(ap);
4075 if (usetoColourbyseq)
4077 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4081 viewer.excludeAlignmentPanelForColourbyseq(ap);
4086 * Get all frames within the Desktop.
4090 protected JInternalFrame[] getAllFrames()
4092 JInternalFrame[] frames = null;
4093 // TODO is this necessary - is it safe - risk of hanging?
4098 frames = Desktop.desktop.getAllFrames();
4099 } catch (ArrayIndexOutOfBoundsException e)
4101 // occasional No such child exceptions are thrown here...
4105 } catch (InterruptedException f)
4109 } while (frames == null);
4114 * Answers true if 'version' is equal to or later than 'supported', where each
4115 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4116 * changes. Development and test values for 'version' are leniently treated
4120 * - minimum version we are comparing against
4122 * - version of data being processsed
4125 public static boolean isVersionStringLaterThan(String supported,
4128 if (supported == null || version == null
4129 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4130 || version.equalsIgnoreCase("Test")
4131 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4133 System.err.println("Assuming project file with "
4134 + (version == null ? "null" : version)
4135 + " is compatible with Jalview version " + supported);
4140 return StringUtils.compareVersions(version, supported, "b") >= 0;
4144 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4146 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4148 if (newStructureViewers != null)
4150 sview.getBinding().setFinishedLoadingFromArchive(false);
4151 newStructureViewers.add(sview);
4155 protected void setLoadingFinishedForNewStructureViewers()
4157 if (newStructureViewers != null)
4159 for (JalviewStructureDisplayI sview : newStructureViewers)
4161 sview.getBinding().setFinishedLoadingFromArchive(true);
4163 newStructureViewers.clear();
4164 newStructureViewers = null;
4168 AlignFrame loadViewport(String file, JSeq[] JSEQ,
4169 List<SequenceI> hiddenSeqs, AlignmentI al,
4170 JalviewModelSequence jms, Viewport view, String uniqueSeqSetId,
4171 String viewId, List<JvAnnotRow> autoAlan)
4173 AlignFrame af = null;
4174 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
4175 uniqueSeqSetId, viewId);
4177 af.setFileName(file, "Jalview");
4179 for (int i = 0; i < JSEQ.length; i++)
4181 af.viewport.setSequenceColour(af.viewport.getAlignment()
4182 .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour()));
4187 af.getViewport().setColourByReferenceSeq(true);
4188 af.getViewport().setDisplayReferenceSeq(true);
4191 af.viewport.setGatherViewsHere(view.getGatheredViews());
4193 if (view.getSequenceSetId() != null)
4195 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4197 af.viewport.setSequenceSetId(uniqueSeqSetId);
4200 // propagate shared settings to this new view
4201 af.viewport.setHistoryList(av.getHistoryList());
4202 af.viewport.setRedoList(av.getRedoList());
4206 viewportsAdded.put(uniqueSeqSetId, af.viewport);
4208 // TODO: check if this method can be called repeatedly without
4209 // side-effects if alignpanel already registered.
4210 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4212 // apply Hidden regions to view.
4213 if (hiddenSeqs != null)
4215 for (int s = 0; s < JSEQ.length; s++)
4217 SequenceGroup hidden = new SequenceGroup();
4218 boolean isRepresentative = false;
4219 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
4221 isRepresentative = true;
4222 SequenceI sequenceToHide = al.getSequenceAt(JSEQ[s]
4223 .getHiddenSequences(r));
4224 hidden.addSequence(sequenceToHide, false);
4225 // remove from hiddenSeqs list so we don't try to hide it twice
4226 hiddenSeqs.remove(sequenceToHide);
4228 if (isRepresentative)
4230 SequenceI representativeSequence = al.getSequenceAt(s);
4231 hidden.addSequence(representativeSequence, false);
4232 af.viewport.hideRepSequences(representativeSequence, hidden);
4236 SequenceI[] hseqs = hiddenSeqs.toArray(new SequenceI[hiddenSeqs
4238 af.viewport.hideSequence(hseqs);
4241 // recover view properties and display parameters
4242 if (view.getViewName() != null)
4244 af.viewport.viewName = view.getViewName();
4245 af.setInitialTabVisible();
4247 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
4250 af.viewport.setShowAnnotation(view.getShowAnnotation());
4251 af.viewport.setAbovePIDThreshold(view.getPidSelected());
4253 af.viewport.setColourText(view.getShowColourText());
4255 af.viewport.setConservationSelected(view.getConservationSelected());
4256 af.viewport.setShowJVSuffix(view.getShowFullId());
4257 af.viewport.setRightAlignIds(view.getRightAlignIds());
4258 af.viewport.setFont(
4259 new java.awt.Font(view.getFontName(), view.getFontStyle(), view
4260 .getFontSize()), true);
4261 ViewStyleI vs = af.viewport.getViewStyle();
4262 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
4263 af.viewport.setViewStyle(vs);
4264 // TODO: allow custom charWidth/Heights to be restored by updating them
4265 // after setting font - which means set above to false
4266 af.viewport.setRenderGaps(view.getRenderGaps());
4267 af.viewport.setWrapAlignment(view.getWrapAlignment());
4268 af.viewport.setShowAnnotation(view.getShowAnnotation());
4270 af.viewport.setShowBoxes(view.getShowBoxes());
4272 af.viewport.setShowText(view.getShowText());
4274 af.viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
4275 af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
4276 af.viewport.setThresholdTextColour(view.getTextColThreshold());
4277 af.viewport.setShowUnconserved(view.hasShowUnconserved() ? view
4278 .isShowUnconserved() : false);
4279 af.viewport.setStartRes(view.getStartRes());
4280 af.viewport.setStartSeq(view.getStartSeq());
4281 af.alignPanel.updateLayout();
4282 ColourSchemeI cs = null;
4283 // apply colourschemes
4284 if (view.getBgColour() != null)
4286 if (view.getBgColour().startsWith("ucs"))
4288 cs = getUserColourScheme(jms, view.getBgColour());
4290 else if (view.getBgColour().startsWith("Annotation"))
4292 AnnotationColours viewAnnColour = view.getAnnotationColours();
4293 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
4300 cs = ColourSchemeProperty.getColour(al, view.getBgColour());
4305 cs.setThreshold(view.getPidThreshold(), true);
4306 cs.setConsensus(af.viewport.getSequenceConsensusHash());
4310 af.viewport.setGlobalColourScheme(cs);
4311 af.viewport.setColourAppliesToAllGroups(false);
4313 if (view.getConservationSelected() && cs != null)
4315 cs.setConservationInc(view.getConsThreshold());
4318 af.changeColour(cs);
4320 af.viewport.setColourAppliesToAllGroups(true);
4322 af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures());
4324 if (view.hasCentreColumnLabels())
4326 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
4328 if (view.hasIgnoreGapsinConsensus())
4330 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
4333 if (view.hasFollowHighlight())
4335 af.viewport.setFollowHighlight(view.getFollowHighlight());
4337 if (view.hasFollowSelection())
4339 af.viewport.followSelection = view.getFollowSelection();
4341 if (view.hasShowConsensusHistogram())
4343 af.viewport.setShowConsensusHistogram(view
4344 .getShowConsensusHistogram());
4348 af.viewport.setShowConsensusHistogram(true);
4350 if (view.hasShowSequenceLogo())
4352 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
4356 af.viewport.setShowSequenceLogo(false);
4358 if (view.hasNormaliseSequenceLogo())
4360 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
4362 if (view.hasShowDbRefTooltip())
4364 af.viewport.setShowDBRefs(view.getShowDbRefTooltip());
4366 if (view.hasShowNPfeatureTooltip())
4368 af.viewport.setShowNPFeats(view.hasShowNPfeatureTooltip());
4370 if (view.hasShowGroupConsensus())
4372 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
4376 af.viewport.setShowGroupConsensus(false);
4378 if (view.hasShowGroupConservation())
4380 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
4384 af.viewport.setShowGroupConservation(false);
4387 // recover featre settings
4388 if (jms.getFeatureSettings() != null)
4390 FeaturesDisplayed fdi;
4391 af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
4392 String[] renderOrder = new String[jms.getFeatureSettings()
4393 .getSettingCount()];
4394 Map<String, FeatureColourI> featureColours = new Hashtable<String, FeatureColourI>();
4395 Map<String, Float> featureOrder = new Hashtable<String, Float>();
4397 for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
4399 Setting setting = jms.getFeatureSettings().getSetting(fs);
4400 if (setting.hasMincolour())
4402 FeatureColourI gc = setting.hasMin() ? new FeatureColour(
4403 new Color(setting.getMincolour()), new Color(
4404 setting.getColour()), setting.getMin(),
4405 setting.getMax()) : new FeatureColour(new Color(
4406 setting.getMincolour()), new Color(setting.getColour()),
4408 if (setting.hasThreshold())
4410 gc.setThreshold(setting.getThreshold());
4411 int threshstate = setting.getThreshstate();
4412 // -1 = None, 0 = Below, 1 = Above threshold
4413 if (threshstate == 0)
4415 gc.setBelowThreshold(true);
4417 else if (threshstate == 1)
4419 gc.setAboveThreshold(true);
4422 gc.setAutoScaled(true); // default
4423 if (setting.hasAutoScale())
4425 gc.setAutoScaled(setting.getAutoScale());
4427 if (setting.hasColourByLabel())
4429 gc.setColourByLabel(setting.getColourByLabel());
4431 // and put in the feature colour table.
4432 featureColours.put(setting.getType(), gc);
4436 featureColours.put(setting.getType(), new FeatureColour(
4437 new Color(setting.getColour())));
4439 renderOrder[fs] = setting.getType();
4440 if (setting.hasOrder())
4442 featureOrder.put(setting.getType(), setting.getOrder());
4446 featureOrder.put(setting.getType(), new Float(fs
4447 / jms.getFeatureSettings().getSettingCount()));
4449 if (setting.getDisplay())
4451 fdi.setVisible(setting.getType());
4454 Map<String, Boolean> fgtable = new Hashtable<String, Boolean>();
4455 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
4457 Group grp = jms.getFeatureSettings().getGroup(gs);
4458 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
4460 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4461 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
4462 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
4463 FeatureRendererSettings frs = new FeatureRendererSettings(
4464 renderOrder, fgtable, featureColours, 1.0f, featureOrder);
4465 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
4466 .transferSettings(frs);
4470 if (view.getHiddenColumnsCount() > 0)
4472 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
4474 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(), view
4475 .getHiddenColumns(c).getEnd() // +1
4479 if (view.getCalcIdParam() != null)
4481 for (CalcIdParam calcIdParam : view.getCalcIdParam())
4483 if (calcIdParam != null)
4485 if (recoverCalcIdParam(calcIdParam, af.viewport))
4490 warn("Couldn't recover parameters for "
4491 + calcIdParam.getCalcId());
4496 af.setMenusFromViewport(af.viewport);
4498 // TODO: we don't need to do this if the viewport is aready visible.
4500 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
4501 * has a 'cdna/protein complement' view, in which case save it in order to
4502 * populate a SplitFrame once all views have been read in.
4504 String complementaryViewId = view.getComplementId();
4505 if (complementaryViewId == null)
4507 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
4509 // recompute any autoannotation
4510 af.alignPanel.updateAnnotation(false, true);
4511 reorderAutoannotation(af, al, autoAlan);
4512 af.alignPanel.alignmentChanged();
4516 splitFrameCandidates.put(view, af);
4521 private ColourSchemeI constructAnnotationColour(
4522 AnnotationColours viewAnnColour, AlignFrame af, AlignmentI al,
4523 JalviewModelSequence jms, boolean checkGroupAnnColour)
4525 boolean propagateAnnColour = false;
4526 ColourSchemeI cs = null;
4527 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
4528 if (checkGroupAnnColour && al.getGroups() != null
4529 && al.getGroups().size() > 0)
4531 // pre 2.8.1 behaviour
4532 // check to see if we should transfer annotation colours
4533 propagateAnnColour = true;
4534 for (jalview.datamodel.SequenceGroup sg : al.getGroups())
4536 if (sg.cs instanceof AnnotationColourGradient)
4538 propagateAnnColour = false;
4542 // int find annotation
4543 if (annAlignment.getAlignmentAnnotation() != null)
4545 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
4547 if (annAlignment.getAlignmentAnnotation()[i].label
4548 .equals(viewAnnColour.getAnnotation()))
4550 if (annAlignment.getAlignmentAnnotation()[i].getThreshold() == null)
4552 annAlignment.getAlignmentAnnotation()[i]
4553 .setThreshold(new jalview.datamodel.GraphLine(
4554 viewAnnColour.getThreshold(), "Threshold",
4555 java.awt.Color.black)
4560 if (viewAnnColour.getColourScheme().equals("None"))
4562 cs = new AnnotationColourGradient(
4563 annAlignment.getAlignmentAnnotation()[i],
4564 new java.awt.Color(viewAnnColour.getMinColour()),
4565 new java.awt.Color(viewAnnColour.getMaxColour()),
4566 viewAnnColour.getAboveThreshold());
4568 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
4570 cs = new AnnotationColourGradient(
4571 annAlignment.getAlignmentAnnotation()[i],
4572 getUserColourScheme(jms,
4573 viewAnnColour.getColourScheme()),
4574 viewAnnColour.getAboveThreshold());
4578 cs = new AnnotationColourGradient(
4579 annAlignment.getAlignmentAnnotation()[i],
4580 ColourSchemeProperty.getColour(al,
4581 viewAnnColour.getColourScheme()),
4582 viewAnnColour.getAboveThreshold());
4584 if (viewAnnColour.hasPerSequence())
4586 ((AnnotationColourGradient) cs).setSeqAssociated(viewAnnColour
4589 if (viewAnnColour.hasPredefinedColours())
4591 ((AnnotationColourGradient) cs)
4592 .setPredefinedColours(viewAnnColour
4593 .isPredefinedColours());
4595 if (propagateAnnColour && al.getGroups() != null)
4597 // Also use these settings for all the groups
4598 for (int g = 0; g < al.getGroups().size(); g++)
4600 jalview.datamodel.SequenceGroup sg = al.getGroups().get(g);
4608 * if (viewAnnColour.getColourScheme().equals("None" )) { sg.cs =
4609 * new AnnotationColourGradient(
4610 * annAlignment.getAlignmentAnnotation()[i], new
4611 * java.awt.Color(viewAnnColour. getMinColour()), new
4612 * java.awt.Color(viewAnnColour. getMaxColour()),
4613 * viewAnnColour.getAboveThreshold()); } else
4616 sg.cs = new AnnotationColourGradient(
4617 annAlignment.getAlignmentAnnotation()[i], sg.cs,
4618 viewAnnColour.getAboveThreshold());
4619 if (cs instanceof AnnotationColourGradient)
4621 if (viewAnnColour.hasPerSequence())
4623 ((AnnotationColourGradient) cs)
4624 .setSeqAssociated(viewAnnColour.isPerSequence());
4626 if (viewAnnColour.hasPredefinedColours())
4628 ((AnnotationColourGradient) cs)
4629 .setPredefinedColours(viewAnnColour
4630 .isPredefinedColours());
4646 private void reorderAutoannotation(AlignFrame af, AlignmentI al,
4647 List<JvAnnotRow> autoAlan)
4649 // copy over visualization settings for autocalculated annotation in the
4651 if (al.getAlignmentAnnotation() != null)
4654 * Kludge for magic autoannotation names (see JAL-811)
4656 String[] magicNames = new String[] { "Consensus", "Quality",
4658 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
4659 Hashtable<String, JvAnnotRow> visan = new Hashtable<String, JvAnnotRow>();
4660 for (String nm : magicNames)
4662 visan.put(nm, nullAnnot);
4664 for (JvAnnotRow auan : autoAlan)
4666 visan.put(auan.template.label
4667 + (auan.template.getCalcId() == null ? "" : "\t"
4668 + auan.template.getCalcId()), auan);
4670 int hSize = al.getAlignmentAnnotation().length;
4671 List<JvAnnotRow> reorder = new ArrayList<JvAnnotRow>();
4672 // work through any autoCalculated annotation already on the view
4673 // removing it if it should be placed in a different location on the
4674 // annotation panel.
4675 List<String> remains = new ArrayList<String>(visan.keySet());
4676 for (int h = 0; h < hSize; h++)
4678 jalview.datamodel.AlignmentAnnotation jalan = al
4679 .getAlignmentAnnotation()[h];
4680 if (jalan.autoCalculated)
4683 JvAnnotRow valan = visan.get(k = jalan.label);
4684 if (jalan.getCalcId() != null)
4686 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
4691 // delete the auto calculated row from the alignment
4692 al.deleteAnnotation(jalan, false);
4696 if (valan != nullAnnot)
4698 if (jalan != valan.template)
4700 // newly created autoannotation row instance
4701 // so keep a reference to the visible annotation row
4702 // and copy over all relevant attributes
4703 if (valan.template.graphHeight >= 0)
4706 jalan.graphHeight = valan.template.graphHeight;
4708 jalan.visible = valan.template.visible;
4710 reorder.add(new JvAnnotRow(valan.order, jalan));
4715 // Add any (possibly stale) autocalculated rows that were not appended to
4716 // the view during construction
4717 for (String other : remains)
4719 JvAnnotRow othera = visan.get(other);
4720 if (othera != nullAnnot && othera.template.getCalcId() != null
4721 && othera.template.getCalcId().length() > 0)
4723 reorder.add(othera);
4726 // now put the automatic annotation in its correct place
4727 int s = 0, srt[] = new int[reorder.size()];
4728 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
4729 for (JvAnnotRow jvar : reorder)
4732 srt[s++] = jvar.order;
4735 jalview.util.QuickSort.sort(srt, rws);
4736 // and re-insert the annotation at its correct position
4737 for (JvAnnotRow jvar : rws)
4739 al.addAnnotation(jvar.template, jvar.order);
4741 af.alignPanel.adjustAnnotationHeight();
4745 Hashtable skipList = null;
4748 * TODO remove this method
4751 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
4752 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
4753 * throw new Error("Implementation Error. No skipList defined for this
4754 * Jalview2XML instance."); } return (AlignFrame)
4755 * skipList.get(view.getSequenceSetId()); }
4759 * Check if the Jalview view contained in object should be skipped or not.
4762 * @return true if view's sequenceSetId is a key in skipList
4764 private boolean skipViewport(JalviewModel object)
4766 if (skipList == null)
4771 if (skipList.containsKey(id = object.getJalviewModelSequence()
4772 .getViewport()[0].getSequenceSetId()))
4774 if (Cache.log != null && Cache.log.isDebugEnabled())
4776 Cache.log.debug("Skipping seuqence set id " + id);
4783 public void addToSkipList(AlignFrame af)
4785 if (skipList == null)
4787 skipList = new Hashtable();
4789 skipList.put(af.getViewport().getSequenceSetId(), af);
4792 public void clearSkipList()
4794 if (skipList != null)
4801 private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
4802 boolean ignoreUnrefed)
4804 jalview.datamodel.AlignmentI ds = getDatasetFor(vamsasSet
4806 Vector dseqs = null;
4809 // create a list of new dataset sequences
4810 dseqs = new Vector();
4812 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
4814 Sequence vamsasSeq = vamsasSet.getSequence(i);
4815 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed);
4817 // create a new dataset
4820 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
4821 dseqs.copyInto(dsseqs);
4822 ds = new jalview.datamodel.Alignment(dsseqs);
4823 debug("Created new dataset " + vamsasSet.getDatasetId()
4824 + " for alignment " + System.identityHashCode(al));
4825 addDatasetRef(vamsasSet.getDatasetId(), ds);
4827 // set the dataset for the newly imported alignment.
4828 if (al.getDataset() == null && !ignoreUnrefed)
4837 * sequence definition to create/merge dataset sequence for
4841 * vector to add new dataset sequence to
4843 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
4844 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed)
4846 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
4848 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
4849 SequenceI dsq = null;
4850 if (sq != null && sq.getDatasetSequence() != null)
4852 dsq = sq.getDatasetSequence();
4854 if (sq == null && ignoreUnrefed)
4858 String sqid = vamsasSeq.getDsseqid();
4861 // need to create or add a new dataset sequence reference to this sequence
4864 dsq = seqRefIds.get(sqid);
4869 // make a new dataset sequence
4870 dsq = sq.createDatasetSequence();
4873 // make up a new dataset reference for this sequence
4874 sqid = seqHash(dsq);
4876 dsq.setVamsasId(uniqueSetSuffix + sqid);
4877 seqRefIds.put(sqid, dsq);
4882 dseqs.addElement(dsq);
4887 ds.addSequence(dsq);
4893 { // make this dataset sequence sq's dataset sequence
4894 sq.setDatasetSequence(dsq);
4895 // and update the current dataset alignment
4900 if (!dseqs.contains(dsq))
4907 if (ds.findIndex(dsq) < 0)
4909 ds.addSequence(dsq);
4916 // TODO: refactor this as a merge dataset sequence function
4917 // now check that sq (the dataset sequence) sequence really is the union of
4918 // all references to it
4919 // boolean pre = sq.getStart() < dsq.getStart();
4920 // boolean post = sq.getEnd() > dsq.getEnd();
4924 // StringBuffer sb = new StringBuffer();
4925 String newres = jalview.analysis.AlignSeq.extractGaps(
4926 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
4927 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
4928 && newres.length() > dsq.getLength())
4930 // Update with the longer sequence.
4934 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
4935 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
4936 * sb.append(newres.substring(newres.length() - sq.getEnd() -
4937 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
4939 dsq.setSequence(newres);
4941 // TODO: merges will never happen if we 'know' we have the real dataset
4942 // sequence - this should be detected when id==dssid
4944 .println("DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
4945 // + (pre ? "prepended" : "") + " "
4946 // + (post ? "appended" : ""));
4952 * TODO use AlignmentI here and in related methods - needs
4953 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
4955 Hashtable<String, AlignmentI> datasetIds = null;
4957 IdentityHashMap<AlignmentI, String> dataset2Ids = null;
4959 private AlignmentI getDatasetFor(String datasetId)
4961 if (datasetIds == null)
4963 datasetIds = new Hashtable<String, AlignmentI>();
4966 if (datasetIds.containsKey(datasetId))
4968 return datasetIds.get(datasetId);
4973 private void addDatasetRef(String datasetId, AlignmentI dataset)
4975 if (datasetIds == null)
4977 datasetIds = new Hashtable<String, AlignmentI>();
4979 datasetIds.put(datasetId, dataset);
4983 * make a new dataset ID for this jalview dataset alignment
4988 private String getDatasetIdRef(AlignmentI dataset)
4990 if (dataset.getDataset() != null)
4992 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
4994 String datasetId = makeHashCode(dataset, null);
4995 if (datasetId == null)
4997 // make a new datasetId and record it
4998 if (dataset2Ids == null)
5000 dataset2Ids = new IdentityHashMap<AlignmentI, String>();
5004 datasetId = dataset2Ids.get(dataset);
5006 if (datasetId == null)
5008 datasetId = "ds" + dataset2Ids.size() + 1;
5009 dataset2Ids.put(dataset, datasetId);
5015 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
5017 for (int d = 0; d < sequence.getDBRefCount(); d++)
5019 DBRef dr = sequence.getDBRef(d);
5020 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
5021 sequence.getDBRef(d).getSource(), sequence.getDBRef(d)
5022 .getVersion(), sequence.getDBRef(d).getAccessionId());
5023 if (dr.getMapping() != null)
5025 entry.setMap(addMapping(dr.getMapping()));
5027 datasetSequence.addDBRef(entry);
5031 private jalview.datamodel.Mapping addMapping(Mapping m)
5033 SequenceI dsto = null;
5034 // Mapping m = dr.getMapping();
5035 int fr[] = new int[m.getMapListFromCount() * 2];
5036 Enumeration f = m.enumerateMapListFrom();
5037 for (int _i = 0; f.hasMoreElements(); _i += 2)
5039 MapListFrom mf = (MapListFrom) f.nextElement();
5040 fr[_i] = mf.getStart();
5041 fr[_i + 1] = mf.getEnd();
5043 int fto[] = new int[m.getMapListToCount() * 2];
5044 f = m.enumerateMapListTo();
5045 for (int _i = 0; f.hasMoreElements(); _i += 2)
5047 MapListTo mf = (MapListTo) f.nextElement();
5048 fto[_i] = mf.getStart();
5049 fto[_i + 1] = mf.getEnd();
5051 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto,
5052 fr, fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
5053 if (m.getMappingChoice() != null)
5055 MappingChoice mc = m.getMappingChoice();
5056 if (mc.getDseqFor() != null)
5058 String dsfor = "" + mc.getDseqFor();
5059 if (seqRefIds.containsKey(dsfor))
5064 jmap.setTo(seqRefIds.get(dsfor));
5068 frefedSequence.add(newMappingRef(dsfor, jmap));
5074 * local sequence definition
5076 Sequence ms = mc.getSequence();
5077 SequenceI djs = null;
5078 String sqid = ms.getDsseqid();
5079 if (sqid != null && sqid.length() > 0)
5082 * recover dataset sequence
5084 djs = seqRefIds.get(sqid);
5089 .println("Warning - making up dataset sequence id for DbRef sequence map reference");
5090 sqid = ((Object) ms).toString(); // make up a new hascode for
5091 // undefined dataset sequence hash
5092 // (unlikely to happen)
5098 * make a new dataset sequence and add it to refIds hash
5100 djs = new jalview.datamodel.Sequence(ms.getName(),
5102 djs.setStart(jmap.getMap().getToLowest());
5103 djs.setEnd(jmap.getMap().getToHighest());
5104 djs.setVamsasId(uniqueSetSuffix + sqid);
5106 seqRefIds.put(sqid, djs);
5109 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5118 public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
5119 boolean keepSeqRefs)
5122 JalviewModel jm = saveState(ap, null, null, null);
5127 jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
5131 uniqueSetSuffix = "";
5132 jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
5137 if (this.frefedSequence == null)
5139 frefedSequence = new Vector();
5142 viewportsAdded.clear();
5144 AlignFrame af = loadFromObject(jm, null, false, null);
5145 af.alignPanels.clear();
5146 af.closeMenuItem_actionPerformed(true);
5149 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5150 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5151 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5152 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5153 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5156 return af.alignPanel;
5160 * flag indicating if hashtables should be cleared on finalization TODO this
5161 * flag may not be necessary
5163 private final boolean _cleartables = true;
5165 private Hashtable jvids2vobj;
5170 * @see java.lang.Object#finalize()
5173 protected void finalize() throws Throwable
5175 // really make sure we have no buried refs left.
5180 this.seqRefIds = null;
5181 this.seqsToIds = null;
5185 private void warn(String msg)
5190 private void warn(String msg, Exception e)
5192 if (Cache.log != null)
5196 Cache.log.warn(msg, e);
5200 Cache.log.warn(msg);
5205 System.err.println("Warning: " + msg);
5208 e.printStackTrace();
5213 private void debug(String string)
5215 debug(string, null);
5218 private void debug(String msg, Exception e)
5220 if (Cache.log != null)
5224 Cache.log.debug(msg, e);
5228 Cache.log.debug(msg);
5233 System.err.println("Warning: " + msg);
5236 e.printStackTrace();
5242 * set the object to ID mapping tables used to write/recover objects and XML
5243 * ID strings for the jalview project. If external tables are provided then
5244 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
5245 * object goes out of scope. - also populates the datasetIds hashtable with
5246 * alignment objects containing dataset sequences
5249 * Map from ID strings to jalview datamodel
5251 * Map from jalview datamodel to ID strings
5255 public void setObjectMappingTables(Hashtable vobj2jv,
5256 IdentityHashMap jv2vobj)
5258 this.jv2vobj = jv2vobj;
5259 this.vobj2jv = vobj2jv;
5260 Iterator ds = jv2vobj.keySet().iterator();
5262 while (ds.hasNext())
5264 Object jvobj = ds.next();
5265 id = jv2vobj.get(jvobj).toString();
5266 if (jvobj instanceof jalview.datamodel.Alignment)
5268 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
5270 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
5273 else if (jvobj instanceof jalview.datamodel.Sequence)
5275 // register sequence object so the XML parser can recover it.
5276 if (seqRefIds == null)
5278 seqRefIds = new HashMap<String, SequenceI>();
5280 if (seqsToIds == null)
5282 seqsToIds = new IdentityHashMap<SequenceI, String>();
5284 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
5285 seqsToIds.put((SequenceI) jvobj, id);
5287 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
5290 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
5291 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
5292 if (jvann.annotationId == null)
5294 jvann.annotationId = anid;
5296 if (!jvann.annotationId.equals(anid))
5298 // TODO verify that this is the correct behaviour
5299 this.warn("Overriding Annotation ID for " + anid
5300 + " from different id : " + jvann.annotationId);
5301 jvann.annotationId = anid;
5304 else if (jvobj instanceof String)
5306 if (jvids2vobj == null)
5308 jvids2vobj = new Hashtable();
5309 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
5314 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
5320 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
5321 * objects created from the project archive. If string is null (default for
5322 * construction) then suffix will be set automatically.
5326 public void setUniqueSetSuffix(String string)
5328 uniqueSetSuffix = string;
5333 * uses skipList2 as the skipList for skipping views on sequence sets
5334 * associated with keys in the skipList
5338 public void setSkipList(Hashtable skipList2)
5340 skipList = skipList2;
5344 * Reads the jar entry of given name and returns its contents, or null if the
5345 * entry is not found.
5348 * @param jarEntryName
5351 protected String readJarEntry(jarInputStreamProvider jprovider,
5352 String jarEntryName)
5354 String result = null;
5355 BufferedReader in = null;
5360 * Reopen the jar input stream and traverse its entries to find a matching
5363 JarInputStream jin = jprovider.getJarInputStream();
5364 JarEntry entry = null;
5367 entry = jin.getNextJarEntry();
5368 } while (entry != null && !entry.getName().equals(jarEntryName));
5372 StringBuilder out = new StringBuilder(256);
5373 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
5376 while ((data = in.readLine()) != null)
5380 result = out.toString();
5384 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
5386 } catch (Exception ex)
5388 ex.printStackTrace();
5396 } catch (IOException e)
5407 * Returns an incrementing counter (0, 1, 2...)
5411 private synchronized int nextCounter()