-
Notifications
You must be signed in to change notification settings - Fork 0
/
automated_mcce.py
executable file
·225 lines (192 loc) · 8.72 KB
/
automated_mcce.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
#!/usr/local/bin/env python
# -*- coding: utf-8 -*-
"""
Automate MCCE Calculations.
Description
-----------
This module implements a program to set up and run automated mcce calculations.
Notes
-----
This is still in development.
Examples
--------
Coming soon!
"""
import sys
from subprocess import call
import os
import shutil
import re
from collections import OrderedDict
from argparse import ArgumentParser
sys.dont_write_bytecode = True
class MCCEParams(object):
"""
A class representing an MCCE parameter file
Parameters
----------
mcce_directory : str
A string containing full path of the MCCE installation directory.
calculation_type : str, default=quick
A string specifying the type of MCCE calculation, if not specified "quick" is used by default.
Notes
-----
This class uses run.prm.quick as a template file to build an MCCE parameter object.
Should there be an option to initialize with quick or full (?)
"""
def __init__(self, mcce_directory, calculation_type="default"):
"""Initialize parameters for an MCCE calculation.
"""
self.mcce_directory = mcce_directory
self.calculation_type = calculation_type
if calculation_type not in ["quick", "full", "default"]:
sys.exit(
"Unrecognized MCCE calculation type, allowed values are: quick, full or default.")
self.mcce_params = self.load_params()
def load_params(self):
"""Loads parameters for MCCE calculation from run.prm file in MCCE installation directory.
Returns
-------
params : dict
A dictionary of MCCE calculation parameters, each element of the dictionary is a key:
key = string, containing the parameter name in the prm file, without parentheses
value = list, first element is the value and second element is the description, both are read from the prm file
"""
prm_source_file = open(self.mcce_directory +
"/" + "run.prm." + self.calculation_type, "r")
prm_lines = prm_source_file.readlines()
prm_source_file.close()
params = OrderedDict()
for line in prm_lines:
words = line.split(" ")
if re.search(r'\((.\w*)\)', words[-1]):
parameter = words[-1].strip("()\n")
value = words[0]
description = line.split(" ")[1:-1]
if parameter == "MCCE_HOME":
value = self.mcce_directory
if parameter in ["EXTRA", "RENAME_RULES"]:
value = self.mcce_directory + "/" + value.split("/")[-1]
if parameter == "DELPHI_EXE":
value = self.mcce_directory + \
"/bin/" + value.split("/")[-1]
if "//" in value:
value = value.replace("//", "/")
params[parameter] = [value, " ".join(description)]
return params
def edit_parameters(self, **kwargs):
"""Edits MCCE parameters by updating values in MCCE parameter dictionary keys.
Parameters
----------
**kwargs : Arbitrary keyword arguments
Any number of parameters can be specified as MCCE_PARAM="VALUE", where MCCE_PARAM is a valid
parameter name and "VALUE" is a string with corresponding value.
Examples
--------
>>> prm = MCCEParams("~/mcce/")
>>> prm.edit_parameters(DO_PREMCCE="t", DO_ROTAMERS="t", DO_ENERGY="t", DO_MONTE="f")
>>> prm.edit_parameters(DO_PREMCCE="t", DO_ROTAMERS="t")
Notes
-----
During parameter editing, there is no way to check if legal values are passed on.
This is probably handled by MCCE initialization step. It is therefore assumed that this function is used responsibly.
"""
for parameter in kwargs:
update_value = kwargs[parameter]
if parameter not in self.mcce_params.keys():
raise KeyError(
"Could not find %s parameter in parameter dictionary, please supply valid parameters" % parameter)
else:
self.mcce_params[parameter][0] = update_value
def write_runprm(self, destination_dir):
"""Writes run.prm file in a sub-directory
Parameters
----------
destination_dir : string
String containing path of the directory, where run.prm will be saved.
"""
runprm_filepath = destination_dir + "run.prm"
runprm_file = open(runprm_filepath, "w")
param_line_format = "{0:s} {1:s} ({2:s})\n"
for parameter in self.mcce_params.keys():
line_to_write = param_line_format.format(
self.mcce_params[parameter][0], self.mcce_params[parameter][1], parameter)
runprm_file.write(line_to_write)
runprm_file.close()
def write_submitsh(self, destination_dir, run_name=""):
submit_text = ["#!/bin/sh\n", "#$ -S /bin/sh\n", "#$ -N mcce\n", "#$ -cwd\n",
"#$ -o run.log\n", "#$ -e error.log\n", self.mcce_directory + "mcce"]
submit_text[2] = submit_text[2].replace("mcce", "mcce_" + run_name)
submitsh = open("submit.sh", "w")
for line in submit_text:
submitsh.write(line)
submitsh.close()
def automated_run(input_dir, destination_dir, mcce_dir, local=False):
"""Performs an automated mcce calculation on a set of pdb file, located in an input folder.
Parameters
----------
input_dir : str
String consisting of a valid path of a directory containing pdb files.
destination_dir : str
String consisting of a path representing a target directory where results of each mcce calculation will be stored.
mcce_dir : str
Location of the mcce installation, should contain mcce executable.
Notes
-----
This function will not work if each pdb file that should be processed is present in its own sub-directory. It is suggested that
all pdb files are collected in the input directory before running this.
"""
# check if input_dir exists and is not empty
if not os.path.isdir(input_dir):
sys.exit("Input directory not found.")
# check if mcce exists
input_pdb_files = [pdb_file for pdb_file in os.listdir(
input_dir) if pdb_file.endswith(".pdb")]
for pdb_file in input_pdb_files:
print("Preparing input files for: ", pdb_file[0:-4])
output_dir = destination_dir + "/mcce_results_" + pdb_file[0:-4]
if not os.path.exists(output_dir):
os.makedirs(output_dir)
output_dir = output_dir.replace("//", "/")
source_pdb_file_path = input_dir + "/" + pdb_file
target_pdb_file_path = output_dir + "/" + "prot.pdb"
source_pdb_file_path = source_pdb_file_path.replace("//", "/")
target_pdb_file_path = target_pdb_file_path.replace("//", "/")
shutil.copy(source_pdb_file_path, target_pdb_file_path)
# generate prm file
os.chdir(output_dir)
prm = MCCEParams(mcce_dir)
prm.edit_parameters(DO_PREMCCE="t", DO_ROTAMERS="t",
DO_ENERGY="t", DO_MONTE="t")
prm.write_runprm("")
prm.write_submitsh("", run_name=pdb_file[0:-4])
call("qsub submit.sh", shell=True)
def parse_args():
"""Parse the command line arguments and perform some validation on the
arguments
Returns
-------
args : argparse.Namespace
The namespace containing the arguments
"""
parser = ArgumentParser(description='''Run MCCE on multiple PDB files''')
required = parser.add_argument_group('required arguments')
required.add_argument('-i', '--input_directory', required=True, type=str,
help='''path to the directory containing input
PDB files, already preprocessed for MCCE calculations''')
required.add_argument('-d', '--destination_directory', required=True, type=str,
help='''path to the directory where output of mcce
calculations will be stored.''')
required.add_argument('-e', '--mcce_directory', required=True, type=str,
help='''path to the directory where MCCE is installed.''')
args = parser.parse_args()
return args
def main():
args = parse_args()
automated_run(args.input_directory,
args.destination_directory, args.mcce_directory)
# Using entry point approach for future conda packaging
def entry_point():
main()
if __name__ == '__main__':
entry_point()