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}.<br>Do you want to close the {1} window as well?
label.all = All
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
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
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
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
warn.delete_all=<html>Borrar todas las secuencias cerrará la ventana del alineamiento.<br>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
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;
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,
{
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
+ }
}
}
@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())
}
@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);
return commands;
}
+ /**
+ * Returns a viewer command to set the given atom property value on atoms
+ * specified by the AtomSpecModel, for example
+ *
+ * <pre>
+ * iterate 4zho//B/12-34,48-55/CA,jv_chain='primary'
+ * </pre>
+ *
+ * @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.
+ * <p>
+ * The format of each command is
+ *
+ * <pre>
+ * <blockquote> iterate atomspec, p.featureName='value'
+ * e.g. iterate 4zho//A/23,28-29/CA, p.jv_Metal='Fe'
+ * </blockquote>
+ * </pre>
+ *
+ * @param featureMap
+ * @return
+ */
+ @Override
+ public List<StructureCommandI> setAttributes(
+ Map<String, Map<Object, AtomSpecModel>> featureMap)
+ {
+ List<StructureCommandI> 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<Object, AtomSpecModel> 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;
+ }
+
}
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;
/**
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");
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);
}
/**
- * 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<StructureCommandI> setAttributesForFeatures(
- StructureSelectionManager ssm, String[] files, SequenceI[][] seqs,
- AlignmentViewPanel viewPanel)
- {
- Map<String, Map<Object, AtomSpecModel>> featureMap = buildFeaturesMap(
- ssm, files, seqs, viewPanel);
-
- return setAttributes(featureMap);
- }
-
- /**
- * <pre>
- * Helper method to build a map of
- * { featureType, { feature value, AtomSpecModel } }
- * </pre>
- *
- * @param ssm
- * @param files
- * @param seqs
- * @param viewPanel
- * @return
- */
- protected Map<String, Map<Object, AtomSpecModel>> buildFeaturesMap(
- StructureSelectionManager ssm, String[] files, SequenceI[][] seqs,
- AlignmentViewPanel viewPanel)
- {
- Map<String, Map<Object, AtomSpecModel>> theMap = new LinkedHashMap<>();
-
- FeatureRenderer fr = viewPanel.getFeatureRenderer();
- if (fr == null)
- {
- return theMap;
- }
-
- AlignViewportI viewport = viewPanel.getAlignViewport();
- List<String> 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<String> 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<String, Map<Object, AtomSpecModel>> 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<int[]> 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<Object, AtomSpecModel> 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<String> visibleFeatures,
- StructureMapping mapping, SequenceI seq,
- Map<String, Map<Object, AtomSpecModel>> theMap, String modelId)
- {
- List<SequenceFeature> 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<int[]> 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<Object, AtomSpecModel> 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).
* <p>
* @param featureMap
* @return
*/
- protected List<StructureCommandI> setAttributes(
+ @Override
+ public List<StructureCommandI> setAttributes(
Map<String, Map<Object, AtomSpecModel>> featureMap)
{
List<StructureCommandI> commands = new ArrayList<>();
* @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;
}
@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);
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;
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;
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
*/
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;
/**
* Constructs and send commands to Chimera to set attributes on residues for
- * features visible in Jalview
+ * features visible in Jalview.
+ * <p>
+ * The syntax is: setattr r <attName> <attValue> <atomSpec>
+ * <p>
+ * For example: setattr r jv_chain "Ferredoxin-1, Chloroplastic" #0:94.A
*
* @param avp
* @return
public int sendFeaturesToViewer(AlignmentViewPanel avp)
{
// TODO refactor as required to pull up to an interface
- String[] files = getStructureFiles();
- if (files == null)
- {
- return 0;
- }
+ Map<String, Map<Object, AtomSpecModel>> featureValues = buildFeaturesMap(
+ avp);
List<StructureCommandI> commands = getCommandGenerator()
- .setAttributesForFeatures(getSsm(), files, getSequence(), avp);
+ .setAttributes(featureValues);
if (commands.size() > 10)
{
sendCommandsByFile(commands);
return CHIMERA_SESSION_EXTENSION;
}
+ @Override
public String getHelpURL()
{
return "https://www.cgl.ucsf.edu/chimera/docs/UsersGuide";
{
super.initMenus();
- viewerActionMenu.setText(MessageManager.getString("label.jmol"));
-
viewerColour
.setText(MessageManager.getString("label.colour_with_jmol"));
viewerColour.setToolTipText(MessageManager
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;
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;
{
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
}
/**
- * Send a command to Chimera to create residue attributes for Jalview features
- * <p>
- * The syntax is: setattr r <attName> <attValue> <atomSpec>
- * <p>
- * 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));
}
@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;
return new JalviewChimeraXBindingModel(this,
ap.getStructureSelectionManager(), pdbentrys, seqs, null);
}
-
- @Override
- protected void initMenus()
- {
- super.initMenus();
-
- viewerActionMenu.setText("ChimeraX");
- }
-
}
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;
}
@Override
- public SequenceRenderer getSequenceRenderer(AlignmentViewPanel alignment)
+ public SequenceRenderer getSequenceRenderer(AlignmentViewPanel avp)
{
- // pull up?
- return new SequenceRenderer(alignment.getAlignViewport());
+ return new SequenceRenderer(avp.getAlignViewport());
}
@Override
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<String, Map<Object, AtomSpecModel>> featureValues = buildFeaturesMap(
+ avp);
+ List<StructureCommandI> commands = getCommandGenerator()
+ .setAttributes(featureValues);
+ executeCommands(commands, false, null);
+ return commands.size();
+ }
+
}
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;
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));
+ }
+
}
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;
}
else
{
- // update the Chimera display now.
+ // update the viewer display now.
seqColour_actionPerformed();
}
}
}
});
+ viewerActionMenu.setText(getViewerName());
+ helpItem.setText(MessageManager.formatMessage("label.viewer_help",
+ getViewerName()));
+
buildColourMenu();
}
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());
+ }
+ }
+
}
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
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
return CMD_SEPARATOR;
}
- @Override
- public List<StructureCommandI> 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
*
}
/**
+ * 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.
Color colour)
{
String atomSpec = getAtomSpec(atomSpecModel, false);
- return getColourCommand(atomSpec, colour);
+ return colourResidues(atomSpec, colour);
}
/**
* @param colour
* @return
*/
- protected abstract StructureCommandI getColourCommand(String atomSpec,
+ protected abstract StructureCommandI colourResidues(String atomSpec,
Color colour);
@Override
private StructureCommandI colourResidue(String resName, Color col)
{
String atomSpec = getResidueSpec(resName);
- return getColourCommand(atomSpec, col);
+ return colourResidues(atomSpec, col);
}
/**
* @return
*/
protected abstract String getResidueSpec(String residue);
+
+ @Override
+ public List<StructureCommandI> setAttributes(
+ Map<String, Map<Object, AtomSpecModel>> featureValues)
+ {
+ // default does nothing, override where this is implemented
+ return null;
+ }
}
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)
List<StructureCommandI> showChains(List<String> 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<StructureCommandI> 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
*/
// 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<StructureCommandI> setAttributes(
+ Map<String, Map<Object, AtomSpecModel>> featureValues);
}
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;
* @param getReply
* @param msg
*/
- private List<String> executeCommands(List<StructureCommandI> commands,
+ protected List<String> executeCommands(
+ List<StructureCommandI> commands,
boolean getReply, String msg)
{
return executeCommands(getReply, msg,
}
/**
- * 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<Object, AtomSpecModel> colourMap = buildColoursMap(ssm, files,
- sequence, sr, alignmentv);
+ Map<Object, AtomSpecModel> colourMap = buildColoursMap(ssm, sequence,
+ alignmentv);
List<StructureCommandI> colourBySequenceCommands = commandGenerator
.colourBySequence(colourMap);
* models and chains)
*
* @param ssm
- * @param files
* @param sequence
- * @param sr
* @param viewPanel
* @return
*/
protected Map<Object, AtomSpecModel> 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();
// 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;
+ }
+
+ /**
+ * <pre>
+ * Helper method to build a map of
+ * { featureType, { feature value, AtomSpecModel } }
+ * </pre>
+ *
+ * @param viewPanel
+ * @return
+ */
+ protected Map<String, Map<Object, AtomSpecModel>> buildFeaturesMap(
+ AlignmentViewPanel viewPanel)
+ {
+ Map<String, Map<Object, AtomSpecModel>> 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<String> 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<String> 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<String, Map<Object, AtomSpecModel>> 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<int[]> 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<Object, AtomSpecModel> 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<String> visibleFeatures,
+ StructureMapping mapping, SequenceI seq,
+ Map<String, Map<Object, AtomSpecModel>> theMap, String modelId)
+ {
+ List<SequenceFeature> 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<int[]> 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<Object, AtomSpecModel> 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());
+ }
+ }
+ }
+ }
}
{
PymolCommands testee = new PymolCommands();
assertEquals(
- testee.getColourCommand("something", Color.MAGENTA).toString(),
+ testee.colourResidues("something", Color.MAGENTA).toString(),
"color(0xff00ff,something)");
}
}
/**
* 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_");
}
public void testGetColourCommand()
{
ChimeraCommands testee = new ChimeraCommands();
- assertEquals(testee.getColourCommand("something", Color.MAGENTA)
+ assertEquals(testee.colourResidues("something", Color.MAGENTA)
.getCommand(),
"color #ff00ff something");
}
public void testGetColourCommand()
{
ChimeraCommands testee = new ChimeraXCommands();
- assertEquals(testee.getColourCommand("something", Color.MAGENTA)
+ assertEquals(testee.colourResidues("something", Color.MAGENTA)
.getCommand(),
"color something #ff00ff");
}
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;
ssm.setMapping(new SequenceI[] { seq3 }, null, PDB_3,
DataSourceType.PASTE, null);
- testee = newBindingModel(pdbFiles, seqs, ssm);
+ testee = newBindingModel(pdbFiles, seqs, ssm, null);
}
/**
* @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)
@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
@Override
public SequenceRenderer getSequenceRenderer(
- AlignmentViewPanel alignment)
+ AlignmentViewPanel avp)
{
- return null;
+ return avp == null ? null
+ : new jalview.gui.SequenceRenderer(
+ avp.getAlignViewport());
}
@Override
* 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);
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");
"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<Object, AtomSpecModel> colours = binding.buildColoursMap(ssm, files,
- seqs, sr, af.alignPanel);
+ Map<Object, AtomSpecModel> colours = binding.buildColoursMap(ssm, seqs,
+ af.alignPanel);
ChimeraCommands helper = new ChimeraCommands();
/*