/* * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) * Copyright (C) $$Year-Rel$$ The Jalview Authors * * This file is part of Jalview. * * Jalview is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. * * Jalview is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Jalview. If not, see . * The Jalview Authors are detailed in the 'AUTHORS' file. */ package jalview.ext.rbvi.chimera; import java.awt.Color; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import jalview.structure.AtomSpecModel; import jalview.structure.StructureCommand; import jalview.structure.StructureCommandI; /** * Routines for generating ChimeraX commands for Jalview/ChimeraX binding */ public class ChimeraXCommands extends ChimeraCommands { // https://www.cgl.ucsf.edu/chimerax/docs/user/commands/info.html#resattr private static final StructureCommand LIST_RESIDUE_ATTRIBUTES = new StructureCommand("info resattr"); // https://www.cgl.ucsf.edu/chimerax/docs/user/commands/exit.html private static final StructureCommand CLOSE_CHIMERAX = new StructureCommand("exit"); // https://www.cgl.ucsf.edu/chimerax/docs/user/commands/info.html#notify private static final StructureCommand STOP_NOTIFY_SELECTION = new StructureCommand("info notify stop selection jalview"); private static final StructureCommand STOP_NOTIFY_MODELS = new StructureCommand("info notify stop models jalview"); // https://www.cgl.ucsf.edu/chimerax/docs/user/commands/info.html#selection private static final StructureCommand GET_SELECTION = new StructureCommand( "info selection level residue"); private static final StructureCommand SHOW_BACKBONE = new StructureCommand( "~display all;~ribbon;show @CA|P atoms"); // https://www.cgl.ucsf.edu/chimerax/docs/user/commands/view.html private static final StructureCommand FOCUS_VIEW = new StructureCommand( "view"); private static final StructureCommandI COLOUR_BY_CHARGE = new StructureCommand( "color white;color :ASP,GLU red;color :LYS,ARG blue;color :CYS yellow"); @Override public List colourByCharge() { return Arrays.asList(COLOUR_BY_CHARGE); } @Override public String getResidueSpec(String residue) { return ":" + residue; } @Override public StructureCommandI colourResidues(String atomSpec, Color colour) { // https://www.cgl.ucsf.edu/chimerax/docs/user/commands/color.html String colourCode = getColourString(colour); return new StructureCommand("color " + atomSpec + " " + colourCode); } @Override public StructureCommandI focusView() { return FOCUS_VIEW; } /** * {@inheritDoc} * * @return */ @Override public int getModelStartNo() { return 1; } /** * Returns a viewer command to set the given residue attribute value on * residues specified by the AtomSpecModel, for example * *
   * setattr #0/A:3-9,14-20,39-43 res jv_strand 'strand' create true
   * 
* * @param attributeName * @param attributeValue * @param atomSpecModel * @return */ @Override protected StructureCommandI setAttribute(String attributeName, String attributeValue, AtomSpecModel atomSpecModel) { StringBuilder sb = new StringBuilder(128); sb.append("setattr ").append(getAtomSpec(atomSpecModel, false)); sb.append(" res ").append(attributeName).append(" '") .append(attributeValue).append("'"); sb.append(" create true"); return new StructureCommand(sb.toString()); } @Override public StructureCommandI openCommandFile(String path) { // https://www.cgl.ucsf.edu/chimerax/docs/user/commands/open.html return new StructureCommand("open " + path); } @Override public StructureCommandI saveSession(String filepath) { // https://www.cgl.ucsf.edu/chimerax/docs/user/commands/save.html // note ChimeraX will append ".cxs" to the filepath! return new StructureCommand("save " + filepath + " format session"); } /** * Returns the range(s) formatted as a ChimeraX atomspec, for example *

* #1/A:2-20,30-40/B:10-20|#2/A:12-30 * * @return */ @Override public String getAtomSpec(AtomSpecModel atomSpec, boolean alphaOnly) { StringBuilder sb = new StringBuilder(128); boolean firstModel = true; for (String model : atomSpec.getModels()) { if (!firstModel) { sb.append("|"); } firstModel = false; appendModel(sb, model, atomSpec); if (alphaOnly) { // TODO @P if RNA - add nucleotide flag to AtomSpecModel? sb.append("@CA"); } // todo: is there ChimeraX syntax to exclude altlocs? } return sb.toString(); } /** * A helper method to append an atomSpec string for atoms in the given model * * @param sb * @param model * @param atomSpec */ protected void appendModel(StringBuilder sb, String model, AtomSpecModel atomSpec) { sb.append("#").append(model); for (String chain : atomSpec.getChains(model)) { boolean firstPositionForChain = true; sb.append("/").append(chain.trim()).append(":"); List rangeList = atomSpec.getRanges(model, chain); boolean first = true; for (int[] range : rangeList) { if (!first) { sb.append(","); } first = false; appendRange(sb, range[0], range[1], chain, firstPositionForChain, true); } } } @Override public List showBackbone() { return Arrays.asList(SHOW_BACKBONE); } @Override public List superposeStructures(AtomSpecModel ref, AtomSpecModel spec) { /* * Form ChimeraX match command to match spec to ref * * match #1/A:2-94 toAtoms #2/A:1-93 * * @see https://www.cgl.ucsf.edu/chimerax/docs/user/commands/align.html */ StringBuilder cmd = new StringBuilder(); String atomSpec = getAtomSpec(spec, true); String refSpec = getAtomSpec(ref, true); cmd.append("align ").append(atomSpec).append(" toAtoms ") .append(refSpec); /* * show superposed residues as ribbon, others as chain */ cmd.append("; ribbon "); cmd.append(getAtomSpec(spec, false)).append("|"); cmd.append(getAtomSpec(ref, false)).append("; view"); return Arrays.asList(new StructureCommand(cmd.toString())); } @Override public StructureCommandI openSession(String filepath) { // https://www.cgl.ucsf.edu/chimerax/docs/user/commands/open.html#composite // this version of the command has no dependency on file extension return new StructureCommand("open " + filepath + " format session"); } @Override public StructureCommandI closeViewer() { return CLOSE_CHIMERAX; } @Override public List startNotifications(String uri) { List cmds = new ArrayList<>(); cmds.add(new StructureCommand("info notify start models jalview prefix ModelChanged url " + uri)); cmds.add(new StructureCommand("info notify start selection jalview prefix SelectionChanged url " + uri)); return cmds; } @Override public List stopNotifications() { List cmds = new ArrayList<>(); cmds.add(STOP_NOTIFY_MODELS); cmds.add(STOP_NOTIFY_SELECTION); return cmds; } @Override public StructureCommandI getSelectedResidues() { return GET_SELECTION; } @Override public StructureCommandI listResidueAttributes() { return LIST_RESIDUE_ATTRIBUTES; } }