From: gmungoc Date: Tue, 19 May 2020 16:27:32 +0000 (+0100) Subject: Merge branch 'develop' into feature/JAL-3551Pymol X-Git-Tag: Release_2_11_2_0~37^2~13 X-Git-Url: http://source.jalview.org/gitweb/?p=jalview.git;a=commitdiff_plain;h=4f30214e8098748469c6a4269ac2ed6c5750e4b0 Merge branch 'develop' into feature/JAL-3551Pymol Conflicts: src/jalview/ext/jmol/JalviewJmolBinding.java src/jalview/ext/jmol/JmolCommands.java src/jalview/gui/AppJmol.java src/jalview/gui/AppJmolBinding.java src/jalview/gui/ChimeraViewFrame.java src/jalview/gui/StructureViewerBase.java src/jalview/jbgui/GPreferences.java src/jalview/jbgui/GStructureViewer.java src/jalview/project/Jalview2XML.java --- 4f30214e8098748469c6a4269ac2ed6c5750e4b0 diff --cc src/jalview/datamodel/features/SequenceFeatures.java index db2f0e1,70485b6..8ac4991 --- a/src/jalview/datamodel/features/SequenceFeatures.java +++ b/src/jalview/datamodel/features/SequenceFeatures.java @@@ -414,7 -413,9 +413,10 @@@ public class SequenceFeatures implement public static void sortFeatures(List features, final boolean forwardStrand) { - IntervalI.sortIntervals(features, forwardStrand); + Collections.sort(features, - forwardStrand ? IntervalI.COMPARE_BEGIN_ASC_END_ASC ++ forwardStrand ++ ? IntervalI.COMPARE_BEGIN_ASC_END_DESC + : IntervalI.COMPARE_END_DESC); } /** diff --cc src/jalview/ext/jmol/JalviewJmolBinding.java index c3a22fb,453152e..54eb599 --- a/src/jalview/ext/jmol/JalviewJmolBinding.java +++ b/src/jalview/ext/jmol/JalviewJmolBinding.java @@@ -37,21 -58,9 +37,22 @@@ import org.jmol.api.JmolSelectionListen import org.jmol.api.JmolStatusListener; import org.jmol.api.JmolViewer; import org.jmol.c.CBK; -import org.jmol.script.T; import org.jmol.viewer.Viewer; +import jalview.api.FeatureRenderer; ++import jalview.bin.Cache; +import jalview.datamodel.PDBEntry; +import jalview.datamodel.SequenceI; +import jalview.gui.IProgressIndicator; +import jalview.gui.StructureViewer.ViewerType; +import jalview.io.DataSourceType; +import jalview.io.StructureFile; +import jalview.structure.AtomSpec; +import jalview.structure.StructureCommand; +import jalview.structure.StructureCommandI; +import jalview.structure.StructureSelectionManager; +import jalview.structures.models.AAStructureBindingModel; + public abstract class JalviewJmolBinding extends AAStructureBindingModel implements JmolStatusListener, JmolSelectionListener, ComponentListener @@@ -111,23 -132,409 +112,32 @@@ return getViewerTitle("Jmol", true); } - /** - * prepare the view for a given set of models/chains. chainList contains - * strings of the form 'pdbfilename:Chaincode' - * - * @param chainList - * list of chains to make visible - */ - public void centerViewer(Vector chainList) - { - StringBuilder cmd = new StringBuilder(128); - int mlength, p; - for (String lbl : chainList) - { - mlength = 0; - do - { - p = mlength; - mlength = lbl.indexOf(":", p); - } while (p < mlength && mlength < (lbl.length() - 2)); - // TODO: lookup each pdb id and recover proper model number for it. - cmd.append(":" + lbl.substring(mlength + 1) + " /" - + (1 + getModelNum(chainFile.get(lbl))) + " or "); - } - if (cmd.length() > 0) - { - cmd.setLength(cmd.length() - 4); - } - evalStateCommand("select *;restrict " + cmd + ";cartoon;center " + cmd); - } - - public void closeViewer() - { - // remove listeners for all structures in viewer - getSsm().removeStructureViewerListener(this, this.getStructureFiles()); - if (viewer != null) - { - viewer.dispose(); - } - lastCommand = null; - viewer = null; - releaseUIResources(); - } - - @Override - public void colourByChain() - { - colourBySequence = false; - // TODO: colour by chain should colour each chain distinctly across all - // visible models - // TODO: http://issues.jalview.org/browse/JAL-628 - evalStateCommand("select *;color chain"); - } - - @Override - public void colourByCharge() - { - colourBySequence = false; - evalStateCommand("select *;color white;select ASP,GLU;color red;" - + "select LYS,ARG;color blue;select CYS;color yellow"); - } - - /** - * superpose the structures associated with sequences in the alignment - * according to their corresponding positions. - */ - public void superposeStructures(AlignmentI alignment) ++ private String jmolScript(String script) + { - superposeStructures(alignment, -1, null); - } ++ Cache.log.debug(">>Jmol>> " + script); ++ String s = jmolViewer.evalStringQuiet(script); ++ Cache.log.debug("< executeCommand(StructureCommandI command, + boolean getReply) { - while (viewer.isScriptExecuting()) - { - try - { - Thread.sleep(10); - } catch (InterruptedException i) - { - } - } - - /* - * get the distinct structure files modelled - * (a file with multiple chains may map to multiple sequences) - */ - String[] files = getStructureFiles(); - if (!waitForFileLoad(files)) + if (command == null) { return null; } - - StringBuilder selectioncom = new StringBuilder(256); - // In principle - nSeconds specifies the speed of animation for each - // superposition - but is seems to behave weirdly, so we don't specify it. - String nSeconds = " "; - if (files.length > 10) - { - nSeconds = " 0.005 "; - } - else - { - nSeconds = " " + (2.0 / files.length) + " "; - // if (nSeconds).substring(0,5)+" "; - } - - // see JAL-1345 - should really automatically turn off the animation for - // large numbers of structures, but Jmol doesn't seem to allow that. - // nSeconds = " "; - // union of all aligned positions are collected together. - for (int a = 0; a < _alignment.length; a++) - { - int refStructure = _refStructure[a]; - AlignmentI alignment = _alignment[a]; - HiddenColumns hiddenCols = _hiddenCols[a]; - if (a > 0 && selectioncom.length() > 0 && !selectioncom - .substring(selectioncom.length() - 1).equals("|")) - { - selectioncom.append("|"); - } - // process this alignment - if (refStructure >= files.length) - { - System.err.println( - "Invalid reference structure value " + refStructure); - refStructure = -1; - } - - /* - * 'matched' bit j will be set for visible alignment columns j where - * all sequences have a residue with a mapping to the PDB structure - */ - BitSet matched = new BitSet(); - for (int m = 0; m < alignment.getWidth(); m++) - { - if (hiddenCols == null || hiddenCols.isVisible(m)) - { - matched.set(m); - } - } - - SuperposeData[] structures = new SuperposeData[files.length]; - for (int f = 0; f < files.length; f++) - { - structures[f] = new SuperposeData(alignment.getWidth()); - } - - /* - * Calculate the superposable alignment columns ('matched'), and the - * corresponding structure residue positions (structures.pdbResNo) - */ - int candidateRefStructure = findSuperposableResidues(alignment, - matched, structures); - if (refStructure < 0) - { - /* - * If no reference structure was specified, pick the first one that has - * a mapping in the alignment - */ - refStructure = candidateRefStructure; - } - - String[] selcom = new String[files.length]; - int nmatched = matched.cardinality(); - if (nmatched < 4) - { - return (MessageManager.formatMessage("label.insufficient_residues", - nmatched)); - } - - /* - * generate select statements to select regions to superimpose structures - */ - { - // TODO extract method to construct selection statements - for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++) - { - String chainCd = ":" + structures[pdbfnum].chain; - int lpos = -1; - boolean run = false; - StringBuilder molsel = new StringBuilder(); - molsel.append("{"); - - int nextColumnMatch = matched.nextSetBit(0); - while (nextColumnMatch != -1) - { - int pdbResNo = structures[pdbfnum].pdbResNo[nextColumnMatch]; - if (lpos != pdbResNo - 1) - { - // discontinuity - if (lpos != -1) - { - molsel.append(lpos); - molsel.append(chainCd); - molsel.append("|"); - } - run = false; - } - else - { - // continuous run - and lpos >-1 - if (!run) - { - // at the beginning, so add dash - molsel.append(lpos); - molsel.append("-"); - } - run = true; - } - lpos = pdbResNo; - nextColumnMatch = matched.nextSetBit(nextColumnMatch + 1); - } - /* - * add final selection phrase - */ - if (lpos != -1) - { - molsel.append(lpos); - molsel.append(chainCd); - molsel.append("}"); - } - if (molsel.length() > 1) - { - selcom[pdbfnum] = molsel.toString(); - selectioncom.append("(("); - selectioncom.append(selcom[pdbfnum].substring(1, - selcom[pdbfnum].length() - 1)); - selectioncom.append(" )& "); - selectioncom.append(pdbfnum + 1); - selectioncom.append(".1)"); - if (pdbfnum < files.length - 1) - { - selectioncom.append("|"); - } - } - else - { - selcom[pdbfnum] = null; - } - } - } - StringBuilder command = new StringBuilder(256); - // command.append("set spinFps 10;\n"); - - for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++) - { - if (pdbfnum == refStructure || selcom[pdbfnum] == null - || selcom[refStructure] == null) - { - continue; - } - command.append("echo "); - command.append("\"Superposing ("); - command.append(structures[pdbfnum].pdbId); - command.append(") against reference ("); - command.append(structures[refStructure].pdbId); - command.append(")\";\ncompare " + nSeconds); - command.append("{"); - command.append(Integer.toString(1 + pdbfnum)); - command.append(".1} {"); - command.append(Integer.toString(1 + refStructure)); - // conformation=1 excludes alternate locations for CA (JAL-1757) - command.append( - ".1} SUBSET {(*.CA | *.P) and conformation=1} ATOMS "); - - // for (int s = 0; s < 2; s++) - // { - // command.append(selcom[(s == 0 ? pdbfnum : refStructure)]); - // } - command.append(selcom[pdbfnum]); - command.append(selcom[refStructure]); - command.append(" ROTATE TRANSLATE;\n"); - } - if (selectioncom.length() > 0) - { - // TODO is performing selectioncom redundant here? is done later on - // System.out.println("Select regions:\n" + selectioncom.toString()); - evalStateCommand("select *; cartoons off; backbone; select (" - + selectioncom.toString() + "); cartoons; "); - // selcom.append("; ribbons; "); - String cmdString = command.toString(); - // System.out.println("Superimpose command(s):\n" + cmdString); - - evalStateCommand(cmdString); - } - } - if (selectioncom.length() > 0) - {// finally, mark all regions that were superposed. - if (selectioncom.substring(selectioncom.length() - 1).equals("|")) - { - selectioncom.setLength(selectioncom.length() - 1); - } - // System.out.println("Select regions:\n" + selectioncom.toString()); - evalStateCommand("select *; cartoons off; backbone; select (" - + selectioncom.toString() + "); cartoons; "); - // evalStateCommand("select *; backbone; select "+selcom.toString()+"; - // cartoons; center "+selcom.toString()); - } - - return null; - } - - public void evalStateCommand(String command) - { + String cmd = command.getCommand(); jmolHistory(false); - if (lastCommand == null || !lastCommand.equals(command)) + if (lastCommand == null || !lastCommand.equals(cmd)) { - jmolViewer.evalStringQuiet(cmd + "\n"); - jmolScript(command + "\n"); ++ jmolScript(cmd + "\n"); } jmolHistory(true); - lastCommand = command; - } - - Thread colourby = null; - - /** - * Sends a set of colour commands to the structure viewer - * - * @param colourBySequenceCommands - */ - @Override - protected void colourBySequence( - final StructureMappingcommandSet[] colourBySequenceCommands) - { - if (colourby != null) - { - colourby.interrupt(); - colourby = null; - } - Thread colourby = new Thread(new Runnable() - { - @Override - public void run() - { - for (StructureMappingcommandSet cpdbbyseq : colourBySequenceCommands) - { - for (String cbyseq : cpdbbyseq.commands) - { - executeWhenReady(cbyseq); - } - } - } - }); - colourby.start(); - this.colourby = colourby; - } - - /** - * @param files - * @param sr - * @param viewPanel - * @return - */ - @Override - protected StructureMappingcommandSet[] getColourBySequenceCommands( - String[] files, SequenceRenderer sr, AlignmentViewPanel viewPanel) - { - return JmolCommands.getColourBySequenceCommand(getSsm(), files, - getSequence(), sr, viewPanel); - } - - /** - * @param command - */ - protected void executeWhenReady(String command) - { - evalStateCommand(command); + lastCommand = cmd; + return null; } public void createImage(String file, String type, int quality) @@@ -258,27 -710,35 +268,27 @@@ jmolHistory(false); + StringBuilder selection = new StringBuilder(32); StringBuilder cmd = new StringBuilder(64); - cmd.append("select " + pdbResNum); // +modelNum - - resetLastRes.append("select " + pdbResNum); // +modelNum - - cmd.append(":"); - resetLastRes.append(":"); + selection.append("select ").append(String.valueOf(pdbResNum)); + selection.append(":"); if (!chain.equals(" ")) { - cmd.append(chain); - resetLastRes.append(chain); - } - { - cmd.append(" /" + (mdlNum + 1)); - resetLastRes.append("/" + (mdlNum + 1)); + selection.append(chain); } - cmd.append(";wireframe 100;" + cmd.toString() + " and not hetero;"); + selection.append(" /").append(modelId); - resetLastRes.append(";wireframe 0;" + resetLastRes.toString() - + " and not hetero; spacefill 0;"); + cmd.append(selection).append(";wireframe 100;").append(selection) + .append(" and not hetero;").append("spacefill 200;select none"); - cmd.append("spacefill 200;select none"); + resetLastRes.append(selection).append(";wireframe 0;").append(selection) + .append(" and not hetero; spacefill 0;"); - jmolViewer.evalStringQuiet(cmd.toString()); + jmolScript(cmd.toString()); jmolHistory(true); - } - boolean debug = true; + private boolean debug = true; private void jmolHistory(boolean enable) { @@@ -777,9 -1252,40 +786,11 @@@ } - @Override - public void setJalviewColourScheme(ColourSchemeI cs) - { - colourBySequence = false; - - if (cs == null) - { - return; - } - - jmolHistory(false); - StringBuilder command = new StringBuilder(128); - command.append("select *;color white;"); - List residueSet = ResidueProperties.getResidues(isNucleotide(), - false); - for (String resName : residueSet) - { - char res = resName.length() == 3 - ? ResidueProperties.getSingleCharacterCode(resName) - : resName.charAt(0); - Color col = cs.findColour(res, 0, null, null, 0f); - command.append("select " + resName + ";color[" + col.getRed() + "," - + col.getGreen() + "," + col.getBlue() + "];"); - } - - evalStateCommand(command.toString()); - jmolHistory(true); - } - public void showHelp() { - showUrl("http://jmol.sourceforge.net/docs/JmolUserGuide/", "jmolHelp"); + showUrl("http://wiki.jmol.org" + // BH 2018 "http://jmol.sourceforge.net/docs/JmolUserGuide/" + , "jmolHelp"); } /** @@@ -843,9 -1368,17 +866,17 @@@ htmlName + ((Object) this).toString(), documentBase, codeBase, commandOptions, this); - viewer.setJmolStatusListener(this); // extends JmolCallbackListener + jmolViewer.setJmolStatusListener(this); // extends JmolCallbackListener - console = createJmolConsole(consolePanel, buttonsToShow); + try + { + console = createJmolConsole(consolePanel, buttonsToShow); + } catch (Throwable e) + { + System.err.println("Could not create Jmol application console. " + + e.getMessage()); + e.printStackTrace(); + } if (consolePanel != null) { consolePanel.addComponentListener(this); diff --cc src/jalview/ext/jmol/JmolCommands.java index 9c05a37,603202a..3e0afd7 --- a/src/jalview/ext/jmol/JmolCommands.java +++ b/src/jalview/ext/jmol/JmolCommands.java @@@ -48,403 -43,171 +48,422 @@@ import jalview.util.Comparison * @author JimP * */ -public class JmolCommands +public class JmolCommands extends StructureCommandsBase { + private static final StructureCommand SHOW_BACKBONE = new StructureCommand( + "select *; cartoons off; backbone"); + + private static final StructureCommand FOCUS_VIEW = new StructureCommand("zoom 0"); + + private static final StructureCommand COLOUR_ALL_WHITE = new StructureCommand( + "select *;color white;"); + + private static final StructureCommandI COLOUR_BY_CHARGE = new StructureCommand( + "select *;color white;select ASP,GLU;color red;" + + "select LYS,ARG;color blue;select CYS;color yellow"); + + private static final StructureCommandI COLOUR_BY_CHAIN = new StructureCommand( + "select *;color chain"); + + private static final String PIPE = "|"; + + private static final String HYPHEN = "-"; + + private static final String COLON = ":"; + + private static final String SLASH = "/"; + + /** + * {@inheritDoc} + * + * @return + */ + @Override + public int getModelStartNo() + { + return 1; + } + + /** + * Returns a string representation of the given colour suitable for inclusion + * in Jmol commands + * + * @param c + * @return + */ + protected String getColourString(Color c) + { + return c == null ? null + : String.format("[%d,%d,%d]", c.getRed(), c.getGreen(), + c.getBlue()); + } + - @Deprecated - public String[] colourBySequence(StructureSelectionManager ssm, - String[] files, - SequenceI[][] sequence, SequenceRenderer sr, - AlignmentViewPanel viewPanel) - { - // TODO delete method - - FeatureRenderer fr = viewPanel.getFeatureRenderer(); - FeatureColourFinder finder = new FeatureColourFinder(fr); - AlignViewportI viewport = viewPanel.getAlignViewport(); - HiddenColumns cs = viewport.getAlignment().getHiddenColumns(); - AlignmentI al = viewport.getAlignment(); - List cset = new ArrayList<>(); - - for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++) - { - StructureMapping[] mapping = ssm.getMapping(files[pdbfnum]); - StringBuilder command = new StringBuilder(128); - List str = new ArrayList<>(); - - if (mapping == null || mapping.length < 1) - { - continue; - } - - for (int s = 0; s < sequence[pdbfnum].length; s++) - { - for (int sp, m = 0; m < mapping.length; m++) - { - if (mapping[m].getSequence() == sequence[pdbfnum][s] - && (sp = al.findIndex(sequence[pdbfnum][s])) > -1) - { - int lastPos = StructureMapping.UNASSIGNED_VALUE; - SequenceI asp = al.getSequenceAt(sp); - for (int r = 0; r < asp.getLength(); r++) - { - // no mapping to gaps in sequence - if (Comparison.isGap(asp.getCharAt(r))) - { - continue; - } - int pos = mapping[m].getPDBResNum(asp.findPosition(r)); - - if (pos == lastPos) - { - continue; - } - if (pos == StructureMapping.UNASSIGNED_VALUE) - { - // terminate current colour op - if (command.length() > 0 - && command.charAt(command.length() - 1) != ';') - { - command.append(";"); - } - // reset lastPos - lastPos = StructureMapping.UNASSIGNED_VALUE; - continue; - } - - lastPos = pos; - - Color col = sr.getResidueColour(sequence[pdbfnum][s], r, - finder); - - /* - * shade hidden regions darker - */ - if (!cs.isVisible(r)) - { - col = Color.GRAY; - } - - String newSelcom = (mapping[m].getChain() != " " - ? ":" + mapping[m].getChain() - : "") + "/" + (pdbfnum + 1) + ".1" + ";color" - + getColourString(col); - if (command.length() > newSelcom.length() && command - .substring(command.length() - newSelcom.length()) - .equals(newSelcom)) - { - command = JmolCommands.condenseCommand(command, pos); - continue; - } - // TODO: deal with case when buffer is too large for Jmol to parse - // - execute command and flush - - if (command.length() > 0 - && command.charAt(command.length() - 1) != ';') - { - command.append(";"); - } - - if (command.length() > 51200) - { - // add another chunk - str.add(command.toString()); - command.setLength(0); - } - command.append("select " + pos); - command.append(newSelcom); - } - // break; - } - } - } - { - // add final chunk - str.add(command.toString()); - command.setLength(0); - } - cset.addAll(str); - - } - return cset.toArray(new String[cset.size()]); - } - - public static StringBuilder condenseCommand(StringBuilder command, - int pos) - { - - // work back to last 'select' - int p = command.length(), q = p; - do - { - p -= 6; - if (p < 1) - { - p = 0; - } - ; - } while ((q = command.indexOf("select", p)) == -1 && p > 0); - - StringBuilder sb = new StringBuilder(command.substring(0, q + 7)); - - command = command.delete(0, q + 7); - - String start; - - if (command.indexOf("-") > -1) - { - start = command.substring(0, command.indexOf("-")); - } - else - { - start = command.substring(0, command.indexOf(":")); - } - - sb.append(start + "-" + pos + command.substring(command.indexOf(":"))); - - return sb; - } - + @Override + public StructureCommandI colourByChain() + { + return COLOUR_BY_CHAIN; + } + + @Override + public List colourByCharge() + { + return Arrays.asList(COLOUR_BY_CHARGE); + } + + @Override + public List colourByResidues(Map colours) + { + List cmds = super.colourByResidues(colours); + cmds.add(0, COLOUR_ALL_WHITE); + return cmds; + } + + @Override + public StructureCommandI setBackgroundColour(Color col) + { + return new StructureCommand("background " + getColourString(col)); + } + + @Override + public StructureCommandI focusView() + { + return FOCUS_VIEW; + } + + @Override + public List showChains(List toShow) + { + StringBuilder atomSpec = new StringBuilder(128); + boolean first = true; + for (String chain : toShow) + { + String[] tokens = chain.split(":"); + if (tokens.length == 2) + { + if (!first) + { + atomSpec.append(" or "); + } + first = false; + atomSpec.append(":").append(tokens[1]).append(" /").append(tokens[0]); + } + } + + String spec = atomSpec.toString(); + String command = "select *;restrict " + spec + ";cartoon;center " + + spec; + return Arrays.asList(new StructureCommand(command)); + } /** - * Jmol utility which constructs the commands to colour chains by the given - * alignment + * Returns a command to superpose atoms in {@code atomSpec} to those in + * {@code refAtoms}, restricted to alpha carbons only (Phosphorous for rna). + * For example + * + *
 +   * compare {2.1} {1.1} SUBSET {(*.CA | *.P) and conformation=1} 
 +   *         ATOMS {1-87:A}{2-54:A|61-94:A} ROTATE TRANSLATE 1.0;
 +   * 
