diff --git a/actions/ost-compare-structures b/actions/ost-compare-structures index 7ffef2083fb5dc5e3d40e688b79d6410f2e8dd61..4723f573bda777513cd3bb053fddae7055fd0fce 100644 --- a/actions/ost-compare-structures +++ b/actions/ost-compare-structures @@ -50,17 +50,19 @@ compare-structures as follows: # lDDT parameters ################# --lddt \\ - --structural-checks \\ - --consistency-checks \\ --inclusion-radius 15.0 \\ - --bond-tolerance 15.0 \\ - --angle-tolerance 15.0 \\ - # Molck parameters - ################## + # Molecular check parameters + ############################ --molck \\ --remove oxt hyd unk \\ --clean-element-column \\ - --map-nonstandard-residues + --map-nonstandard-residues \\ + # Additional checks + ################### + --structural-checks \\ + --bond-tolerance 15.0 \\ + --angle-tolerance 15.0 \\ + --consistency-checks """ import os @@ -78,77 +80,51 @@ from ost.conop import CompoundLib from ost.seq.alg.renumber import Renumber -class _DefaultStereochemicalParamAction(argparse.Action): - def __init__(self, default=None, required=False, **kwargs): - # Try to set default - cwd = os.path.abspath(os.getcwd()) - parameter_file_path = os.path.join(cwd, "stereo_chemical_props.txt") - if not os.path.exists(parameter_file_path): - try: - parameter_file_path = os.path.join( - ost.GetSharedDataPath(), - "stereo_chemical_props.txt") - default = parameter_file_path - msg = "" - except RuntimeError: - msg = ( - "Could not set default stereochemical parameter file. In " - "order to use the default one please set $OST_ROOT " - "environmental variable, run the script with OST binary or" - " provide a local copy of 'stereo_chemical_props.txt' in " - "CWD. Alternatively provide the path to the local copy") - else: - default = parameter_file_path - msg = "" - super(_DefaultStereochemicalParamAction, self).__init__( - default=default, - required=required, - **kwargs) - if msg: - self.help += " (WARNING: %s)" % (msg,) - - def __call__(self, parser, namespace, values, option_string=None): - if not os.path.exists(values): - parser.error( - "Parameter file %s does not exist." % values) - setattr(namespace, self.dest, values) - - -class _DefaultCompoundLibraryAction(argparse.Action): - def __init__(self, default=None, required=False, **kwargs): - # Try to set default - cwd = os.path.abspath(os.getcwd()) - compound_library_path = os.path.join(cwd, "compounds.chemlib") - if not os.path.exists(compound_library_path): - try: - compound_library_path = os.path.join( - ost.GetSharedDataPath(), - "compounds.chemlib") - default = compound_library_path - msg = "" - except RuntimeError: - msg = ( - "Could not set default compounds library path. In " - "order to use the default one please set $OST_ROOT " - "environmental variable, run the script with OST binary or" - " provide a local copy of 'compounds.chemlib' in CWD" - ". Alternatively provide the path to the local copy") - else: - default = compound_library_path - msg = "" - super(_DefaultCompoundLibraryAction, self).__init__( - default=default, - required=required, - **kwargs) - if msg: - self.help += " (WARNING: %s)" % (msg,) - - def __call__(self, parser, namespace, values, option_string=None): - if not os.path.exists(values): - parser.error( - "Compounds library file %s does not exist." % values) - setattr(namespace, self.dest, values) - +def _GetDefaultShareFilePath(filename): + """Look for filename in working directory and OST shared data path. + :return: Path to valid file or None if not found. + """ + # Try current directory + cwd = os.path.abspath(os.getcwd()) + file_path = os.path.join(cwd, filename) + if not os.path.isfile(file_path): + try: + file_path = os.path.join(ost.GetSharedDataPath(), filename) + except RuntimeError: + # Ignore errors here (caught later together with non-existing file) + pass + if not os.path.isfile(file_path): + file_path = None + # Either file_path is valid file path or None + return file_path + +def _GetDefaultParameterFilePath(): + # Try to get in default locations + parameter_file_path = _GetDefaultShareFilePath("stereo_chemical_props.txt") + if parameter_file_path is None: + msg = ( + "Could not set default stereochemical parameter file. In " + "order to use the default one please set $OST_ROOT " + "environmental variable, run the script with OST binary or" + " provide a local copy of 'stereo_chemical_props.txt' in " + "CWD. Alternatively provide the path to the local copy.") + else: + msg = "" + return parameter_file_path, msg + +def _GetDefaultCompoundLibraryPath(): + # Try to get in default locations + compound_library_path = _GetDefaultShareFilePath("compounds.chemlib") + if compound_library_path is None: + msg = ( + "Could not set default compounds library path. In " + "order to use the default one please set $OST_ROOT " + "environmental variable, run the script with OST binary or" + " provide a local copy of 'compounds.chemlib' in CWD" + ". Alternatively provide the path to the local copy.") + else: + msg = "" + return compound_library_path, msg def _ParseArgs(): """Parse command-line arguments.""" @@ -227,6 +203,15 @@ def _ParseArgs(): default=False, action="store_true", help=("Fault tolerant parsing.")) + parser.add_argument( + "-cl", + "--compound-library", + dest="compound_library", + default=None, + help=("Location of the compound library file (compounds.chemlib).\n" + "If not provided, the following locations are searched in this\n" + "order: 1. Working directory, 2. OpenStructure standard library" + "\nlocation.")) # # QS-scorer options # @@ -265,37 +250,6 @@ def _ParseArgs(): default=False, action="store_true", help=("Calculate lDDT.")) - parser.add_argument( - "-sc", - "--structural-checks", - dest="structural_checks", - default=False, - action="store_true", - help=("Perform structural checks and filter input data.")) - parser.add_argument( - "-p", - "--parameter-file", - dest="parameter_file", - action=_DefaultStereochemicalParamAction, - help=("Location of the stereochemical parameter file\n" - "(stereo_chemical_props.txt).\n" - "If not provided, the following locations are searched in this\n" - "order: 1. Working directory, 2. OpenStructure standard library" - "\nlocation.")) - parser.add_argument( - "-bt", - "--bond-tolerance", - dest="bond_tolerance", - type=float, - default=12.0, - help=("Tolerance in STD for bonds.")) - parser.add_argument( - "-at", - "--angle-tolerance", - dest="angle_tolerance", - type=float, - default=12.0, - help=("Tolerance in STD for angles.")) parser.add_argument( "-ir", "--inclusion-radius", @@ -312,18 +266,6 @@ def _ParseArgs(): help=("Sequence separation. Only distances between residues whose\n" "separation is higher than the provided parameter are\n" "considered when computing the score")) - parser.add_argument( - "-cc", - "--consistency-checks", - dest="consistency_checks", - default=False, - action="store_true", - help=("Take consistency checks into account. By default residue name\n" - "consistency between a model-reference pair would be checked\n" - "but only a warning message will be displayed and the script\n" - "will continue to calculate scores. If this flag is ON, checks\n" - "will not be ignored and if the pair does not pass the test\n" - "all the scores for that pair will be marked as a FAILURE.")) parser.add_argument( "-spr", "--save-per-residue-scores", @@ -332,7 +274,7 @@ def _ParseArgs(): action="store_true", help=("")) # - # Molck parameters + # Molecular check parameters # parser.add_argument( "-ml", @@ -341,15 +283,6 @@ def _ParseArgs(): default=False, action="store_true", help=("Run molecular checker to clean up input.")) - parser.add_argument( - "-cl", - "--compound-library", - dest="compound_library", - action=_DefaultCompoundLibraryAction, - help=("Location of the compound library file (compounds.chemlib).\n" - "If not provided, the following locations are searched in this\n" - "order: 1. Working directory, 2. OpenStructure standard library" - "\nlocation.")) parser.add_argument( "-rm", "--remove", @@ -380,6 +313,52 @@ def _ParseArgs(): action="store_true", help=("Map modified residues back to the parent amino acid, for\n" "example MSE -> MET, SEP -> SER.")) + # + # Options for various checks + # + parser.add_argument( + "-sc", + "--structural-checks", + dest="structural_checks", + default=False, + action="store_true", + help=("Perform structural checks and filter input data.")) + parser.add_argument( + "-p", + "--parameter-file", + dest="parameter_file", + default=None, + help=("Location of the stereochemical parameter file\n" + "(stereo_chemical_props.txt).\n" + "If not provided, the following locations are searched in this\n" + "order: 1. Working directory, 2. OpenStructure standard library" + "\nlocation.")) + parser.add_argument( + "-bt", + "--bond-tolerance", + dest="bond_tolerance", + type=float, + default=12.0, + help=("Tolerance in STD for bonds.")) + parser.add_argument( + "-at", + "--angle-tolerance", + dest="angle_tolerance", + type=float, + default=12.0, + help=("Tolerance in STD for angles.")) + parser.add_argument( + "-cc", + "--consistency-checks", + dest="consistency_checks", + default=False, + action="store_true", + help=("Take consistency checks into account. By default residue name\n" + "consistency between a model-reference pair would be checked\n" + "but only a warning message will be displayed and the script\n" + "will continue to calculate scores. If this flag is ON, checks\n" + "will not be ignored and if the pair does not pass the test\n" + "all the scores for that pair will be marked as a FAILURE.")) # Print full help is no arguments provided if len(sys.argv) == 1: @@ -395,17 +374,37 @@ def _ParseArgs(): parser.error( "Cannot parse chain mapping into dictionary. The " "correct format is: key:value [key2:value2 ...].") - # Check parameter file if lddt is on - if opts.lddt and opts.parameter_file is None: - parser.error( - "argument -p/--parameter-file is required when --lddt " - "option is selected.") - - # Check parameter file if lddt is on - if opts.molck and opts.compound_library is None: - parser.error( - "argument -cl/--compound-library is required when --molck " - "option is selected.") + + # Check parameter file if structural checks are on + if opts.structural_checks: + if opts.parameter_file is None: + # try to get default if none provided + opts.parameter_file, msg = _GetDefaultParameterFilePath() + if msg: + parser.error(msg) + else: + # if provided it must exist + if not os.path.isfile(opts.parameter_file): + parser.error("Parameter file %s does not exist." \ + % opts.parameter_file) + + # Check compound library path (always required!) + if opts.compound_library is None: + # try to get default if none provided + opts.compound_library, msg = _GetDefaultCompoundLibraryPath() + if msg: + parser.error(msg) + else: + # if provided it must exist + if not os.path.isfile(opts.compound_library): + parser.error("Compounds library file %s does not exist." \ + % opts.compound_library) + + # Check model and reference paths + if not os.path.isfile(opts.model): + parser.error("Model file %s does not exist." % opts.model) + if not os.path.isfile(opts.reference): + parser.error("Reference file %s does not exist." % opts.reference) return opts diff --git a/modules/doc/actions.rst b/modules/doc/actions.rst index c8502eff4a82e27b1702f57604b364a555b4d66c..779a95ea47b393a7ede6dd395f1f6d650fda576d 100644 --- a/modules/doc/actions.rst +++ b/modules/doc/actions.rst @@ -22,13 +22,13 @@ lDDT scores between two complexes from the command line with: $ ost compare-structures [-h] [-v VERBOSITY] -m MODEL -r REFERENCE [-o OUTPUT] [-d] [-ds DUMP_SUFFIX] [-rs REFERENCE_SELECTION] [-ms MODEL_SELECTION] - [-ca] [-ft] [-qs] + [-ca] [-ft] [-cl COMPOUND_LIBRARY] [-qs] [-c CHAIN_MAPPING [CHAIN_MAPPING ...]] [-rna] - [-l] [-sc] [-p PARAMETER_FILE] - [-bt BOND_TOLERANCE] [-at ANGLE_TOLERANCE] - [-ir INCLUSION_RADIUS] [-ss SEQUENCE_SEPARATION] - [-cc] [-spr] [-ml] [-cl COMPOUND_LIBRARY] - [-rm REMOVE [REMOVE ...]] [-ce] [-mn] + [-l] [-ir INCLUSION_RADIUS] + [-ss SEQUENCE_SEPARATION] [-spr] [-ml] + [-rm REMOVE [REMOVE ...]] [-ce] [-mn] [-sc] + [-p PARAMETER_FILE] [-bt BOND_TOLERANCE] + [-at ANGLE_TOLERANCE] [-cc] By default the verbosity is set to 3 which will result in the informations being shown in the console. The result can be (optionally) saved as JSON file