def test_grid_multi_conformers(): "Test generating grid multiconformer" smiles = 'HC(H)(C(H)(H)OH)OH' mapped_smiles = '[H:5][C:1]([H:6])([C:2]([H:7])([H:8])[O:4][H:10])[O:3][H:9]' mol = cmiles.utils.load_molecule(smiles) mapped_mol = cmiles.utils.load_molecule(mapped_smiles) dihedrals = [(2, 0, 1, 3), (0, 1, 3, 9), (1, 0, 2, 8)] intervals = [60, 60, 60] with pytest.raises(ValueError): chemi.generate_grid_conformers(mol, dihedrals, intervals) mult_conf = chemi.generate_grid_conformers(mapped_mol, dihedrals, intervals)
def generate_grid_conformers(): mol = chemi.smiles_to_oemol('CCCC') dihedrals = [(0, 2, 3, 1), (3, 2, 0, 4)] intervals = [30, 90] grid = chemi.generate_grid_conformers(mol, dihedrals=dihedrals, intervals=intervals) assert grid.GetMaxConfIdx() == 48
def teat_qcschema_to_xyz(): smiles = 'HC(H)(C(H)(H)OH)OH' mapped_smiles = '[H:5][C:1]([H:6])([C:2]([H:7])([H:8])[O:4][H:10])[O:3][H:9]' mol = cmiles.utils.load_molecule(smiles) mapped_mol = cmiles.utils.load_molecule(mapped_smiles) dihedrals = [(2, 0, 1, 3), (0, 1, 3, 9), (1, 0, 2, 8)] intervals = [90, 90, 90] mult_conf = chemi.generate_grid_conformers(mapped_mol, dihedrals, intervals) # generate list of qcschema molecules qcschema_molecules = [ cmiles.utils.mol_to_map_ordered_qcschema(conf, mol_id) for conf in multi_conf.GetConfs() ]
def generate_torsiondrive_input(self, frag, json_filename=None): """ Generate input for torsiondrive QCFractal portal Parameters ---------- fragment_dict: dict dictionary with fragment identifiers and provenance workflow_id: str workflow to use for options options: dict, optional, default None Keyword options. If None will use options defined in workflow json_filename: str, optional, default None If given will write jobs to json file Returns ------- torsiondrive_inputs: dictionary defining the molecule and torsiondrive job options. """ options = self.off_workflow.get_options('torsiondrive_input') provenance = _get_provenance(workflow_id=self.workflow_id, routine='torsiondrive_input') frag['provenance']['routine']['torsiondrive_input'] = provenance[ 'routine']['torsiondrive_input'] provenance = frag['provenance'] mol_id = frag['identifiers'] mapped_smiles = mol_id[ 'canonical_isomeric_explicit_hydrogen_mapped_smiles'] mapped_mol = chemi.smiles_to_oemol(mapped_smiles) needed_torsions = torsions.find_torsions(mapped_mol, options['restricted']) if options['multiple_confs']: # Generate grid of multiple conformers dihedrals = [] for torsion_type in needed_torsions: for tor in needed_torsions[torsion_type]: dihedrals.append(needed_torsions[torsion_type][tor]) intervals = options['initial_conf_grid_resolution'] if not isinstance(intervals, list): intervals = [intervals] * len(dihedrals) try: conformers = chemi.generate_grid_conformers( mapped_mol, dihedrals=dihedrals, intervals=intervals) except RuntimeError: utils.logger().warning( "{} does not have coordinates. This can happen for several reasons related to Omega. " "{} will not be included in fragments dictionary".format( mol_id['canonical_isomeric_smiles'], mol_id['canonical_isomeric_smiles'])) return False chemi.resolve_clashes(conformers) qcschema_molecules = [ mol_to_map_ordered_qcschema(conf, mol_id) for conf in conformers.GetConfs() ] try: conformer = chemi.generate_conformers(mapped_mol, max_confs=1) # resolve clashes qcschema_molecule = mol_to_map_ordered_qcschema(conformer, mol_id) except RuntimeError: utils.logger().warning( "{} does not have coordinates. This can happen for several reasons related to Omega. " "{} will not be included in fragments dictionary".format( mol_id['canonical_isomeric_smiles'], mol_id['canonical_isomeric_smiles'])) return False identifier = mol_id[ 'canonical_isomeric_explicit_hydrogen_mapped_smiles'] torsiondrive_inputs = { identifier: { 'torsiondrive_input': {}, 'provenance': provenance } } restricted_torsions = needed_torsions.pop('restricted') optimization_jobs = torsions.generate_constraint_opt_input( qcschema_molecule, restricted_torsions, **options['restricted_optimization_options']) torsiondrive_inputs[identifier][ 'optimization_input'] = optimization_jobs torsiondrive_jobs = torsions.define_torsiondrive_jobs( needed_torsions, **options['torsiondrive_options']) if options['multiple_confs']: qcschema_molecule = qcschema_molecules # Currently, all jobs are started from same initial conformation # ToDo Start later job from optimized conformers from last job for i, job in enumerate(torsiondrive_jobs): torsiondrive_input = {'type': 'torsiondrive_input'} torsiondrive_input['initial_molecule'] = qcschema_molecule #torsiondrive_input['initial_molecule']['identifiers'] = mol_id torsiondrive_input['dihedrals'] = torsiondrive_jobs[job][ 'dihedrals'] torsiondrive_input['grid_spacing'] = torsiondrive_jobs[job][ 'grid_spacing'] job_name = '' for i, torsion in enumerate(torsiondrive_input['dihedrals']): if i > 0: job_name += '_{}'.format(torsion) else: job_name += '{}'.format(torsion) torsiondrive_inputs[identifier]['torsiondrive_input'][ job_name] = torsiondrive_input if json_filename: with open(json_filename, 'w') as f: json.dump(torsiondrive_inputs, f, indent=2, sort_keys=True) return torsiondrive_inputs