Source code for gromacs_extra.ndx2resttop

#!/usr/bin/env python3

"""Module containing the Ndx2resttop class and the command line interface."""
import fnmatch
import argparse
from pathlib import Path
from biobb_common.generic.biobb_object import BiobbObject
from biobb_common.configuration import settings
from biobb_common.tools import file_utils as fu
from biobb_common.tools.file_utils import launchlogger


[docs]class Ndx2resttop(BiobbObject): """ | biobb_md Ndx2resttop | Generate a restrained topology from an index NDX file. | This module automatizes the process of restrained topology generation starting from an index NDX file. Args: input_ndx_path (str): Path to the input NDX index file. File type: input. `Sample file <https://github.com/bioexcel/biobb_md/raw/master/biobb_md/test/data/gromacs_extra/ndx2resttop.ndx>`_. Accepted formats: ndx (edam:format_2033). input_top_zip_path (str): Path the input TOP topology in zip format. File type: input. `Sample file <https://github.com/bioexcel/biobb_md/raw/master/biobb_md/test/data/gromacs_extra/ndx2resttop.zip>`_. Accepted formats: zip (edam:format_3987). output_top_zip_path (str): Path the output TOP topology in zip format. File type: output. `Sample file <https://github.com/bioexcel/biobb_md/raw/master/biobb_md/test/reference/gromacs_extra/ref_ndx2resttop.zip>`_. Accepted formats: zip (edam:format_3987). properties (dict - Python dictionary object containing the tool parameters, not input/output files): * **force_constants** (*str*) - ("500 500 500") Array of three floats defining the force constants. * **ref_rest_chain_triplet_list** (*str*) - (None) Triplet list composed by (reference group, restrain group, chain) list. Examples: This is a use example of how to use the building block from Python:: from biobb_md.gromacs_extra.ndx2resttop import ndx2resttop prop = { 'ref_rest_chain_triplet_list': '( Chain_A, Chain_A_noMut, A ), ( Chain_B, Chain_B_noMut, B ), ( Chain_C, Chain_C_noMut, C ), ( Chain_D, Chain_D_noMut, D )' } ndx2resttop(input_ndx_path='/path/to/myIndex.ndx', input_top_zip_path='/path/to/myTopology.zip', output_top_zip_path='/path/to/newTopology.zip', properties=prop) Info: * wrapped_software: * name: In house * license: Apache-2.0 * ontology: * name: EDAM * schema: http://edamontology.org/EDAM.owl """ def __init__(self, input_ndx_path: str, input_top_zip_path: str, output_top_zip_path: str, properties: dict = None, **kwargs) -> None: properties = properties or {} # Call parent class constructor super().__init__(properties) # Input/Output files self.io_dict = { "in": {"input_ndx_path": input_ndx_path, "input_top_zip_path": input_top_zip_path}, "out": {"output_top_zip_path": output_top_zip_path} } # Properties specific for BB self.force_constants = properties.get('force_constants', '500 500 500') self.ref_rest_chain_triplet_list = properties.get('ref_rest_chain_triplet_list') # Check the properties self.check_properties(properties)
[docs] @launchlogger def launch(self) -> int: """Execute the :class:`Ndx2resttop <gromacs_extra.ndx2resttop.Ndx2resttop>` object.""" # Setup Biobb if self.check_restart(): return 0 top_file = fu.unzip_top(zip_file=self.io_dict['in'].get("input_top_zip_path"), out_log=self.out_log) # Create index list of index file :) index_dic = {} lines = open(self.io_dict['in'].get("input_ndx_path")).read().splitlines() for index, line in enumerate(lines): if line.startswith('['): index_dic[line] = index, label = line if index > 0: index_dic[label] = index_dic[label][0], index index_dic[label] = index_dic[label][0], index fu.log('Index_dic: '+str(index_dic), self.out_log, self.global_log) self.ref_rest_chain_triplet_list = [tuple(elem.strip(' ()').replace(' ', '').split(',')) for elem in self.ref_rest_chain_triplet_list.split('),')] fu.log('ref_rest_chain_triplet_list: ' + str(self.ref_rest_chain_triplet_list), self.out_log, self.global_log) for reference_group, restrain_group, chain in self.ref_rest_chain_triplet_list: fu.log('Reference group: '+reference_group, self.out_log, self.global_log) fu.log('Restrain group: '+restrain_group, self.out_log, self.global_log) fu.log('Chain: '+chain, self.out_log, self.global_log) self.io_dict['out']["output_itp_path"] = fu.create_name(path=str(Path(top_file).parent), prefix=self.prefix, step=self.step, name=restrain_group+'.itp') # Mapping atoms from absolute enumeration to Chain relative enumeration fu.log('reference_group_index: start_closed:'+str(index_dic['[ '+reference_group+' ]'][0]+1)+' stop_open: '+str(index_dic['[ '+reference_group+' ]'][1]), self.out_log, self.global_log) reference_group_list = [int(elem) for line in lines[index_dic['[ '+reference_group+' ]'][0]+1: index_dic['[ '+reference_group+' ]'][1]] for elem in line.split()] fu.log('restrain_group_index: start_closed:'+str(index_dic['[ '+restrain_group+' ]'][0]+1)+' stop_open: '+str(index_dic['[ '+restrain_group+' ]'][1]), self.out_log, self.global_log) restrain_group_list = [int(elem) for line in lines[index_dic['[ '+restrain_group+' ]'][0]+1: index_dic['[ '+restrain_group+' ]'][1]] for elem in line.split()] selected_list = [reference_group_list.index(atom)+1 for atom in restrain_group_list] # Creating new ITP with restrictions with open(self.io_dict['out'].get("output_itp_path"), 'w') as f: fu.log('Creating: '+str(f)+' and adding the selected atoms force constants', self.out_log, self.global_log) f.write('[ position_restraints ]\n') f.write('; atom type fx fy fz\n') for atom in selected_list: f.write(str(atom)+' 1 '+self.force_constants+'\n') # Including new ITP in the corresponding ITP-chain file for file_dir in Path(top_file).parent.iterdir(): if not file_dir.name.startswith("posre") and not file_dir.name.endswith("_pr.itp"): if fnmatch.fnmatch(str(file_dir), "*_chain_"+chain+".itp"): with open(str(file_dir), 'a') as f: fu.log('Opening: '+str(f)+' and adding the ifdef include statement', self.out_log, self.global_log) f.write('\n') f.write('; Include Position restraint file\n') f.write('#ifdef CUSTOM_POSRES\n') f.write('#include "'+str(Path(self.io_dict['out'].get("output_itp_path")).name)+'"\n') f.write('#endif\n') # zip topology fu.zip_top(zip_file=self.io_dict['out'].get("output_top_zip_path"), top_file=top_file, out_log=self.out_log) # Remove temporal files self.remove_tmp_files() return 0
[docs]def ndx2resttop(input_ndx_path: str, input_top_zip_path: str, output_top_zip_path: str, properties: dict = None, **kwargs) -> int: """Create :class:`Ndx2resttop <gromacs_extra.ndx2resttop.Ndx2resttop>` class and execute the :meth:`launch() <gromacs_extra.ndx2resttop.Ndx2resttop.launch>` method.""" return Ndx2resttop(input_ndx_path=input_ndx_path, input_top_zip_path=input_top_zip_path, output_top_zip_path=output_top_zip_path, properties=properties, **kwargs).launch()
[docs]def main(): """Command line execution of this building block. Please check the command line documentation.""" parser = argparse.ArgumentParser(description="Wrapper for the GROMACS extra ndx2resttop module.", formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, width=99999)) parser.add_argument('-c', '--config', required=False, help="This file can be a YAML file, JSON file or JSON string") # Specific args of each building block required_args = parser.add_argument_group('required arguments') required_args.add_argument('--input_ndx_path', required=True) required_args.add_argument('--input_top_zip_path', required=True) required_args.add_argument('--output_top_zip_path', required=True) args = parser.parse_args() config = args.config if args.config else None properties = settings.ConfReader(config=config).get_prop_dic() # Specific call of each building block ndx2resttop(input_ndx_path=args.input_ndx_path, input_top_zip_path=args.input_top_zip_path, output_top_zip_path=args.output_top_zip_path, properties=properties)
if __name__ == '__main__': main()