MayaChemTools

   1 #!/bin/env python
   2 #
   3 # File: PyMOLExtractSelection.py
   4 # Author: Manish Sud <msud@san.rr.com>
   5 #
   6 # Copyright (C) 2026 Manish Sud. All rights reserved.
   7 #
   8 # The functionality available in this script is implemented using PyMOL, a
   9 # molecular visualization system on an open source foundation originally
  10 # developed by Warren DeLano.
  11 #
  12 # This file is part of MayaChemTools.
  13 #
  14 # MayaChemTools is free software; you can redistribute it and/or modify it under
  15 # the terms of the GNU Lesser General Public License as published by the Free
  16 # Software Foundation; either version 3 of the License, or (at your option) any
  17 # later version.
  18 #
  19 # MayaChemTools is distributed in the hope that it will be useful, but without
  20 # any warranty; without even the implied warranty of merchantability of fitness
  21 # for a particular purpose.  See the GNU Lesser General Public License for more
  22 # details.
  23 #
  24 # You should have received a copy of the GNU Lesser General Public License
  25 # along with MayaChemTools; if not, see <http://www.gnu.org/licenses/> or
  26 # write to the Free Software Foundation Inc., 59 Temple Place, Suite 330,
  27 # Boston, MA, 02111-1307, USA.
  28 #
  29 
  30 from __future__ import print_function
  31 
  32 import os
  33 import sys
  34 import time
  35 import re
  36 
  37 # PyMOL imports...
  38 try:
  39     import pymol
  40 
  41     # Finish launching PyMOL in  a command line mode for batch processing (-c)
  42     # along with the following options:  disable loading of pymolrc and plugins (-k);
  43     # suppress start up messages (-q)
  44     pymol.finish_launching(["pymol", "-ckq"])
  45 except ImportError as ErrMsg:
  46     sys.stderr.write("\nFailed to import PyMOL module/package: %s\n" % ErrMsg)
  47     sys.stderr.write("Check/update your PyMOL environment and try again.\n\n")
  48     sys.exit(1)
  49 
  50 # MayaChemTools imports...
  51 sys.path.insert(0, os.path.join(os.path.dirname(sys.argv[0]), "..", "lib", "Python"))
  52 try:
  53     from docopt import docopt
  54     import MiscUtil
  55 except ImportError as ErrMsg:
  56     sys.stderr.write("\nFailed to import MayaChemTools module/package: %s\n" % ErrMsg)
  57     sys.stderr.write("Check/update your MayaChemTools environment and try again.\n\n")
  58     sys.exit(1)
  59 
  60 ScriptName = os.path.basename(sys.argv[0])
  61 Options = {}
  62 OptionsInfo = {}
  63 
  64 
  65 def main():
  66     """Start execution of the script."""
  67 
  68     MiscUtil.PrintInfo(
  69         "\n%s (PyMOL v%s; MayaChemTools v%s; %s): Starting...\n"
  70         % (ScriptName, pymol.cmd.get_version()[0], MiscUtil.GetMayaChemToolsVersion(), time.asctime())
  71     )
  72 
  73     (WallClockTime, ProcessorTime) = MiscUtil.GetWallClockAndProcessorTime()
  74 
  75     # Retrieve command line arguments and options...
  76     RetrieveOptions()
  77 
  78     # Process and validate command line arguments and options...
  79     ProcessOptions()
  80 
  81     # Perform actions required by the script...
  82     ExtractSelection()
  83 
  84     MiscUtil.PrintInfo("\n%s: Done...\n" % ScriptName)
  85     MiscUtil.PrintInfo("Total time: %s" % MiscUtil.GetFormattedElapsedTime(WallClockTime, ProcessorTime))
  86 
  87 
  88 def ExtractSelection():
  89     """Extract selection from input file and write it out."""
  90 
  91     MiscUtil.PrintInfo("\nGenerating output files...")
  92 
  93     # Load macromolecule from input file...
  94     MolName = OptionsInfo["InfileRoot"]
  95     pymol.cmd.load(OptionsInfo["Infile"], MolName)
  96 
  97     # Extract and write selection...
  98     ExtractAndWriteSelection(MolName)
  99 
 100     # Delete macromolecule...
 101     pymol.cmd.delete(MolName)
 102 
 103 
 104 def ExtractAndWriteSelection(MolName):
 105     """Extract selection from an input file  and write it out."""
 106 
 107     Outfile = OptionsInfo["Outfile"]
 108     MiscUtil.PrintInfo("\nGenerating output file %s..." % Outfile)
 109 
 110     # Setup selection...
 111     if OptionsInfo["SelectionAppend"]:
 112         MolSelection = "(%s and (%s))" % (MolName, OptionsInfo["Selection"])
 113     else:
 114         MolSelection = "(%s)" % (OptionsInfo["Selection"])
 115 
 116     MolSelectionName = OptionsInfo["SelectionName"]
 117 
 118     # Create selection object and write it out...
 119     MiscUtil.PrintInfo("Extracting selection: %s" % MolSelection)
 120 
 121     pymol.cmd.create(MolSelectionName, MolSelection)
 122     pymol.cmd.save(Outfile, MolSelectionName)
 123     pymol.cmd.delete(MolSelectionName)
 124 
 125     if not os.path.exists(Outfile):
 126         MiscUtil.PrintWarning("Failed to generate output file, %s..." % (Outfile))
 127 
 128 
 129 def ProcessOptions():
 130     """Process and validate command line arguments and options."""
 131 
 132     MiscUtil.PrintInfo("Processing options...")
 133 
 134     # Validate options...
 135     ValidateOptions()
 136 
 137     OptionsInfo["Infile"] = Options["--infile"]
 138     FileDir, FileName, FileExt = MiscUtil.ParseFileName(OptionsInfo["Infile"])
 139     OptionsInfo["InfileRoot"] = FileName
 140 
 141     OptionsInfo["Outfile"] = Options["--outfile"]
 142 
 143     OptionsInfo["Selection"] = Options["--selection"]
 144     OptionsInfo["SelectionName"] = "%s_Selection" % OptionsInfo["InfileRoot"]
 145 
 146     OptionsInfo["SelectionAppend"] = True if re.match("^Yes$", Options["--selectionAppend"], re.I) else False
 147 
 148     OptionsInfo["Overwrite"] = Options["--overwrite"]
 149 
 150 
 151 def RetrieveOptions():
 152     """Retrieve command line arguments and options."""
 153 
 154     # Get options...
 155     global Options
 156     Options = docopt(_docoptUsage_)
 157 
 158     # Set current working directory to the specified directory...
 159     WorkingDir = Options["--workingdir"]
 160     if WorkingDir:
 161         os.chdir(WorkingDir)
 162 
 163     # Handle examples option...
 164     if "--examples" in Options and Options["--examples"]:
 165         MiscUtil.PrintInfo(MiscUtil.GetExamplesTextFromDocOptText(_docoptUsage_))
 166         sys.exit(0)
 167 
 168 
 169 def ValidateOptions():
 170     """Validate option values."""
 171 
 172     MiscUtil.ValidateOptionFilePath("-i, --infile", Options["--infile"])
 173     MiscUtil.ValidateOptionFileExt("-i, --infile", Options["--infile"], "pdb cif")
 174 
 175     MiscUtil.ValidateOptionFileExt("-o, --outfile", Options["--outfile"], "pdb cif")
 176     MiscUtil.ValidateOptionsOutputFileOverwrite(
 177         "-o, --outfile", Options["--outfile"], "--overwrite", Options["--overwrite"]
 178     )
 179     MiscUtil.ValidateOptionsDistinctFileNames(
 180         "-i, --infile", Options["--infile"], "-o, --outfile", Options["--outfile"]
 181     )
 182 
 183     MiscUtil.ValidateOptionTextValue("--selectionAppend", Options["--selectionAppend"], "yes no")
 184 
 185 
 186 # Setup a usage string for docopt...
 187 _docoptUsage_ = """
 188 PyMOLExtractSelection.py - Extract selection from a macromolecule
 189 
 190 Usage:
 191     PyMOLExtractSelection.py [--overwrite] [--selectionAppend <yes or no>]
 192                              [-w <dir>] -i <infile> -o <outfile> -s <selection>
 193     PyMOLExtractSelection.py -h | --help | -e | --examples
 194 
 195 Description:
 196     Extract data corresponding to a PyMOL selection specification from a
 197     macromolecule in an input file and write it out to an output file.
 198 
 199     The selection specification must be a valid PyMOL specification. No
 200     validation is performed.
 201 
 202     The supported input file format are:  PDB (.pdb) and CIF (.cif)
 203 
 204     The supported output file formats are:  PDB (.pdb) and CIF (.cif)
 205 
 206 Options:
 207     -e, --examples
 208         Print examples.
 209     -h, --help
 210         Print this help message.
 211     -i, --infile <infile>
 212         Input file name.
 213     -o, --outfile <infile>
 214         Output file name.
 215     -s, --selection <PyMOL SelectionSpec>
 216         Selection specification for extracting data from a macromolecule in an
 217         input file. The selection specification must be a valid PyMOL specification.
 218         No Validation is performed.
 219         
 220         The specified selection specification is optionally appended to PyMOL
 221         object name for input file.
 222     --selectionAppend <yes or no>  [default: yes]
 223         Append specified selection specification to  PyMOL object name for input
 224         file  before creating PyMOL object for a specified selection specification.
 225         The PyMOL object name for input file is <InfileRoot>.
 226         
 227         You may choose to explicitly specify PyMOL object name in the selection
 228         specification instead of automatically appending it to the selection.
 229     --overwrite
 230         Overwrite existing files.
 231     -w, --workingdir <dir>
 232         Location of working directory which defaults to the current directory.
 233 
 234 Examples:
 235     To extract all data corresponding to chain E in a macromolecule and write
 236     out to a PDB file, type:
 237 
 238         % PyMOLExtractSelection.py -i Sample3.cif -o Sample3Out.pdb -s "chain E" --ov
 239 
 240     To extract only polymer chain data for chains E and I in a macromolecule and
 241     write out to a PDB file, type:
 242 
 243         % PyMOLExtractSelection.py -i Sample3.cif -o Sample3Out.pdb
 244           -s "((chain E) or (chain I)) and polymer" --ov
 245 
 246     To extract only polymer chain data for chain E in a macromolecule and write
 247     out to a PDB file, type:
 248 
 249         % PyMOLExtractSelection.py -i Sample3.pdb -o Sample3Out.pdb
 250           -s "(chain E) and polymer" --ov
 251 
 252     To extract only polymer chain data for chain E in a macromolecule by explicitly
 253     ignoring non-polymer chain data and write out to a CIF file, type:
 254 
 255         % PyMOLExtractSelection.py -i Sample3.pdb -o Sample3Out.cif
 256           -s "(chain E) and (not organic) and (not solvent) and
 257           (not inorganic)" --ov
 258 
 259     To extract solvent data corresponding to chain E in a macromolecule and write
 260     out to a PDB file, type:
 261 
 262         % PyMOLExtractSelection.py -i Sample3.pdb -o Sample3Out.pdb
 263           -s "(chain E) and solvent" --ov
 264 
 265     To extract ligand data corresponding to chain E in a macromolecule and write
 266     out to a PDB file, type:
 267 
 268         % PyMOLExtractSelection.py -i Sample3.pdb -o Sample3Out.pdb
 269           -s "(chain E) and organic" --ov
 270 
 271     To extract binding pocket residues with 5.0 of ligand ID ADP in chain E and write
 272     out a PDB file, type:
 273 
 274         % PyMOLExtractSelection.py -i Sample3.pdb -o Sample3Out.pdb
 275            --selectionAppend no -s "(byresidue (Sample3 and chain E)
 276           within 5.0 of (Sample3 and chain E and organic and resn ADP))
 277           and polymer" --ov
 278 
 279 Author:
 280     Manish Sud(msud@san.rr.com)
 281 
 282 See also:
 283     PyMOLAlignChains.py, PyMOLSplitChainsAndLigands.py,
 284     PyMOLVisualizeMacromolecules.py
 285 
 286 Copyright:
 287     Copyright (C) 2026 Manish Sud. All rights reserved.
 288 
 289     The functionality available in this script is implemented using PyMOL, a
 290     molecular visualization system on an open source foundation originally
 291     developed by Warren DeLano.
 292 
 293     This file is part of MayaChemTools.
 294 
 295     MayaChemTools is free software; you can redistribute it and/or modify it under
 296     the terms of the GNU Lesser General Public License as published by the Free
 297     Software Foundation; either version 3 of the License, or (at your option) any
 298     later version.
 299 
 300 """
 301 
 302 if __name__ == "__main__":
 303     main()