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.ViewStyleI;
24 import jalview.api.structures.JalviewStructureDisplayI;
25 import jalview.bin.Cache;
26 import jalview.datamodel.AlignedCodonFrame;
27 import jalview.datamodel.Alignment;
28 import jalview.datamodel.AlignmentAnnotation;
29 import jalview.datamodel.AlignmentI;
30 import jalview.datamodel.PDBEntry;
31 import jalview.datamodel.RnaViewerModel;
32 import jalview.datamodel.SequenceGroup;
33 import jalview.datamodel.SequenceI;
34 import jalview.datamodel.StructureViewerModel;
35 import jalview.datamodel.StructureViewerModel.StructureData;
36 import jalview.ext.varna.RnaModel;
37 import jalview.gui.StructureViewer.ViewerType;
38 import jalview.schemabinding.version2.AlcodMap;
39 import jalview.schemabinding.version2.AlcodonFrame;
40 import jalview.schemabinding.version2.Annotation;
41 import jalview.schemabinding.version2.AnnotationColours;
42 import jalview.schemabinding.version2.AnnotationElement;
43 import jalview.schemabinding.version2.CalcIdParam;
44 import jalview.schemabinding.version2.DBRef;
45 import jalview.schemabinding.version2.Features;
46 import jalview.schemabinding.version2.Group;
47 import jalview.schemabinding.version2.HiddenColumns;
48 import jalview.schemabinding.version2.JGroup;
49 import jalview.schemabinding.version2.JSeq;
50 import jalview.schemabinding.version2.JalviewModel;
51 import jalview.schemabinding.version2.JalviewModelSequence;
52 import jalview.schemabinding.version2.MapListFrom;
53 import jalview.schemabinding.version2.MapListTo;
54 import jalview.schemabinding.version2.Mapping;
55 import jalview.schemabinding.version2.MappingChoice;
56 import jalview.schemabinding.version2.OtherData;
57 import jalview.schemabinding.version2.PdbentryItem;
58 import jalview.schemabinding.version2.Pdbids;
59 import jalview.schemabinding.version2.Property;
60 import jalview.schemabinding.version2.RnaViewer;
61 import jalview.schemabinding.version2.SecondaryStructure;
62 import jalview.schemabinding.version2.Sequence;
63 import jalview.schemabinding.version2.SequenceSet;
64 import jalview.schemabinding.version2.SequenceSetProperties;
65 import jalview.schemabinding.version2.Setting;
66 import jalview.schemabinding.version2.StructureState;
67 import jalview.schemabinding.version2.ThresholdLine;
68 import jalview.schemabinding.version2.Tree;
69 import jalview.schemabinding.version2.UserColours;
70 import jalview.schemabinding.version2.Viewport;
71 import jalview.schemes.AnnotationColourGradient;
72 import jalview.schemes.ColourSchemeI;
73 import jalview.schemes.ColourSchemeProperty;
74 import jalview.schemes.GraduatedColor;
75 import jalview.schemes.ResidueColourScheme;
76 import jalview.schemes.ResidueProperties;
77 import jalview.schemes.UserColourScheme;
78 import jalview.structure.StructureSelectionManager;
79 import jalview.structures.models.AAStructureBindingModel;
80 import jalview.util.MessageManager;
81 import jalview.util.Platform;
82 import jalview.util.StringUtils;
83 import jalview.util.jarInputStreamProvider;
84 import jalview.viewmodel.AlignmentViewport;
85 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
86 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
87 import jalview.ws.jws2.Jws2Discoverer;
88 import jalview.ws.jws2.dm.AAConSettings;
89 import jalview.ws.jws2.jabaws2.Jws2Instance;
90 import jalview.ws.params.ArgumentI;
91 import jalview.ws.params.AutoCalcSetting;
92 import jalview.ws.params.WsParamSetI;
94 import java.awt.Color;
95 import java.awt.Rectangle;
96 import java.io.BufferedReader;
97 import java.io.DataInputStream;
98 import java.io.DataOutputStream;
100 import java.io.FileInputStream;
101 import java.io.FileOutputStream;
102 import java.io.IOException;
103 import java.io.InputStreamReader;
104 import java.io.OutputStreamWriter;
105 import java.io.PrintWriter;
106 import java.lang.reflect.InvocationTargetException;
107 import java.net.MalformedURLException;
109 import java.util.ArrayList;
110 import java.util.Enumeration;
111 import java.util.HashMap;
112 import java.util.HashSet;
113 import java.util.Hashtable;
114 import java.util.IdentityHashMap;
115 import java.util.Iterator;
116 import java.util.LinkedHashMap;
117 import java.util.List;
118 import java.util.Map;
119 import java.util.Map.Entry;
120 import java.util.Set;
121 import java.util.Vector;
122 import java.util.jar.JarEntry;
123 import java.util.jar.JarInputStream;
124 import java.util.jar.JarOutputStream;
126 import javax.swing.JInternalFrame;
127 import javax.swing.JOptionPane;
128 import javax.swing.SwingUtilities;
130 import org.exolab.castor.xml.Marshaller;
131 import org.exolab.castor.xml.Unmarshaller;
134 * Write out the current jalview desktop state as a Jalview XML stream.
136 * Note: the vamsas objects referred to here are primitive versions of the
137 * VAMSAS project schema elements - they are not the same and most likely never
141 * @version $Revision: 1.134 $
143 public class Jalview2XML
145 private static final String VIEWER_PREFIX = "viewer_";
147 private static final String RNA_PREFIX = "rna_";
149 private static final String UTF_8 = "UTF-8";
151 // use this with nextCounter() to make unique names for entities
152 private int counter = 0;
155 * SequenceI reference -> XML ID string in jalview XML. Populated as XML reps
156 * of sequence objects are created.
158 IdentityHashMap<SequenceI, String> seqsToIds = null;
161 * jalview XML Sequence ID to jalview sequence object reference (both dataset
162 * and alignment sequences. Populated as XML reps of sequence objects are
165 Map<String, SequenceI> seqRefIds = null;
167 Vector<Object[]> frefedSequence = null;
169 boolean raiseGUI = true; // whether errors are raised in dialog boxes or not
172 * Map of reconstructed AlignFrame objects that appear to have come from
173 * SplitFrame objects (have a dna/protein complement view).
175 private Map<Viewport, AlignFrame> splitFrameCandidates = new HashMap<Viewport, AlignFrame>();
178 * Map from displayed rna structure models to their saved session state jar
181 private Map<RnaModel, String> rnaSessions = new HashMap<RnaModel, String>();
184 * create/return unique hash string for sq
187 * @return new or existing unique string for sq
189 String seqHash(SequenceI sq)
191 if (seqsToIds == null)
195 if (seqsToIds.containsKey(sq))
197 return seqsToIds.get(sq);
201 // create sequential key
202 String key = "sq" + (seqsToIds.size() + 1);
203 key = makeHashCode(sq, key); // check we don't have an external reference
205 seqsToIds.put(sq, key);
214 if (seqRefIds != null)
218 if (seqsToIds != null)
228 warn("clearSeqRefs called when _cleartables was not set. Doing nothing.");
229 // seqRefIds = new Hashtable();
230 // seqsToIds = new IdentityHashMap();
236 if (seqsToIds == null)
238 seqsToIds = new IdentityHashMap<SequenceI, String>();
240 if (seqRefIds == null)
242 seqRefIds = new HashMap<String, SequenceI>();
250 public Jalview2XML(boolean raiseGUI)
252 this.raiseGUI = raiseGUI;
255 public void resolveFrefedSequences()
257 if (frefedSequence.size() > 0)
259 int r = 0, rSize = frefedSequence.size();
262 Object[] ref = frefedSequence.elementAt(r);
265 String sref = (String) ref[0];
266 if (seqRefIds.containsKey(sref))
268 if (ref[1] instanceof jalview.datamodel.Mapping)
270 SequenceI seq = seqRefIds.get(sref);
271 while (seq.getDatasetSequence() != null)
273 seq = seq.getDatasetSequence();
275 ((jalview.datamodel.Mapping) ref[1]).setTo(seq);
279 if (ref[1] instanceof jalview.datamodel.AlignedCodonFrame)
281 SequenceI seq = seqRefIds.get(sref);
282 while (seq.getDatasetSequence() != null)
284 seq = seq.getDatasetSequence();
287 && ref[2] instanceof jalview.datamodel.Mapping)
289 jalview.datamodel.Mapping mp = (jalview.datamodel.Mapping) ref[2];
290 ((jalview.datamodel.AlignedCodonFrame) ref[1]).addMap(
291 seq, mp.getTo(), mp.getMap());
296 .println("IMPLEMENTATION ERROR: Unimplemented forward sequence references for AlcodonFrames involving "
297 + ref[2].getClass() + " type objects.");
303 .println("IMPLEMENTATION ERROR: Unimplemented forward sequence references for "
304 + ref[1].getClass() + " type objects.");
307 frefedSequence.remove(r);
313 .println("IMPLEMENTATION WARNING: Unresolved forward reference for hash string "
315 + " with objecttype "
316 + ref[1].getClass());
323 frefedSequence.remove(r);
331 * This maintains a map of viewports, the key being the seqSetId. Important to
332 * set historyItem and redoList for multiple views
334 Map<String, AlignViewport> viewportsAdded = new HashMap<String, AlignViewport>();
336 Map<String, AlignmentAnnotation> annotationIds = new HashMap<String, AlignmentAnnotation>();
338 String uniqueSetSuffix = "";
341 * List of pdbfiles added to Jar
343 List<String> pdbfiles = null;
345 // SAVES SEVERAL ALIGNMENT WINDOWS TO SAME JARFILE
346 public void saveState(File statefile)
348 FileOutputStream fos = null;
351 fos = new FileOutputStream(statefile);
352 JarOutputStream jout = new JarOutputStream(fos);
355 } catch (Exception e)
357 // TODO: inform user of the problem - they need to know if their data was
359 if (errorMessage == null)
361 errorMessage = "Couldn't write Jalview Archive to output file '"
362 + statefile + "' - See console error log for details";
366 errorMessage += "(output file was '" + statefile + "')";
376 } catch (IOException e)
386 * Writes a jalview project archive to the given Jar output stream.
390 public void saveState(JarOutputStream jout)
392 AlignFrame[] frames = Desktop.getAlignFrames();
399 Hashtable<String, AlignFrame> dsses = new Hashtable<String, AlignFrame>();
402 * ensure cached data is clear before starting
404 // todo tidy up seqRefIds, seqsToIds initialisation / reset
406 splitFrameCandidates.clear();
411 // NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
412 // //////////////////////////////////////////////////
414 List<String> shortNames = new ArrayList<String>();
415 List<String> viewIds = new ArrayList<String>();
418 for (int i = frames.length - 1; i > -1; i--)
420 AlignFrame af = frames[i];
424 .containsKey(af.getViewport().getSequenceSetId()))
429 String shortName = makeFilename(af, shortNames);
431 int ap, apSize = af.alignPanels.size();
433 for (ap = 0; ap < apSize; ap++)
435 AlignmentPanel apanel = af.alignPanels.get(ap);
436 String fileName = apSize == 1 ? shortName : ap + shortName;
437 if (!fileName.endsWith(".xml"))
439 fileName = fileName + ".xml";
442 saveState(apanel, fileName, jout, viewIds);
444 String dssid = getDatasetIdRef(af.getViewport().getAlignment()
446 if (!dsses.containsKey(dssid))
448 dsses.put(dssid, af);
453 writeDatasetFor(dsses, "" + jout.hashCode() + " " + uniqueSetSuffix,
459 } catch (Exception foo)
464 } catch (Exception ex)
466 // TODO: inform user of the problem - they need to know if their data was
468 if (errorMessage == null)
470 errorMessage = "Couldn't write Jalview Archive - see error output for details";
472 ex.printStackTrace();
477 * Generates a distinct file name, based on the title of the AlignFrame, by
478 * appending _n for increasing n until an unused name is generated. The new
479 * name (without its extension) is added to the list.
483 * @return the generated name, with .xml extension
485 protected String makeFilename(AlignFrame af, List<String> namesUsed)
487 String shortName = af.getTitle();
489 if (shortName.indexOf(File.separatorChar) > -1)
491 shortName = shortName.substring(shortName
492 .lastIndexOf(File.separatorChar) + 1);
497 while (namesUsed.contains(shortName))
499 if (shortName.endsWith("_" + (count - 1)))
501 shortName = shortName.substring(0, shortName.lastIndexOf("_"));
504 shortName = shortName.concat("_" + count);
508 namesUsed.add(shortName);
510 if (!shortName.endsWith(".xml"))
512 shortName = shortName + ".xml";
517 // USE THIS METHOD TO SAVE A SINGLE ALIGNMENT WINDOW
518 public boolean saveAlignment(AlignFrame af, String jarFile,
524 int apSize = af.alignPanels.size();
525 FileOutputStream fos = new FileOutputStream(jarFile);
526 JarOutputStream jout = new JarOutputStream(fos);
527 Hashtable<String, AlignFrame> dsses = new Hashtable<String, AlignFrame>();
528 List<String> viewIds = new ArrayList<String>();
530 for (AlignmentPanel apanel : af.alignPanels)
532 String jfileName = apSize == 1 ? fileName : fileName + ap;
534 if (!jfileName.endsWith(".xml"))
536 jfileName = jfileName + ".xml";
538 saveState(apanel, jfileName, jout, viewIds);
539 String dssid = getDatasetIdRef(af.getViewport().getAlignment()
541 if (!dsses.containsKey(dssid))
543 dsses.put(dssid, af);
546 writeDatasetFor(dsses, fileName, jout);
550 } catch (Exception foo)
556 } catch (Exception ex)
558 errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
559 ex.printStackTrace();
564 private void writeDatasetFor(Hashtable<String, AlignFrame> dsses,
565 String fileName, JarOutputStream jout)
568 for (String dssids : dsses.keySet())
570 AlignFrame _af = dsses.get(dssids);
571 String jfileName = fileName + " Dataset for " + _af.getTitle();
572 if (!jfileName.endsWith(".xml"))
574 jfileName = jfileName + ".xml";
576 saveState(_af.alignPanel, jfileName, true, jout, null);
581 * create a JalviewModel from an alignment view and marshall it to a
585 * panel to create jalview model for
587 * name of alignment panel written to output stream
594 public JalviewModel saveState(AlignmentPanel ap, String fileName,
595 JarOutputStream jout, List<String> viewIds)
597 return saveState(ap, fileName, false, jout, viewIds);
601 * create a JalviewModel from an alignment view and marshall it to a
605 * panel to create jalview model for
607 * name of alignment panel written to output stream
609 * when true, only write the dataset for the alignment, not the data
610 * associated with the view.
616 public JalviewModel saveState(AlignmentPanel ap, String fileName,
617 boolean storeDS, JarOutputStream jout, List<String> viewIds)
621 viewIds = new ArrayList<String>();
626 List<UserColourScheme> userColours = new ArrayList<UserColourScheme>();
628 AlignViewport av = ap.av;
630 JalviewModel object = new JalviewModel();
631 object.setVamsasModel(new jalview.schemabinding.version2.VamsasModel());
633 object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
634 object.setVersion(jalview.bin.Cache.getDefault("VERSION",
635 "Development Build"));
638 * rjal is full height alignment, jal is actual alignment with full metadata
639 * but excludes hidden sequences.
641 jalview.datamodel.AlignmentI rjal = av.getAlignment(), jal = rjal;
643 if (av.hasHiddenRows())
645 rjal = jal.getHiddenSequences().getFullAlignment();
648 SequenceSet vamsasSet = new SequenceSet();
650 JalviewModelSequence jms = new JalviewModelSequence();
652 vamsasSet.setGapChar(jal.getGapCharacter() + "");
654 if (jal.getDataset() != null)
656 // dataset id is the dataset's hashcode
657 vamsasSet.setDatasetId(getDatasetIdRef(jal.getDataset()));
660 // switch jal and the dataset
661 jal = jal.getDataset();
665 if (jal.getProperties() != null)
667 Enumeration en = jal.getProperties().keys();
668 while (en.hasMoreElements())
670 String key = en.nextElement().toString();
671 SequenceSetProperties ssp = new SequenceSetProperties();
673 ssp.setValue(jal.getProperties().get(key).toString());
674 vamsasSet.addSequenceSetProperties(ssp);
679 Set<String> calcIdSet = new HashSet<String>();
682 for (int i = 0; i < rjal.getHeight(); i++)
684 final SequenceI jds = rjal.getSequenceAt(i);
685 final SequenceI jdatasq = jds.getDatasetSequence() == null ? jds
686 : jds.getDatasetSequence();
687 String id = seqHash(jds);
689 if (seqRefIds.get(id) != null)
691 // This happens for two reasons: 1. multiple views are being serialised.
692 // 2. the hashCode has collided with another sequence's code. This DOES
693 // HAPPEN! (PF00072.15.stk does this)
694 // JBPNote: Uncomment to debug writing out of files that do not read
695 // back in due to ArrayOutOfBoundExceptions.
696 // System.err.println("vamsasSeq backref: "+id+"");
697 // System.err.println(jds.getName()+"
698 // "+jds.getStart()+"-"+jds.getEnd()+" "+jds.getSequenceAsString());
699 // System.err.println("Hashcode: "+seqHash(jds));
700 // SequenceI rsq = (SequenceI) seqRefIds.get(id + "");
701 // System.err.println(rsq.getName()+"
702 // "+rsq.getStart()+"-"+rsq.getEnd()+" "+rsq.getSequenceAsString());
703 // System.err.println("Hashcode: "+seqHash(rsq));
707 vamsasSeq = createVamsasSequence(id, jds);
708 vamsasSet.addSequence(vamsasSeq);
709 seqRefIds.put(id, jds);
713 jseq.setStart(jds.getStart());
714 jseq.setEnd(jds.getEnd());
715 jseq.setColour(av.getSequenceColour(jds).getRGB());
717 jseq.setId(id); // jseq id should be a string not a number
720 // Store any sequences this sequence represents
721 if (av.hasHiddenRows())
723 // use rjal, contains the full height alignment
724 jseq.setHidden(av.getAlignment().getHiddenSequences()
727 if (av.isHiddenRepSequence(rjal.getSequenceAt(i)))
729 jalview.datamodel.SequenceI[] reps = av
730 .getRepresentedSequences(rjal.getSequenceAt(i))
731 .getSequencesInOrder(rjal);
733 for (int h = 0; h < reps.length; h++)
735 if (reps[h] != rjal.getSequenceAt(i))
737 jseq.addHiddenSequences(rjal.findIndex(reps[h]));
742 // mark sequence as reference - if it is the reference for this view
745 jseq.setViewreference(rjal.getSequenceAt(i) == jal.getSeqrep());
749 // TODO: omit sequence features from each alignment view's XML dump if we
750 // are storing dataset
751 if (jds.getSequenceFeatures() != null)
753 jalview.datamodel.SequenceFeature[] sf = jds.getSequenceFeatures();
755 while (index < sf.length)
757 Features features = new Features();
759 features.setBegin(sf[index].getBegin());
760 features.setEnd(sf[index].getEnd());
761 features.setDescription(sf[index].getDescription());
762 features.setType(sf[index].getType());
763 features.setFeatureGroup(sf[index].getFeatureGroup());
764 features.setScore(sf[index].getScore());
765 if (sf[index].links != null)
767 for (int l = 0; l < sf[index].links.size(); l++)
769 OtherData keyValue = new OtherData();
770 keyValue.setKey("LINK_" + l);
771 keyValue.setValue(sf[index].links.elementAt(l).toString());
772 features.addOtherData(keyValue);
775 if (sf[index].otherDetails != null)
778 Iterator<String> keys = sf[index].otherDetails.keySet()
780 while (keys.hasNext())
783 OtherData keyValue = new OtherData();
784 keyValue.setKey(key);
785 keyValue.setValue(sf[index].otherDetails.get(key).toString());
786 features.addOtherData(keyValue);
790 jseq.addFeatures(features);
795 if (jdatasq.getAllPDBEntries() != null)
797 Enumeration en = jdatasq.getAllPDBEntries().elements();
798 while (en.hasMoreElements())
800 Pdbids pdb = new Pdbids();
801 jalview.datamodel.PDBEntry entry = (jalview.datamodel.PDBEntry) en
804 String pdbId = entry.getId();
806 pdb.setType(entry.getType());
809 * Store any structure views associated with this sequence. This
810 * section copes with duplicate entries in the project, so a dataset
811 * only view *should* be coped with sensibly.
813 // This must have been loaded, is it still visible?
814 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
815 String matchedFile = null;
816 for (int f = frames.length - 1; f > -1; f--)
818 if (frames[f] instanceof StructureViewerBase)
820 StructureViewerBase viewFrame = (StructureViewerBase) frames[f];
821 matchedFile = saveStructureState(ap, jds, pdb, entry,
822 viewIds, matchedFile, viewFrame);
824 * Only store each structure viewer's state once in the project
825 * jar. First time through only (storeDS==false)
827 String viewId = viewFrame.getViewId();
828 if (!storeDS && !viewIds.contains(viewId))
833 String viewerState = viewFrame.getStateInfo();
834 writeJarEntry(jout, getViewerJarEntryName(viewId),
835 viewerState.getBytes());
836 } catch (IOException e)
838 System.err.println("Error saving viewer state: "
845 if (matchedFile != null || entry.getFile() != null)
847 if (entry.getFile() != null)
850 matchedFile = entry.getFile();
852 pdb.setFile(matchedFile); // entry.getFile());
853 if (pdbfiles == null)
855 pdbfiles = new ArrayList<String>();
858 if (!pdbfiles.contains(pdbId))
861 copyFileToJar(jout, matchedFile, pdbId);
865 if (entry.getProperty() != null && !entry.getProperty().isEmpty())
867 PdbentryItem item = new PdbentryItem();
868 Hashtable properties = entry.getProperty();
869 Enumeration en2 = properties.keys();
870 while (en2.hasMoreElements())
872 Property prop = new Property();
873 String key = en2.nextElement().toString();
875 prop.setValue(properties.get(key).toString());
876 item.addProperty(prop);
878 pdb.addPdbentryItem(item);
885 saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
890 if (!storeDS && av.hasHiddenRows())
892 jal = av.getAlignment();
895 if (jal.getCodonFrames() != null)
897 List<AlignedCodonFrame> jac = jal.getCodonFrames();
898 for (AlignedCodonFrame acf : jac)
900 AlcodonFrame alc = new AlcodonFrame();
901 vamsasSet.addAlcodonFrame(alc);
902 if (acf.getProtMappings() != null
903 && acf.getProtMappings().length > 0)
905 SequenceI[] dnas = acf.getdnaSeqs();
906 jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
907 for (int m = 0; m < pmaps.length; m++)
909 AlcodMap alcmap = new AlcodMap();
910 alcmap.setDnasq(seqHash(dnas[m]));
911 alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
913 alc.addAlcodMap(alcmap);
916 // TODO: delete this ? dead code from 2.8.3->2.9 ?
918 // AlcodonFrame alc = new AlcodonFrame();
919 // vamsasSet.addAlcodonFrame(alc);
920 // for (int p = 0; p < acf.aaWidth; p++)
922 // Alcodon cmap = new Alcodon();
923 // if (acf.codons[p] != null)
925 // // Null codons indicate a gapped column in the translated peptide
927 // cmap.setPos1(acf.codons[p][0]);
928 // cmap.setPos2(acf.codons[p][1]);
929 // cmap.setPos3(acf.codons[p][2]);
931 // alc.addAlcodon(cmap);
933 // if (acf.getProtMappings() != null
934 // && acf.getProtMappings().length > 0)
936 // SequenceI[] dnas = acf.getdnaSeqs();
937 // jalview.datamodel.Mapping[] pmaps = acf.getProtMappings();
938 // for (int m = 0; m < pmaps.length; m++)
940 // AlcodMap alcmap = new AlcodMap();
941 // alcmap.setDnasq(seqHash(dnas[m]));
942 // alcmap.setMapping(createVamsasMapping(pmaps[m], dnas[m], null,
944 // alc.addAlcodMap(alcmap);
951 // /////////////////////////////////
952 if (!storeDS && av.currentTree != null)
954 // FIND ANY ASSOCIATED TREES
955 // NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
956 if (Desktop.desktop != null)
958 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
960 for (int t = 0; t < frames.length; t++)
962 if (frames[t] instanceof TreePanel)
964 TreePanel tp = (TreePanel) frames[t];
966 if (tp.treeCanvas.av.getAlignment() == jal)
968 Tree tree = new Tree();
969 tree.setTitle(tp.getTitle());
970 tree.setCurrentTree((av.currentTree == tp.getTree()));
971 tree.setNewick(tp.getTree().toString());
972 tree.setThreshold(tp.treeCanvas.threshold);
974 tree.setFitToWindow(tp.fitToWindow.getState());
975 tree.setFontName(tp.getTreeFont().getName());
976 tree.setFontSize(tp.getTreeFont().getSize());
977 tree.setFontStyle(tp.getTreeFont().getStyle());
978 tree.setMarkUnlinked(tp.placeholdersMenu.getState());
980 tree.setShowBootstrap(tp.bootstrapMenu.getState());
981 tree.setShowDistances(tp.distanceMenu.getState());
983 tree.setHeight(tp.getHeight());
984 tree.setWidth(tp.getWidth());
985 tree.setXpos(tp.getX());
986 tree.setYpos(tp.getY());
987 tree.setId(makeHashCode(tp, null));
997 * store forward refs from an annotationRow to any groups
999 IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<SequenceGroup, String>();
1002 for (SequenceI sq : jal.getSequences())
1004 // Store annotation on dataset sequences only
1005 AlignmentAnnotation[] aa = sq.getAnnotation();
1006 if (aa != null && aa.length > 0)
1008 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1015 if (jal.getAlignmentAnnotation() != null)
1017 // Store the annotation shown on the alignment.
1018 AlignmentAnnotation[] aa = jal.getAlignmentAnnotation();
1019 storeAlignmentAnnotation(aa, groupRefs, av, calcIdSet, storeDS,
1024 if (jal.getGroups() != null)
1026 JGroup[] groups = new JGroup[jal.getGroups().size()];
1028 for (jalview.datamodel.SequenceGroup sg : jal.getGroups())
1030 JGroup jGroup = new JGroup();
1031 groups[++i] = jGroup;
1033 jGroup.setStart(sg.getStartRes());
1034 jGroup.setEnd(sg.getEndRes());
1035 jGroup.setName(sg.getName());
1036 if (groupRefs.containsKey(sg))
1038 // group has references so set its ID field
1039 jGroup.setId(groupRefs.get(sg));
1043 if (sg.cs.conservationApplied())
1045 jGroup.setConsThreshold(sg.cs.getConservationInc());
1047 if (sg.cs instanceof jalview.schemes.UserColourScheme)
1049 jGroup.setColour(setUserColourScheme(sg.cs, userColours, jms));
1053 jGroup.setColour(ColourSchemeProperty.getColourName(sg.cs));
1056 else if (sg.cs instanceof jalview.schemes.AnnotationColourGradient)
1058 jGroup.setColour("AnnotationColourGradient");
1059 jGroup.setAnnotationColours(constructAnnotationColours(
1060 (jalview.schemes.AnnotationColourGradient) sg.cs,
1063 else if (sg.cs instanceof jalview.schemes.UserColourScheme)
1065 jGroup.setColour(setUserColourScheme(sg.cs, userColours, jms));
1069 jGroup.setColour(ColourSchemeProperty.getColourName(sg.cs));
1072 jGroup.setPidThreshold(sg.cs.getThreshold());
1075 jGroup.setOutlineColour(sg.getOutlineColour().getRGB());
1076 jGroup.setDisplayBoxes(sg.getDisplayBoxes());
1077 jGroup.setDisplayText(sg.getDisplayText());
1078 jGroup.setColourText(sg.getColourText());
1079 jGroup.setTextCol1(sg.textColour.getRGB());
1080 jGroup.setTextCol2(sg.textColour2.getRGB());
1081 jGroup.setTextColThreshold(sg.thresholdTextColour);
1082 jGroup.setShowUnconserved(sg.getShowNonconserved());
1083 jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
1084 jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
1085 jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
1086 jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
1087 for (SequenceI seq : sg.getSequences())
1089 jGroup.addSeq(seqHash(seq));
1093 jms.setJGroup(groups);
1097 // /////////SAVE VIEWPORT
1098 Viewport view = new Viewport();
1099 view.setTitle(ap.alignFrame.getTitle());
1100 view.setSequenceSetId(makeHashCode(av.getSequenceSetId(),
1101 av.getSequenceSetId()));
1102 view.setId(av.getViewId());
1103 if (av.getCodingComplement() != null)
1105 view.setComplementId(av.getCodingComplement().getViewId());
1107 view.setViewName(av.viewName);
1108 view.setGatheredViews(av.isGatherViewsHere());
1110 Rectangle size = ap.av.getExplodedGeometry();
1111 Rectangle position = size;
1114 size = ap.alignFrame.getBounds();
1115 if (av.getCodingComplement() != null)
1117 position = ((SplitFrame) ap.alignFrame.getSplitViewContainer())
1125 view.setXpos(position.x);
1126 view.setYpos(position.y);
1128 view.setWidth(size.width);
1129 view.setHeight(size.height);
1131 view.setStartRes(av.startRes);
1132 view.setStartSeq(av.startSeq);
1134 if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
1136 view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
1139 else if (av.getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
1141 AnnotationColours ac = constructAnnotationColours(
1142 (jalview.schemes.AnnotationColourGradient) av
1143 .getGlobalColourScheme(),
1146 view.setAnnotationColours(ac);
1147 view.setBgColour("AnnotationColourGradient");
1151 view.setBgColour(ColourSchemeProperty.getColourName(av
1152 .getGlobalColourScheme()));
1155 ColourSchemeI cs = av.getGlobalColourScheme();
1159 if (cs.conservationApplied())
1161 view.setConsThreshold(cs.getConservationInc());
1162 if (cs instanceof jalview.schemes.UserColourScheme)
1164 view.setBgColour(setUserColourScheme(cs, userColours, jms));
1168 if (cs instanceof ResidueColourScheme)
1170 view.setPidThreshold(cs.getThreshold());
1174 view.setConservationSelected(av.getConservationSelected());
1175 view.setPidSelected(av.getAbovePIDThreshold());
1176 view.setFontName(av.font.getName());
1177 view.setFontSize(av.font.getSize());
1178 view.setFontStyle(av.font.getStyle());
1179 view.setScaleProteinAsCdna(av.getViewStyle().isScaleProteinAsCdna());
1180 view.setRenderGaps(av.isRenderGaps());
1181 view.setShowAnnotation(av.isShowAnnotation());
1182 view.setShowBoxes(av.getShowBoxes());
1183 view.setShowColourText(av.getColourText());
1184 view.setShowFullId(av.getShowJVSuffix());
1185 view.setRightAlignIds(av.isRightAlignIds());
1186 view.setShowSequenceFeatures(av.isShowSequenceFeatures());
1187 view.setShowText(av.getShowText());
1188 view.setShowUnconserved(av.getShowUnconserved());
1189 view.setWrapAlignment(av.getWrapAlignment());
1190 view.setTextCol1(av.getTextColour().getRGB());
1191 view.setTextCol2(av.getTextColour2().getRGB());
1192 view.setTextColThreshold(av.getThresholdTextColour());
1193 view.setShowConsensusHistogram(av.isShowConsensusHistogram());
1194 view.setShowSequenceLogo(av.isShowSequenceLogo());
1195 view.setNormaliseSequenceLogo(av.isNormaliseSequenceLogo());
1196 view.setShowGroupConsensus(av.isShowGroupConsensus());
1197 view.setShowGroupConservation(av.isShowGroupConservation());
1198 view.setShowNPfeatureTooltip(av.isShowNPFeats());
1199 view.setShowDbRefTooltip(av.isShowDBRefs());
1200 view.setFollowHighlight(av.isFollowHighlight());
1201 view.setFollowSelection(av.followSelection);
1202 view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
1203 if (av.getFeaturesDisplayed() != null)
1205 jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
1207 String[] renderOrder = ap.getSeqPanel().seqCanvas
1208 .getFeatureRenderer().getRenderOrder()
1209 .toArray(new String[0]);
1211 Vector<String> settingsAdded = new Vector<String>();
1212 Object gstyle = null;
1213 GraduatedColor gcol = null;
1214 if (renderOrder != null)
1216 for (String featureType : renderOrder)
1218 gstyle = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1219 .getFeatureStyle(featureType);
1220 Setting setting = new Setting();
1221 setting.setType(featureType);
1222 if (gstyle instanceof GraduatedColor)
1224 gcol = (GraduatedColor) gstyle;
1225 setting.setColour(gcol.getMaxColor().getRGB());
1226 setting.setMincolour(gcol.getMinColor().getRGB());
1227 setting.setMin(gcol.getMin());
1228 setting.setMax(gcol.getMax());
1229 setting.setColourByLabel(gcol.isColourByLabel());
1230 setting.setAutoScale(gcol.isAutoScale());
1231 setting.setThreshold(gcol.getThresh());
1232 setting.setThreshstate(gcol.getThreshType());
1236 setting.setColour(((Color) gstyle).getRGB());
1239 setting.setDisplay(av.getFeaturesDisplayed().isVisible(
1241 float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
1242 .getOrder(featureType);
1245 setting.setOrder(rorder);
1247 fs.addSetting(setting);
1248 settingsAdded.addElement(featureType);
1252 // is groups actually supposed to be a map here ?
1253 Iterator<String> en = ap.getSeqPanel().seqCanvas
1254 .getFeatureRenderer()
1255 .getFeatureGroups().iterator();
1256 Vector<String> groupsAdded = new Vector<String>();
1257 while (en.hasNext())
1259 String grp = en.next();
1260 if (groupsAdded.contains(grp))
1264 Group g = new Group();
1266 g.setDisplay(((Boolean) ap.getSeqPanel().seqCanvas
1267 .getFeatureRenderer().checkGroupVisibility(grp, false))
1270 groupsAdded.addElement(grp);
1272 jms.setFeatureSettings(fs);
1276 if (av.hasHiddenColumns())
1278 if (av.getColumnSelection() == null
1279 || av.getColumnSelection().getHiddenColumns() == null)
1281 warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
1285 for (int c = 0; c < av.getColumnSelection().getHiddenColumns()
1288 int[] region = av.getColumnSelection().getHiddenColumns()
1290 HiddenColumns hc = new HiddenColumns();
1291 hc.setStart(region[0]);
1292 hc.setEnd(region[1]);
1293 view.addHiddenColumns(hc);
1297 if (calcIdSet.size() > 0)
1299 for (String calcId : calcIdSet)
1301 if (calcId.trim().length() > 0)
1303 CalcIdParam cidp = createCalcIdParam(calcId, av);
1304 // Some calcIds have no parameters.
1307 view.addCalcIdParam(cidp);
1313 jms.addViewport(view);
1315 object.setJalviewModelSequence(jms);
1316 object.getVamsasModel().addSequenceSet(vamsasSet);
1318 if (jout != null && fileName != null)
1320 // We may not want to write the object to disk,
1321 // eg we can copy the alignViewport to a new view object
1322 // using save and then load
1325 System.out.println("Writing jar entry " + fileName);
1326 JarEntry entry = new JarEntry(fileName);
1327 jout.putNextEntry(entry);
1328 PrintWriter pout = new PrintWriter(new OutputStreamWriter(jout,
1330 Marshaller marshaller = new Marshaller(pout);
1331 marshaller.marshal(object);
1334 } catch (Exception ex)
1336 // TODO: raise error in GUI if marshalling failed.
1337 ex.printStackTrace();
1344 * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
1345 * for each viewer, with
1347 * <li>viewer geometry (position, size, split pane divider location)</li>
1348 * <li>index of the selected structure in the viewer (currently shows gapped
1350 * <li>the id of the annotation holding RNA secondary structure</li>
1351 * <li>(currently only one SS is shown per viewer, may be more in future)</li>
1353 * Varna viewer state is also written out (in native Varna XML) to separate
1354 * project jar entries. A separate entry is written for each RNA structure
1355 * displayed, with the naming convention
1357 * <li>rna_viewId_sequenceId_annotationId_[gapped|trimmed]</li>
1365 * @param storeDataset
1367 protected void saveRnaViewers(JarOutputStream jout, JSeq jseq,
1368 final SequenceI jds, List<String> viewIds, AlignmentPanel ap,
1369 boolean storeDataset)
1371 if (Desktop.desktop == null)
1375 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
1376 for (int f = frames.length - 1; f > -1; f--)
1378 if (frames[f] instanceof AppVarna)
1380 AppVarna varna = (AppVarna) frames[f];
1382 * link the sequence to every viewer that is showing it and is linked to
1383 * its alignment panel
1385 if (varna.isListeningFor(jds) && ap == varna.getAlignmentPanel())
1387 String viewId = varna.getViewId();
1388 RnaViewer rna = new RnaViewer();
1389 rna.setViewId(viewId);
1390 rna.setTitle(varna.getTitle());
1391 rna.setXpos(varna.getX());
1392 rna.setYpos(varna.getY());
1393 rna.setWidth(varna.getWidth());
1394 rna.setHeight(varna.getHeight());
1395 rna.setDividerLocation(varna.getDividerLocation());
1396 rna.setSelectedRna(varna.getSelectedIndex());
1397 jseq.addRnaViewer(rna);
1400 * Store each Varna panel's state once in the project per sequence.
1401 * First time through only (storeDataset==false)
1403 // boolean storeSessions = false;
1404 // String sequenceViewId = viewId + seqsToIds.get(jds);
1405 // if (!storeDataset && !viewIds.contains(sequenceViewId))
1407 // viewIds.add(sequenceViewId);
1408 // storeSessions = true;
1410 for (RnaModel model : varna.getModels())
1412 if (model.seq == jds)
1415 * VARNA saves each view (sequence or alignment secondary
1416 * structure, gapped or trimmed) as a separate XML file
1418 String jarEntryName = rnaSessions.get(model);
1419 if (jarEntryName == null)
1422 String varnaStateFile = varna.getStateInfo(model.rna);
1423 jarEntryName = RNA_PREFIX + viewId + "_" + nextCounter();
1424 copyFileToJar(jout, varnaStateFile, jarEntryName);
1425 rnaSessions.put(model, jarEntryName);
1427 SecondaryStructure ss = new SecondaryStructure();
1428 String annotationId = varna.getAnnotation(jds).annotationId;
1429 ss.setAnnotationId(annotationId);
1430 ss.setViewerState(jarEntryName);
1431 ss.setGapped(model.gapped);
1432 ss.setTitle(model.title);
1433 rna.addSecondaryStructure(ss);
1442 * Copy the contents of a file to a new entry added to the output jar
1446 * @param jarEntryName
1448 protected void copyFileToJar(JarOutputStream jout, String infilePath,
1449 String jarEntryName)
1451 DataInputStream dis = null;
1454 File file = new File(infilePath);
1455 if (file.exists() && jout != null)
1457 dis = new DataInputStream(new FileInputStream(file));
1458 byte[] data = new byte[(int) file.length()];
1459 dis.readFully(data);
1460 writeJarEntry(jout, jarEntryName, data);
1462 } catch (Exception ex)
1464 ex.printStackTrace();
1472 } catch (IOException e)
1481 * Write the data to a new entry of given name in the output jar file
1484 * @param jarEntryName
1486 * @throws IOException
1488 protected void writeJarEntry(JarOutputStream jout, String jarEntryName,
1489 byte[] data) throws IOException
1493 System.out.println("Writing jar entry " + jarEntryName);
1494 jout.putNextEntry(new JarEntry(jarEntryName));
1495 DataOutputStream dout = new DataOutputStream(jout);
1496 dout.write(data, 0, data.length);
1503 * Save the state of a structure viewer
1508 * the archive XML element under which to save the state
1511 * @param matchedFile
1515 protected String saveStructureState(AlignmentPanel ap, SequenceI jds,
1516 Pdbids pdb, PDBEntry entry, List<String> viewIds,
1517 String matchedFile, StructureViewerBase viewFrame)
1519 final AAStructureBindingModel bindingModel = viewFrame.getBinding();
1522 * Look for any bindings for this viewer to the PDB file of interest
1523 * (including part matches excluding chain id)
1525 for (int peid = 0; peid < bindingModel.getPdbCount(); peid++)
1527 final PDBEntry pdbentry = bindingModel.getPdbEntry(peid);
1528 final String pdbId = pdbentry.getId();
1529 if (!pdbId.equals(entry.getId())
1530 && !(entry.getId().length() > 4 && entry.getId()
1531 .toLowerCase().startsWith(pdbId.toLowerCase())))
1534 * not interested in a binding to a different PDB entry here
1538 if (matchedFile == null)
1540 matchedFile = pdbentry.getFile();
1542 else if (!matchedFile.equals(pdbentry.getFile()))
1545 .warn("Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
1546 + pdbentry.getFile());
1550 // can get at it if the ID
1551 // match is ambiguous (e.g.
1554 for (int smap = 0; smap < viewFrame.getBinding().getSequence()[peid].length; smap++)
1556 // if (jal.findIndex(jmol.jmb.sequence[peid][smap]) > -1)
1557 if (jds == viewFrame.getBinding().getSequence()[peid][smap])
1559 StructureState state = new StructureState();
1560 state.setVisible(true);
1561 state.setXpos(viewFrame.getX());
1562 state.setYpos(viewFrame.getY());
1563 state.setWidth(viewFrame.getWidth());
1564 state.setHeight(viewFrame.getHeight());
1565 final String viewId = viewFrame.getViewId();
1566 state.setViewId(viewId);
1567 state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap));
1568 state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
1569 state.setColourByJmol(viewFrame.isColouredByViewer());
1570 state.setType(viewFrame.getViewerType().toString());
1571 pdb.addStructureState(state);
1578 private AnnotationColours constructAnnotationColours(
1579 AnnotationColourGradient acg, List<UserColourScheme> userColours,
1580 JalviewModelSequence jms)
1582 AnnotationColours ac = new AnnotationColours();
1583 ac.setAboveThreshold(acg.getAboveThreshold());
1584 ac.setThreshold(acg.getAnnotationThreshold());
1585 ac.setAnnotation(acg.getAnnotation());
1586 if (acg.getBaseColour() instanceof jalview.schemes.UserColourScheme)
1588 ac.setColourScheme(setUserColourScheme(acg.getBaseColour(),
1593 ac.setColourScheme(ColourSchemeProperty.getColourName(acg
1597 ac.setMaxColour(acg.getMaxColour().getRGB());
1598 ac.setMinColour(acg.getMinColour().getRGB());
1599 ac.setPerSequence(acg.isSeqAssociated());
1600 ac.setPredefinedColours(acg.isPredefinedColours());
1604 private void storeAlignmentAnnotation(AlignmentAnnotation[] aa,
1605 IdentityHashMap<SequenceGroup, String> groupRefs,
1606 AlignmentViewport av, Set<String> calcIdSet, boolean storeDS,
1607 SequenceSet vamsasSet)
1610 for (int i = 0; i < aa.length; i++)
1612 Annotation an = new Annotation();
1614 AlignmentAnnotation annotation = aa[i];
1615 if (annotation.annotationId != null)
1617 annotationIds.put(annotation.annotationId, annotation);
1620 an.setId(annotation.annotationId);
1622 an.setVisible(annotation.visible);
1624 an.setDescription(annotation.description);
1626 if (annotation.sequenceRef != null)
1628 // 2.9 JAL-1781 xref on sequence id rather than name
1629 an.setSequenceRef(seqsToIds.get(annotation.sequenceRef));
1631 if (annotation.groupRef != null)
1633 String groupIdr = groupRefs.get(annotation.groupRef);
1634 if (groupIdr == null)
1636 // make a locally unique String
1638 annotation.groupRef,
1639 groupIdr = ("" + System.currentTimeMillis()
1640 + annotation.groupRef.getName() + groupRefs
1643 an.setGroupRef(groupIdr.toString());
1646 // store all visualization attributes for annotation
1647 an.setGraphHeight(annotation.graphHeight);
1648 an.setCentreColLabels(annotation.centreColLabels);
1649 an.setScaleColLabels(annotation.scaleColLabel);
1650 an.setShowAllColLabels(annotation.showAllColLabels);
1651 an.setBelowAlignment(annotation.belowAlignment);
1653 if (annotation.graph > 0)
1656 an.setGraphType(annotation.graph);
1657 an.setGraphGroup(annotation.graphGroup);
1658 if (annotation.getThreshold() != null)
1660 ThresholdLine line = new ThresholdLine();
1661 line.setLabel(annotation.getThreshold().label);
1662 line.setValue(annotation.getThreshold().value);
1663 line.setColour(annotation.getThreshold().colour.getRGB());
1664 an.setThresholdLine(line);
1672 an.setLabel(annotation.label);
1674 if (annotation == av.getAlignmentQualityAnnot()
1675 || annotation == av.getAlignmentConservationAnnotation()
1676 || annotation == av.getAlignmentConsensusAnnotation()
1677 || annotation.autoCalculated)
1679 // new way of indicating autocalculated annotation -
1680 an.setAutoCalculated(annotation.autoCalculated);
1682 if (annotation.hasScore())
1684 an.setScore(annotation.getScore());
1687 if (annotation.getCalcId() != null)
1689 calcIdSet.add(annotation.getCalcId());
1690 an.setCalcId(annotation.getCalcId());
1692 if (annotation.hasProperties())
1694 for (String pr : annotation.getProperties())
1696 Property prop = new Property();
1698 prop.setValue(annotation.getProperty(pr));
1699 an.addProperty(prop);
1703 AnnotationElement ae;
1704 if (annotation.annotations != null)
1706 an.setScoreOnly(false);
1707 for (int a = 0; a < annotation.annotations.length; a++)
1709 if ((annotation == null) || (annotation.annotations[a] == null))
1714 ae = new AnnotationElement();
1715 if (annotation.annotations[a].description != null)
1717 ae.setDescription(annotation.annotations[a].description);
1719 if (annotation.annotations[a].displayCharacter != null)
1721 ae.setDisplayCharacter(annotation.annotations[a].displayCharacter);
1724 if (!Float.isNaN(annotation.annotations[a].value))
1726 ae.setValue(annotation.annotations[a].value);
1730 if (annotation.annotations[a].secondaryStructure > ' ')
1732 ae.setSecondaryStructure(annotation.annotations[a].secondaryStructure
1736 if (annotation.annotations[a].colour != null
1737 && annotation.annotations[a].colour != java.awt.Color.black)
1739 ae.setColour(annotation.annotations[a].colour.getRGB());
1742 an.addAnnotationElement(ae);
1743 if (annotation.autoCalculated)
1745 // only write one non-null entry into the annotation row -
1746 // sufficient to get the visualization attributes necessary to
1754 an.setScoreOnly(true);
1756 if (!storeDS || (storeDS && !annotation.autoCalculated))
1758 // skip autocalculated annotation - these are only provided for
1760 vamsasSet.addAnnotation(an);
1766 private CalcIdParam createCalcIdParam(String calcId, AlignViewport av)
1768 AutoCalcSetting settings = av.getCalcIdSettingsFor(calcId);
1769 if (settings != null)
1771 CalcIdParam vCalcIdParam = new CalcIdParam();
1772 vCalcIdParam.setCalcId(calcId);
1773 vCalcIdParam.addServiceURL(settings.getServiceURI());
1774 // generic URI allowing a third party to resolve another instance of the
1775 // service used for this calculation
1776 for (String urls : settings.getServiceURLs())
1778 vCalcIdParam.addServiceURL(urls);
1780 vCalcIdParam.setVersion("1.0");
1781 if (settings.getPreset() != null)
1783 WsParamSetI setting = settings.getPreset();
1784 vCalcIdParam.setName(setting.getName());
1785 vCalcIdParam.setDescription(setting.getDescription());
1789 vCalcIdParam.setName("");
1790 vCalcIdParam.setDescription("Last used parameters");
1792 // need to be able to recover 1) settings 2) user-defined presets or
1793 // recreate settings from preset 3) predefined settings provided by
1794 // service - or settings that can be transferred (or discarded)
1795 vCalcIdParam.setParameters(settings.getWsParamFile().replace("\n",
1797 vCalcIdParam.setAutoUpdate(settings.isAutoUpdate());
1798 // todo - decide if updateImmediately is needed for any projects.
1800 return vCalcIdParam;
1805 private boolean recoverCalcIdParam(CalcIdParam calcIdParam,
1808 if (calcIdParam.getVersion().equals("1.0"))
1810 Jws2Instance service = Jws2Discoverer.getDiscoverer()
1811 .getPreferredServiceFor(calcIdParam.getServiceURL());
1812 if (service != null)
1814 WsParamSetI parmSet = null;
1817 parmSet = service.getParamStore().parseServiceParameterFile(
1818 calcIdParam.getName(), calcIdParam.getDescription(),
1819 calcIdParam.getServiceURL(),
1820 calcIdParam.getParameters().replace("|\\n|", "\n"));
1821 } catch (IOException x)
1823 warn("Couldn't parse parameter data for "
1824 + calcIdParam.getCalcId(), x);
1827 List<ArgumentI> argList = null;
1828 if (calcIdParam.getName().length() > 0)
1830 parmSet = service.getParamStore()
1831 .getPreset(calcIdParam.getName());
1832 if (parmSet != null)
1834 // TODO : check we have a good match with settings in AACon -
1835 // otherwise we'll need to create a new preset
1840 argList = parmSet.getArguments();
1843 AAConSettings settings = new AAConSettings(
1844 calcIdParam.isAutoUpdate(), service, parmSet, argList);
1845 av.setCalcIdSettingsFor(calcIdParam.getCalcId(), settings,
1846 calcIdParam.isNeedsUpdate());
1851 warn("Cannot resolve a service for the parameters used in this project. Try configuring a JABAWS server.");
1855 throw new Error(MessageManager.formatMessage(
1856 "error.unsupported_version_calcIdparam",
1857 new Object[] { calcIdParam.toString() }));
1861 * External mapping between jalview objects and objects yielding a valid and
1862 * unique object ID string. This is null for normal Jalview project IO, but
1863 * non-null when a jalview project is being read or written as part of a
1866 IdentityHashMap jv2vobj = null;
1869 * Construct a unique ID for jvobj using either existing bindings or if none
1870 * exist, the result of the hashcode call for the object.
1873 * jalview data object
1874 * @return unique ID for referring to jvobj
1876 private String makeHashCode(Object jvobj, String altCode)
1878 if (jv2vobj != null)
1880 Object id = jv2vobj.get(jvobj);
1883 return id.toString();
1885 // check string ID mappings
1886 if (jvids2vobj != null && jvobj instanceof String)
1888 id = jvids2vobj.get(jvobj);
1892 return id.toString();
1894 // give up and warn that something has gone wrong
1895 warn("Cannot find ID for object in external mapping : " + jvobj);
1901 * return local jalview object mapped to ID, if it exists
1905 * @return null or object bound to idcode
1907 private Object retrieveExistingObj(String idcode)
1909 if (idcode != null && vobj2jv != null)
1911 return vobj2jv.get(idcode);
1917 * binding from ID strings from external mapping table to jalview data model
1920 private Hashtable vobj2jv;
1922 private Sequence createVamsasSequence(String id, SequenceI jds)
1924 return createVamsasSequence(true, id, jds, null);
1927 private Sequence createVamsasSequence(boolean recurse, String id,
1928 SequenceI jds, SequenceI parentseq)
1930 Sequence vamsasSeq = new Sequence();
1931 vamsasSeq.setId(id);
1932 vamsasSeq.setName(jds.getName());
1933 vamsasSeq.setSequence(jds.getSequenceAsString());
1934 vamsasSeq.setDescription(jds.getDescription());
1935 jalview.datamodel.DBRefEntry[] dbrefs = null;
1936 if (jds.getDatasetSequence() != null)
1938 vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence()));
1939 if (jds.getDatasetSequence().getDBRefs() != null)
1941 dbrefs = jds.getDatasetSequence().getDBRefs();
1946 vamsasSeq.setDsseqid(id); // so we can tell which sequences really are
1947 // dataset sequences only
1948 dbrefs = jds.getDBRefs();
1952 for (int d = 0; d < dbrefs.length; d++)
1954 DBRef dbref = new DBRef();
1955 dbref.setSource(dbrefs[d].getSource());
1956 dbref.setVersion(dbrefs[d].getVersion());
1957 dbref.setAccessionId(dbrefs[d].getAccessionId());
1958 if (dbrefs[d].hasMap())
1960 Mapping mp = createVamsasMapping(dbrefs[d].getMap(), parentseq,
1962 dbref.setMapping(mp);
1964 vamsasSeq.addDBRef(dbref);
1970 private Mapping createVamsasMapping(jalview.datamodel.Mapping jmp,
1971 SequenceI parentseq, SequenceI jds, boolean recurse)
1974 if (jmp.getMap() != null)
1978 jalview.util.MapList mlst = jmp.getMap();
1979 List<int[]> r = mlst.getFromRanges();
1980 for (int[] range : r)
1982 MapListFrom mfrom = new MapListFrom();
1983 mfrom.setStart(range[0]);
1984 mfrom.setEnd(range[1]);
1985 mp.addMapListFrom(mfrom);
1987 r = mlst.getToRanges();
1988 for (int[] range : r)
1990 MapListTo mto = new MapListTo();
1991 mto.setStart(range[0]);
1992 mto.setEnd(range[1]);
1993 mp.addMapListTo(mto);
1995 mp.setMapFromUnit(mlst.getFromRatio());
1996 mp.setMapToUnit(mlst.getToRatio());
1997 if (jmp.getTo() != null)
1999 MappingChoice mpc = new MappingChoice();
2001 && (parentseq != jmp.getTo() || parentseq
2002 .getDatasetSequence() != jmp.getTo()))
2004 mpc.setSequence(createVamsasSequence(false, seqHash(jmp.getTo()),
2010 SequenceI ps = null;
2011 if (parentseq != jmp.getTo()
2012 && parentseq.getDatasetSequence() != jmp.getTo())
2014 // chaining dbref rather than a handshaking one
2015 jmpid = seqHash(ps = jmp.getTo());
2019 jmpid = seqHash(ps = parentseq);
2021 mpc.setDseqFor(jmpid);
2022 if (!seqRefIds.containsKey(mpc.getDseqFor()))
2024 jalview.bin.Cache.log.debug("creatign new DseqFor ID");
2025 seqRefIds.put(mpc.getDseqFor(), ps);
2029 jalview.bin.Cache.log.debug("reusing DseqFor ID");
2032 mp.setMappingChoice(mpc);
2038 String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
2039 List<UserColourScheme> userColours, JalviewModelSequence jms)
2042 jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
2043 boolean newucs = false;
2044 if (!userColours.contains(ucs))
2046 userColours.add(ucs);
2049 id = "ucs" + userColours.indexOf(ucs);
2052 // actually create the scheme's entry in the XML model
2053 java.awt.Color[] colours = ucs.getColours();
2054 jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
2055 jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
2057 for (int i = 0; i < colours.length; i++)
2059 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2060 col.setName(ResidueProperties.aa[i]);
2061 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2062 jbucs.addColour(col);
2064 if (ucs.getLowerCaseColours() != null)
2066 colours = ucs.getLowerCaseColours();
2067 for (int i = 0; i < colours.length; i++)
2069 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
2070 col.setName(ResidueProperties.aa[i].toLowerCase());
2071 col.setRGB(jalview.util.Format.getHexString(colours[i]));
2072 jbucs.addColour(col);
2077 uc.setUserColourScheme(jbucs);
2078 jms.addUserColours(uc);
2084 jalview.schemes.UserColourScheme getUserColourScheme(
2085 JalviewModelSequence jms, String id)
2087 UserColours[] uc = jms.getUserColours();
2088 UserColours colours = null;
2090 for (int i = 0; i < uc.length; i++)
2092 if (uc[i].getId().equals(id))
2100 java.awt.Color[] newColours = new java.awt.Color[24];
2102 for (int i = 0; i < 24; i++)
2104 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2105 .getUserColourScheme().getColour(i).getRGB(), 16));
2108 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
2111 if (colours.getUserColourScheme().getColourCount() > 24)
2113 newColours = new java.awt.Color[23];
2114 for (int i = 0; i < 23; i++)
2116 newColours[i] = new java.awt.Color(Integer.parseInt(colours
2117 .getUserColourScheme().getColour(i + 24).getRGB(), 16));
2119 ucs.setLowerCaseColours(newColours);
2126 * contains last error message (if any) encountered by XML loader.
2128 String errorMessage = null;
2131 * flag to control whether the Jalview2XML_V1 parser should be deferred to if
2132 * exceptions are raised during project XML parsing
2134 public boolean attemptversion1parse = true;
2137 * Load a jalview project archive from a jar file
2140 * - HTTP URL or filename
2142 public AlignFrame loadJalviewAlign(final String file)
2145 jalview.gui.AlignFrame af = null;
2149 // create list to store references for any new Jmol viewers created
2150 newStructureViewers = new Vector<JalviewStructureDisplayI>();
2151 // UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
2152 // Workaround is to make sure caller implements the JarInputStreamProvider
2154 // so we can re-open the jar input stream for each entry.
2156 jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
2157 af = loadJalviewAlign(jprovider);
2159 } catch (MalformedURLException e)
2161 errorMessage = "Invalid URL format for '" + file + "'";
2167 SwingUtilities.invokeAndWait(new Runnable()
2172 setLoadingFinishedForNewStructureViewers();
2175 } catch (Exception x)
2177 System.err.println("Error loading alignment: " + x.getMessage());
2183 private jarInputStreamProvider createjarInputStreamProvider(
2184 final String file) throws MalformedURLException
2187 errorMessage = null;
2188 uniqueSetSuffix = null;
2190 viewportsAdded.clear();
2191 frefedSequence = null;
2193 if (file.startsWith("http://"))
2195 url = new URL(file);
2197 final URL _url = url;
2198 return new jarInputStreamProvider()
2202 public JarInputStream getJarInputStream() throws IOException
2206 return new JarInputStream(_url.openStream());
2210 return new JarInputStream(new FileInputStream(file));
2215 public String getFilename()
2223 * Recover jalview session from a jalview project archive. Caller may
2224 * initialise uniqueSetSuffix, seqRefIds, viewportsAdded and frefedSequence
2225 * themselves. Any null fields will be initialised with default values,
2226 * non-null fields are left alone.
2231 public AlignFrame loadJalviewAlign(final jarInputStreamProvider jprovider)
2233 errorMessage = null;
2234 if (uniqueSetSuffix == null)
2236 uniqueSetSuffix = System.currentTimeMillis() % 100000 + "";
2238 if (seqRefIds == null)
2240 seqRefIds = new HashMap<String, SequenceI>();
2242 if (frefedSequence == null)
2244 frefedSequence = new Vector<Object[]>();
2247 AlignFrame af = null, _af = null;
2248 Map<String, AlignFrame> gatherToThisFrame = new HashMap<String, AlignFrame>();
2249 final String file = jprovider.getFilename();
2252 JarInputStream jin = null;
2253 JarEntry jarentry = null;
2258 jin = jprovider.getJarInputStream();
2259 for (int i = 0; i < entryCount; i++)
2261 jarentry = jin.getNextJarEntry();
2264 if (jarentry != null && jarentry.getName().endsWith(".xml"))
2266 InputStreamReader in = new InputStreamReader(jin, UTF_8);
2267 JalviewModel object = new JalviewModel();
2269 Unmarshaller unmar = new Unmarshaller(object);
2270 unmar.setValidation(false);
2271 object = (JalviewModel) unmar.unmarshal(in);
2272 if (true) // !skipViewport(object))
2274 _af = loadFromObject(object, file, true, jprovider);
2275 if (object.getJalviewModelSequence().getViewportCount() > 0)
2278 if (af.viewport.isGatherViewsHere())
2280 gatherToThisFrame.put(af.viewport.getSequenceSetId(), af);
2286 else if (jarentry != null)
2288 // Some other file here.
2291 } while (jarentry != null);
2292 resolveFrefedSequences();
2293 } catch (IOException ex)
2295 ex.printStackTrace();
2296 errorMessage = "Couldn't locate Jalview XML file : " + file;
2297 System.err.println("Exception whilst loading jalview XML file : "
2299 } catch (Exception ex)
2301 System.err.println("Parsing as Jalview Version 2 file failed.");
2302 ex.printStackTrace(System.err);
2303 if (attemptversion1parse)
2305 // Is Version 1 Jar file?
2308 af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
2309 } catch (Exception ex2)
2311 System.err.println("Exception whilst loading as jalviewXMLV1:");
2312 ex2.printStackTrace();
2316 if (Desktop.instance != null)
2318 Desktop.instance.stopLoading();
2322 System.out.println("Successfully loaded archive file");
2325 ex.printStackTrace();
2327 System.err.println("Exception whilst loading jalview XML file : "
2329 } catch (OutOfMemoryError e)
2331 // Don't use the OOM Window here
2332 errorMessage = "Out of memory loading jalview XML file";
2333 System.err.println("Out of memory whilst loading jalview XML file");
2334 e.printStackTrace();
2337 if (Desktop.instance != null)
2339 Desktop.instance.stopLoading();
2343 * Regather multiple views (with the same sequence set id) to the frame (if
2344 * any) that is flagged as the one to gather to, i.e. convert them to tabbed
2345 * views instead of separate frames. Note this doesn't restore a state where
2346 * some expanded views in turn have tabbed views - the last "first tab" read
2347 * in will play the role of gatherer for all.
2349 for (AlignFrame fr : gatherToThisFrame.values())
2351 Desktop.instance.gatherViews(fr);
2354 restoreSplitFrames();
2356 if (errorMessage != null)
2364 * Try to reconstruct and display SplitFrame windows, where each contains
2365 * complementary dna and protein alignments. Done by pairing up AlignFrame
2366 * objects (created earlier) which have complementary viewport ids associated.
2368 protected void restoreSplitFrames()
2370 List<SplitFrame> gatherTo = new ArrayList<SplitFrame>();
2371 List<AlignFrame> addedToSplitFrames = new ArrayList<AlignFrame>();
2372 Map<String, AlignFrame> dna = new HashMap<String, AlignFrame>();
2375 * Identify the DNA alignments
2377 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2380 AlignFrame af = candidate.getValue();
2381 if (af.getViewport().getAlignment().isNucleotide())
2383 dna.put(candidate.getKey().getId(), af);
2388 * Try to match up the protein complements
2390 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2393 AlignFrame af = candidate.getValue();
2394 if (!af.getViewport().getAlignment().isNucleotide())
2396 String complementId = candidate.getKey().getComplementId();
2397 // only non-null complements should be in the Map
2398 if (complementId != null && dna.containsKey(complementId))
2400 final AlignFrame dnaFrame = dna.get(complementId);
2401 SplitFrame sf = createSplitFrame(dnaFrame, af);
2402 addedToSplitFrames.add(dnaFrame);
2403 addedToSplitFrames.add(af);
2404 if (af.viewport.isGatherViewsHere())
2413 * Open any that we failed to pair up (which shouldn't happen!) as
2414 * standalone AlignFrame's.
2416 for (Entry<Viewport, AlignFrame> candidate : splitFrameCandidates
2419 AlignFrame af = candidate.getValue();
2420 if (!addedToSplitFrames.contains(af))
2422 Viewport view = candidate.getKey();
2423 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
2425 System.err.println("Failed to restore view " + view.getTitle()
2426 + " to split frame");
2431 * Gather back into tabbed views as flagged.
2433 for (SplitFrame sf : gatherTo)
2435 Desktop.instance.gatherViews(sf);
2438 splitFrameCandidates.clear();
2442 * Construct and display one SplitFrame holding DNA and protein alignments.
2445 * @param proteinFrame
2448 protected SplitFrame createSplitFrame(AlignFrame dnaFrame,
2449 AlignFrame proteinFrame)
2451 SplitFrame splitFrame = new SplitFrame(dnaFrame, proteinFrame);
2452 String title = MessageManager.getString("label.linked_view_title");
2453 int width = (int) dnaFrame.getBounds().getWidth();
2454 int height = (int) (dnaFrame.getBounds().getHeight()
2455 + proteinFrame.getBounds().getHeight() + 50);
2458 * SplitFrame location is saved to both enclosed frames
2460 splitFrame.setLocation(dnaFrame.getX(), dnaFrame.getY());
2461 Desktop.addInternalFrame(splitFrame, title, width, height);
2464 * And compute cDNA consensus (couldn't do earlier with consensus as
2465 * mappings were not yet present)
2467 proteinFrame.viewport.alignmentChanged(proteinFrame.alignPanel);
2473 * check errorMessage for a valid error message and raise an error box in the
2474 * GUI or write the current errorMessage to stderr and then clear the error
2477 protected void reportErrors()
2479 reportErrors(false);
2482 protected void reportErrors(final boolean saving)
2484 if (errorMessage != null)
2486 final String finalErrorMessage = errorMessage;
2489 javax.swing.SwingUtilities.invokeLater(new Runnable()
2494 JOptionPane.showInternalMessageDialog(Desktop.desktop,
2495 finalErrorMessage, "Error "
2496 + (saving ? "saving" : "loading")
2497 + " Jalview file", JOptionPane.WARNING_MESSAGE);
2503 System.err.println("Problem loading Jalview file: " + errorMessage);
2506 errorMessage = null;
2509 Map<String, String> alreadyLoadedPDB = new HashMap<String, String>();
2512 * when set, local views will be updated from view stored in JalviewXML
2513 * Currently (28th Sep 2008) things will go horribly wrong in vamsas document
2514 * sync if this is set to true.
2516 private final boolean updateLocalViews = false;
2519 * Returns the path to a temporary file holding the PDB file for the given PDB
2520 * id. The first time of asking, searches for a file of that name in the
2521 * Jalview project jar, and copies it to a new temporary file. Any repeat
2522 * requests just return the path to the file previously created.
2528 String loadPDBFile(jarInputStreamProvider jprovider, String pdbId)
2530 if (alreadyLoadedPDB.containsKey(pdbId))
2532 return alreadyLoadedPDB.get(pdbId).toString();
2535 String tempFile = copyJarEntry(jprovider, pdbId, "jalview_pdb");
2536 if (tempFile != null)
2538 alreadyLoadedPDB.put(pdbId, tempFile);
2544 * Copies the jar entry of given name to a new temporary file and returns the
2545 * path to the file, or null if the entry is not found.
2548 * @param jarEntryName
2550 * a prefix for the temporary file name, must be at least three
2554 protected String copyJarEntry(jarInputStreamProvider jprovider,
2555 String jarEntryName, String prefix)
2557 BufferedReader in = null;
2558 PrintWriter out = null;
2562 JarInputStream jin = jprovider.getJarInputStream();
2564 * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new
2565 * URL(jprovider).openStream()); } else { jin = new JarInputStream(new
2566 * FileInputStream(jprovider)); }
2569 JarEntry entry = null;
2572 entry = jin.getNextJarEntry();
2573 } while (entry != null && !entry.getName().equals(jarEntryName));
2576 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
2577 File outFile = File.createTempFile(prefix, ".tmp");
2578 outFile.deleteOnExit();
2579 out = new PrintWriter(new FileOutputStream(outFile));
2582 while ((data = in.readLine()) != null)
2587 String t = outFile.getAbsolutePath();
2592 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
2594 } catch (Exception ex)
2596 ex.printStackTrace();
2604 } catch (IOException e)
2618 private class JvAnnotRow
2620 public JvAnnotRow(int i, AlignmentAnnotation jaa)
2627 * persisted version of annotation row from which to take vis properties
2629 public jalview.datamodel.AlignmentAnnotation template;
2632 * original position of the annotation row in the alignment
2638 * Load alignment frame from jalview XML DOM object
2643 * filename source string
2644 * @param loadTreesAndStructures
2645 * when false only create Viewport
2647 * data source provider
2648 * @return alignment frame created from view stored in DOM
2650 AlignFrame loadFromObject(JalviewModel object, String file,
2651 boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
2653 SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
2654 Sequence[] vamsasSeq = vamsasSet.getSequence();
2656 JalviewModelSequence jms = object.getJalviewModelSequence();
2658 Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
2661 // ////////////////////////////////
2664 List<SequenceI> hiddenSeqs = null;
2665 jalview.datamodel.Sequence jseq;
2667 List<SequenceI> tmpseqs = new ArrayList<SequenceI>();
2669 boolean multipleView = false;
2670 SequenceI referenceseqForView = null;
2671 JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
2672 int vi = 0; // counter in vamsasSeq array
2673 for (int i = 0; i < jseqs.length; i++)
2675 String seqId = jseqs[i].getId();
2677 if (seqRefIds.get(seqId) != null)
2679 tmpseqs.add(seqRefIds.get(seqId));
2680 multipleView = true;
2684 jseq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
2685 vamsasSeq[vi].getSequence());
2686 jseq.setDescription(vamsasSeq[vi].getDescription());
2687 jseq.setStart(jseqs[i].getStart());
2688 jseq.setEnd(jseqs[i].getEnd());
2689 jseq.setVamsasId(uniqueSetSuffix + seqId);
2690 seqRefIds.put(vamsasSeq[vi].getId(), jseq);
2695 if (jseqs[i].hasViewreference() && jseqs[i].getViewreference())
2697 referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
2700 if (jseqs[i].getHidden())
2702 if (hiddenSeqs == null)
2704 hiddenSeqs = new ArrayList<SequenceI>();
2707 hiddenSeqs.add(seqRefIds.get(seqId));
2712 // Create the alignment object from the sequence set
2713 // ///////////////////////////////
2714 SequenceI[] orderedSeqs = tmpseqs
2715 .toArray(new SequenceI[tmpseqs.size()]);
2717 Alignment al = new Alignment(orderedSeqs);
2719 if (referenceseqForView != null)
2721 al.setSeqrep(referenceseqForView);
2723 // / Add the alignment properties
2724 for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
2726 SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
2727 al.setProperty(ssp.getKey(), ssp.getValue());
2731 // SequenceFeatures are added to the DatasetSequence,
2732 // so we must create or recover the dataset before loading features
2733 // ///////////////////////////////
2734 if (vamsasSet.getDatasetId() == null || vamsasSet.getDatasetId() == "")
2736 // older jalview projects do not have a dataset id.
2737 al.setDataset(null);
2741 // recover dataset - passing on flag indicating if this a 'viewless'
2742 // sequence set (a.k.a. a stored dataset for the project)
2743 recoverDatasetFor(vamsasSet, al, object.getJalviewModelSequence()
2744 .getViewportCount() == 0);
2746 // ///////////////////////////////
2748 Hashtable pdbloaded = new Hashtable(); // TODO nothing writes to this??
2751 // load sequence features, database references and any associated PDB
2752 // structures for the alignment
2753 for (int i = 0; i < vamsasSeq.length; i++)
2755 if (jseqs[i].getFeaturesCount() > 0)
2757 Features[] features = jseqs[i].getFeatures();
2758 for (int f = 0; f < features.length; f++)
2760 jalview.datamodel.SequenceFeature sf = new jalview.datamodel.SequenceFeature(
2761 features[f].getType(), features[f].getDescription(),
2762 features[f].getStatus(), features[f].getBegin(),
2763 features[f].getEnd(), features[f].getFeatureGroup());
2765 sf.setScore(features[f].getScore());
2766 for (int od = 0; od < features[f].getOtherDataCount(); od++)
2768 OtherData keyValue = features[f].getOtherData(od);
2769 if (keyValue.getKey().startsWith("LINK"))
2771 sf.addLink(keyValue.getValue());
2775 sf.setValue(keyValue.getKey(), keyValue.getValue());
2780 al.getSequenceAt(i).getDatasetSequence().addSequenceFeature(sf);
2783 if (vamsasSeq[i].getDBRefCount() > 0)
2785 addDBRefs(al.getSequenceAt(i).getDatasetSequence(), vamsasSeq[i]);
2787 if (jseqs[i].getPdbidsCount() > 0)
2789 Pdbids[] ids = jseqs[i].getPdbids();
2790 for (int p = 0; p < ids.length; p++)
2792 jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
2793 entry.setId(ids[p].getId());
2794 if (ids[p].getType() != null)
2796 if (ids[p].getType().equalsIgnoreCase("PDB"))
2798 entry.setType(PDBEntry.Type.PDB);
2802 entry.setType(PDBEntry.Type.FILE);
2805 if (ids[p].getFile() != null)
2807 if (!pdbloaded.containsKey(ids[p].getFile()))
2809 entry.setFile(loadPDBFile(jprovider, ids[p].getId()));
2813 entry.setFile(pdbloaded.get(ids[p].getId()).toString());
2816 StructureSelectionManager.getStructureSelectionManager(
2817 Desktop.instance).registerPDBEntry(entry);
2818 al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
2822 } // end !multipleview
2824 // ///////////////////////////////
2825 // LOAD SEQUENCE MAPPINGS
2827 if (vamsasSet.getAlcodonFrameCount() > 0)
2829 // TODO Potentially this should only be done once for all views of an
2831 AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
2832 for (int i = 0; i < alc.length; i++)
2834 AlignedCodonFrame cf = new AlignedCodonFrame();
2835 if (alc[i].getAlcodMapCount() > 0)
2837 AlcodMap[] maps = alc[i].getAlcodMap();
2838 for (int m = 0; m < maps.length; m++)
2840 SequenceI dnaseq = seqRefIds.get(maps[m].getDnasq());
2842 jalview.datamodel.Mapping mapping = null;
2843 // attach to dna sequence reference.
2844 if (maps[m].getMapping() != null)
2846 mapping = addMapping(maps[m].getMapping());
2848 if (dnaseq != null && mapping.getTo() != null)
2850 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
2855 frefedSequence.add(new Object[] { maps[m].getDnasq(), cf,
2860 al.addCodonFrame(cf);
2864 // ////////////////////////////////
2866 List<JvAnnotRow> autoAlan = new ArrayList<JvAnnotRow>();
2869 * store any annotations which forward reference a group's ID
2871 Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<String, List<AlignmentAnnotation>>();
2873 if (vamsasSet.getAnnotationCount() > 0)
2875 Annotation[] an = vamsasSet.getAnnotation();
2877 for (int i = 0; i < an.length; i++)
2879 Annotation annotation = an[i];
2882 * test if annotation is automatically calculated for this view only
2884 boolean autoForView = false;
2885 if (annotation.getLabel().equals("Quality")
2886 || annotation.getLabel().equals("Conservation")
2887 || annotation.getLabel().equals("Consensus"))
2889 // Kludge for pre 2.5 projects which lacked the autocalculated flag
2891 if (!annotation.hasAutoCalculated())
2893 annotation.setAutoCalculated(true);
2897 || (annotation.hasAutoCalculated() && annotation
2898 .isAutoCalculated()))
2900 // remove ID - we don't recover annotation from other views for
2901 // view-specific annotation
2902 annotation.setId(null);
2905 // set visiblity for other annotation in this view
2906 String annotationId = annotation.getId();
2907 if (annotationId != null && annotationIds.containsKey(annotationId))
2909 AlignmentAnnotation jda = annotationIds.get(annotationId);
2910 // in principle Visible should always be true for annotation displayed
2911 // in multiple views
2912 if (annotation.hasVisible())
2914 jda.visible = annotation.getVisible();
2917 al.addAnnotation(jda);
2921 // Construct new annotation from model.
2922 AnnotationElement[] ae = annotation.getAnnotationElement();
2923 jalview.datamodel.Annotation[] anot = null;
2924 java.awt.Color firstColour = null;
2926 if (!annotation.getScoreOnly())
2928 anot = new jalview.datamodel.Annotation[al.getWidth()];
2929 for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
2931 anpos = ae[aa].getPosition();
2933 if (anpos >= anot.length)
2938 anot[anpos] = new jalview.datamodel.Annotation(
2940 ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
2941 (ae[aa].getSecondaryStructure() == null || ae[aa]
2942 .getSecondaryStructure().length() == 0) ? ' '
2943 : ae[aa].getSecondaryStructure().charAt(0),
2947 // JBPNote: Consider verifying dataflow for IO of secondary
2948 // structure annotation read from Stockholm files
2949 // this was added to try to ensure that
2950 // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
2952 // anot[ae[aa].getPosition()].displayCharacter = "";
2954 anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
2955 if (firstColour == null)
2957 firstColour = anot[anpos].colour;
2961 jalview.datamodel.AlignmentAnnotation jaa = null;
2963 if (annotation.getGraph())
2965 float llim = 0, hlim = 0;
2966 // if (autoForView || an[i].isAutoCalculated()) {
2969 jaa = new jalview.datamodel.AlignmentAnnotation(
2970 annotation.getLabel(), annotation.getDescription(), anot,
2971 llim, hlim, annotation.getGraphType());
2973 jaa.graphGroup = annotation.getGraphGroup();
2974 jaa._linecolour = firstColour;
2975 if (annotation.getThresholdLine() != null)
2977 jaa.setThreshold(new jalview.datamodel.GraphLine(annotation
2978 .getThresholdLine().getValue(), annotation
2979 .getThresholdLine().getLabel(), new java.awt.Color(
2980 annotation.getThresholdLine().getColour())));
2983 if (autoForView || annotation.isAutoCalculated())
2985 // Hardwire the symbol display line to ensure that labels for
2986 // histograms are displayed
2992 jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
2993 an[i].getDescription(), anot);
2994 jaa._linecolour = firstColour;
2996 // register new annotation
2997 if (an[i].getId() != null)
2999 annotationIds.put(an[i].getId(), jaa);
3000 jaa.annotationId = an[i].getId();
3002 // recover sequence association
3003 String sequenceRef = an[i].getSequenceRef();
3004 if (sequenceRef != null)
3006 // from 2.9 sequenceRef is to sequence id (JAL-1781)
3007 SequenceI sequence = seqRefIds.get(sequenceRef);
3008 if (sequence == null)
3010 // in pre-2.9 projects sequence ref is to sequence name
3011 sequence = al.findName(sequenceRef);
3013 if (sequence != null)
3015 jaa.createSequenceMapping(sequence, 1, true);
3016 sequence.addAlignmentAnnotation(jaa);
3019 // and make a note of any group association
3020 if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
3022 List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
3023 .get(an[i].getGroupRef());
3026 aal = new ArrayList<jalview.datamodel.AlignmentAnnotation>();
3027 groupAnnotRefs.put(an[i].getGroupRef(), aal);
3032 if (an[i].hasScore())
3034 jaa.setScore(an[i].getScore());
3036 if (an[i].hasVisible())
3038 jaa.visible = an[i].getVisible();
3041 if (an[i].hasCentreColLabels())
3043 jaa.centreColLabels = an[i].getCentreColLabels();
3046 if (an[i].hasScaleColLabels())
3048 jaa.scaleColLabel = an[i].getScaleColLabels();
3050 if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
3052 // newer files have an 'autoCalculated' flag and store calculation
3053 // state in viewport properties
3054 jaa.autoCalculated = true; // means annotation will be marked for
3055 // update at end of load.
3057 if (an[i].hasGraphHeight())
3059 jaa.graphHeight = an[i].getGraphHeight();
3061 if (an[i].hasBelowAlignment())
3063 jaa.belowAlignment = an[i].isBelowAlignment();
3065 jaa.setCalcId(an[i].getCalcId());
3066 if (an[i].getPropertyCount() > 0)
3068 for (jalview.schemabinding.version2.Property prop : an[i]
3071 jaa.setProperty(prop.getName(), prop.getValue());
3074 if (jaa.autoCalculated)
3076 autoAlan.add(new JvAnnotRow(i, jaa));
3079 // if (!autoForView)
3081 // add autocalculated group annotation and any user created annotation
3083 al.addAnnotation(jaa);
3087 // ///////////////////////
3089 // Create alignment markup and styles for this view
3090 if (jms.getJGroupCount() > 0)
3092 JGroup[] groups = jms.getJGroup();
3093 boolean addAnnotSchemeGroup = false;
3094 for (int i = 0; i < groups.length; i++)
3096 JGroup jGroup = groups[i];
3097 ColourSchemeI cs = null;
3098 if (jGroup.getColour() != null)
3100 if (jGroup.getColour().startsWith("ucs"))
3102 cs = getUserColourScheme(jms, jGroup.getColour());
3104 else if (jGroup.getColour().equals("AnnotationColourGradient")
3105 && jGroup.getAnnotationColours() != null)
3107 addAnnotSchemeGroup = true;
3112 cs = ColourSchemeProperty.getColour(al, jGroup.getColour());
3117 cs.setThreshold(jGroup.getPidThreshold(), true);
3121 Vector<SequenceI> seqs = new Vector<SequenceI>();
3123 for (int s = 0; s < jGroup.getSeqCount(); s++)
3125 String seqId = jGroup.getSeq(s) + "";
3126 SequenceI ts = seqRefIds.get(seqId);
3130 seqs.addElement(ts);
3134 if (seqs.size() < 1)
3139 SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
3140 jGroup.getDisplayBoxes(), jGroup.getDisplayText(),
3141 jGroup.getColourText(), jGroup.getStart(), jGroup.getEnd());
3143 sg.setOutlineColour(new java.awt.Color(jGroup.getOutlineColour()));
3145 sg.textColour = new java.awt.Color(jGroup.getTextCol1());
3146 sg.textColour2 = new java.awt.Color(jGroup.getTextCol2());
3147 sg.setShowNonconserved(jGroup.hasShowUnconserved() ? jGroup
3148 .isShowUnconserved() : false);
3149 sg.thresholdTextColour = jGroup.getTextColThreshold();
3150 if (jGroup.hasShowConsensusHistogram())
3152 sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
3155 if (jGroup.hasShowSequenceLogo())
3157 sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
3159 if (jGroup.hasNormaliseSequenceLogo())
3161 sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
3163 if (jGroup.hasIgnoreGapsinConsensus())
3165 sg.setIgnoreGapsConsensus(jGroup.getIgnoreGapsinConsensus());
3167 if (jGroup.getConsThreshold() != 0)
3169 jalview.analysis.Conservation c = new jalview.analysis.Conservation(
3170 "All", ResidueProperties.propHash, 3,
3171 sg.getSequences(null), 0, sg.getWidth() - 1);
3173 c.verdict(false, 25);
3174 sg.cs.setConservation(c);
3177 if (jGroup.getId() != null && groupAnnotRefs.size() > 0)
3179 // re-instate unique group/annotation row reference
3180 List<AlignmentAnnotation> jaal = groupAnnotRefs.get(jGroup
3184 for (AlignmentAnnotation jaa : jaal)
3187 if (jaa.autoCalculated)
3189 // match up and try to set group autocalc alignment row for this
3191 if (jaa.label.startsWith("Consensus for "))
3193 sg.setConsensus(jaa);
3195 // match up and try to set group autocalc alignment row for this
3197 if (jaa.label.startsWith("Conservation for "))
3199 sg.setConservationRow(jaa);
3206 if (addAnnotSchemeGroup)
3208 // reconstruct the annotation colourscheme
3209 sg.cs = constructAnnotationColour(jGroup.getAnnotationColours(),
3210 null, al, jms, false);
3216 // only dataset in this model, so just return.
3219 // ///////////////////////////////
3222 // If we just load in the same jar file again, the sequenceSetId
3223 // will be the same, and we end up with multiple references
3224 // to the same sequenceSet. We must modify this id on load
3225 // so that each load of the file gives a unique id
3226 String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
3227 String viewId = (view.getId() == null ? null : view.getId()
3229 AlignFrame af = null;
3230 AlignViewport av = null;
3231 // now check to see if we really need to create a new viewport.
3232 if (multipleView && viewportsAdded.size() == 0)
3234 // We recovered an alignment for which a viewport already exists.
3235 // TODO: fix up any settings necessary for overlaying stored state onto
3236 // state recovered from another document. (may not be necessary).
3237 // we may need a binding from a viewport in memory to one recovered from
3239 // and then recover its containing af to allow the settings to be applied.
3240 // TODO: fix for vamsas demo
3242 .println("About to recover a viewport for existing alignment: Sequence set ID is "
3244 Object seqsetobj = retrieveExistingObj(uniqueSeqSetId);
3245 if (seqsetobj != null)
3247 if (seqsetobj instanceof String)
3249 uniqueSeqSetId = (String) seqsetobj;
3251 .println("Recovered extant sequence set ID mapping for ID : New Sequence set ID is "
3257 .println("Warning : Collision between sequence set ID string and existing jalview object mapping.");
3263 * indicate that annotation colours are applied across all groups (pre
3264 * Jalview 2.8.1 behaviour)
3266 boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan(
3267 "2.8.1", object.getVersion());
3269 AlignmentPanel ap = null;
3270 boolean isnewview = true;
3273 // Check to see if this alignment already has a view id == viewId
3274 jalview.gui.AlignmentPanel views[] = Desktop
3275 .getAlignmentPanels(uniqueSeqSetId);
3276 if (views != null && views.length > 0)
3278 for (int v = 0; v < views.length; v++)
3280 if (views[v].av.getViewId().equalsIgnoreCase(viewId))
3282 // recover the existing alignpanel, alignframe, viewport
3283 af = views[v].alignFrame;
3286 // TODO: could even skip resetting view settings if we don't want to
3287 // change the local settings from other jalview processes
3296 af = loadViewport(file, jseqs, hiddenSeqs, al, jms, view,
3297 uniqueSeqSetId, viewId, autoAlan);
3303 * Load any trees, PDB structures and viewers
3305 * Not done if flag is false (when this method is used for New View)
3307 if (loadTreesAndStructures)
3309 loadTrees(jms, view, af, av, ap);
3310 loadPDBStructures(jprovider, jseqs, af, ap);
3311 loadRnaViewers(jprovider, jseqs, ap);
3313 // and finally return.
3318 * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
3319 * panel is restored from separate jar entries, two (gapped and trimmed) per
3320 * sequence and secondary structure.
3322 * Currently each viewer shows just one sequence and structure (gapped and
3323 * trimmed), however this method is designed to support multiple sequences or
3324 * structures in viewers if wanted in future.
3330 private void loadRnaViewers(jarInputStreamProvider jprovider,
3331 JSeq[] jseqs, AlignmentPanel ap)
3334 * scan the sequences for references to viewers; create each one the first
3335 * time it is referenced, add Rna models to existing viewers
3337 for (JSeq jseq : jseqs)
3339 for (int i = 0; i < jseq.getRnaViewerCount(); i++)
3341 RnaViewer viewer = jseq.getRnaViewer(i);
3342 AppVarna appVarna = findOrCreateVarnaViewer(viewer,
3343 uniqueSetSuffix, ap);
3345 for (int j = 0; j < viewer.getSecondaryStructureCount(); j++)
3347 SecondaryStructure ss = viewer.getSecondaryStructure(j);
3348 SequenceI seq = seqRefIds.get(jseq.getId());
3349 AlignmentAnnotation ann = this.annotationIds.get(ss
3350 .getAnnotationId());
3353 * add the structure to the Varna display (with session state copied
3354 * from the jar to a temporary file)
3356 boolean gapped = ss.isGapped();
3357 String rnaTitle = ss.getTitle();
3358 String sessionState = ss.getViewerState();
3359 String tempStateFile = copyJarEntry(jprovider, sessionState,
3361 RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
3362 appVarna.addModelSession(rna, rnaTitle, tempStateFile);
3364 appVarna.setInitialSelection(viewer.getSelectedRna());
3370 * Locate and return an already instantiated matching AppVarna, or create one
3374 * @param viewIdSuffix
3378 protected AppVarna findOrCreateVarnaViewer(RnaViewer viewer,
3379 String viewIdSuffix, AlignmentPanel ap)
3382 * on each load a suffix is appended to the saved viewId, to avoid conflicts
3383 * if load is repeated
3385 String postLoadId = viewer.getViewId() + viewIdSuffix;
3386 for (JInternalFrame frame : getAllFrames())
3388 if (frame instanceof AppVarna)
3390 AppVarna varna = (AppVarna) frame;
3391 if (postLoadId.equals(varna.getViewId()))
3393 // this viewer is already instantiated
3394 // could in future here add ap as another 'parent' of the
3395 // AppVarna window; currently just 1-to-many
3402 * viewer not found - make it
3404 RnaViewerModel model = new RnaViewerModel(postLoadId,
3405 viewer.getTitle(), viewer.getXpos(), viewer.getYpos(),
3406 viewer.getWidth(), viewer.getHeight(),
3407 viewer.getDividerLocation());
3408 AppVarna varna = new AppVarna(model, ap);
3414 * Load any saved trees
3422 protected void loadTrees(JalviewModelSequence jms, Viewport view,
3423 AlignFrame af, AlignViewport av, AlignmentPanel ap)
3425 // TODO result of automated refactoring - are all these parameters needed?
3428 for (int t = 0; t < jms.getTreeCount(); t++)
3431 Tree tree = jms.getTree(t);
3433 TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
3436 tp = af.ShowNewickTree(
3437 new jalview.io.NewickFile(tree.getNewick()),
3438 tree.getTitle(), tree.getWidth(), tree.getHeight(),
3439 tree.getXpos(), tree.getYpos());
3440 if (tree.getId() != null)
3442 // perhaps bind the tree id to something ?
3447 // update local tree attributes ?
3448 // TODO: should check if tp has been manipulated by user - if so its
3449 // settings shouldn't be modified
3450 tp.setTitle(tree.getTitle());
3451 tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(), tree
3452 .getWidth(), tree.getHeight()));
3453 tp.av = av; // af.viewport; // TODO: verify 'associate with all
3456 tp.treeCanvas.av = av; // af.viewport;
3457 tp.treeCanvas.ap = ap; // af.alignPanel;
3462 warn("There was a problem recovering stored Newick tree: \n"
3463 + tree.getNewick());
3467 tp.fitToWindow.setState(tree.getFitToWindow());
3468 tp.fitToWindow_actionPerformed(null);
3470 if (tree.getFontName() != null)
3472 tp.setTreeFont(new java.awt.Font(tree.getFontName(), tree
3473 .getFontStyle(), tree.getFontSize()));
3477 tp.setTreeFont(new java.awt.Font(view.getFontName(), view
3478 .getFontStyle(), tree.getFontSize()));
3481 tp.showPlaceholders(tree.getMarkUnlinked());
3482 tp.showBootstrap(tree.getShowBootstrap());
3483 tp.showDistances(tree.getShowDistances());
3485 tp.treeCanvas.threshold = tree.getThreshold();
3487 if (tree.getCurrentTree())
3489 af.viewport.setCurrentTree(tp.getTree());
3493 } catch (Exception ex)
3495 ex.printStackTrace();
3500 * Load and link any saved structure viewers.
3507 protected void loadPDBStructures(jarInputStreamProvider jprovider,
3508 JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
3511 * Run through all PDB ids on the alignment, and collect mappings between
3512 * distinct view ids and all sequences referring to that view.
3514 Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<String, StructureViewerModel>();
3516 for (int i = 0; i < jseqs.length; i++)
3518 if (jseqs[i].getPdbidsCount() > 0)
3520 Pdbids[] ids = jseqs[i].getPdbids();
3521 for (int p = 0; p < ids.length; p++)
3523 final int structureStateCount = ids[p].getStructureStateCount();
3524 for (int s = 0; s < structureStateCount; s++)
3526 // check to see if we haven't already created this structure view
3527 final StructureState structureState = ids[p]
3528 .getStructureState(s);
3529 String sviewid = (structureState.getViewId() == null) ? null
3530 : structureState.getViewId() + uniqueSetSuffix;
3531 jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
3532 // Originally : ids[p].getFile()
3533 // : TODO: verify external PDB file recovery still works in normal
3534 // jalview project load
3535 jpdb.setFile(loadPDBFile(jprovider, ids[p].getId()));
3536 jpdb.setId(ids[p].getId());
3538 int x = structureState.getXpos();
3539 int y = structureState.getYpos();
3540 int width = structureState.getWidth();
3541 int height = structureState.getHeight();
3543 // Probably don't need to do this anymore...
3544 // Desktop.desktop.getComponentAt(x, y);
3545 // TODO: NOW: check that this recovers the PDB file correctly.
3546 String pdbFile = loadPDBFile(jprovider, ids[p].getId());
3547 jalview.datamodel.SequenceI seq = seqRefIds.get(jseqs[i]
3549 if (sviewid == null)
3551 sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width
3554 if (!structureViewers.containsKey(sviewid))
3556 structureViewers.put(sviewid,
3557 new StructureViewerModel(x, y, width, height, false,
3558 false, true, structureState.getViewId(),
3559 structureState.getType()));
3560 // Legacy pre-2.7 conversion JAL-823 :
3561 // do not assume any view has to be linked for colour by
3565 // assemble String[] { pdb files }, String[] { id for each
3566 // file }, orig_fileloc, SequenceI[][] {{ seqs_file 1 }, {
3567 // seqs_file 2}, boolean[] {
3568 // linkAlignPanel,superposeWithAlignpanel}} from hash
3569 StructureViewerModel jmoldat = structureViewers.get(sviewid);
3570 jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
3571 | (structureState.hasAlignwithAlignPanel() ? structureState
3572 .getAlignwithAlignPanel() : false));
3575 * Default colour by linked panel to false if not specified (e.g.
3576 * for pre-2.7 projects)
3578 boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
3579 colourWithAlignPanel |= (structureState
3580 .hasColourwithAlignPanel() ? structureState
3581 .getColourwithAlignPanel() : false);
3582 jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
3585 * Default colour by viewer to true if not specified (e.g. for
3588 boolean colourByViewer = jmoldat.isColourByViewer();
3589 colourByViewer &= structureState.hasColourByJmol() ? structureState
3590 .getColourByJmol() : true;
3591 jmoldat.setColourByViewer(colourByViewer);
3593 if (jmoldat.getStateData().length() < structureState
3594 .getContent().length())
3597 jmoldat.setStateData(structureState.getContent());
3600 if (ids[p].getFile() != null)
3602 File mapkey = new File(ids[p].getFile());
3603 StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
3604 if (seqstrmaps == null)
3606 jmoldat.getFileData().put(
3608 seqstrmaps = jmoldat.new StructureData(pdbFile,
3611 if (!seqstrmaps.getSeqList().contains(seq))
3613 seqstrmaps.getSeqList().add(seq);
3619 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");
3626 // Instantiate the associated structure views
3627 for (Entry<String, StructureViewerModel> entry : structureViewers
3632 createOrLinkStructureViewer(entry, af, ap, jprovider);
3633 } catch (Exception e)
3635 System.err.println("Error loading structure viewer: "
3637 // failed - try the next one
3649 protected void createOrLinkStructureViewer(
3650 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3651 AlignmentPanel ap, jarInputStreamProvider jprovider)
3653 final StructureViewerModel stateData = viewerData.getValue();
3656 * Search for any viewer windows already open from other alignment views
3657 * that exactly match the stored structure state
3659 StructureViewerBase comp = findMatchingViewer(viewerData);
3663 linkStructureViewer(ap, comp, stateData);
3668 * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry
3669 * "viewer_"+stateData.viewId
3671 if (ViewerType.CHIMERA.toString().equals(stateData.getType()))
3673 createChimeraViewer(viewerData, af, jprovider);
3678 * else Jmol (if pre-2.9, stateData contains JMOL state string)
3680 createJmolViewer(viewerData, af, jprovider);
3685 * Create a new Chimera viewer.
3691 protected void createChimeraViewer(
3692 Entry<String, StructureViewerModel> viewerData, AlignFrame af,
3693 jarInputStreamProvider jprovider)
3695 StructureViewerModel data = viewerData.getValue();
3696 String chimeraSessionFile = data.getStateData();
3699 * Copy Chimera session from jar entry "viewer_"+viewId to a temporary file
3701 * NB this is the 'saved' viewId as in the project file XML, _not_ the
3702 * 'uniquified' sviewid used to reconstruct the viewer here
3704 String viewerJarEntryName = getViewerJarEntryName(data.getViewId());
3705 chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName,
3708 Set<Entry<File, StructureData>> fileData = data.getFileData()
3710 List<PDBEntry> pdbs = new ArrayList<PDBEntry>();
3711 List<SequenceI[]> allseqs = new ArrayList<SequenceI[]>();
3712 for (Entry<File, StructureData> pdb : fileData)
3714 String filePath = pdb.getValue().getFilePath();
3715 String pdbId = pdb.getValue().getPdbId();
3716 // pdbs.add(new PDBEntry(filePath, pdbId));
3717 pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath));
3718 final List<SequenceI> seqList = pdb.getValue().getSeqList();
3719 SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]);
3723 boolean colourByChimera = data.isColourByViewer();
3724 boolean colourBySequence = data.isColourWithAlignPanel();
3726 // TODO use StructureViewer as a factory here, see JAL-1761
3727 final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]);
3728 final SequenceI[][] seqsArray = allseqs.toArray(new SequenceI[allseqs
3730 String newViewId = viewerData.getKey();
3732 ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile,
3733 af.alignPanel, pdbArray, seqsArray, colourByChimera,
3734 colourBySequence, newViewId);
3735 cvf.setSize(data.getWidth(), data.getHeight());
3736 cvf.setLocation(data.getX(), data.getY());
3740 * Create a new Jmol window. First parse the Jmol state to translate filenames
3741 * loaded into the view, and record the order in which files are shown in the
3742 * Jmol view, so we can add the sequence mappings in same order.
3748 protected void createJmolViewer(
3749 final Entry<String, StructureViewerModel> viewerData,
3750 AlignFrame af, jarInputStreamProvider jprovider)
3752 final StructureViewerModel svattrib = viewerData.getValue();
3753 String state = svattrib.getStateData();
3756 * Pre-2.9: state element value is the Jmol state string
3758 * 2.9+: @type is "JMOL", state data is in a Jar file member named "viewer_"
3761 if (ViewerType.JMOL.toString().equals(svattrib.getType()))
3763 state = readJarEntry(jprovider,
3764 getViewerJarEntryName(svattrib.getViewId()));
3767 List<String> pdbfilenames = new ArrayList<String>();
3768 List<SequenceI[]> seqmaps = new ArrayList<SequenceI[]>();
3769 List<String> pdbids = new ArrayList<String>();
3770 StringBuilder newFileLoc = new StringBuilder(64);
3771 int cp = 0, ncp, ecp;
3772 Map<File, StructureData> oldFiles = svattrib.getFileData();
3773 while ((ncp = state.indexOf("load ", cp)) > -1)
3777 // look for next filename in load statement
3778 newFileLoc.append(state.substring(cp,
3779 ncp = (state.indexOf("\"", ncp + 1) + 1)));
3780 String oldfilenam = state.substring(ncp,
3781 ecp = state.indexOf("\"", ncp));
3782 // recover the new mapping data for this old filename
3783 // have to normalize filename - since Jmol and jalview do
3785 // translation differently.
3786 StructureData filedat = oldFiles.get(new File(oldfilenam));
3787 newFileLoc.append(Platform.escapeString(filedat.getFilePath()));
3788 pdbfilenames.add(filedat.getFilePath());
3789 pdbids.add(filedat.getPdbId());
3790 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
3791 newFileLoc.append("\"");
3792 cp = ecp + 1; // advance beyond last \" and set cursor so we can
3793 // look for next file statement.
3794 } while ((ncp = state.indexOf("/*file*/", cp)) > -1);
3798 // just append rest of state
3799 newFileLoc.append(state.substring(cp));
3803 System.err.print("Ignoring incomplete Jmol state for PDB ids: ");
3804 newFileLoc = new StringBuilder(state);
3805 newFileLoc.append("; load append ");
3806 for (File id : oldFiles.keySet())
3808 // add this and any other pdb files that should be present in
3810 StructureData filedat = oldFiles.get(id);
3811 newFileLoc.append(filedat.getFilePath());
3812 pdbfilenames.add(filedat.getFilePath());
3813 pdbids.add(filedat.getPdbId());
3814 seqmaps.add(filedat.getSeqList().toArray(new SequenceI[0]));
3815 newFileLoc.append(" \"");
3816 newFileLoc.append(filedat.getFilePath());
3817 newFileLoc.append("\"");
3820 newFileLoc.append(";");
3823 if (newFileLoc.length() == 0)
3827 int histbug = newFileLoc.indexOf("history = ");
3831 * change "history = [true|false];" to "history = [1|0];"
3834 int diff = histbug == -1 ? -1 : newFileLoc.indexOf(";", histbug);
3835 String val = (diff == -1) ? null : newFileLoc
3836 .substring(histbug, diff);
3837 if (val != null && val.length() >= 4)
3839 if (val.contains("e")) // eh? what can it be?
3841 if (val.trim().equals("true"))
3849 newFileLoc.replace(histbug, diff, val);
3854 final String[] pdbf = pdbfilenames.toArray(new String[pdbfilenames
3856 final String[] id = pdbids.toArray(new String[pdbids.size()]);
3857 final SequenceI[][] sq = seqmaps
3858 .toArray(new SequenceI[seqmaps.size()][]);
3859 final String fileloc = newFileLoc.toString();
3860 final String sviewid = viewerData.getKey();
3861 final AlignFrame alf = af;
3862 final Rectangle rect = new Rectangle(svattrib.getX(), svattrib.getY(),
3863 svattrib.getWidth(), svattrib.getHeight());
3866 javax.swing.SwingUtilities.invokeAndWait(new Runnable()
3871 JalviewStructureDisplayI sview = null;
3874 sview = new StructureViewer(alf.alignPanel
3875 .getStructureSelectionManager()).createView(
3876 StructureViewer.ViewerType.JMOL, pdbf, id, sq,
3877 alf.alignPanel, svattrib, fileloc, rect, sviewid);
3878 addNewStructureViewer(sview);
3879 } catch (OutOfMemoryError ex)
3881 new OOMWarning("restoring structure view for PDB id " + id,
3882 (OutOfMemoryError) ex.getCause());
3883 if (sview != null && sview.isVisible())
3885 sview.closeViewer(false);
3886 sview.setVisible(false);
3892 } catch (InvocationTargetException ex)
3894 warn("Unexpected error when opening Jmol view.", ex);
3896 } catch (InterruptedException e)
3898 // e.printStackTrace();
3904 * Generates a name for the entry in the project jar file to hold state
3905 * information for a structure viewer
3910 protected String getViewerJarEntryName(String viewId)
3912 return VIEWER_PREFIX + viewId;
3916 * Returns any open frame that matches given structure viewer data. The match
3917 * is based on the unique viewId, or (for older project versions) the frame's
3923 protected StructureViewerBase findMatchingViewer(
3924 Entry<String, StructureViewerModel> viewerData)
3926 final String sviewid = viewerData.getKey();
3927 final StructureViewerModel svattrib = viewerData.getValue();
3928 StructureViewerBase comp = null;
3929 JInternalFrame[] frames = getAllFrames();
3930 for (JInternalFrame frame : frames)
3932 if (frame instanceof StructureViewerBase)
3935 * Post jalview 2.4 schema includes structure view id
3938 && ((StructureViewerBase) frame).getViewId()
3941 comp = (StructureViewerBase) frame;
3942 break; // break added in 2.9
3945 * Otherwise test for matching position and size of viewer frame
3947 else if (frame.getX() == svattrib.getX()
3948 && frame.getY() == svattrib.getY()
3949 && frame.getHeight() == svattrib.getHeight()
3950 && frame.getWidth() == svattrib.getWidth())
3952 comp = (StructureViewerBase) frame;
3953 // no break in faint hope of an exact match on viewId
3961 * Link an AlignmentPanel to an existing structure viewer.
3966 * @param useinViewerSuperpos
3967 * @param usetoColourbyseq
3968 * @param viewerColouring
3970 protected void linkStructureViewer(AlignmentPanel ap,
3971 StructureViewerBase viewer, StructureViewerModel stateData)
3973 // NOTE: if the jalview project is part of a shared session then
3974 // view synchronization should/could be done here.
3976 final boolean useinViewerSuperpos = stateData.isAlignWithPanel();
3977 final boolean usetoColourbyseq = stateData.isColourWithAlignPanel();
3978 final boolean viewerColouring = stateData.isColourByViewer();
3979 Map<File, StructureData> oldFiles = stateData.getFileData();
3982 * Add mapping for sequences in this view to an already open viewer
3984 final AAStructureBindingModel binding = viewer.getBinding();
3985 for (File id : oldFiles.keySet())
3987 // add this and any other pdb files that should be present in the
3989 StructureData filedat = oldFiles.get(id);
3990 String pdbFile = filedat.getFilePath();
3991 SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
3992 binding.getSsm().setMapping(seq, null, pdbFile,
3993 jalview.io.AppletFormatAdapter.FILE);
3994 binding.addSequenceForStructFile(pdbFile, seq);
3996 // and add the AlignmentPanel's reference to the view panel
3997 viewer.addAlignmentPanel(ap);
3998 if (useinViewerSuperpos)
4000 viewer.useAlignmentPanelForSuperposition(ap);
4004 viewer.excludeAlignmentPanelForSuperposition(ap);
4006 if (usetoColourbyseq)
4008 viewer.useAlignmentPanelForColourbyseq(ap, !viewerColouring);
4012 viewer.excludeAlignmentPanelForColourbyseq(ap);
4017 * Get all frames within the Desktop.
4021 protected JInternalFrame[] getAllFrames()
4023 JInternalFrame[] frames = null;
4024 // TODO is this necessary - is it safe - risk of hanging?
4029 frames = Desktop.desktop.getAllFrames();
4030 } catch (ArrayIndexOutOfBoundsException e)
4032 // occasional No such child exceptions are thrown here...
4036 } catch (InterruptedException f)
4040 } while (frames == null);
4045 * Answers true if 'version' is equal to or later than 'supported', where each
4046 * is formatted as major/minor versions like "2.8.3" or "2.3.4b1" for bugfix
4047 * changes. Development and test values for 'version' are leniently treated
4051 * - minimum version we are comparing against
4053 * - version of data being processsed
4056 public static boolean isVersionStringLaterThan(String supported,
4059 if (supported == null || version == null
4060 || version.equalsIgnoreCase("DEVELOPMENT BUILD")
4061 || version.equalsIgnoreCase("Test")
4062 || version.equalsIgnoreCase("AUTOMATED BUILD"))
4064 System.err.println("Assuming project file with "
4065 + (version == null ? "null" : version)
4066 + " is compatible with Jalview version " + supported);
4071 return StringUtils.compareVersions(version, supported, "b") >= 0;
4075 Vector<JalviewStructureDisplayI> newStructureViewers = null;
4077 protected void addNewStructureViewer(JalviewStructureDisplayI sview)
4079 if (newStructureViewers != null)
4081 sview.getBinding().setFinishedLoadingFromArchive(false);
4082 newStructureViewers.add(sview);
4086 protected void setLoadingFinishedForNewStructureViewers()
4088 if (newStructureViewers != null)
4090 for (JalviewStructureDisplayI sview : newStructureViewers)
4092 sview.getBinding().setFinishedLoadingFromArchive(true);
4094 newStructureViewers.clear();
4095 newStructureViewers = null;
4099 AlignFrame loadViewport(String file, JSeq[] JSEQ,
4100 List<SequenceI> hiddenSeqs, Alignment al,
4101 JalviewModelSequence jms, Viewport view, String uniqueSeqSetId,
4102 String viewId, List<JvAnnotRow> autoAlan)
4104 AlignFrame af = null;
4105 af = new AlignFrame(al, view.getWidth(), view.getHeight(),
4106 uniqueSeqSetId, viewId);
4108 af.setFileName(file, "Jalview");
4110 for (int i = 0; i < JSEQ.length; i++)
4112 af.viewport.setSequenceColour(af.viewport.getAlignment()
4113 .getSequenceAt(i), new java.awt.Color(JSEQ[i].getColour()));
4118 af.getViewport().setColourByReferenceSeq(true);
4119 af.getViewport().setDisplayReferenceSeq(true);
4122 af.viewport.setGatherViewsHere(view.getGatheredViews());
4124 if (view.getSequenceSetId() != null)
4126 AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
4128 af.viewport.setSequenceSetId(uniqueSeqSetId);
4131 // propagate shared settings to this new view
4132 af.viewport.setHistoryList(av.getHistoryList());
4133 af.viewport.setRedoList(av.getRedoList());
4137 viewportsAdded.put(uniqueSeqSetId, af.viewport);
4139 // TODO: check if this method can be called repeatedly without
4140 // side-effects if alignpanel already registered.
4141 PaintRefresher.Register(af.alignPanel, uniqueSeqSetId);
4143 // apply Hidden regions to view.
4144 if (hiddenSeqs != null)
4146 for (int s = 0; s < JSEQ.length; s++)
4148 jalview.datamodel.SequenceGroup hidden = new jalview.datamodel.SequenceGroup();
4150 for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
4153 al.getSequenceAt(JSEQ[s].getHiddenSequences(r)), false);
4155 af.viewport.hideRepSequences(al.getSequenceAt(s), hidden);
4158 // jalview.datamodel.SequenceI[] hseqs = new
4159 // jalview.datamodel.SequenceI[hiddenSeqs
4162 // for (int s = 0; s < hiddenSeqs.size(); s++)
4164 // hseqs[s] = (jalview.datamodel.SequenceI) hiddenSeqs.elementAt(s);
4167 SequenceI[] hseqs = hiddenSeqs.toArray(new SequenceI[hiddenSeqs
4169 af.viewport.hideSequence(hseqs);
4172 // recover view properties and display parameters
4173 if (view.getViewName() != null)
4175 af.viewport.viewName = view.getViewName();
4176 af.setInitialTabVisible();
4178 af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
4181 af.viewport.setShowAnnotation(view.getShowAnnotation());
4182 af.viewport.setAbovePIDThreshold(view.getPidSelected());
4184 af.viewport.setColourText(view.getShowColourText());
4186 af.viewport.setConservationSelected(view.getConservationSelected());
4187 af.viewport.setShowJVSuffix(view.getShowFullId());
4188 af.viewport.setRightAlignIds(view.getRightAlignIds());
4189 af.viewport.setFont(
4190 new java.awt.Font(view.getFontName(), view.getFontStyle(), view
4191 .getFontSize()), true);
4192 ViewStyleI vs = af.viewport.getViewStyle();
4193 vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
4194 af.viewport.setViewStyle(vs);
4195 // TODO: allow custom charWidth/Heights to be restored by updating them
4196 // after setting font - which means set above to false
4197 af.viewport.setRenderGaps(view.getRenderGaps());
4198 af.viewport.setWrapAlignment(view.getWrapAlignment());
4199 af.viewport.setShowAnnotation(view.getShowAnnotation());
4201 af.viewport.setShowBoxes(view.getShowBoxes());
4203 af.viewport.setShowText(view.getShowText());
4205 af.viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
4206 af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
4207 af.viewport.setThresholdTextColour(view.getTextColThreshold());
4208 af.viewport.setShowUnconserved(view.hasShowUnconserved() ? view
4209 .isShowUnconserved() : false);
4210 af.viewport.setStartRes(view.getStartRes());
4211 af.viewport.setStartSeq(view.getStartSeq());
4212 af.alignPanel.updateLayout();
4213 ColourSchemeI cs = null;
4214 // apply colourschemes
4215 if (view.getBgColour() != null)
4217 if (view.getBgColour().startsWith("ucs"))
4219 cs = getUserColourScheme(jms, view.getBgColour());
4221 else if (view.getBgColour().startsWith("Annotation"))
4223 AnnotationColours viewAnnColour = view.getAnnotationColours();
4224 cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
4231 cs = ColourSchemeProperty.getColour(al, view.getBgColour());
4236 cs.setThreshold(view.getPidThreshold(), true);
4237 cs.setConsensus(af.viewport.getSequenceConsensusHash());
4241 af.viewport.setGlobalColourScheme(cs);
4242 af.viewport.setColourAppliesToAllGroups(false);
4244 if (view.getConservationSelected() && cs != null)
4246 cs.setConservationInc(view.getConsThreshold());
4249 af.changeColour(cs);
4251 af.viewport.setColourAppliesToAllGroups(true);
4253 af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures());
4255 if (view.hasCentreColumnLabels())
4257 af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
4259 if (view.hasIgnoreGapsinConsensus())
4261 af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
4264 if (view.hasFollowHighlight())
4266 af.viewport.setFollowHighlight(view.getFollowHighlight());
4268 if (view.hasFollowSelection())
4270 af.viewport.followSelection = view.getFollowSelection();
4272 if (view.hasShowConsensusHistogram())
4274 af.viewport.setShowConsensusHistogram(view
4275 .getShowConsensusHistogram());
4279 af.viewport.setShowConsensusHistogram(true);
4281 if (view.hasShowSequenceLogo())
4283 af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
4287 af.viewport.setShowSequenceLogo(false);
4289 if (view.hasNormaliseSequenceLogo())
4291 af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
4293 if (view.hasShowDbRefTooltip())
4295 af.viewport.setShowDBRefs(view.getShowDbRefTooltip());
4297 if (view.hasShowNPfeatureTooltip())
4299 af.viewport.setShowNPFeats(view.hasShowNPfeatureTooltip());
4301 if (view.hasShowGroupConsensus())
4303 af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
4307 af.viewport.setShowGroupConsensus(false);
4309 if (view.hasShowGroupConservation())
4311 af.viewport.setShowGroupConservation(view.getShowGroupConservation());
4315 af.viewport.setShowGroupConservation(false);
4318 // recover featre settings
4319 if (jms.getFeatureSettings() != null)
4321 FeaturesDisplayed fdi;
4322 af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
4323 String[] renderOrder = new String[jms.getFeatureSettings()
4324 .getSettingCount()];
4325 Hashtable featureGroups = new Hashtable();
4326 Hashtable featureColours = new Hashtable();
4327 Hashtable featureOrder = new Hashtable();
4329 for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
4331 Setting setting = jms.getFeatureSettings().getSetting(fs);
4332 if (setting.hasMincolour())
4334 GraduatedColor gc = setting.hasMin() ? new GraduatedColor(
4335 new java.awt.Color(setting.getMincolour()),
4336 new java.awt.Color(setting.getColour()),
4337 setting.getMin(), setting.getMax()) : new GraduatedColor(
4338 new java.awt.Color(setting.getMincolour()),
4339 new java.awt.Color(setting.getColour()), 0, 1);
4340 if (setting.hasThreshold())
4342 gc.setThresh(setting.getThreshold());
4343 gc.setThreshType(setting.getThreshstate());
4345 gc.setAutoScaled(true); // default
4346 if (setting.hasAutoScale())
4348 gc.setAutoScaled(setting.getAutoScale());
4350 if (setting.hasColourByLabel())
4352 gc.setColourByLabel(setting.getColourByLabel());
4354 // and put in the feature colour table.
4355 featureColours.put(setting.getType(), gc);
4359 featureColours.put(setting.getType(),
4360 new java.awt.Color(setting.getColour()));
4362 renderOrder[fs] = setting.getType();
4363 if (setting.hasOrder())
4365 featureOrder.put(setting.getType(), setting.getOrder());
4369 featureOrder.put(setting.getType(), new Float(fs
4370 / jms.getFeatureSettings().getSettingCount()));
4372 if (setting.getDisplay())
4374 fdi.setVisible(setting.getType());
4377 Hashtable fgtable = new Hashtable();
4378 for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
4380 Group grp = jms.getFeatureSettings().getGroup(gs);
4381 fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
4383 // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
4384 // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
4385 // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
4386 FeatureRendererSettings frs = new FeatureRendererSettings(
4387 renderOrder, fgtable, featureColours, 1.0f, featureOrder);
4388 af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
4389 .transferSettings(frs);
4393 if (view.getHiddenColumnsCount() > 0)
4395 for (int c = 0; c < view.getHiddenColumnsCount(); c++)
4397 af.viewport.hideColumns(view.getHiddenColumns(c).getStart(), view
4398 .getHiddenColumns(c).getEnd() // +1
4402 if (view.getCalcIdParam() != null)
4404 for (CalcIdParam calcIdParam : view.getCalcIdParam())
4406 if (calcIdParam != null)
4408 if (recoverCalcIdParam(calcIdParam, af.viewport))
4413 warn("Couldn't recover parameters for "
4414 + calcIdParam.getCalcId());
4419 af.setMenusFromViewport(af.viewport);
4421 // TODO: we don't need to do this if the viewport is aready visible.
4423 * Add the AlignFrame to the desktop (it may be 'gathered' later), unless it
4424 * has a 'cdna/protein complement' view, in which case save it in order to
4425 * populate a SplitFrame once all views have been read in.
4427 String complementaryViewId = view.getComplementId();
4428 if (complementaryViewId == null)
4430 Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
4432 // recompute any autoannotation
4433 af.alignPanel.updateAnnotation(false, true);
4434 reorderAutoannotation(af, al, autoAlan);
4435 af.alignPanel.alignmentChanged();
4439 splitFrameCandidates.put(view, af);
4444 private ColourSchemeI constructAnnotationColour(
4445 AnnotationColours viewAnnColour, AlignFrame af, Alignment al,
4446 JalviewModelSequence jms, boolean checkGroupAnnColour)
4448 boolean propagateAnnColour = false;
4449 ColourSchemeI cs = null;
4450 AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
4451 if (checkGroupAnnColour && al.getGroups() != null
4452 && al.getGroups().size() > 0)
4454 // pre 2.8.1 behaviour
4455 // check to see if we should transfer annotation colours
4456 propagateAnnColour = true;
4457 for (jalview.datamodel.SequenceGroup sg : al.getGroups())
4459 if (sg.cs instanceof AnnotationColourGradient)
4461 propagateAnnColour = false;
4465 // int find annotation
4466 if (annAlignment.getAlignmentAnnotation() != null)
4468 for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
4470 if (annAlignment.getAlignmentAnnotation()[i].label
4471 .equals(viewAnnColour.getAnnotation()))
4473 if (annAlignment.getAlignmentAnnotation()[i].getThreshold() == null)
4475 annAlignment.getAlignmentAnnotation()[i]
4476 .setThreshold(new jalview.datamodel.GraphLine(
4477 viewAnnColour.getThreshold(), "Threshold",
4478 java.awt.Color.black)
4483 if (viewAnnColour.getColourScheme().equals("None"))
4485 cs = new AnnotationColourGradient(
4486 annAlignment.getAlignmentAnnotation()[i],
4487 new java.awt.Color(viewAnnColour.getMinColour()),
4488 new java.awt.Color(viewAnnColour.getMaxColour()),
4489 viewAnnColour.getAboveThreshold());
4491 else if (viewAnnColour.getColourScheme().startsWith("ucs"))
4493 cs = new AnnotationColourGradient(
4494 annAlignment.getAlignmentAnnotation()[i],
4495 getUserColourScheme(jms,
4496 viewAnnColour.getColourScheme()),
4497 viewAnnColour.getAboveThreshold());
4501 cs = new AnnotationColourGradient(
4502 annAlignment.getAlignmentAnnotation()[i],
4503 ColourSchemeProperty.getColour(al,
4504 viewAnnColour.getColourScheme()),
4505 viewAnnColour.getAboveThreshold());
4507 if (viewAnnColour.hasPerSequence())
4509 ((AnnotationColourGradient) cs).setSeqAssociated(viewAnnColour
4512 if (viewAnnColour.hasPredefinedColours())
4514 ((AnnotationColourGradient) cs)
4515 .setPredefinedColours(viewAnnColour
4516 .isPredefinedColours());
4518 if (propagateAnnColour && al.getGroups() != null)
4520 // Also use these settings for all the groups
4521 for (int g = 0; g < al.getGroups().size(); g++)
4523 jalview.datamodel.SequenceGroup sg = al.getGroups().get(g);
4531 * if (viewAnnColour.getColourScheme().equals("None" )) { sg.cs =
4532 * new AnnotationColourGradient(
4533 * annAlignment.getAlignmentAnnotation()[i], new
4534 * java.awt.Color(viewAnnColour. getMinColour()), new
4535 * java.awt.Color(viewAnnColour. getMaxColour()),
4536 * viewAnnColour.getAboveThreshold()); } else
4539 sg.cs = new AnnotationColourGradient(
4540 annAlignment.getAlignmentAnnotation()[i], sg.cs,
4541 viewAnnColour.getAboveThreshold());
4542 if (cs instanceof AnnotationColourGradient)
4544 if (viewAnnColour.hasPerSequence())
4546 ((AnnotationColourGradient) cs)
4547 .setSeqAssociated(viewAnnColour.isPerSequence());
4549 if (viewAnnColour.hasPredefinedColours())
4551 ((AnnotationColourGradient) cs)
4552 .setPredefinedColours(viewAnnColour
4553 .isPredefinedColours());
4569 private void reorderAutoannotation(AlignFrame af, Alignment al,
4570 List<JvAnnotRow> autoAlan)
4572 // copy over visualization settings for autocalculated annotation in the
4574 if (al.getAlignmentAnnotation() != null)
4577 * Kludge for magic autoannotation names (see JAL-811)
4579 String[] magicNames = new String[] { "Consensus", "Quality",
4581 JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
4582 Hashtable<String, JvAnnotRow> visan = new Hashtable<String, JvAnnotRow>();
4583 for (String nm : magicNames)
4585 visan.put(nm, nullAnnot);
4587 for (JvAnnotRow auan : autoAlan)
4589 visan.put(auan.template.label
4590 + (auan.template.getCalcId() == null ? "" : "\t"
4591 + auan.template.getCalcId()), auan);
4593 int hSize = al.getAlignmentAnnotation().length;
4594 List<JvAnnotRow> reorder = new ArrayList<JvAnnotRow>();
4595 // work through any autoCalculated annotation already on the view
4596 // removing it if it should be placed in a different location on the
4597 // annotation panel.
4598 List<String> remains = new ArrayList<String>(visan.keySet());
4599 for (int h = 0; h < hSize; h++)
4601 jalview.datamodel.AlignmentAnnotation jalan = al
4602 .getAlignmentAnnotation()[h];
4603 if (jalan.autoCalculated)
4606 JvAnnotRow valan = visan.get(k = jalan.label);
4607 if (jalan.getCalcId() != null)
4609 valan = visan.get(k = jalan.label + "\t" + jalan.getCalcId());
4614 // delete the auto calculated row from the alignment
4615 al.deleteAnnotation(jalan, false);
4619 if (valan != nullAnnot)
4621 if (jalan != valan.template)
4623 // newly created autoannotation row instance
4624 // so keep a reference to the visible annotation row
4625 // and copy over all relevant attributes
4626 if (valan.template.graphHeight >= 0)
4629 jalan.graphHeight = valan.template.graphHeight;
4631 jalan.visible = valan.template.visible;
4633 reorder.add(new JvAnnotRow(valan.order, jalan));
4638 // Add any (possibly stale) autocalculated rows that were not appended to
4639 // the view during construction
4640 for (String other : remains)
4642 JvAnnotRow othera = visan.get(other);
4643 if (othera != nullAnnot && othera.template.getCalcId() != null
4644 && othera.template.getCalcId().length() > 0)
4646 reorder.add(othera);
4649 // now put the automatic annotation in its correct place
4650 int s = 0, srt[] = new int[reorder.size()];
4651 JvAnnotRow[] rws = new JvAnnotRow[reorder.size()];
4652 for (JvAnnotRow jvar : reorder)
4655 srt[s++] = jvar.order;
4658 jalview.util.QuickSort.sort(srt, rws);
4659 // and re-insert the annotation at its correct position
4660 for (JvAnnotRow jvar : rws)
4662 al.addAnnotation(jvar.template, jvar.order);
4664 af.alignPanel.adjustAnnotationHeight();
4668 Hashtable skipList = null;
4671 * TODO remove this method
4674 * @return AlignFrame bound to sequenceSetId from view, if one exists. private
4675 * AlignFrame getSkippedFrame(Viewport view) { if (skipList==null) {
4676 * throw new Error("Implementation Error. No skipList defined for this
4677 * Jalview2XML instance."); } return (AlignFrame)
4678 * skipList.get(view.getSequenceSetId()); }
4682 * Check if the Jalview view contained in object should be skipped or not.
4685 * @return true if view's sequenceSetId is a key in skipList
4687 private boolean skipViewport(JalviewModel object)
4689 if (skipList == null)
4694 if (skipList.containsKey(id = object.getJalviewModelSequence()
4695 .getViewport()[0].getSequenceSetId()))
4697 if (Cache.log != null && Cache.log.isDebugEnabled())
4699 Cache.log.debug("Skipping seuqence set id " + id);
4706 public void addToSkipList(AlignFrame af)
4708 if (skipList == null)
4710 skipList = new Hashtable();
4712 skipList.put(af.getViewport().getSequenceSetId(), af);
4715 public void clearSkipList()
4717 if (skipList != null)
4724 private void recoverDatasetFor(SequenceSet vamsasSet, Alignment al,
4725 boolean ignoreUnrefed)
4727 jalview.datamodel.Alignment ds = getDatasetFor(vamsasSet.getDatasetId());
4728 Vector dseqs = null;
4731 // create a list of new dataset sequences
4732 dseqs = new Vector();
4734 for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
4736 Sequence vamsasSeq = vamsasSet.getSequence(i);
4737 ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed);
4739 // create a new dataset
4742 SequenceI[] dsseqs = new SequenceI[dseqs.size()];
4743 dseqs.copyInto(dsseqs);
4744 ds = new jalview.datamodel.Alignment(dsseqs);
4745 debug("Created new dataset " + vamsasSet.getDatasetId()
4746 + " for alignment " + System.identityHashCode(al));
4747 addDatasetRef(vamsasSet.getDatasetId(), ds);
4749 // set the dataset for the newly imported alignment.
4750 if (al.getDataset() == null && !ignoreUnrefed)
4759 * sequence definition to create/merge dataset sequence for
4763 * vector to add new dataset sequence to
4765 private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
4766 AlignmentI ds, Vector dseqs, boolean ignoreUnrefed)
4768 // JBP TODO: Check this is called for AlCodonFrames to support recovery of
4770 SequenceI sq = seqRefIds.get(vamsasSeq.getId());
4771 SequenceI dsq = null;
4772 if (sq != null && sq.getDatasetSequence() != null)
4774 dsq = sq.getDatasetSequence();
4776 if (sq == null && ignoreUnrefed)
4780 String sqid = vamsasSeq.getDsseqid();
4783 // need to create or add a new dataset sequence reference to this sequence
4786 dsq = seqRefIds.get(sqid);
4791 // make a new dataset sequence
4792 dsq = sq.createDatasetSequence();
4795 // make up a new dataset reference for this sequence
4796 sqid = seqHash(dsq);
4798 dsq.setVamsasId(uniqueSetSuffix + sqid);
4799 seqRefIds.put(sqid, dsq);
4804 dseqs.addElement(dsq);
4809 ds.addSequence(dsq);
4815 { // make this dataset sequence sq's dataset sequence
4816 sq.setDatasetSequence(dsq);
4817 // and update the current dataset alignment
4822 if (!dseqs.contains(dsq))
4829 if (ds.findIndex(dsq) < 0)
4831 ds.addSequence(dsq);
4838 // TODO: refactor this as a merge dataset sequence function
4839 // now check that sq (the dataset sequence) sequence really is the union of
4840 // all references to it
4841 // boolean pre = sq.getStart() < dsq.getStart();
4842 // boolean post = sq.getEnd() > dsq.getEnd();
4846 // StringBuffer sb = new StringBuffer();
4847 String newres = jalview.analysis.AlignSeq.extractGaps(
4848 jalview.util.Comparison.GapChars, sq.getSequenceAsString());
4849 if (!newres.equalsIgnoreCase(dsq.getSequenceAsString())
4850 && newres.length() > dsq.getLength())
4852 // Update with the longer sequence.
4856 * if (pre) { sb.insert(0, newres .substring(0, dsq.getStart() -
4857 * sq.getStart())); dsq.setStart(sq.getStart()); } if (post) {
4858 * sb.append(newres.substring(newres.length() - sq.getEnd() -
4859 * dsq.getEnd())); dsq.setEnd(sq.getEnd()); }
4861 dsq.setSequence(newres);
4863 // TODO: merges will never happen if we 'know' we have the real dataset
4864 // sequence - this should be detected when id==dssid
4866 .println("DEBUG Notice: Merged dataset sequence (if you see this often, post at http://issues.jalview.org/browse/JAL-1474)"); // ("
4867 // + (pre ? "prepended" : "") + " "
4868 // + (post ? "appended" : ""));
4874 * TODO use AlignmentI here and in related methods - needs
4875 * AlignmentI.getDataset() changed to return AlignmentI instead of Alignment
4877 Hashtable<String, Alignment> datasetIds = null;
4879 IdentityHashMap<Alignment, String> dataset2Ids = null;
4881 private Alignment getDatasetFor(String datasetId)
4883 if (datasetIds == null)
4885 datasetIds = new Hashtable<String, Alignment>();
4888 if (datasetIds.containsKey(datasetId))
4890 return datasetIds.get(datasetId);
4895 private void addDatasetRef(String datasetId, Alignment dataset)
4897 if (datasetIds == null)
4899 datasetIds = new Hashtable<String, Alignment>();
4901 datasetIds.put(datasetId, dataset);
4905 * make a new dataset ID for this jalview dataset alignment
4910 private String getDatasetIdRef(Alignment dataset)
4912 if (dataset.getDataset() != null)
4914 warn("Serious issue! Dataset Object passed to getDatasetIdRef is not a Jalview DATASET alignment...");
4916 String datasetId = makeHashCode(dataset, null);
4917 if (datasetId == null)
4919 // make a new datasetId and record it
4920 if (dataset2Ids == null)
4922 dataset2Ids = new IdentityHashMap<Alignment, String>();
4926 datasetId = dataset2Ids.get(dataset);
4928 if (datasetId == null)
4930 datasetId = "ds" + dataset2Ids.size() + 1;
4931 dataset2Ids.put(dataset, datasetId);
4937 private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
4939 for (int d = 0; d < sequence.getDBRefCount(); d++)
4941 DBRef dr = sequence.getDBRef(d);
4942 jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
4943 sequence.getDBRef(d).getSource(), sequence.getDBRef(d)
4944 .getVersion(), sequence.getDBRef(d).getAccessionId());
4945 if (dr.getMapping() != null)
4947 entry.setMap(addMapping(dr.getMapping()));
4949 datasetSequence.addDBRef(entry);
4953 private jalview.datamodel.Mapping addMapping(Mapping m)
4955 SequenceI dsto = null;
4956 // Mapping m = dr.getMapping();
4957 int fr[] = new int[m.getMapListFromCount() * 2];
4958 Enumeration f = m.enumerateMapListFrom();
4959 for (int _i = 0; f.hasMoreElements(); _i += 2)
4961 MapListFrom mf = (MapListFrom) f.nextElement();
4962 fr[_i] = mf.getStart();
4963 fr[_i + 1] = mf.getEnd();
4965 int fto[] = new int[m.getMapListToCount() * 2];
4966 f = m.enumerateMapListTo();
4967 for (int _i = 0; f.hasMoreElements(); _i += 2)
4969 MapListTo mf = (MapListTo) f.nextElement();
4970 fto[_i] = mf.getStart();
4971 fto[_i + 1] = mf.getEnd();
4973 jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto,
4974 fr, fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
4975 if (m.getMappingChoice() != null)
4977 MappingChoice mc = m.getMappingChoice();
4978 if (mc.getDseqFor() != null)
4980 String dsfor = "" + mc.getDseqFor();
4981 if (seqRefIds.containsKey(dsfor))
4986 jmap.setTo(seqRefIds.get(dsfor));
4990 frefedSequence.add(new Object[] { dsfor, jmap });
4996 * local sequence definition
4998 Sequence ms = mc.getSequence();
4999 SequenceI djs = null;
5000 String sqid = ms.getDsseqid();
5001 if (sqid != null && sqid.length() > 0)
5004 * recover dataset sequence
5006 djs = seqRefIds.get(sqid);
5011 .println("Warning - making up dataset sequence id for DbRef sequence map reference");
5012 sqid = ((Object) ms).toString(); // make up a new hascode for
5013 // undefined dataset sequence hash
5014 // (unlikely to happen)
5020 * make a new dataset sequence and add it to refIds hash
5022 djs = new jalview.datamodel.Sequence(ms.getName(),
5024 djs.setStart(jmap.getMap().getToLowest());
5025 djs.setEnd(jmap.getMap().getToHighest());
5026 djs.setVamsasId(uniqueSetSuffix + sqid);
5028 seqRefIds.put(sqid, djs);
5031 jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
5040 public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
5041 boolean keepSeqRefs)
5044 JalviewModel jm = saveState(ap, null, null, null);
5049 jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
5053 uniqueSetSuffix = "";
5054 jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
5059 if (this.frefedSequence == null)
5061 frefedSequence = new Vector();
5064 viewportsAdded.clear();
5066 AlignFrame af = loadFromObject(jm, null, false, null);
5067 af.alignPanels.clear();
5068 af.closeMenuItem_actionPerformed(true);
5071 * if(ap.av.getAlignment().getAlignmentAnnotation()!=null) { for(int i=0;
5072 * i<ap.av.getAlignment().getAlignmentAnnotation().length; i++) {
5073 * if(!ap.av.getAlignment().getAlignmentAnnotation()[i].autoCalculated) {
5074 * af.alignPanel.av.getAlignment().getAlignmentAnnotation()[i] =
5075 * ap.av.getAlignment().getAlignmentAnnotation()[i]; } } }
5078 return af.alignPanel;
5082 * flag indicating if hashtables should be cleared on finalization TODO this
5083 * flag may not be necessary
5085 private final boolean _cleartables = true;
5087 private Hashtable jvids2vobj;
5092 * @see java.lang.Object#finalize()
5095 protected void finalize() throws Throwable
5097 // really make sure we have no buried refs left.
5102 this.seqRefIds = null;
5103 this.seqsToIds = null;
5107 private void warn(String msg)
5112 private void warn(String msg, Exception e)
5114 if (Cache.log != null)
5118 Cache.log.warn(msg, e);
5122 Cache.log.warn(msg);
5127 System.err.println("Warning: " + msg);
5130 e.printStackTrace();
5135 private void debug(String string)
5137 debug(string, null);
5140 private void debug(String msg, Exception e)
5142 if (Cache.log != null)
5146 Cache.log.debug(msg, e);
5150 Cache.log.debug(msg);
5155 System.err.println("Warning: " + msg);
5158 e.printStackTrace();
5164 * set the object to ID mapping tables used to write/recover objects and XML
5165 * ID strings for the jalview project. If external tables are provided then
5166 * finalize and clearSeqRefs will not clear the tables when the Jalview2XML
5167 * object goes out of scope. - also populates the datasetIds hashtable with
5168 * alignment objects containing dataset sequences
5171 * Map from ID strings to jalview datamodel
5173 * Map from jalview datamodel to ID strings
5177 public void setObjectMappingTables(Hashtable vobj2jv,
5178 IdentityHashMap jv2vobj)
5180 this.jv2vobj = jv2vobj;
5181 this.vobj2jv = vobj2jv;
5182 Iterator ds = jv2vobj.keySet().iterator();
5184 while (ds.hasNext())
5186 Object jvobj = ds.next();
5187 id = jv2vobj.get(jvobj).toString();
5188 if (jvobj instanceof jalview.datamodel.Alignment)
5190 if (((jalview.datamodel.Alignment) jvobj).getDataset() == null)
5192 addDatasetRef(id, (jalview.datamodel.Alignment) jvobj);
5195 else if (jvobj instanceof jalview.datamodel.Sequence)
5197 // register sequence object so the XML parser can recover it.
5198 if (seqRefIds == null)
5200 seqRefIds = new HashMap<String, SequenceI>();
5202 if (seqsToIds == null)
5204 seqsToIds = new IdentityHashMap<SequenceI, String>();
5206 seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
5207 seqsToIds.put((SequenceI) jvobj, id);
5209 else if (jvobj instanceof jalview.datamodel.AlignmentAnnotation)
5212 AlignmentAnnotation jvann = (AlignmentAnnotation) jvobj;
5213 annotationIds.put(anid = jv2vobj.get(jvobj).toString(), jvann);
5214 if (jvann.annotationId == null)
5216 jvann.annotationId = anid;
5218 if (!jvann.annotationId.equals(anid))
5220 // TODO verify that this is the correct behaviour
5221 this.warn("Overriding Annotation ID for " + anid
5222 + " from different id : " + jvann.annotationId);
5223 jvann.annotationId = anid;
5226 else if (jvobj instanceof String)
5228 if (jvids2vobj == null)
5230 jvids2vobj = new Hashtable();
5231 jvids2vobj.put(jvobj, jv2vobj.get(jvobj).toString());
5236 Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
5242 * set the uniqueSetSuffix used to prefix/suffix object IDs for jalview
5243 * objects created from the project archive. If string is null (default for
5244 * construction) then suffix will be set automatically.
5248 public void setUniqueSetSuffix(String string)
5250 uniqueSetSuffix = string;
5255 * uses skipList2 as the skipList for skipping views on sequence sets
5256 * associated with keys in the skipList
5260 public void setSkipList(Hashtable skipList2)
5262 skipList = skipList2;
5266 * Reads the jar entry of given name and returns its contents, or null if the
5267 * entry is not found.
5270 * @param jarEntryName
5273 protected String readJarEntry(jarInputStreamProvider jprovider,
5274 String jarEntryName)
5276 String result = null;
5277 BufferedReader in = null;
5282 * Reopen the jar input stream and traverse its entries to find a matching
5285 JarInputStream jin = jprovider.getJarInputStream();
5286 JarEntry entry = null;
5289 entry = jin.getNextJarEntry();
5290 } while (entry != null && !entry.getName().equals(jarEntryName));
5294 StringBuilder out = new StringBuilder(256);
5295 in = new BufferedReader(new InputStreamReader(jin, UTF_8));
5298 while ((data = in.readLine()) != null)
5302 result = out.toString();
5306 warn("Couldn't find entry in Jalview Jar for " + jarEntryName);
5308 } catch (Exception ex)
5310 ex.printStackTrace();
5318 } catch (IOException e)
5329 * Returns an incrementing counter (0, 1, 2...)
5333 private synchronized int nextCounter()