def test_binder_2(): """ test binder 2 Test that the C++ binder runs """ import os from pnab import bind os.chdir(os.path.dirname(os.path.realpath(__file__))) backbone = bind.Backbone() backbone.file_path = os.path.join('files', 'rna_bb.pdb') backbone.interconnects = [10, 1] backbone.linker = [13, 14] base = bind.Base() base.file_path = os.path.join('files', 'adenine.pdb') base.code = 'A' base.linker = [5, 11] base.name = 'Adenine' base.pair_name = 'Uracil' bases = [base] hp = bind.HelicalParameters() hp.h_twist = 32.39 hp.h_rise = 2.53 hp.inclination = 22.9 hp.tip = 0.08 hp.x_displacement = -4.54 hp.y_displacement = -0.02 rp = bind.RuntimeParameters() rp.search_algorithm = 'weighted random search' rp.num_steps = 1000000 rp.ff_type = 'GAFF' rp.energy_filter = [2.0, 5.0, 10.0, 10000.0, 10000.0] rp.max_distance = 0.2 rp.strand = ['Adenine'] * 5 rp.num_candidates = 2 output = bind.run(rp, backbone, bases, hp, 'test') print(output)
def test_binder_1(): """ test binder Test exposed C++ classes attributes and their types """ from pnab import bind backbone = bind.Backbone() backbone_attr = {'file_path': str, 'interconnects': list, 'linker': list} assert all([i in backbone.__dir__() for i in backbone_attr]) assert all([ type(backbone.__getattribute__(k)) is val for k, val in backbone_attr.items() ]) base = bind.Base() base_attr = { 'name': str, 'code': str, 'pair_name': str, 'file_path': str, 'linker': list } assert all([i in base.__dir__() for i in base_attr]) assert all([ type(base.__getattribute__(k)) is val for k, val in base_attr.items() ]) runtime_parameters = bind.RuntimeParameters() runtime_parameters_attr = { 'energy_filter': list, 'max_distance': float, 'ff_type': str, 'seed': int, 'search_algorithm': str, 'num_steps': int, 'dihedral_step': float, 'strand': list, 'is_hexad': bool, 'build_strand': list, 'strand_orientation': list, 'weighting_temperature': float, 'monte_carlo_temperature': float, 'mutation_rate': float, 'crossover_rate': float, 'population_size': int, 'glycosidic_bond_distance': float, 'num_candidates': int } assert all( [i in runtime_parameters.__dir__() for i in runtime_parameters_attr]) assert all([ type(runtime_parameters.__getattribute__(k)) is val for k, val in runtime_parameters_attr.items() ]) helical_parameters = bind.HelicalParameters() helical_parameters_attr = [ 'h_twist', 'tip', 'inclination', 'h_rise', 'x_displacement', 'y_displacement', 'twist', 'roll', 'tilt', 'rise', 'slide', 'shift', 'buckle', 'propeller', 'opening', 'stretch', 'shear', 'stagger' ] assert all( [i in helical_parameters.__dir__() for i in helical_parameters_attr]) assert all([ type(helical_parameters.__getattribute__(i)) is float for i in helical_parameters_attr ]) assert type(helical_parameters.__getattribute__('is_helical')) is bool
def test_helical_parameters(): """ Test the equivalence between helical and step parameters. The test compares 3 sets of values for helical and step parameters. Using the two schemes should give identical results for the accepted candidates. To ensure correct comparisons, the step parameter values are set to many digits. """ import os from pnab import bind os.chdir(os.path.dirname(os.path.realpath(__file__))) parameters = [[[1, 2, 3, 4, 5, 6], [ -0.4691332223, 0.3125034304, 2.9558478770, -0.5222738076, 0.4178190461, 5.9626387714 ]], [[-1, -2, -3, -4, -5, -6], [ -0.4691332223, 0.3125034304, -2.9558478770, -0.5222738076, 0.4178190461, -5.9626387714 ]], [[-2, 5, 3, -15, 20, -40], [ 2.2177307312, 0.4662275467, 4.1753711904, 13.2973947701, 9.9730460776, -36.5122480218 ]]] backbone = bind.Backbone() backbone.file_path = os.path.join('files', 'rna_bb.pdb') backbone.interconnects = [10, 1] backbone.linker = [13, 14] base = bind.Base() base.file_path = os.path.join('files', 'adenine.pdb') base.code = 'A' base.linker = [5, 11] base.name = 'Adenine' base.pair_name = 'Uracil' bases = [base] rp = bind.RuntimeParameters() rp.search_algorithm = 'weighted random search' rp.num_steps = 10 rp.ff_type = 'GAFF' rp.energy_filter = [1e10] * 5 rp.max_distance = 1e10 rp.strand = ['Adenine'] * 5 rp.num_candidates = 10 for p in parameters: hp = bind.HelicalParameters() hp.is_helical = True hp.x_displacement = p[0][0] hp.y_displacement = p[0][1] hp.h_rise = p[0][2] hp.inclination = p[0][3] hp.tip = p[0][4] hp.h_twist = p[0][5] output_helical = bind.run(rp, backbone, bases, hp, 'test') hp.is_helical = False hp.shift = p[1][0] hp.slide = p[1][1] hp.rise = p[1][2] hp.tilt = p[1][3] hp.roll = p[1][4] hp.twist = p[1][5] output_step = bind.run(rp, backbone, bases, hp, 'test') assert output_helical == output_step
def _run(self, config): """!@brief Function to run one helical configuration. Setup the options to call the C++ code using the pybind11 bind class in @a binder.cpp. After the run finishes, it returns the results for processing. @param config (list) a list containing two entries: the list of helical parameter values for this configuration, and a string index for the sequnce of the run @returns results [prefix, header, result] A list containing the index of the run, a string describing the helical configuration, and a numpy array of the results @sa run @sa _single_result """ config, prefix = config[0], config[1] # Add a header of the helical parameters header_dict = {'%s' %k: '%.2f' %val for k, val in zip(self.options['HelicalParameters'], config)} if self._is_helical: header = ''.join(['%s=%s, ' %(k, header_dict[k]) for k in ['x_displacement', 'y_displacement', 'h_rise', 'inclination', 'tip', 'h_twist']]) else: header = ''.join(['%s=%s, ' %(k, header_dict[k]) for k in ['shift', 'slide', 'rise', 'tilt', 'roll', 'twist']]) header += ''.join(['%s=%s, ' %(k, header_dict[k]) for k in ['shear', 'stretch', 'stagger', 'buckle', 'propeller', 'opening']]) header = header.strip(', ') # Set runtime parameters runtime_parameters = bind.RuntimeParameters() [runtime_parameters.__setattr__(k, val) for k, val in self.options['RuntimeParameters'].items()] # Set backbone parameters backbone = bind.Backbone() [backbone.__setattr__(k, val) for k, val in self.options['Backbone'].items()] # Set a list of all defined bases asd there parameters # We include all the bases even though not all of them are requested by the user py_bases = [self.options[i] for i in self.options if 'Base' in i] bases = [bind.Base() for i in range(len(py_bases))] for i, b in enumerate(py_bases): [bases[i].__setattr__(k, val) for k, val in b.items()] # Set helical parameters helical_parameters = bind.HelicalParameters() [helical_parameters.__setattr__(k, val) for k, val in zip(self.options['HelicalParameters'], config)] helical_parameters.is_helical = self._is_helical # Run code result = bind.run(runtime_parameters, backbone, bases, helical_parameters, prefix, self._verbose) # Get results from the comma-separated output string result = np.genfromtxt(StringIO(result), delimiter=',') if result.size == 0: result = None elif result.ndim == 1: result = result.reshape(1, len(result)) if result is not None: result = result[result[:, 7].argsort()] results = [prefix, header, result] return results
def _run(self, config): """!@brief Function to run one helical configuration. Setup the options to call the C++ code using the pybind11 bind class in @a binder.cpp. After the run finishes, it writes the results. Two files are written: "prefix.yaml" contains a dictionary of the sequence of the run and the corresponding helical configuration "results.csv" contains the information on the accepted candidates for all of configurations @param config (list) a list containing two entries: the list of helical parameter values for this configuration, and a string index for the sequnce of the run @sa run """ config, prefix = config[0], config[1] # Add a header of the helical parameters header_dict = { '%s' % k: '%.2f' % val for k, val in zip(self._options['HelicalParameters'], config) } units = ["A", "A", "A", "deg", "deg", "deg"] if self._is_helical: header = ''.join([ '%s (%s): %s; ' % (k, units[i], header_dict[k]) for i, k in enumerate([ 'x_displacement', 'y_displacement', 'h_rise', 'inclination', 'tip', 'h_twist' ]) ]) else: header = ''.join([ '%s (%s): %s; ' % (k, units[i], header_dict[k]) for i, k in enumerate(['shift', 'slide', 'rise', 'tilt', 'roll', 'twist']) ]) header += ''.join([ '%s (%s): %s; ' % (k, units[i], header_dict[k]) for i, k in enumerate([ 'shear', 'stretch', 'stagger', 'buckle', 'propeller', 'opening' ]) ]) header = header.strip('; ') # Set runtime parameters runtime_parameters = bind.RuntimeParameters() [ runtime_parameters.__setattr__(k, val) for k, val in self._options['RuntimeParameters'].items() ] # Set backbone parameters backbone = bind.Backbone() [ backbone.__setattr__(k, val) for k, val in self._options['Backbone'].items() ] # Set a list of all defined bases asd there parameters # We include all the bases even though not all of them are requested by the user py_bases = [self._options[i] for i in self._options if 'Base' in i] bases = [bind.Base() for i in range(len(py_bases))] for i, b in enumerate(py_bases): [bases[i].__setattr__(k, val) for k, val in b.items()] # Set helical parameters helical_parameters = bind.HelicalParameters() [ helical_parameters.__setattr__(k, val) for k, val in zip(self._options['HelicalParameters'], config) ] helical_parameters.is_helical = self._is_helical # Run code result = bind.run(runtime_parameters, backbone, bases, helical_parameters, prefix, self._verbose) # Get results from the comma-separated output string result = np.genfromtxt(StringIO(result), delimiter=',') if result.size == 0: result = None elif result.ndim == 1: result = result.reshape(1, len(result)) if result is not None: result = result[result[:, 7].argsort()] results = [prefix, header, result] # Write prefix and helical configuration with open('prefix.yaml', 'ab') as f: f.write(str.encode(yaml.dump({results[0]: results[1]}))) # If there are no results, return if results[2] is None: return # Update header header = results[1] + '\n' header2 = self.header ## Add header entries for the dihedral angles for i in range(results[2].shape[1] - 8): header2 += ", Dihedral " + str(i + 1) + " (degrees)" header += header2 # Write results to file fmt = "%i,%i" for i in range(results[2].shape[1] - 2): fmt += ",%.6f" with open('results.csv', 'ab') as f: np.savetxt(f, results[2], header=header, fmt=fmt)
def test_energy_filter(): """ test that energy filters are enforced and that the program generates lower energy conformers """ import os from io import StringIO import numpy as np from pnab import bind os.chdir(os.path.dirname(os.path.realpath(__file__))) backbone = bind.Backbone() backbone.file_path = os.path.join('files', 'rna_bb.pdb') backbone.interconnects = [10, 1] backbone.linker = [13, 14] base = bind.Base() base.file_path = os.path.join('files', 'adenine.pdb') base.code = 'A' base.linker = [5, 11] base.name = 'Adenine' base.pair_name = 'Uracil' bases = [base] hp = bind.HelicalParameters() hp.h_twist = 32.39 hp.h_rise = 2.53 hp.inclination = 22.9 hp.tip = 0.08 hp.x_displacement = -4.54 hp.y_displacement = -0.02 rp = bind.RuntimeParameters() rp.search_algorithm = 'weighted monte carlo search' rp.num_steps = 1 rp.ff_type = 'GAFF' rp.energy_filter = [1e100] * 5 rp.max_distance = 1e100 rp.strand = ['Adenine'] * 5 output1 = bind.run(rp, backbone, bases, hp, '1') output1 = np.genfromtxt(StringIO(output1), delimiter=',') rp.num_steps = 1000000 rp.energy_filter = [ output1[3], output1[4], output1[5], output1[6], output1[7] ] rp.max_distance = 0.05 output2 = bind.run(rp, backbone, bases, hp, '2') output2 = np.genfromtxt(StringIO(output2), delimiter=',') if output2.size == 0: return elif output2.ndim == 1: output2 = output2.reshape(1, len(output2)) filter_index = [3, 4, 5, 6, 7] for i in filter_index: assert all([val < output1[i] for val in output2[:, i]])