def test_remove_water_ions(self): # Complex file name fcomplex = "tests/data/pP38_lp38a_2x_complex.pdb" # Read OEMol molecule mol = oechem.OEMol() with oechem.oemolistream(fcomplex) as ifs: oechem.OEReadMolecule(ifs, mol) clean_system = utils.strip_water_ions(mol) prot, lig, wat, cofactors, lipids, metals, excipients = utils.split( clean_system) npa = prot.GetMaxAtomIdx() nla = lig.GetMaxAtomIdx() noa = excipients.GetMaxAtomIdx() nwa = wat.GetMaxAtomIdx() nlpa = lipids.GetMaxAtomIdx() nma = metals.GetMaxAtomIdx() nca = cofactors.GetMaxAtomIdx() self.assertEqual(npa, 5629) self.assertEqual(nla, 43) self.assertEqual(noa, 0) self.assertEqual(nwa, 0) self.assertEqual(nlpa, 0) self.assertEqual(nca, 0) self.assertEqual(nma, 0)
def test_solvation_packmol_tip3p(self): # Complex file name fcomplex = "tests/data/Bace_protein.pdb" # Read OEMol molecule mol = oechem.OEMol() with oechem.oemolistream(fcomplex) as ifs: oechem.OEReadMolecule(ifs, mol) # Solvate the system solv_complex = packmol.oesolvate(mol, density=1.0, padding_distance=10.0, distance_between_atoms=2.0, solvents='tip3p', molar_fractions='1.0', geometry='box', close_solvent=True, salt='[Na+], [Cl-]', salt_concentration=100.0, neutralize_solute=True) prot, lig, wat, other = utils.split(solv_complex) npa = prot.GetMaxAtomIdx() nla = lig.GetMaxAtomIdx() noa = other.GetMaxAtomIdx() nwa = wat.GetMaxAtomIdx() self.assertEqual(npa, 6044) self.assertEqual(nla, 0) # Ions added to excipients self.assertEqual(noa, 94) # Water molecules added self.assertEqual(nwa, 48279) box_vectors = solv_complex.GetData('box_vectors') box_vectors = data_utils.decodePyObj(box_vectors) box_vectors = box_vectors.in_units_of(unit.nanometers) self.assertAlmostEqual(box_vectors[0][0] / unit.nanometers, 8.23, delta=0.01) self.assertEqual(box_vectors[0][1] / unit.nanometers, 0.0) self.assertEqual(box_vectors[0][2] / unit.nanometers, 0.0) self.assertAlmostEqual(box_vectors[1][1] / unit.nanometers, 8.23, delta=0.01) self.assertEqual(box_vectors[1][0] / unit.nanometers, 0.0) self.assertEqual(box_vectors[1][2] / unit.nanometers, 0.0) self.assertAlmostEqual(box_vectors[2][2] / unit.nanometers, 8.23, delta=0.01) self.assertEqual(box_vectors[2][0] / unit.nanometers, 0.0) self.assertEqual(box_vectors[2][1] / unit.nanometers, 0.0)
def test_solvation_packmol_components(self): # Complex file name fcomplex = "tests/data/Bace_protein.pdb" # Read OEMol molecule mol = oechem.OEMol() with oechem.oemolistream(fcomplex) as ifs: oechem.OEReadMolecule(ifs, mol) # Solvate the system solv_complex, solvent, salt, counter_ions = packmol.oesolvate( mol, density=1.0, padding_distance=10.0, distance_between_atoms=2.0, solvents='tip3p', molar_fractions='1.0', geometry='box', close_solvent=True, salt='[Na+], [Cl-]', salt_concentration=100.0, neutralize_solute=True, return_components=True) prot, lig, wat, cofactors, lipids, metals, excipients = utils.split( solv_complex) npa = prot.GetMaxAtomIdx() nla = lig.GetMaxAtomIdx() noa = excipients.GetMaxAtomIdx() nwa = wat.GetMaxAtomIdx() nlpa = lipids.GetMaxAtomIdx() nma = metals.GetMaxAtomIdx() nca = cofactors.GetMaxAtomIdx() self.assertEqual(npa, 6044) self.assertEqual(nla, 0) self.assertEqual(nlpa, 0) self.assertEqual(nca, 0) self.assertEqual(nma, 0) # The Bace system has 19 water molecules self.assertEqual(nwa, solvent.NumAtoms() + 19 * 3) # The Bace system has the TLA excipient with 14 atoms self.assertEqual(noa, salt.NumAtoms() + counter_ions.NumAtoms() + 14)
def test_splitter(self): # Complex file name flask_name = "tests/data/thrombin_flask.oeb" # Read OEMol molecule flask = oechem.OEMol() with oechem.oemolistream(flask_name) as ifs: oechem.OEReadMolecule(ifs, flask) prot, lig, wat, cofactors, lipids, metals, excipients = utils.split( flask, ligand_res_name='LIG') self.assertEqual(prot.NumAtoms(), 4686) self.assertEqual(lig.NumAtoms(), 52) self.assertEqual(wat.NumAtoms(), 33783) self.assertEqual(cofactors.NumAtoms(), 0) self.assertEqual(lipids.NumAtoms(), 0) self.assertEqual(metals.NumAtoms(), 0) self.assertEqual(excipients.NumAtoms(), 25)
def process(self, record, port): try: mdrecord = MDDataRecord(record) protein = mdrecord.get_protein protein, ligand, water, exc = oeutils.split(protein, ligand_res_name='LIG') if protein.NumAtoms() == 0: raise ValueError("The Protein Atom number is zero") ligand = mdrecord.get_ligand if self.opt['explicit_water']: if self.opt['water_number'] != 0: self.opt['Logger'].info( "User selected number of waters: {}".format( self.opt['water_number'])) nmax = self.opt['water_number'] else: nmax = nmax_waters(protein, ligand, self.opt['cutoff']) else: self.opt['Logger'].info("MMPBSA Explicit Water set off") nmax = 0 self.nwaters.append(nmax) self.records.append(record) except Exception as e: print("Failed to complete", str(e), flush=True) self.opt['Logger'].info('Exception {} {}'.format( str(e), self.title)) self.log.error(traceback.format_exc()) self.failure.emit(record) return
def test_solvation_packmol_components_None(self): # Complex file name fcomplex = "tests/data/Bace_protein.pdb" # Read OEMol molecule mol = oechem.OEMol() with oechem.oemolistream(fcomplex) as ifs: oechem.OEReadMolecule(ifs, mol) # Solvate the system solv_complex, solvent, salt, counter_ions = packmol.oesolvate( mol, density=1.0, padding_distance=10.0, distance_between_atoms=2.0, solvents='tip3p', molar_fractions='1.0', geometry='box', close_solvent=True, salt='[Na+], [Cl-]', salt_concentration=0.0, neutralize_solute=False, return_components=True) prot, lig, wat, cofactors, lipids, metals, excipients = utils.split( solv_complex) npa = prot.GetMaxAtomIdx() nla = lig.GetMaxAtomIdx() self.assertEqual(npa, 6044) self.assertEqual(nla, 0) assert salt is None assert counter_ions is None
def process(self, mol, port): try: # Split the complex in components in order to apply the FF protein, ligand, water, excipients = oeommutils.split( mol, ligand_res_name=self.opt['ligand_res_name']) self.log.info( "\nComplex name: {}\nProtein atom numbers = {}\nLigand atom numbers = {}\n" "Water atom numbers = {}\nExcipients atom numbers = {}".format( mol.GetTitle(), protein.NumAtoms(), ligand.NumAtoms(), water.NumAtoms(), excipients.NumAtoms())) # Unique prefix name used to output parametrization files self.opt['prefix_name'] = mol.GetTitle() oe_mol_list = [] par_mol_list = [] # Apply FF to the Protein if protein.NumAtoms(): oe_mol_list.append(protein) protein_structure = utils.applyffProtein(protein, self.opt) par_mol_list.append(protein_structure) # Apply FF to the ligand if ligand.NumAtoms(): oe_mol_list.append(ligand) ligand_structure = utils.applyffLigand(ligand, self.opt) par_mol_list.append(ligand_structure) # Apply FF to water molecules if water.NumAtoms(): oe_mol_list.append(water) water_structure = utils.applyffWater(water, self.opt) par_mol_list.append(water_structure) # Apply FF to the excipients if excipients.NumAtoms(): excipient_structure = utils.applyffExcipients( excipients, self.opt) par_mol_list.append(excipient_structure) # The excipient order is set equal to the order in related # parmed structure to avoid possible atom index mismatching excipients = oeommutils.openmmTop_to_oemol( excipient_structure.topology, excipient_structure.positions, verbose=False) oechem.OEPerceiveBondOrders(excipients) oe_mol_list.append(excipients) # Build the overall Parmed structure complex_structure = parmed.Structure() for struc in par_mol_list: complex_structure = complex_structure + struc complx = oe_mol_list[0].CreateCopy() num_atom_system = complx.NumAtoms() for idx in range(1, len(oe_mol_list)): oechem.OEAddMols(complx, oe_mol_list[idx]) num_atom_system += oe_mol_list[idx].NumAtoms() if not num_atom_system == complex_structure.topology.getNumAtoms(): oechem.OEThrow.Fatal( "Parmed and OE topologies mismatch atom number error") complx.SetTitle(mol.GetTitle()) # Set Parmed structure box_vectors is_periodic = True try: vec_data = pack_utils.PackageOEMol.getData(complx, tag='box_vectors') vec = pack_utils.PackageOEMol.decodePyObj(vec_data) complex_structure.box_vectors = vec except: is_periodic = False self.log.warn( "System has been parametrize without periodic box vectors for vacuum simulation" ) # Attach the Parmed structure to the complex packed_complex = pack_utils.PackageOEMol.pack( complx, complex_structure) # Attach the reference positions to the complex ref_positions = complex_structure.positions packedpos = pack_utils.PackageOEMol.encodePyObj(ref_positions) packed_complex.SetData(oechem.OEGetTag('OEMDDataRefPositions'), packedpos) # Set atom serial numbers, Ligand name and HETATM flag # oechem.OEPerceiveResidues(packed_complex, oechem.OEPreserveResInfo_SerialNumber) for at in packed_complex.GetAtoms(): thisRes = oechem.OEAtomGetResidue(at) thisRes.SetSerialNumber(at.GetIdx()) if thisRes.GetName() == 'UNL': # thisRes.SetName("LIG") thisRes.SetHetAtom(True) oechem.OEAtomSetResidue(at, thisRes) if packed_complex.GetMaxAtomIdx( ) != complex_structure.topology.getNumAtoms(): raise ValueError( "OEMol complex and Parmed structure mismatch atom numbers") # Check if it is possible to create the OpenMM System if is_periodic: complex_structure.createSystem( nonbondedMethod=app.CutoffPeriodic, nonbondedCutoff=10.0 * unit.angstroms, constraints=app.HBonds, removeCMMotion=False) else: complex_structure.createSystem(nonbondedMethod=app.NoCutoff, constraints=app.HBonds, removeCMMotion=False) self.success.emit(packed_complex) except Exception as e: # Attach error message to the molecule that failed self.log.error(traceback.format_exc()) mol.SetData('error', str(e)) # Return failed mol self.failure.emit(mol) return
def process(self, mol, port): try: if port == 'system_port': # Remove from solution water and ions if self.opt['remove_explicit_solvent']: mol = oeommutils.strip_water_ions(mol) self.system = mol self.check_system = True return if self.check_system: num_conf = 0 try: lig_id = mol.GetData("IDTag") name = 'p' + self.system.GetTitle() + '_' + lig_id except: name = 'p' + self.system.GetTitle() + '_l' + mol.GetTitle( )[0:12] + '_' + str(self.count) for conf in mol.GetConfs(): conf_mol = oechem.OEMol(conf) complx = self.system.CreateCopy() oechem.OEAddMols(complx, conf_mol) # Split the complex in components protein, ligand, water, excipients = oeommutils.split( complx) # If the protein does not contain any atom emit a failure if not protein.NumAtoms( ): # Error: protein molecule is empty oechem.OEThrow.Fatal( "The protein molecule does not contains atoms") # If the ligand does not contain any atom emit a failure if not ligand.NumAtoms( ): # Error: ligand molecule is empty oechem.OEThrow.Fatal( "The Ligand molecule does not contains atoms") # Check if the ligand is inside the binding site. Cutoff distance 3A if not oeommutils.check_shell(ligand, protein, 3): oechem.OEThrow.Fatal( "The ligand is probably outside the protein binding site" ) # Removing possible clashes between the ligand and water or excipients if water.NumAtoms(): water_del = oeommutils.delete_shell(ligand, water, 1.5, in_out='in') if excipients.NumAtoms(): excipient_del = oeommutils.delete_shell(ligand, excipients, 1.5, in_out='in') # Reassemble the complex new_complex = protein.CreateCopy() oechem.OEAddMols(new_complex, ligand) if excipients.NumAtoms(): oechem.OEAddMols(new_complex, excipient_del) if water.NumAtoms(): oechem.OEAddMols(new_complex, water_del) name_c = name if mol.GetMaxConfIdx() > 1: name_c = name + '_c' + str(num_conf) new_complex.SetData(oechem.OEGetTag('IDTag'), name_c) new_complex.SetTitle(name_c) num_conf += 1 self.success.emit(new_complex) self.count += 1 except Exception as e: # Attach error message to the molecule that failed self.log.error(traceback.format_exc()) mol.SetData('error', str(e)) # Return failed mol self.failure.emit(mol) return
def test_compex_prep_split_floe(self): workfloe = WorkFloeWrapper.get_workfloe(os.path.join( FLOES_DEV_DIR, "Complex_prep.py"), run_timeout=43200, queue_timeout=2000) ligand_file = DatasetWrapper.get_dataset( os.path.join(FILE_DIR, "MCL1_lig26.oeb")) protein_file = DatasetWrapper.get_dataset( os.path.join(FILE_DIR, "MCL1_protein_ACE_NMA_caps.pdb")) output_file = OutputDatasetWrapper(extension=".oedb") fail_output_file = OutputDatasetWrapper(extension=".oedb") workfloe.start({ "promoted": { "ligands": ligand_file.identifier, "protein": protein_file.identifier, "out": output_file.identifier, "fail": fail_output_file.identifier } }) self.assertWorkFloeComplete(workfloe) fail_ifs = oechem.oeifstream() records_fail = [] for rec_fail in read_records(fail_ifs): records_fail.append(rec_fail) fail_ifs.close() count = len(records_fail) # The fail record must be empty self.assertEqual(count, 0) ifs = oeifstream(output_file.path) records = [] for rec in read_records(ifs): records.append(rec) ifs.close() count = len(records) # Check the out record list self.assertEqual(count, 1) # Each record should have the MD record interface for record in records: mdrecord = MDDataRecord(record) self.assertTrue(record.has_value(Fields.flaskid)) self.assertTrue(record.has_value(Fields.title)) self.assertTrue(record.has_value(Fields.ligand)) self.assertTrue(record.has_value(Fields.protein)) self.assertTrue(record.has_value(Fields.primary_molecule)) self.assertTrue(record.has_value(Fields.flask)) self.assertTrue(record.has_value(Fields.md_stages)) self.assertTrue(record.has_value(Fields.pmd_structure)) self.assertEqual(mdrecord.get_flask_id, 0) self.assertEqual(mdrecord.get_title, "pMCL1_l26") self.assertEqual(record.get_value(Fields.ligand).NumAtoms(), 43) self.assertEqual(record.get_value(Fields.protein).NumAtoms(), 2432) complx = mdrecord.get_flask protein_split, ligand_split, water, excipients = oeommutils.split( complx) self.assertEqual(protein_split.NumAtoms(), 2432) self.assertEqual(ligand_split.NumAtoms(), 43) self.assertEqual(water.NumAtoms(), 20022) self.assertEqual(excipients.NumAtoms(), 17) stages = mdrecord.get_stages self.assertEqual(len(stages), 1) stage = stages[0] self.assertTrue(stage.has_value(Fields.stage_name)) self.assertTrue(stage.has_value(Fields.mddata)) self.assertEqual(stage.get_value(Fields.stage_type), "SETUP") top_mol = mdrecord.get_stage_topology() self.assertEqual(top_mol.NumAtoms(), complx.NumAtoms())
def process(self, solvated_system, port): try: opt = dict(self.opt) # Extract the solvated ligand and the solvated complex solvated_ligand = solvated_system[0] solvated_complex = solvated_system[1] # Update cube simulation parameters with the eventually molecule SD tags new_args = {dp.GetTag(): dp.GetValue() for dp in oechem.OEGetSDDataPairs(solvated_ligand) if dp.GetTag() in ["temperature", "pressure"]} if new_args: for k in new_args: try: new_args[k] = float(new_args[k]) except: pass self.log.info("Updating parameters for molecule: {}\n{}".format(solvated_ligand.GetTitle(), new_args)) opt.update(new_args) # Extract the MD data mdData_ligand = data_utils.MDData(solvated_ligand) solvated_ligand_structure = mdData_ligand.structure mdData_complex = data_utils.MDData(solvated_complex) solvated_complex_structure = mdData_complex.structure # Create the solvated OpenMM systems solvated_complex_omm_sys = solvated_complex_structure.createSystem(nonbondedMethod=app.PME, nonbondedCutoff=opt['nonbondedCutoff'] * unit.angstroms, constraints=app.HBonds, removeCMMotion=False) solvated_ligand_omm_sys = solvated_ligand_structure.createSystem(nonbondedMethod=app.PME, nonbondedCutoff=opt['nonbondedCutoff'] * unit.angstroms, constraints=app.HBonds, removeCMMotion=False) # Write out all the required files and set-run the Yank experiment with TemporaryDirectory() as output_directory: opt['Logger'].info("Output Directory {}".format(output_directory)) solvated_complex_structure_fn = os.path.join(output_directory, "complex.pdb") solvated_complex_structure.save(solvated_complex_structure_fn, overwrite=True) solvated_ligand_structure_fn = os.path.join(output_directory, "solvent.pdb") solvated_ligand_structure.save(solvated_ligand_structure_fn, overwrite=True) solvated_complex_omm_serialized = XmlSerializer.serialize(solvated_complex_omm_sys) solvated_complex_omm_serialized_fn = os.path.join(output_directory, "complex.xml") solvated_complex_f = open(solvated_complex_omm_serialized_fn, 'w') solvated_complex_f.write(solvated_complex_omm_serialized) solvated_complex_f.close() solvated_ligand_omm_serialized = XmlSerializer.serialize(solvated_ligand_omm_sys) solvated_ligand_omm_serialized_fn = os.path.join(output_directory, "solvent.xml") solvated_ligand_f = open(solvated_ligand_omm_serialized_fn, 'w') solvated_ligand_f.write(solvated_ligand_omm_serialized) solvated_ligand_f.close() # Build the Yank Experiment yaml_builder = ExperimentBuilder(yank_binding_template.format( verbose='yes' if opt['verbose'] else 'no', minimize='yes' if opt['minimize'] else 'no', output_directory=output_directory, timestep=opt['timestep'], nsteps_per_iteration=opt['nsteps_per_iteration'], number_iterations=opt['iterations'], temperature=opt['temperature'], pressure=opt['pressure'], complex_pdb_fn=solvated_complex_structure_fn, complex_xml_fn=solvated_complex_omm_serialized_fn, solvent_pdb_fn=solvated_ligand_structure_fn, solvent_xml_fn=solvated_ligand_omm_serialized_fn, restraints=opt['restraints'], ligand_resname=opt['ligand_resname'])) # Run Yank yaml_builder.run_experiments() exp_dir = os.path.join(output_directory, "experiments") DeltaG_binding, dDeltaG_binding, DeltaH, dDeltaH = yankutils.analyze_directory(exp_dir) protein, ligand, water, excipients = oeommutils.split(solvated_ligand, ligand_res_name=opt['ligand_resname']) # Add result to the extracted ligand in kcal/mol oechem.OESetSDData(ligand, 'DG_yank_binding', str(DeltaG_binding)) oechem.OESetSDData(ligand, 'dG_yank_binding', str(dDeltaG_binding)) self.success.emit(ligand) except Exception as e: # Attach an error message to the molecule that failed self.log.error(traceback.format_exc()) solvated_system[1].SetData('error', str(e)) # Return failed mol self.failure.emit(solvated_system[1]) return
def process(self, solvated_system, port): try: # The copy of the dictionary option as local variable # is necessary to avoid filename collisions due to # the parallel cube processes opt = dict(self.opt) # Split the complex in components protein, solute, water, excipients = oeommutils.split(solvated_system, ligand_res_name='LIG') # Update cube simulation parameters with the eventually molecule SD tags new_args = {dp.GetTag(): dp.GetValue() for dp in oechem.OEGetSDDataPairs(solute) if dp.GetTag() in ["temperature", "pressure"]} if new_args: for k in new_args: try: new_args[k] = float(new_args[k]) except: pass self.log.info("Updating parameters for molecule: {}\n{}".format(solute.GetTitle(), new_args)) opt.update(new_args) # Extract the MD data mdData = data_utils.MDData(solvated_system) solvated_structure = mdData.structure # Extract the ligand parmed structure solute_structure = solvated_structure.split()[0][0] solute_structure.box = None # Set the ligand title solute.SetTitle(solvated_system.GetTitle()) # Create the solvated and vacuum system solvated_omm_sys = solvated_structure.createSystem(nonbondedMethod=app.PME, nonbondedCutoff=opt['nonbondedCutoff'] * unit.angstroms, constraints=app.HBonds, removeCMMotion=False) solute_omm_sys = solute_structure.createSystem(nonbondedMethod=app.NoCutoff, constraints=app.HBonds, removeCMMotion=False) # This is a note from: # https://github.com/MobleyLab/SMIRNOFF_paper_code/blob/e5012c8fdc4570ca0ec750f7ab81dd7102e813b9/scripts/create_input_files.py#L114 # Fix switching function. for force in solvated_omm_sys.getForces(): if isinstance(force, openmm.NonbondedForce): force.setUseSwitchingFunction(True) force.setSwitchingDistance((opt['nonbondedCutoff'] - 1.0) * unit.angstrom) # Write out all the required files and set-run the Yank experiment with TemporaryDirectory() as output_directory: opt['Logger'].info("Output Directory {}".format(output_directory)) solvated_structure_fn = os.path.join(output_directory, "solvated.pdb") solvated_structure.save(solvated_structure_fn, overwrite=True) solute_structure_fn = os.path.join(output_directory, "solute.pdb") solute_structure.save(solute_structure_fn, overwrite=True) solvated_omm_sys_serialized = XmlSerializer.serialize(solvated_omm_sys) solvated_omm_sys_serialized_fn = os.path.join(output_directory, "solvated.xml") solvated_f = open(solvated_omm_sys_serialized_fn, 'w') solvated_f.write(solvated_omm_sys_serialized) solvated_f.close() solute_omm_sys_serialized = XmlSerializer.serialize(solute_omm_sys) solute_omm_sys_serialized_fn = os.path.join(output_directory, "solute.xml") solute_f = open(solute_omm_sys_serialized_fn, 'w') solute_f.write(solute_omm_sys_serialized) solute_f.close() # Build the Yank Experiment yaml_builder = ExperimentBuilder(yank_solvation_template.format( verbose='yes' if opt['verbose'] else 'no', minimize='yes' if opt['minimize'] else 'no', output_directory=output_directory, timestep=opt['timestep'], nsteps_per_iteration=opt['nsteps_per_iteration'], number_iterations=opt['iterations'], temperature=opt['temperature'], pressure=opt['pressure'], solvated_pdb_fn=solvated_structure_fn, solvated_xml_fn=solvated_omm_sys_serialized_fn, solute_pdb_fn=solute_structure_fn, solute_xml_fn=solute_omm_sys_serialized_fn)) # Run Yank yaml_builder.run_experiments() exp_dir = os.path.join(output_directory, "experiments") # Calculate solvation free energy, solvation Enthalpy and their errors DeltaG_solvation, dDeltaG_solvation, DeltaH, dDeltaH = yankutils.analyze_directory(exp_dir) # # Add result to the original molecule in kcal/mol oechem.OESetSDData(solute, 'DG_yank_solv', str(DeltaG_solvation)) oechem.OESetSDData(solute, 'dG_yank_solv', str(dDeltaG_solvation)) # Emit the ligand self.success.emit(solute) except Exception as e: # Attach an error message to the molecule that failed self.log.error(traceback.format_exc()) solvated_system.SetData('error', str(e)) # Return failed mol self.failure.emit(solvated_system) return