* - * @returns Object[] { Object[] { , + * where {@code conformation=1} excludes ALTLOC atom locations, and 1.0 is the + * time in seconds to animate the action. For this example, atoms in model 2 + * are moved towards atoms in model 1. + *

+ * The two atomspecs should each be for one model only, but may have more than + * one chain. The number of atoms specified should be the same for both + * models, though if not, Jmol may make a 'best effort' at superposition. * + * @see https://chemapps.stolaf.edu/jmol/docs/#compare */ - public static StructureMappingcommandSet[] getColourBySequenceCommand( - StructureSelectionManager ssm, String[] files, - SequenceI[][] sequence, SequenceRenderer sr, + @Override + public List superposeStructures(AtomSpecModel refAtoms, + AtomSpecModel atomSpec) + { + StringBuilder sb = new StringBuilder(64); + String refModel = refAtoms.getModels().iterator().next(); + String model2 = atomSpec.getModels().iterator().next(); + sb.append(String.format("compare {%s.1} {%s.1}", model2, refModel)); + sb.append(" SUBSET {(*.CA | *.P) and conformation=1} ATOMS {"); + + /* + * command examples don't include modelspec with atoms, getAtomSpec does; + * it works, so leave it as it is for simplicity + */ + sb.append(getAtomSpec(atomSpec, true)).append("}{"); + sb.append(getAtomSpec(refAtoms, true)).append("}"); + sb.append(" ROTATE TRANSLATE "); + sb.append(getCommandSeparator()); + + /* + * show residues used for superposition as ribbon + */ + sb.append("select ").append(getAtomSpec(atomSpec, false)).append("|"); + sb.append(getAtomSpec(refAtoms, false)).append(getCommandSeparator()) + .append("cartoons"); + + return Arrays.asList(new StructureCommand(sb.toString())); + } + + @Override + public StructureCommandI openCommandFile(String path) + { + /* + * https://chemapps.stolaf.edu/jmol/docs/#script + * not currently used in Jalview + */ + return new StructureCommand("script " + path); + } + + @Override + public StructureCommandI saveSession(String filepath) + { + /* + * https://chemapps.stolaf.edu/jmol/docs/#writemodel + */ + return new StructureCommand("write STATE \"" + filepath + "\""); + } + + @Override + protected StructureCommandI getColourCommand(String atomSpec, Color colour) + { + StringBuilder sb = new StringBuilder(atomSpec.length()+20); + sb.append("select ").append(atomSpec).append(getCommandSeparator()) + .append("color").append(getColourString(colour)); + return new StructureCommand(sb.toString()); + } + + @Override + protected String getResidueSpec(String residue) + { + return residue; + } + + /** + * Generates a Jmol atomspec string like + * + *

 +   * 2-5:A/1.1,8:A/1.1,5-10:B/2.1
 +   * 
+ * + * Parameter {@code alphaOnly} is not used here - this restriction is made by + * a separate clause in the {@code compare} (superposition) command. + */ + @Override + public String getAtomSpec(AtomSpecModel model, boolean alphaOnly) + { + StringBuilder sb = new StringBuilder(128); + + boolean first = true; + for (String modelNo : model.getModels()) + { + for (String chain : model.getChains(modelNo)) + { + for (int[] range : model.getRanges(modelNo, chain)) + { + if (!first) + { + sb.append(PIPE); + } + first = false; + if (range[0] == range[1]) + { + sb.append(range[0]); + } + else + { + sb.append(range[0]).append(HYPHEN).append(range[1]); + } + sb.append(COLON).append(chain.trim()).append(SLASH); + sb.append(String.valueOf(modelNo)).append(".1"); + } + } + } + + return sb.toString(); + } + + @Override + public List showBackbone() + { + return Arrays.asList(SHOW_BACKBONE); + } + + @Override + public StructureCommandI loadFile(String file) + { + return null; + } ++ ++ /** ++ * Obsolete method, only referenced from ++ * jalview.javascript.MouseOverStructureListener ++ * ++ * @param ssm ++ * @param files ++ * @param sequence ++ * @param sr ++ * @param viewPanel ++ * @return ++ */ ++ @Deprecated ++ public String[] colourBySequence(StructureSelectionManager ssm, ++ String[] files, SequenceI[][] sequence, SequenceRenderer sr, + AlignmentViewPanel viewPanel) + { ++ // TODO delete method ++ + FeatureRenderer fr = viewPanel.getFeatureRenderer(); + FeatureColourFinder finder = new FeatureColourFinder(fr); + AlignViewportI viewport = viewPanel.getAlignViewport(); + HiddenColumns cs = viewport.getAlignment().getHiddenColumns(); + AlignmentI al = viewport.getAlignment(); - List cset = new ArrayList(); ++ List cset = new ArrayList<>(); + + for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++) + { + StructureMapping[] mapping = ssm.getMapping(files[pdbfnum]); - StringBuilder command = new StringBuilder(); - StructureMappingcommandSet smc; - ArrayList str = new ArrayList(); ++ StringBuilder command = new StringBuilder(128); ++ List str = new ArrayList<>(); + + if (mapping == null || mapping.length < 1) + { + continue; + } + + for (int s = 0; s < sequence[pdbfnum].length; s++) + { + for (int sp, m = 0; m < mapping.length; m++) + { + if (mapping[m].getSequence() == sequence[pdbfnum][s] + && (sp = al.findIndex(sequence[pdbfnum][s])) > -1) + { + int lastPos = StructureMapping.UNASSIGNED_VALUE; + SequenceI asp = al.getSequenceAt(sp); + for (int r = 0; r < asp.getLength(); r++) + { + // no mapping to gaps in sequence - if (jalview.util.Comparison.isGap(asp.getCharAt(r))) ++ if (Comparison.isGap(asp.getCharAt(r))) + { + continue; + } + int pos = mapping[m].getPDBResNum(asp.findPosition(r)); + + if (pos == lastPos) + { + continue; + } + if (pos == StructureMapping.UNASSIGNED_VALUE) + { + // terminate current colour op + if (command.length() > 0 + && command.charAt(command.length() - 1) != ';') + { + command.append(";"); + } + // reset lastPos + lastPos = StructureMapping.UNASSIGNED_VALUE; + continue; + } + + lastPos = pos; + + Color col = sr.getResidueColour(sequence[pdbfnum][s], r, + finder); + + /* + * shade hidden regions darker + */ + if (!cs.isVisible(r)) + { + col = Color.GRAY; + } + - // todo JAL-3152 handle 'no chain' case without errors - boolean hasChain = true || mapping[m].getChain() != " "; - String chainSpec = hasChain ++ String newSelcom = (mapping[m].getChain() != " " + ? ":" + mapping[m].getChain() - : ""; - String newSelcom = chainSpec + "/" + (pdbfnum + 1) + ".1" + ";color[" - + col.getRed() + "," + col.getGreen() + "," - + col.getBlue() + "]"; ++ : "") + "/" + (pdbfnum + 1) + ".1" + ";color" ++ + getColourString(col); + if (command.length() > newSelcom.length() && command + .substring(command.length() - newSelcom.length()) + .equals(newSelcom)) + { + command = JmolCommands.condenseCommand(command, pos); + continue; + } + // TODO: deal with case when buffer is too large for Jmol to parse + // - execute command and flush + + if (command.length() > 0 + && command.charAt(command.length() - 1) != ';') + { + command.append(";"); + } + + if (command.length() > 51200) + { + // add another chunk + str.add(command.toString()); + command.setLength(0); + } + command.append("select " + pos); + command.append(newSelcom); + } + // break; + } + } + } + { + // add final chunk + str.add(command.toString()); + command.setLength(0); + } - // Finally, add the command set ready to be returned. - cset.add(new StructureMappingcommandSet(JmolCommands.class, - files[pdbfnum], str.toArray(new String[str.size()]))); ++ cset.addAll(str); + + } - return cset.toArray(new StructureMappingcommandSet[cset.size()]); ++ return cset.toArray(new String[cset.size()]); + } + - public static StringBuilder condenseCommand(StringBuilder command, int pos) ++ /** ++ * Helper method ++ * ++ * @param command ++ * @param pos ++ * @return ++ */ ++ @Deprecated ++ private static StringBuilder condenseCommand( ++ StringBuilder command, ++ int pos) + { + + // work back to last 'select' + int p = command.length(), q = p; + do + { + p -= 6; + if (p < 1) + { + p = 0; + } + ; + } while ((q = command.indexOf("select", p)) == -1 && p > 0); + + StringBuilder sb = new StringBuilder(command.substring(0, q + 7)); + + command = command.delete(0, q + 7); + + String start; + + if (command.indexOf("-") > -1) + { + start = command.substring(0, command.indexOf("-")); + } + else + { + start = command.substring(0, command.indexOf(":")); + } + + sb.append(start + "-" + pos + command.substring(command.indexOf(":"))); + + return sb; + } - } diff --cc src/jalview/gui/AppJmol.java index 0610239,e13df4a..4058cda --- a/src/jalview/gui/AppJmol.java +++ b/src/jalview/gui/AppJmol.java @@@ -36,20 -52,6 +36,21 @@@ import javax.swing.SwingUtilities import javax.swing.event.InternalFrameAdapter; import javax.swing.event.InternalFrameEvent; +import jalview.api.AlignmentViewPanel; +import jalview.bin.Cache; +import jalview.datamodel.AlignmentI; +import jalview.datamodel.PDBEntry; +import jalview.datamodel.SequenceI; ++import jalview.gui.ImageExporter.ImageWriterI; +import jalview.gui.StructureViewer.ViewerType; +import jalview.structure.StructureCommand; +import jalview.structures.models.AAStructureBindingModel; +import jalview.util.BrowserLauncher; +import jalview.util.ImageMaker; +import jalview.util.MessageManager; +import jalview.util.Platform; +import jalview.ws.dbsources.Pdb; + public class AppJmol extends StructureViewerBase { // ms to wait for Jmol to load files @@@ -502,49 -556,29 +508,30 @@@ return files; } + /** + * Outputs the Jmol viewer image as an image file, after prompting the user to + * choose a file and (for EPS) choice of Text or Lineart character rendering + * (unless a preference for this is set) + * + * @param type + */ + @Override - public void eps_actionPerformed() - { - makePDBImage(ImageMaker.TYPE.EPS); - } - - @Override - public void png_actionPerformed() - { - makePDBImage(ImageMaker.TYPE.PNG); - } - - void makePDBImage(ImageMaker.TYPE type) + public void makePDBImage(ImageMaker.TYPE type) { int width = getWidth(); int height = getHeight(); - - ImageMaker im; - - if (type == ImageMaker.TYPE.PNG) + ImageWriterI writer = new ImageWriterI() { - im = new ImageMaker(this, ImageMaker.TYPE.PNG, - "Make PNG image from view", - width, height, null, null, null, 0, false); - } - else if (type == ImageMaker.TYPE.EPS) - { - im = new ImageMaker(this, ImageMaker.TYPE.EPS, - "Make EPS file from view", - width, height, null, this.getTitle(), null, 0, false); - } - else - { - im = new jalview.util.ImageMaker(this, - ImageMaker.TYPE.SVG, "Make SVG file from PCA", - width, height, null, this.getTitle(), null, 0, false); - } - - if (im.getGraphics() != null) - { - jmb.jmolViewer.renderScreenImage(im.getGraphics(), width, height); - im.writeImage(); - } + @Override + public void exportImage(Graphics g) throws Exception + { - jmb.viewer.renderScreenImage(g, width, height); ++ jmb.jmolViewer.renderScreenImage(g, width, height); + } + }; + String view = MessageManager.getString("action.view").toLowerCase(); + ImageExporter exporter = new ImageExporter(writer, - jmb.getIProgressIndicator(), type, getTitle()); ++ getProgressIndicator(), type, getTitle()); + exporter.doExport(null, this, width, height, view); } @Override @@@ -552,11 -586,10 +539,11 @@@ { try { - BrowserLauncher - .openURL("http://jmol.sourceforge.net/docs/JmolUserGuide/"); + BrowserLauncher // BH 2018 + .openURL("http://wiki.jmol.org");//http://jmol.sourceforge.net/docs/JmolUserGuide/"); } catch (Exception ex) { + System.err.println("Show Jmol help failed with: " + ex.getMessage()); } } diff --cc src/jalview/gui/AppJmolBinding.java index 34ff7b3,75b98bc..3298509 --- a/src/jalview/gui/AppJmolBinding.java +++ b/src/jalview/gui/AppJmolBinding.java @@@ -20,18 -20,6 +20,16 @@@ */ package jalview.gui; +import java.awt.Container; +import java.io.File; - import java.io.FileWriter; - import java.io.IOException; ++import java.util.List; +import java.util.Map; + +import javax.swing.JComponent; + +import org.jmol.api.JmolAppConsoleInterface; - import org.jmol.java.BS; +import org.openscience.jmol.app.jmolpanel.console.AppConsole; + import jalview.api.AlignmentViewPanel; import jalview.api.structures.JalviewStructureDisplayI; import jalview.bin.Cache; @@@ -40,6 -28,16 +38,8 @@@ import jalview.datamodel.SequenceI import jalview.ext.jmol.JalviewJmolBinding; import jalview.io.DataSourceType; import jalview.structure.StructureSelectionManager; + import jalview.util.Platform; - -import java.awt.Container; -import java.io.File; -import java.util.List; -import java.util.Map; - -import org.jmol.api.JmolAppConsoleInterface; - + import javajs.util.BS; public class AppJmolBinding extends JalviewJmolBinding { @@@ -99,9 -105,10 +99,10 @@@ @Override public void run() { - appJmolWindow.updateTitleAndMenus(); - // initiates a colourbySequence - // via seqColour_ActionPerformed. - appJmolWindow.revalidate(); + JalviewStructureDisplayI theViewer = getViewer(); ++ // invokes colourbySequence() via seqColour_ActionPerformed() + theViewer.updateTitleAndMenus(); + ((JComponent) theViewer).revalidate(); } }); } @@@ -142,8 -173,8 +143,10 @@@ protected JmolAppConsoleInterface createJmolConsole( Container consolePanel, String buttonsToShow) { - viewer.setJmolCallbackListener(this); - return null;//BH can't do this yet. new AppConsole(viewer, consolePanel, buttonsToShow); + jmolViewer.setJmolCallbackListener(this); - return new AppConsole(jmolViewer, consolePanel, buttonsToShow); ++ // BH comment: can't do this yet [for JS only, or generally?] ++ return Platform.isJS() ? null ++ : new AppConsole(jmolViewer, consolePanel, buttonsToShow); } @Override @@@ -169,31 -200,37 +172,16 @@@ return null; } - /** - * Overrides the default method to save a session to file, in order to - * guarantee it is done synchronously. Jmol command 'write STATE path' would - * execute asynchronously, so instead we get the state and write it directly - * here. - */ -- @Override - protected void saveSession(File f) - public JalviewStructureDisplayI getViewer() - { - return appJmolWindow; - } - - @Override - public jalview.api.FeatureRenderer getFeatureRenderer( - AlignmentViewPanel alignment) - { - AlignmentPanel ap = (alignment == null) - ? appJmolWindow.getAlignmentPanel() - : (AlignmentPanel) alignment; - if (ap.av.isShowSequenceFeatures()) - { - return ap.av.getAlignPanel().getSeqPanel().seqCanvas.fr; - } - - return null; - } - + @SuppressWarnings("unused") + public void cacheFiles(List files) { - String state = jmolViewer.getStateInfo(); - if (state != null) + if (files == null) { - try - { - FileWriter fw = new FileWriter(f); - fw.write(state); - fw.close(); - } catch (IOException e) - { - Cache.log.error("Error writing Jmol state: " + e.toString()); - } + return; } - else + for (File f : files) { - Cache.log.error("Error requesting Jmol state to save"); + Platform.cacheFileData(f); } } } diff --cc src/jalview/gui/ChimeraViewFrame.java index 8fcea0c,c6d6e97..45ab9a9 --- a/src/jalview/gui/ChimeraViewFrame.java +++ b/src/jalview/gui/ChimeraViewFrame.java @@@ -36,20 -57,6 +36,21 @@@ import javax.swing.JMenuItem import javax.swing.event.InternalFrameAdapter; import javax.swing.event.InternalFrameEvent; +import jalview.api.AlignmentViewPanel; +import jalview.api.FeatureRenderer; +import jalview.bin.Cache; +import jalview.datamodel.PDBEntry; +import jalview.datamodel.SequenceI; +import jalview.ext.rbvi.chimera.JalviewChimeraBinding; +import jalview.gui.StructureViewer.ViewerType; +import jalview.io.DataSourceType; +import jalview.io.StructureFile; +import jalview.structures.models.AAStructureBindingModel; +import jalview.util.BrowserLauncher; ++import jalview.util.ImageMaker.TYPE; +import jalview.util.MessageManager; +import jalview.util.Platform; + /** * GUI elements for handling an external chimera display * @@@ -520,18 -607,110 +521,11 @@@ public class ChimeraViewFrame extends S worker = null; } - /** - * Fetch PDB data and save to a local file. Returns the full path to the file, - * or null if fetch fails. TODO: refactor to common with Jmol ? duplication - * - * @param processingEntry - * @return - * @throws Exception - */ - - private void stashFoundChains(StructureFile pdb, String file) - { - for (int i = 0; i < pdb.getChains().size(); i++) - { - String chid = new String( - pdb.getId() + ":" + pdb.getChains().elementAt(i).id); - jmb.getChainNames().add(chid); - jmb.getChainFile().put(chid, file); - } - } - - private String fetchPdbFile(PDBEntry processingEntry) throws Exception - { - String filePath = null; - Pdb pdbclient = new Pdb(); - AlignmentI pdbseq = null; - String pdbid = processingEntry.getId(); - long handle = System.currentTimeMillis() - + Thread.currentThread().hashCode(); - - /* - * Write 'fetching PDB' progress on AlignFrame as we are not yet visible - */ - String msg = MessageManager.formatMessage("status.fetching_pdb", - new Object[] - { pdbid }); - getAlignmentPanel().alignFrame.setProgressBar(msg, handle); - // long hdl = startProgressBar(MessageManager.formatMessage( - // "status.fetching_pdb", new Object[] - // { pdbid })); - try - { - pdbseq = pdbclient.getSequenceRecords(pdbid); - } catch (OutOfMemoryError oomerror) - { - new OOMWarning("Retrieving PDB id " + pdbid, oomerror); - } finally - { - msg = pdbid + " " + MessageManager.getString("label.state_completed"); - getAlignmentPanel().alignFrame.setProgressBar(msg, handle); - // stopProgressBar(msg, hdl); - } - /* - * If PDB data were saved and are not invalid (empty alignment), return the - * file path. - */ - if (pdbseq != null && pdbseq.getHeight() > 0) - { - // just use the file name from the first sequence's first PDBEntry - filePath = new File(pdbseq.getSequenceAt(0).getAllPDBEntries() - .elementAt(0).getFile()).getAbsolutePath(); - processingEntry.setFile(filePath); - } - return filePath; - } - - /** - * Convenience method to update the progress bar if there is one. Be sure to - * call stopProgressBar with the returned handle to remove the message. - * - * @param msg - * @param handle - */ - public long startProgressBar(String msg) - { - // TODO would rather have startProgress/stopProgress as the - // IProgressIndicator interface - long tm = random.nextLong(); - if (progressBar != null) - { - progressBar.setProgressBar(msg, tm); - } - return tm; - } - - /** - * End the progress bar with the specified handle, leaving a message (if not - * null) on the status bar - * - * @param msg - * @param handle - */ - public void stopProgressBar(String msg, long handle) - { - if (progressBar != null) - { - progressBar.setProgressBar(msg, handle); - } - } - @Override - public void eps_actionPerformed() + public void makePDBImage(TYPE imageType) { - throw new Error(MessageManager - .getString("error.eps_generation_not_implemented")); - } - - @Override - public void png_actionPerformed() - { - throw new Error(MessageManager - .getString("error.png_generation_not_implemented")); + throw new UnsupportedOperationException( + "Image export for Chimera is not implemented"); } @Override diff --cc src/jalview/gui/StructureViewerBase.java index 9b6fd61,418a84d..e180f6b --- a/src/jalview/gui/StructureViewerBase.java +++ b/src/jalview/gui/StructureViewerBase.java @@@ -46,24 -64,6 +45,25 @@@ import javax.swing.JRadioButtonMenuItem import javax.swing.event.MenuEvent; import javax.swing.event.MenuListener; +import jalview.api.AlignmentViewPanel; +import jalview.bin.Cache; +import jalview.datamodel.AlignmentI; +import jalview.datamodel.PDBEntry; +import jalview.datamodel.SequenceI; ++import jalview.gui.JalviewColourChooser.ColourChooserListener; +import jalview.gui.StructureViewer.ViewerType; +import jalview.gui.ViewSelectionMenu.ViewSetProvider; +import jalview.io.DataSourceType; +import jalview.io.JalviewFileChooser; +import jalview.io.JalviewFileView; +import jalview.jbgui.GStructureViewer; +import jalview.schemes.ColourSchemeI; +import jalview.schemes.ColourSchemes; +import jalview.structure.StructureMapping; +import jalview.structures.models.AAStructureBindingModel; +import jalview.util.MessageManager; +import jalview.ws.dbsources.Pdb; + /** * Base class with common functionality for JMol, Chimera or other structure * viewers. @@@ -800,16 -810,23 +800,23 @@@ public abstract class StructureViewerBa return reply; } + /** + * Opens a colour chooser dialog, and applies the chosen colour to the + * background of the structure viewer + */ @Override - public void background_actionPerformed(ActionEvent actionEvent) + public void background_actionPerformed() { - Color col = JColorChooser.showDialog(this, - MessageManager.getString("label.select_background_colour"), - null); - if (col != null) + String ttl = MessageManager.getString("label.select_background_colour"); + ColourChooserListener listener = new ColourChooserListener() { - getBinding().setBackgroundColour(col); - } + @Override + public void colourSelected(Color c) + { + getBinding().setBackgroundColour(c); + } + }; + JalviewColourChooser.showColourChooser(this, ttl, null, listener); } @Override @@@ -865,8 -882,9 +872,9 @@@ } @Override - public void pdbFile_actionPerformed(ActionEvent actionEvent) + public void pdbFile_actionPerformed() { + // TODO: JAL-3048 not needed for Jalview-JS - save PDB file JalviewFileChooser chooser = new JalviewFileChooser( Cache.getProperty("LAST_DIRECTORY")); diff --cc src/jalview/jbgui/GPreferences.java index 8963be4,6de3888..ae6727a --- a/src/jalview/jbgui/GPreferences.java +++ b/src/jalview/jbgui/GPreferences.java @@@ -71,21 -87,6 +71,22 @@@ import javax.swing.event.ChangeListener import javax.swing.table.TableCellEditor; import javax.swing.table.TableCellRenderer; +import jalview.bin.Cache; +import jalview.fts.core.FTSDataColumnPreferences; +import jalview.fts.core.FTSDataColumnPreferences.PreferenceSource; +import jalview.fts.service.pdb.PDBFTSRestClient; +import jalview.gui.Desktop; +import jalview.gui.JalviewBooleanRadioButtons; +import jalview.gui.JvOptionPane; +import jalview.gui.JvSwingUtils; +import jalview.gui.StructureViewer.ViewerType; +import jalview.io.BackupFilenameParts; +import jalview.io.BackupFiles; +import jalview.io.BackupFilesPresetEntry; +import jalview.io.IntKeyStringValueEntry; +import jalview.util.MessageManager; ++import jalview.util.Platform; + /** * Base class for the Preferences panel. * @@@ -1327,9 -1354,20 +1365,20 @@@ public class GPreferences extends JPane ypos += lineSpacing; FTSDataColumnPreferences docFieldPref = new FTSDataColumnPreferences( PreferenceSource.PREFERENCES, PDBFTSRestClient.getInstance()); - docFieldPref.setBounds(new Rectangle(10, ypos, 450, 120)); + docFieldPref.setBounds(new Rectangle(10, ypos, 470, 120)); structureTab.add(docFieldPref); + /* + * hide Chimera options in JalviewJS + */ + if (Platform.isJS()) + { - pathLabel.setVisible(false); - chimeraPath.setVisible(false); ++ structureViewerPathLabel.setVisible(false); ++ structureViewerPath.setVisible(false); + viewerLabel.setVisible(false); + structViewer.setVisible(false); + } + return structureTab; } diff --cc src/jalview/jbgui/GStructureViewer.java index 1fccdcb,dfee3e2..6c0beda --- a/src/jalview/jbgui/GStructureViewer.java +++ b/src/jalview/jbgui/GStructureViewer.java @@@ -20,10 -20,11 +20,6 @@@ */ package jalview.jbgui; --import jalview.api.structures.JalviewStructureDisplayI; --import jalview.gui.ColourMenuHelper.ColourChangeListener; - import jalview.util.MessageManager; - -import jalview.util.ImageMaker.TYPE; -import jalview.util.MessageManager; - import java.awt.BorderLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; @@@ -37,6 -38,7 +33,12 @@@ import javax.swing.JMenuItem import javax.swing.JPanel; import javax.swing.JRadioButtonMenuItem; ++import jalview.api.structures.JalviewStructureDisplayI; ++import jalview.gui.ColourMenuHelper.ColourChangeListener; ++import jalview.util.ImageMaker.TYPE; ++import jalview.util.MessageManager; ++ + @SuppressWarnings("serial") public abstract class GStructureViewer extends JInternalFrame implements JalviewStructureDisplayI, ColourChangeListener { diff --cc src/jalview/project/Jalview2XML.java index b408c07,6340e64..4cfac7b --- a/src/jalview/project/Jalview2XML.java +++ b/src/jalview/project/Jalview2XML.java @@@ -24,55 -24,6 +24,56 @@@ import static jalview.math.RotatableMat import static jalview.math.RotatableMatrix.Axis.Y; import static jalview.math.RotatableMatrix.Axis.Z; +import java.awt.Color; +import java.awt.Font; +import java.awt.Rectangle; +import java.io.BufferedReader; ++import java.io.ByteArrayInputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.lang.reflect.InvocationTargetException; +import java.math.BigInteger; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Enumeration; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.Vector; +import java.util.jar.JarEntry; +import java.util.jar.JarInputStream; +import java.util.jar.JarOutputStream; + +import javax.swing.JInternalFrame; +import javax.swing.SwingUtilities; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.Marshaller; +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.XMLGregorianCalendar; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamReader; + import jalview.analysis.Conservation; import jalview.analysis.PCA; import jalview.analysis.scoremodels.ScoreModels;