From 2107a91322a1988a8a6b724c74f9d244795341e3 Mon Sep 17 00:00:00 2001 From: gmungoc Date: Thu, 21 May 2020 18:27:28 +0100 Subject: [PATCH] JAL-3551 copy Jalview features to Pymol 'p' (with pull refactoring) --- resources/lang/Messages.properties | 9 +- resources/lang/Messages_es.properties | 5 +- src/jalview/ext/jmol/JalviewJmolBinding.java | 22 ++ src/jalview/ext/jmol/JmolCommands.java | 2 +- src/jalview/ext/pymol/PymolCommands.java | 78 +++++- src/jalview/ext/rbvi/chimera/ChimeraCommands.java | 281 +------------------- src/jalview/ext/rbvi/chimera/ChimeraXCommands.java | 2 +- .../ext/rbvi/chimera/JalviewChimeraBinding.java | 33 +-- src/jalview/gui/AppJmol.java | 2 - src/jalview/gui/ChimeraViewFrame.java | 31 +-- src/jalview/gui/ChimeraXViewFrame.java | 9 - src/jalview/gui/PymolBindingModel.java | 30 ++- src/jalview/gui/PymolViewer.java | 33 +++ src/jalview/gui/StructureViewerBase.java | 25 +- src/jalview/structure/StructureCommandsBase.java | 49 ++-- src/jalview/structure/StructureCommandsI.java | 32 ++- .../structures/models/AAStructureBindingModel.java | 274 +++++++++++++++++-- test/jalview/ext/pymol/PymolCommandsTest.java | 2 +- .../ext/rbvi/chimera/ChimeraCommandsTest.java | 19 +- .../ext/rbvi/chimera/ChimeraXCommandsTest.java | 2 +- .../models/AAStructureBindingModelTest.java | 39 +-- 21 files changed, 554 insertions(+), 425 deletions(-) diff --git a/resources/lang/Messages.properties b/resources/lang/Messages.properties index 3ba0649..ca6ae63 100644 --- a/resources/lang/Messages.properties +++ b/resources/lang/Messages.properties @@ -502,8 +502,7 @@ label.insert_gaps = Insert {0} gaps label.delete_gap = Delete 1 gap label.delete_gaps = Delete {0} gaps label.sequence_details = Sequence Details -label.jmol_help = Jmol Help -label.chimera_help = Chimera Help +label.viewer_help = {0} Help label.close_viewer = Close Viewer label.confirm_close_viewer = This will close Jalview''s connection to {0}.
Do you want to close the {1} window as well? label.all = All @@ -715,10 +714,8 @@ label.colour_with_viewer = Colour in structure viewer label.superpose_structures = Superpose Structures error.superposition_failed = Superposition failed: {0} label.insufficient_residues = Not enough aligned residues ({0}) to perform superposition -label.jmol = Jmol -label.chimera = Chimera -label.create_chimera_attributes = Write Jalview features -label.create_chimera_attributes_tip = Set Chimera residue attributes for visible features +label.create_viewer_attributes = Write Jalview features +label.create_viewer_attributes_tip = Set structure residue attributes for Jalview features label.attributes_set = {0} attribute values set on Chimera label.sort_alignment_by_tree = Sort Alignment By Tree label.mark_unlinked_leaves = Mark Unlinked Leaves diff --git a/resources/lang/Messages_es.properties b/resources/lang/Messages_es.properties index 1d9e5fd..624e619 100644 --- a/resources/lang/Messages_es.properties +++ b/resources/lang/Messages_es.properties @@ -465,7 +465,7 @@ label.insert_gaps = Insertar {0} huecos label.delete_gap = Borrar 1 hueco label.delete_gaps = Borrar {0} huecos label.sequence_details = Detalles de la secuencia -label.jmol_help = Ayuda de Jmol +label.viewer_help = Ayuda sobre {0} # Todos/Todas is gender-sensitive, but currently only used for feminine (cadena / anotación)! label.all = Todas label.sort_by = Ordenar por @@ -653,7 +653,6 @@ label.associate_nodes_with = Asociar nodos con label.link_name = Nombre del enalce label.pdb_file = Fichero PDB label.colour_with_jmol = Colorear con Jmol -label.jmol = Jmol label.sort_alignment_by_tree = Ordenar alineamiento por árbol label.mark_unlinked_leaves = Marcar las hojas como no enlazadas label.associate_leaves_with = Asociar hojas con @@ -1118,7 +1117,6 @@ label.autoadd_secstr=A action.annotations=Anotaciones label.nuc_alignment_colour=Color del Alineamiento Nucleotídico label.copy_format_from=Copiar formato de -label.chimera=Chimera label.create_chimera_attributes = Escribir características de Jalview label.create_chimera_attributes_tip = Establecer atributos en Chimera para características visibles label.attributes_set = {0} valores de atributos establecidos en Chimera @@ -1203,7 +1201,6 @@ label.viewer_missing=Visualizador de estructura no encontrado.
Por favor, in warn.delete_all=Borrar todas las secuencias cerrará la ventana del alineamiento.
Confirmar o Cancelar. label.select_all=Seleccionar Todos label.alpha_helix=Hélice Alfa -label.chimera_help=Ayuda para Chimera label.find_tip=Buscar alineamiento, selección o IDs de secuencia para una subsecuencia (sin huecos) label.structure_viewer=Visualizador por defecto label.embbed_biojson=Incrustar BioJSON al exportar HTML diff --git a/src/jalview/ext/jmol/JalviewJmolBinding.java b/src/jalview/ext/jmol/JalviewJmolBinding.java index 038ca48..0b37ceb 100644 --- a/src/jalview/ext/jmol/JalviewJmolBinding.java +++ b/src/jalview/ext/jmol/JalviewJmolBinding.java @@ -39,7 +39,9 @@ import org.jmol.api.JmolViewer; import org.jmol.c.CBK; import org.jmol.viewer.Viewer; +import jalview.api.AlignmentViewPanel; import jalview.api.FeatureRenderer; +import jalview.api.SequenceRenderer; import jalview.bin.Cache; import jalview.datamodel.PDBEntry; import jalview.datamodel.SequenceI; @@ -52,6 +54,7 @@ import jalview.structure.StructureCommand; import jalview.structure.StructureCommandI; import jalview.structure.StructureSelectionManager; import jalview.structures.models.AAStructureBindingModel; +import javajs.util.BS; public abstract class JalviewJmolBinding extends AAStructureBindingModel implements JmolStatusListener, JmolSelectionListener, @@ -997,4 +1000,23 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel { return ".spt"; } + + @Override + public void selectionChanged(BS arg0) + { + // TODO Auto-generated method stub + + } + + @Override + public SequenceRenderer getSequenceRenderer(AlignmentViewPanel avp) + { + return new jalview.gui.SequenceRenderer(avp.getAlignViewport()); + } + + @Override + public String getHelpURL() + { + return "http://wiki.jmol.org"; // BH 2018 + } } diff --git a/src/jalview/ext/jmol/JmolCommands.java b/src/jalview/ext/jmol/JmolCommands.java index 3e0afd7..99130b4 100644 --- a/src/jalview/ext/jmol/JmolCommands.java +++ b/src/jalview/ext/jmol/JmolCommands.java @@ -224,7 +224,7 @@ public class JmolCommands extends StructureCommandsBase } @Override - protected StructureCommandI getColourCommand(String atomSpec, Color colour) + protected StructureCommandI colourResidues(String atomSpec, Color colour) { StringBuilder sb = new StringBuilder(atomSpec.length()+20); sb.append("select ").append(atomSpec).append(getCommandSeparator()) diff --git a/src/jalview/ext/pymol/PymolCommands.java b/src/jalview/ext/pymol/PymolCommands.java index e4f9f5f..53b1ec5 100644 --- a/src/jalview/ext/pymol/PymolCommands.java +++ b/src/jalview/ext/pymol/PymolCommands.java @@ -191,7 +191,7 @@ public class PymolCommands extends StructureCommandsBase } @Override - protected StructureCommandI getColourCommand(String atomSpec, Color colour) + protected StructureCommandI colourResidues(String atomSpec, Color colour) { // https://pymolwiki.org/index.php/Color return new StructureCommand("color", getColourString(colour), atomSpec); @@ -233,4 +233,80 @@ public class PymolCommands extends StructureCommandsBase return commands; } + /** + * Returns a viewer command to set the given atom property value on atoms + * specified by the AtomSpecModel, for example + * + *
+   * iterate 4zho//B/12-34,48-55/CA,jv_chain='primary'
+   * 
+ * + * @param attributeName + * @param attributeValue + * @param atomSpecModel + * @return + */ + protected StructureCommandI setAttribute(String attributeName, + String attributeValue, + AtomSpecModel atomSpecModel) + { + StringBuilder sb = new StringBuilder(128); + sb.append("p.").append(attributeName).append("='") + .append(attributeValue).append("'"); + String atomSpec = getAtomSpec(atomSpecModel, false); + return new StructureCommand("iterate", atomSpec, sb.toString()); + } + + /** + * Traverse the map of features/values/models/chains/positions to construct a + * list of 'set property' commands (one per distinct feature type and value). + * The values are stored in the 'p' dictionary of user-defined properties of + * each atom. + *

+ * The format of each command is + * + *

+   * 
iterate atomspec, p.featureName='value' + * e.g. iterate 4zho//A/23,28-29/CA, p.jv_Metal='Fe' + *
+ *
+ * + * @param featureMap + * @return + */ + @Override + public List setAttributes( + Map> featureMap) + { + List commands = new ArrayList<>(); + for (String featureType : featureMap.keySet()) + { + String attributeName = makeAttributeName(featureType); + + /* + * todo: clear down existing attributes for this feature? + */ + // commands.add(new StructureCommand("iterate", "all", + // "p."+attributeName+"='None'"); //? + + Map values = featureMap.get(featureType); + for (Object value : values.keySet()) + { + /* + * for each distinct value recorded for this feature type, + * add a command to set the attribute on the mapped residues + * Put values in single quotes, encoding any embedded single quotes + */ + AtomSpecModel atomSpecModel = values.get(value); + String featureValue = value.toString(); + featureValue = featureValue.replaceAll("\\'", "'"); + StructureCommandI cmd = setAttribute(attributeName, featureValue, + atomSpecModel); + commands.add(cmd); + } + } + + return commands; + } + } diff --git a/src/jalview/ext/rbvi/chimera/ChimeraCommands.java b/src/jalview/ext/rbvi/chimera/ChimeraCommands.java index c9dbc1d..ac10b0b 100644 --- a/src/jalview/ext/rbvi/chimera/ChimeraCommands.java +++ b/src/jalview/ext/rbvi/chimera/ChimeraCommands.java @@ -23,25 +23,13 @@ package jalview.ext.rbvi.chimera; import java.awt.Color; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import jalview.api.AlignViewportI; -import jalview.api.AlignmentViewPanel; -import jalview.api.FeatureRenderer; -import jalview.datamodel.AlignmentI; -import jalview.datamodel.MappedFeatures; -import jalview.datamodel.SequenceFeature; -import jalview.datamodel.SequenceI; -import jalview.gui.Desktop; import jalview.structure.AtomSpecModel; import jalview.structure.StructureCommand; import jalview.structure.StructureCommandI; import jalview.structure.StructureCommandsBase; -import jalview.structure.StructureMapping; -import jalview.structure.StructureSelectionManager; import jalview.util.ColorUtils; /** @@ -55,8 +43,6 @@ public class ChimeraCommands extends StructureCommandsBase private static final StructureCommand SHOW_BACKBONE = new StructureCommand( "~display all;~ribbon;chain @CA|P"); - public static final String NAMESPACE_PREFIX = "jv_"; - private static final StructureCommandI COLOUR_BY_CHARGE = new StructureCommand( "color white;color red ::ASP,GLU;color blue ::LYS,ARG;color yellow ::CYS"); @@ -67,7 +53,7 @@ public class ChimeraCommands extends StructureCommandsBase private static final String NO_ALTLOCS = "&~@.B-Z&~@.2-9"; @Override - public StructureCommandI getColourCommand(String atomSpec, Color colour) + public StructureCommandI colourResidues(String atomSpec, Color colour) { // https://www.cgl.ucsf.edu/chimera/current/docs/UsersGuide/midas/color.html String colourCode = getColourString(colour); @@ -86,256 +72,6 @@ public class ChimeraCommands extends StructureCommandsBase } /** - * Constructs and returns Chimera commands to set attributes on residues - * corresponding to features in Jalview. Attribute names are the Jalview feature - * type, with a "jv_" prefix. - * - * @param ssm - * @param files - * @param seqs - * @param viewPanel - * @return - */ - @Override - public List setAttributesForFeatures( - StructureSelectionManager ssm, String[] files, SequenceI[][] seqs, - AlignmentViewPanel viewPanel) - { - Map> featureMap = buildFeaturesMap( - ssm, files, seqs, viewPanel); - - return setAttributes(featureMap); - } - - /** - *
-   * Helper method to build a map of 
-   *   { featureType, { feature value, AtomSpecModel } }
-   * 
- * - * @param ssm - * @param files - * @param seqs - * @param viewPanel - * @return - */ - protected Map> buildFeaturesMap( - StructureSelectionManager ssm, String[] files, SequenceI[][] seqs, - AlignmentViewPanel viewPanel) - { - Map> theMap = new LinkedHashMap<>(); - - FeatureRenderer fr = viewPanel.getFeatureRenderer(); - if (fr == null) - { - return theMap; - } - - AlignViewportI viewport = viewPanel.getAlignViewport(); - List visibleFeatures = fr.getDisplayedFeatureTypes(); - - /* - * if alignment is showing features from complement, we also transfer - * these features to the corresponding mapped structure residues - */ - boolean showLinkedFeatures = viewport.isShowComplementFeatures(); - List complementFeatures = new ArrayList<>(); - FeatureRenderer complementRenderer = null; - if (showLinkedFeatures) - { - AlignViewportI comp = fr.getViewport().getCodingComplement(); - if (comp != null) - { - complementRenderer = Desktop.getAlignFrameFor(comp) - .getFeatureRenderer(); - complementFeatures = complementRenderer.getDisplayedFeatureTypes(); - } - } - if (visibleFeatures.isEmpty() && complementFeatures.isEmpty()) - { - return theMap; - } - - AlignmentI alignment = viewPanel.getAlignment(); - for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++) - { - final int modelNumber = pdbfnum + getModelStartNo(); - String modelId = String.valueOf(modelNumber); - StructureMapping[] mapping = ssm.getMapping(files[pdbfnum]); - - if (mapping == null || mapping.length < 1) - { - continue; - } - - for (int seqNo = 0; seqNo < seqs[pdbfnum].length; seqNo++) - { - for (int m = 0; m < mapping.length; m++) - { - final SequenceI seq = seqs[pdbfnum][seqNo]; - int sp = alignment.findIndex(seq); - StructureMapping structureMapping = mapping[m]; - if (structureMapping.getSequence() == seq && sp > -1) - { - /* - * found a sequence with a mapping to a structure; - * now scan its features - */ - if (!visibleFeatures.isEmpty()) - { - scanSequenceFeatures(visibleFeatures, structureMapping, seq, - theMap, modelId); - } - if (showLinkedFeatures) - { - scanComplementFeatures(complementRenderer, structureMapping, - seq, theMap, modelId); - } - } - } - } - } - return theMap; - } - - /** - * Scans visible features in mapped positions of the CDS/peptide complement, and - * adds any found to the map of attribute values/structure positions - * - * @param complementRenderer - * @param structureMapping - * @param seq - * @param theMap - * @param modelNumber - */ - protected static void scanComplementFeatures( - FeatureRenderer complementRenderer, - StructureMapping structureMapping, SequenceI seq, - Map> theMap, - String modelNumber) - { - /* - * for each sequence residue mapped to a structure position... - */ - for (int seqPos : structureMapping.getMapping().keySet()) - { - /* - * find visible complementary features at mapped position(s) - */ - MappedFeatures mf = complementRenderer - .findComplementFeaturesAtResidue(seq, seqPos); - if (mf != null) - { - for (SequenceFeature sf : mf.features) - { - String type = sf.getType(); - - /* - * Don't copy features which originated from Chimera - */ - if (JalviewChimeraBinding.CHIMERA_FEATURE_GROUP - .equals(sf.getFeatureGroup())) - { - continue; - } - - /* - * record feature 'value' (score/description/type) as at the - * corresponding structure position - */ - List mappedRanges = structureMapping - .getPDBResNumRanges(seqPos, seqPos); - - if (!mappedRanges.isEmpty()) - { - String value = sf.getDescription(); - if (value == null || value.length() == 0) - { - value = type; - } - float score = sf.getScore(); - if (score != 0f && !Float.isNaN(score)) - { - value = Float.toString(score); - } - Map featureValues = theMap.get(type); - if (featureValues == null) - { - featureValues = new HashMap<>(); - theMap.put(type, featureValues); - } - for (int[] range : mappedRanges) - { - addAtomSpecRange(featureValues, value, modelNumber, range[0], - range[1], structureMapping.getChain()); - } - } - } - } - } - } - - /** - * Inspect features on the sequence; for each feature that is visible, - * determine its mapped ranges in the structure (if any) according to the - * given mapping, and add them to the map. - * - * @param visibleFeatures - * @param mapping - * @param seq - * @param theMap - * @param modelId - */ - protected static void scanSequenceFeatures(List visibleFeatures, - StructureMapping mapping, SequenceI seq, - Map> theMap, String modelId) - { - List sfs = seq.getFeatures().getPositionalFeatures( - visibleFeatures.toArray(new String[visibleFeatures.size()])); - for (SequenceFeature sf : sfs) - { - String type = sf.getType(); - - /* - * Don't copy features which originated from Chimera - */ - if (JalviewChimeraBinding.CHIMERA_FEATURE_GROUP - .equals(sf.getFeatureGroup())) - { - continue; - } - - List mappedRanges = mapping.getPDBResNumRanges(sf.getBegin(), - sf.getEnd()); - - if (!mappedRanges.isEmpty()) - { - String value = sf.getDescription(); - if (value == null || value.length() == 0) - { - value = type; - } - float score = sf.getScore(); - if (score != 0f && !Float.isNaN(score)) - { - value = Float.toString(score); - } - Map featureValues = theMap.get(type); - if (featureValues == null) - { - featureValues = new HashMap<>(); - theMap.put(type, featureValues); - } - for (int[] range : mappedRanges) - { - addAtomSpecRange(featureValues, value, modelId, range[0], - range[1], mapping.getChain()); - } - } - } - } - - /** * Traverse the map of features/values/models/chains/positions to construct a * list of 'setattr' commands (one per distinct feature type and value). *

@@ -350,7 +86,8 @@ public class ChimeraCommands extends StructureCommandsBase * @param featureMap * @return */ - protected List setAttributes( + @Override + public List setAttributes( Map> featureMap) { List commands = new ArrayList<>(); @@ -417,17 +154,9 @@ public class ChimeraCommands extends StructureCommandsBase * @return * @see https://www.cgl.ucsf.edu/chimera/current/docs/UsersGuide/midas/setattr.html */ - protected static String makeAttributeName(String featureType) + protected String makeAttributeName(String featureType) { - StringBuilder sb = new StringBuilder(); - if (featureType != null) - { - for (char c : featureType.toCharArray()) - { - sb.append(Character.isLetterOrDigit(c) ? c : '_'); - } - } - String attName = NAMESPACE_PREFIX + sb.toString(); + String attName = super.makeAttributeName(featureType); /* * Chimera treats an attribute name ending in 'color' as colour-valued; diff --git a/src/jalview/ext/rbvi/chimera/ChimeraXCommands.java b/src/jalview/ext/rbvi/chimera/ChimeraXCommands.java index 3341199..b7d9ce3 100644 --- a/src/jalview/ext/rbvi/chimera/ChimeraXCommands.java +++ b/src/jalview/ext/rbvi/chimera/ChimeraXCommands.java @@ -63,7 +63,7 @@ public class ChimeraXCommands extends ChimeraCommands } @Override - public StructureCommandI getColourCommand(String atomSpec, Color colour) + public StructureCommandI colourResidues(String atomSpec, Color colour) { // https://www.cgl.ucsf.edu/chimerax/docs/user/commands/color.html String colourCode = getColourString(colour); diff --git a/src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java b/src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java index 98cc1ff..d1b8583 100644 --- a/src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java +++ b/src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java @@ -38,6 +38,7 @@ import ext.edu.ucsf.rbvi.strucviz2.StructureManager; import ext.edu.ucsf.rbvi.strucviz2.StructureManager.ModelType; import jalview.api.AlignmentViewPanel; import jalview.api.structures.JalviewStructureDisplayI; +import jalview.bin.Cache; import jalview.datamodel.AlignmentI; import jalview.datamodel.PDBEntry; import jalview.datamodel.SearchResultMatchI; @@ -48,6 +49,7 @@ import jalview.gui.StructureViewer.ViewerType; import jalview.httpserver.AbstractRequestHandler; import jalview.io.DataSourceType; import jalview.structure.AtomSpec; +import jalview.structure.AtomSpecModel; import jalview.structure.StructureCommand; import jalview.structure.StructureCommandI; import jalview.structure.StructureSelectionManager; @@ -59,15 +61,6 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel public static final String CHIMERA_FEATURE_GROUP = "Chimera"; - // Chimera clause to exclude alternate locations in atom selection - private static final String NO_ALTLOCS = "&~@.B-Z&~@.2-9"; - - private static final boolean debug = false; - - private static final String PHOSPHORUS = "P"; - - private static final String ALPHACARBON = "CA"; - /* * Object through which we talk to Chimera */ @@ -367,10 +360,8 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel if (getResponse) { reply = lastReply; - if (debug) - { - log("Response from command ('" + cmd + "') was:\n" + lastReply); - } + Cache.log.debug( + "Response from command ('" + cmd + "') was:\n" + lastReply); } return reply; @@ -593,7 +584,11 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel /** * Constructs and send commands to Chimera to set attributes on residues for - * features visible in Jalview + * features visible in Jalview. + *

+ * The syntax is: setattr r <attName> <attValue> <atomSpec> + *

+ * For example: setattr r jv_chain "Ferredoxin-1, Chloroplastic" #0:94.A * * @param avp * @return @@ -601,14 +596,11 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel public int sendFeaturesToViewer(AlignmentViewPanel avp) { // TODO refactor as required to pull up to an interface - String[] files = getStructureFiles(); - if (files == null) - { - return 0; - } + Map> featureValues = buildFeaturesMap( + avp); List commands = getCommandGenerator() - .setAttributesForFeatures(getSsm(), files, getSequence(), avp); + .setAttributes(featureValues); if (commands.size() > 10) { sendCommandsByFile(commands); @@ -844,6 +836,7 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel return CHIMERA_SESSION_EXTENSION; } + @Override public String getHelpURL() { return "https://www.cgl.ucsf.edu/chimera/docs/UsersGuide"; diff --git a/src/jalview/gui/AppJmol.java b/src/jalview/gui/AppJmol.java index ffc8053..87fb1b4 100644 --- a/src/jalview/gui/AppJmol.java +++ b/src/jalview/gui/AppJmol.java @@ -147,8 +147,6 @@ public class AppJmol extends StructureViewerBase { super.initMenus(); - viewerActionMenu.setText(MessageManager.getString("label.jmol")); - viewerColour .setText(MessageManager.getString("label.colour_with_jmol")); viewerColour.setToolTipText(MessageManager diff --git a/src/jalview/gui/ChimeraViewFrame.java b/src/jalview/gui/ChimeraViewFrame.java index 45ab9a9..65b002b 100644 --- a/src/jalview/gui/ChimeraViewFrame.java +++ b/src/jalview/gui/ChimeraViewFrame.java @@ -25,7 +25,6 @@ import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.File; -import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -46,7 +45,6 @@ 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; @@ -80,16 +78,13 @@ public class ChimeraViewFrame extends StructureViewerBase { super.initMenus(); - viewerActionMenu.setText(MessageManager.getString("label.chimera")); - - helpItem.setText(MessageManager.getString("label.chimera_help")); savemenu.setVisible(false); // not yet implemented viewMenu.add(fitToWindow); JMenuItem writeFeatures = new JMenuItem( - MessageManager.getString("label.create_chimera_attributes")); + MessageManager.getString("label.create_viewer_attributes")); writeFeatures.setToolTipText(MessageManager - .getString("label.create_chimera_attributes_tip")); + .getString("label.create_viewer_attributes_tip")); writeFeatures.addActionListener(new ActionListener() { @Override @@ -154,14 +149,12 @@ public class ChimeraViewFrame extends StructureViewerBase } /** - * Send a command to Chimera to create residue attributes for Jalview features - *

- * The syntax is: setattr r <attName> <attValue> <atomSpec> - *

- * For example: setattr r jv_chain "Ferredoxin-1, Chloroplastic" #0:94.A + * Sends command(s) to the structure viewer to create residue attributes for + * visible Jalview features */ protected void sendFeaturesToChimera() { + // todo pull up? int count = jmb.sendFeaturesToViewer(getAlignmentPanel()); statusBar.setText( MessageManager.formatMessage("label.attributes_set", count)); @@ -529,20 +522,6 @@ public class ChimeraViewFrame extends StructureViewerBase } @Override - public void showHelp_actionPerformed() - { - try - { - String url = jmb.getHelpURL(); - BrowserLauncher.openURL(url); - } catch (IOException ex) - { - System.err - .println("Show Chimera help failed with: " + ex.getMessage()); - } - } - - @Override public AAStructureBindingModel getBinding() { return jmb; diff --git a/src/jalview/gui/ChimeraXViewFrame.java b/src/jalview/gui/ChimeraXViewFrame.java index d0353f3..a823235 100644 --- a/src/jalview/gui/ChimeraXViewFrame.java +++ b/src/jalview/gui/ChimeraXViewFrame.java @@ -66,13 +66,4 @@ public class ChimeraXViewFrame extends ChimeraViewFrame return new JalviewChimeraXBindingModel(this, ap.getStructureSelectionManager(), pdbentrys, seqs, null); } - - @Override - protected void initMenus() - { - super.initMenus(); - - viewerActionMenu.setText("ChimeraX"); - } - } diff --git a/src/jalview/gui/PymolBindingModel.java b/src/jalview/gui/PymolBindingModel.java index fc957bb..21ba95c 100644 --- a/src/jalview/gui/PymolBindingModel.java +++ b/src/jalview/gui/PymolBindingModel.java @@ -12,6 +12,7 @@ import jalview.ext.pymol.PymolCommands; import jalview.ext.pymol.PymolManager; import jalview.gui.StructureViewer.ViewerType; import jalview.structure.AtomSpec; +import jalview.structure.AtomSpecModel; import jalview.structure.StructureCommand; import jalview.structure.StructureCommandI; import jalview.structure.StructureSelectionManager; @@ -103,10 +104,9 @@ public class PymolBindingModel extends AAStructureBindingModel } @Override - public SequenceRenderer getSequenceRenderer(AlignmentViewPanel alignment) + public SequenceRenderer getSequenceRenderer(AlignmentViewPanel avp) { - // pull up? - return new SequenceRenderer(alignment.getAlignViewport()); + return new SequenceRenderer(avp.getAlignViewport()); } @Override @@ -222,4 +222,28 @@ public class PymolBindingModel extends AAStructureBindingModel return ".pse"; } + @Override + public String getHelpURL() + { + return "https://pymolwiki.org/"; + } + + /** + * Constructs and sends commands to set atom properties for visible Jalview + * features on residues mapped to structure + * + * @param avp + * @return + */ + public int sendFeaturesToViewer(AlignmentViewPanel avp) + { + // todo pull up this and JalviewChimeraBinding variant + Map> featureValues = buildFeaturesMap( + avp); + List commands = getCommandGenerator() + .setAttributes(featureValues); + executeCommands(commands, false, null); + return commands.size(); + } + } diff --git a/src/jalview/gui/PymolViewer.java b/src/jalview/gui/PymolViewer.java index 98582b2..4e0ac95 100644 --- a/src/jalview/gui/PymolViewer.java +++ b/src/jalview/gui/PymolViewer.java @@ -1,10 +1,13 @@ package jalview.gui; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.io.File; import java.util.ArrayList; import java.util.List; import javax.swing.JInternalFrame; +import javax.swing.JMenuItem; import javax.swing.event.InternalFrameAdapter; import javax.swing.event.InternalFrameEvent; @@ -328,4 +331,34 @@ public class PymolViewer extends StructureViewerBase return "PyMOL"; } + @Override + protected void initMenus() + { + super.initMenus(); + + savemenu.setVisible(false); // not yet implemented + viewMenu.add(fitToWindow); + + JMenuItem writeFeatures = new JMenuItem( + MessageManager.getString("label.create_viewer_attributes")); + writeFeatures.setToolTipText(MessageManager + .getString("label.create_viewer_attributes_tip")); + writeFeatures.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + sendFeaturesToPymol(); + } + }); + viewerActionMenu.add(writeFeatures); + } + + protected void sendFeaturesToPymol() + { + int count = binding.sendFeaturesToViewer(getAlignmentPanel()); + statusBar.setText( + MessageManager.formatMessage("label.attributes_set", count)); + } + } diff --git a/src/jalview/gui/StructureViewerBase.java b/src/jalview/gui/StructureViewerBase.java index e180f6b..fccd9bf 100644 --- a/src/jalview/gui/StructureViewerBase.java +++ b/src/jalview/gui/StructureViewerBase.java @@ -61,6 +61,7 @@ import jalview.schemes.ColourSchemeI; import jalview.schemes.ColourSchemes; import jalview.structure.StructureMapping; import jalview.structures.models.AAStructureBindingModel; +import jalview.util.BrowserLauncher; import jalview.util.MessageManager; import jalview.ws.dbsources.Pdb; @@ -706,7 +707,7 @@ public abstract class StructureViewerBase extends GStructureViewer } else { - // update the Chimera display now. + // update the viewer display now. seqColour_actionPerformed(); } } @@ -756,6 +757,10 @@ public abstract class StructureViewerBase extends GStructureViewer } }); + viewerActionMenu.setText(getViewerName()); + helpItem.setText(MessageManager.formatMessage("label.viewer_help", + getViewerName())); + buildColourMenu(); } @@ -1216,4 +1221,22 @@ public abstract class StructureViewerBase extends GStructureViewer dispose(); } + @Override + public void showHelp_actionPerformed() + { + try + { + String url = getBinding().getHelpURL(); + if (url != null) + { + BrowserLauncher.openURL(url); + } + } catch (IOException ex) + { + System.err + .println("Show " + getViewerName() + " failed with: " + + ex.getMessage()); + } + } + } diff --git a/src/jalview/structure/StructureCommandsBase.java b/src/jalview/structure/StructureCommandsBase.java index e688b64..3c29fd4 100644 --- a/src/jalview/structure/StructureCommandsBase.java +++ b/src/jalview/structure/StructureCommandsBase.java @@ -6,9 +6,6 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; -import jalview.api.AlignmentViewPanel; -import jalview.datamodel.SequenceI; - /** * A base class holding methods useful to all classes that implement commands * for structure viewers @@ -19,6 +16,7 @@ import jalview.datamodel.SequenceI; public abstract class StructureCommandsBase implements StructureCommandsI { private static final String CMD_SEPARATOR = ";"; + public static final String NAMESPACE_PREFIX = "jv_"; /** * Returns something that separates concatenated commands @@ -30,15 +28,6 @@ public abstract class StructureCommandsBase implements StructureCommandsI return CMD_SEPARATOR; } - @Override - public List setAttributesForFeatures( - StructureSelectionManager ssm, - String[] files, SequenceI[][] sequence, AlignmentViewPanel avp) - { - // default does nothing, override where this is implemented - return null; - } - /** * Returns the lowest model number used by the structure viewer * @@ -84,6 +73,28 @@ public abstract class StructureCommandsBase implements StructureCommandsI } /** + * Makes a structure viewer attribute name for a Jalview feature type by + * prefixing it with "jv_", and replacing any non-alphanumeric characters with + * an underscore + * + * @param featureType + * @return + */ + protected String makeAttributeName(String featureType) + { + StringBuilder sb = new StringBuilder(); + if (featureType != null) + { + for (char c : featureType.toCharArray()) + { + sb.append(Character.isLetterOrDigit(c) ? c : '_'); + } + } + String attName = NAMESPACE_PREFIX + sb.toString(); + return attName; + } + + /** * Traverse the map of colours/models/chains/positions to construct a list of * 'color' commands (one per distinct colour used). The format of each command * is specific to the structure viewer. @@ -130,7 +141,7 @@ public abstract class StructureCommandsBase implements StructureCommandsI Color colour) { String atomSpec = getAtomSpec(atomSpecModel, false); - return getColourCommand(atomSpec, colour); + return colourResidues(atomSpec, colour); } /** @@ -141,7 +152,7 @@ public abstract class StructureCommandsBase implements StructureCommandsI * @param colour * @return */ - protected abstract StructureCommandI getColourCommand(String atomSpec, + protected abstract StructureCommandI colourResidues(String atomSpec, Color colour); @Override @@ -159,7 +170,7 @@ public abstract class StructureCommandsBase implements StructureCommandsI private StructureCommandI colourResidue(String resName, Color col) { String atomSpec = getResidueSpec(resName); - return getColourCommand(atomSpec, col); + return colourResidues(atomSpec, col); } /** @@ -204,4 +215,12 @@ public abstract class StructureCommandsBase implements StructureCommandsI * @return */ protected abstract String getResidueSpec(String residue); + + @Override + public List setAttributes( + Map> featureValues) + { + // default does nothing, override where this is implemented + return null; + } } diff --git a/src/jalview/structure/StructureCommandsI.java b/src/jalview/structure/StructureCommandsI.java index 8725b3d..871d84b 100644 --- a/src/jalview/structure/StructureCommandsI.java +++ b/src/jalview/structure/StructureCommandsI.java @@ -1,12 +1,12 @@ package jalview.structure; -import jalview.api.AlignmentViewPanel; -import jalview.datamodel.SequenceI; - import java.awt.Color; import java.util.List; import java.util.Map; +import jalview.api.AlignmentViewPanel; +import jalview.datamodel.SequenceI; + /** * Methods that generate commands that can be sent to a molecular structure * viewer program (e.g. Jmol, Chimera, ChimeraX) @@ -82,20 +82,6 @@ public interface StructureCommandsI List showChains(List toShow); /** - * Returns zero, one or more commands to set attributes on mapped residues in - * the structure viewer for any features present and displayed in Jalview - * - * @param ssm - * @param files - * @param sequence - * @param avp - * @return - */ - List setAttributesForFeatures( - StructureSelectionManager ssm, - String[] files, SequenceI[][] sequence, AlignmentViewPanel avp); - - /** * Returns a command to superpose structures by closest positioning of * residues in {@code atomSpec} to the corresponding residues in * {@code refAtoms}. If wanted, this may include commands to visually @@ -162,4 +148,16 @@ public interface StructureCommandsI */ // refactor if needed to distinguish loading data or session files StructureCommandI loadFile(String file); + + /** + * Returns commands to set atom attributes or properties, given a map of + * Jalview features as {featureType, {featureValue, AtomSpecModel}}. The + * assumption is that one command can be constructed for each feature type and + * value combination, to apply it to one or more residues. + * + * @param featureValues + * @return + */ + List setAttributes( + Map> featureValues); } diff --git a/src/jalview/structures/models/AAStructureBindingModel.java b/src/jalview/structures/models/AAStructureBindingModel.java index 6e926df..8aa1895 100644 --- a/src/jalview/structures/models/AAStructureBindingModel.java +++ b/src/jalview/structures/models/AAStructureBindingModel.java @@ -42,8 +42,12 @@ import jalview.api.structures.JalviewStructureDisplayI; import jalview.bin.Cache; import jalview.datamodel.AlignmentI; import jalview.datamodel.HiddenColumns; +import jalview.datamodel.MappedFeatures; import jalview.datamodel.PDBEntry; +import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; +import jalview.ext.rbvi.chimera.JalviewChimeraBinding; +import jalview.gui.Desktop; import jalview.gui.StructureViewer.ViewerType; import jalview.io.DataSourceType; import jalview.io.StructureFile; @@ -1111,7 +1115,8 @@ public abstract class AAStructureBindingModel * @param getReply * @param msg */ - private List executeCommands(List commands, + protected List executeCommands( + List commands, boolean getReply, String msg) { return executeCommands(getReply, msg, @@ -1160,25 +1165,17 @@ public abstract class AAStructureBindingModel } /** - * colour any structures associated with sequences in the given alignment - * using the getFeatureRenderer() and getSequenceRenderer() renderers but only - * if colourBySequence is enabled. + * Colours any structures associated with sequences in the given alignment as + * coloured in the alignment view, provided colourBySequence is enabled */ public void colourBySequence(AlignmentViewPanel alignmentv) { - if (!colourBySequence || !isLoadingFinished()) + if (!colourBySequence || !isLoadingFinished() || getSsm() == null) { return; } - if (getSsm() == null) - { - return; - } - String[] files = getStructureFiles(); - - SequenceRenderer sr = getSequenceRenderer(alignmentv); - Map colourMap = buildColoursMap(ssm, files, - sequence, sr, alignmentv); + Map colourMap = buildColoursMap(ssm, sequence, + alignmentv); List colourBySequenceCommands = commandGenerator .colourBySequence(colourMap); @@ -1354,16 +1351,16 @@ public abstract class AAStructureBindingModel * models and chains) * * @param ssm - * @param files * @param sequence - * @param sr * @param viewPanel * @return */ protected Map buildColoursMap( - StructureSelectionManager ssm, String[] files, - SequenceI[][] sequence, SequenceRenderer sr, AlignmentViewPanel viewPanel) + StructureSelectionManager ssm, SequenceI[][] sequence, + AlignmentViewPanel viewPanel) { + String[] files = getStructureFiles(); + SequenceRenderer sr = getSequenceRenderer(viewPanel); FeatureRenderer fr = viewPanel.getFeatureRenderer(); FeatureColourFinder finder = new FeatureColourFinder(fr); AlignViewportI viewport = viewPanel.getAlignViewport(); @@ -1594,4 +1591,245 @@ public abstract class AAStructureBindingModel // add external viewer shutdown in overrides // todo - or can maybe pull up to here } + + /** + * Returns the URL of a help page for the structure viewer, or null if none is + * known + * + * @return + */ + public String getHelpURL() + { + return null; + } + + /** + *

+   * Helper method to build a map of 
+   *   { featureType, { feature value, AtomSpecModel } }
+   * 
+ * + * @param viewPanel + * @return + */ + protected Map> buildFeaturesMap( + AlignmentViewPanel viewPanel) + { + Map> theMap = new LinkedHashMap<>(); + String[] files = getStructureFiles(); + if (files == null) + { + return theMap; + } + + FeatureRenderer fr = viewPanel.getFeatureRenderer(); + if (fr == null) + { + return theMap; + } + + AlignViewportI viewport = viewPanel.getAlignViewport(); + List visibleFeatures = fr.getDisplayedFeatureTypes(); + + /* + * if alignment is showing features from complement, we also transfer + * these features to the corresponding mapped structure residues + */ + boolean showLinkedFeatures = viewport.isShowComplementFeatures(); + List complementFeatures = new ArrayList<>(); + FeatureRenderer complementRenderer = null; + if (showLinkedFeatures) + { + AlignViewportI comp = fr.getViewport().getCodingComplement(); + if (comp != null) + { + complementRenderer = Desktop.getAlignFrameFor(comp) + .getFeatureRenderer(); + complementFeatures = complementRenderer.getDisplayedFeatureTypes(); + } + } + if (visibleFeatures.isEmpty() && complementFeatures.isEmpty()) + { + return theMap; + } + + AlignmentI alignment = viewPanel.getAlignment(); + SequenceI[][] seqs = getSequence(); + + for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++) + { + String modelId = getModelIdForFile(files[pdbfnum]); + StructureMapping[] mapping = ssm.getMapping(files[pdbfnum]); + + if (mapping == null || mapping.length < 1) + { + continue; + } + + for (int seqNo = 0; seqNo < seqs[pdbfnum].length; seqNo++) + { + for (int m = 0; m < mapping.length; m++) + { + final SequenceI seq = seqs[pdbfnum][seqNo]; + int sp = alignment.findIndex(seq); + StructureMapping structureMapping = mapping[m]; + if (structureMapping.getSequence() == seq && sp > -1) + { + /* + * found a sequence with a mapping to a structure; + * now scan its features + */ + if (!visibleFeatures.isEmpty()) + { + scanSequenceFeatures(visibleFeatures, structureMapping, seq, + theMap, modelId); + } + if (showLinkedFeatures) + { + scanComplementFeatures(complementRenderer, structureMapping, + seq, theMap, modelId); + } + } + } + } + } + return theMap; + } + + /** + * Scans visible features in mapped positions of the CDS/peptide complement, and + * adds any found to the map of attribute values/structure positions + * + * @param complementRenderer + * @param structureMapping + * @param seq + * @param theMap + * @param modelNumber + */ + protected static void scanComplementFeatures( + FeatureRenderer complementRenderer, + StructureMapping structureMapping, SequenceI seq, + Map> theMap, + String modelNumber) + { + /* + * for each sequence residue mapped to a structure position... + */ + for (int seqPos : structureMapping.getMapping().keySet()) + { + /* + * find visible complementary features at mapped position(s) + */ + MappedFeatures mf = complementRenderer + .findComplementFeaturesAtResidue(seq, seqPos); + if (mf != null) + { + for (SequenceFeature sf : mf.features) + { + String type = sf.getType(); + + /* + * Don't copy features which originated from Chimera + */ + if (JalviewChimeraBinding.CHIMERA_FEATURE_GROUP + .equals(sf.getFeatureGroup())) + { + continue; + } + + /* + * record feature 'value' (score/description/type) as at the + * corresponding structure position + */ + List mappedRanges = structureMapping + .getPDBResNumRanges(seqPos, seqPos); + + if (!mappedRanges.isEmpty()) + { + String value = sf.getDescription(); + if (value == null || value.length() == 0) + { + value = type; + } + float score = sf.getScore(); + if (score != 0f && !Float.isNaN(score)) + { + value = Float.toString(score); + } + Map featureValues = theMap.get(type); + if (featureValues == null) + { + featureValues = new HashMap<>(); + theMap.put(type, featureValues); + } + for (int[] range : mappedRanges) + { + addAtomSpecRange(featureValues, value, modelNumber, range[0], + range[1], structureMapping.getChain()); + } + } + } + } + } + } + + /** + * Inspect features on the sequence; for each feature that is visible, + * determine its mapped ranges in the structure (if any) according to the + * given mapping, and add them to the map. + * + * @param visibleFeatures + * @param mapping + * @param seq + * @param theMap + * @param modelId + */ + protected static void scanSequenceFeatures(List visibleFeatures, + StructureMapping mapping, SequenceI seq, + Map> theMap, String modelId) + { + List sfs = seq.getFeatures().getPositionalFeatures( + visibleFeatures.toArray(new String[visibleFeatures.size()])); + for (SequenceFeature sf : sfs) + { + String type = sf.getType(); + + /* + * Don't copy features which originated from Chimera + */ + if (JalviewChimeraBinding.CHIMERA_FEATURE_GROUP + .equals(sf.getFeatureGroup())) + { + continue; + } + + List mappedRanges = mapping.getPDBResNumRanges(sf.getBegin(), + sf.getEnd()); + + if (!mappedRanges.isEmpty()) + { + String value = sf.getDescription(); + if (value == null || value.length() == 0) + { + value = type; + } + float score = sf.getScore(); + if (score != 0f && !Float.isNaN(score)) + { + value = Float.toString(score); + } + Map featureValues = theMap.get(type); + if (featureValues == null) + { + featureValues = new HashMap<>(); + theMap.put(type, featureValues); + } + for (int[] range : mappedRanges) + { + addAtomSpecRange(featureValues, value, modelId, range[0], + range[1], mapping.getChain()); + } + } + } + } } diff --git a/test/jalview/ext/pymol/PymolCommandsTest.java b/test/jalview/ext/pymol/PymolCommandsTest.java index c0f22c8..38031b6 100644 --- a/test/jalview/ext/pymol/PymolCommandsTest.java +++ b/test/jalview/ext/pymol/PymolCommandsTest.java @@ -225,7 +225,7 @@ public class PymolCommandsTest { PymolCommands testee = new PymolCommands(); assertEquals( - testee.getColourCommand("something", Color.MAGENTA).toString(), + testee.colourResidues("something", Color.MAGENTA).toString(), "color(0xff00ff,something)"); } } diff --git a/test/jalview/ext/rbvi/chimera/ChimeraCommandsTest.java b/test/jalview/ext/rbvi/chimera/ChimeraCommandsTest.java index f087020..5fc9fdc 100644 --- a/test/jalview/ext/rbvi/chimera/ChimeraCommandsTest.java +++ b/test/jalview/ext/rbvi/chimera/ChimeraCommandsTest.java @@ -135,21 +135,24 @@ public class ChimeraCommandsTest /** * Tests for the method that prefixes and sanitises a feature name so it can - * be used as a valid, namespaced attribute name in Chimera + * be used as a valid, namespaced attribute name in Chimera or PyMol */ @Test(groups = { "Functional" }) public void testMakeAttributeName() { - assertEquals(ChimeraCommands.makeAttributeName(null), "jv_"); - assertEquals(ChimeraCommands.makeAttributeName(""), "jv_"); - assertEquals(ChimeraCommands.makeAttributeName("helix"), "jv_helix"); - assertEquals(ChimeraCommands.makeAttributeName("Hello World 24"), + ChimeraCommands testee = new ChimeraCommands(); + assertEquals(testee.makeAttributeName(null), "jv_"); + assertEquals(testee.makeAttributeName(""), "jv_"); + assertEquals(testee.makeAttributeName("helix"), "jv_helix"); + assertEquals(testee.makeAttributeName( + "Hello World 24"), "jv_Hello_World_24"); assertEquals( - ChimeraCommands.makeAttributeName("!this is-a_very*{odd(name"), + testee.makeAttributeName( + "!this is-a_very*{odd(name"), "jv__this_is_a_very__odd_name"); // name ending in color gets underscore appended - assertEquals(ChimeraCommands.makeAttributeName("helixColor"), + assertEquals(testee.makeAttributeName("helixColor"), "jv_helixColor_"); } @@ -295,7 +298,7 @@ public class ChimeraCommandsTest public void testGetColourCommand() { ChimeraCommands testee = new ChimeraCommands(); - assertEquals(testee.getColourCommand("something", Color.MAGENTA) + assertEquals(testee.colourResidues("something", Color.MAGENTA) .getCommand(), "color #ff00ff something"); } diff --git a/test/jalview/ext/rbvi/chimera/ChimeraXCommandsTest.java b/test/jalview/ext/rbvi/chimera/ChimeraXCommandsTest.java index 044a1d9..210c61d 100644 --- a/test/jalview/ext/rbvi/chimera/ChimeraXCommandsTest.java +++ b/test/jalview/ext/rbvi/chimera/ChimeraXCommandsTest.java @@ -299,7 +299,7 @@ public class ChimeraXCommandsTest public void testGetColourCommand() { ChimeraCommands testee = new ChimeraXCommands(); - assertEquals(testee.getColourCommand("something", Color.MAGENTA) + assertEquals(testee.colourResidues("something", Color.MAGENTA) .getCommand(), "color something #ff00ff"); } diff --git a/test/jalview/structures/models/AAStructureBindingModelTest.java b/test/jalview/structures/models/AAStructureBindingModelTest.java index 16452a5..c1ad03a 100644 --- a/test/jalview/structures/models/AAStructureBindingModelTest.java +++ b/test/jalview/structures/models/AAStructureBindingModelTest.java @@ -52,6 +52,7 @@ import jalview.gui.JvOptionPane; import jalview.gui.StructureViewer.ViewerType; import jalview.io.DataSourceType; import jalview.io.FileFormats; +import jalview.io.FileLoader; import jalview.schemes.JalviewColourScheme; import jalview.structure.AtomSpec; import jalview.structure.AtomSpecModel; @@ -233,7 +234,7 @@ public class AAStructureBindingModelTest ssm.setMapping(new SequenceI[] { seq3 }, null, PDB_3, DataSourceType.PASTE, null); - testee = newBindingModel(pdbFiles, seqs, ssm); + testee = newBindingModel(pdbFiles, seqs, ssm, null); } /** @@ -242,10 +243,11 @@ public class AAStructureBindingModelTest * @param pdbFiles * @param seqs * @param ssm + * @param alignPanel */ protected AAStructureBindingModel newBindingModel(PDBEntry[] pdbFiles, SequenceI[][] seqs, - StructureSelectionManager ssm) + StructureSelectionManager ssm, AlignmentViewPanel avp) { AAStructureBindingModel model = new AAStructureBindingModel(ssm, pdbFiles, seqs, null) @@ -253,7 +255,12 @@ public class AAStructureBindingModelTest @Override public String[] getStructureFiles() { - return new String[] { "INLINE1YCS", "INLINE3A6S", "INLINE1OOT" }; + String[] files = new String[getPdbCount()]; + for (int i = 0; i < this.getPdbCount(); i++) + { + files[i] = getPdbEntry(i).getFile(); + } + return files; } @Override @@ -273,9 +280,11 @@ public class AAStructureBindingModelTest @Override public SequenceRenderer getSequenceRenderer( - AlignmentViewPanel alignment) + AlignmentViewPanel avp) { - return null; + return avp == null ? null + : new jalview.gui.SequenceRenderer( + avp.getAlignViewport()); } @Override @@ -409,10 +418,10 @@ public class AAStructureBindingModelTest * load these sequences, coloured by Strand propensity, * with columns 2-4 hidden */ - SequenceI seq1 = new Sequence("seq1", "MHRSQSSSGG"); - SequenceI seq2 = new Sequence("seq2", "MVRSNGGSSS"); - AlignmentI al = new Alignment(new SequenceI[] { seq1, seq2 }); - AlignFrame af = new AlignFrame(al, 800, 500); + String fasta = ">seq1\nMHRSQSSSGG\n>seq2\nMVRSNGGSSS"; + AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(fasta, + DataSourceType.PASTE); + AlignmentI al = af.getViewport().getAlignment(); af.changeColour_actionPerformed(JalviewColourScheme.Strand.toString()); ColumnSelection cs = new ColumnSelection(); cs.addElement(2); @@ -420,10 +429,9 @@ public class AAStructureBindingModelTest cs.addElement(4); af.getViewport().setColumnSelection(cs); af.hideSelColumns_actionPerformed(null); - SequenceRenderer sr = new jalview.gui.SequenceRenderer( - af.getViewport()); + SequenceI seq1 = al.getSequenceAt(0); + SequenceI seq2 = al.getSequenceAt(1); SequenceI[][] seqs = new SequenceI[][] { { seq1 }, { seq2 } }; - String[] files = new String[] { "seq1.pdb", "seq2.pdb" }; PDBEntry[] pdbFiles = new PDBEntry[2]; pdbFiles[0] = new PDBEntry("PDB1", "A", Type.PDB, "seq1.pdb"); pdbFiles[1] = new PDBEntry("PDB2", "B", Type.PDB, "seq2.pdb"); @@ -444,14 +452,15 @@ public class AAStructureBindingModelTest "B", map, null); ssm.addStructureMapping(sm2); - AAStructureBindingModel binding = newBindingModel(pdbFiles, seqs, ssm); + AAStructureBindingModel binding = newBindingModel(pdbFiles, seqs, ssm, + af.alignPanel); /* * method under test builds a map of structures residues by colour * verify the map holds what it should */ - Map colours = binding.buildColoursMap(ssm, files, - seqs, sr, af.alignPanel); + Map colours = binding.buildColoursMap(ssm, seqs, + af.alignPanel); ChimeraCommands helper = new ChimeraCommands(); /* -- 1.7.10.2