def to_force_field(self): """Returns the SMIRNOFF force field created from this source. Returns ------- openforcefield.typing.engines.smirnoff.ForceField The created force field. """ from openforcefield.typing.engines import smirnoff return smirnoff.ForceField(self._inner_xml)
def __init__(self, source_tree, name, filename=None, ff_kwargs=None, verbose=False): super().__init__(source_tree, name, verbose=verbose) # This tree operates on entries self._select = "Entry" self._exception_on_unassigned = True self._transformer = offsb.api.tk.ValenceDict if ff_kwargs is None: ff_kwargs = {} if filename is not None: logger = logging.getLogger("openforcefield") level = logger.getEffectiveLevel() logger.setLevel(level=logging.ERROR) ext = ".offxml" if not filename.endswith(ext): filename += ext self.filename = filename found = False for entry_point in ["."] + list( iter_entry_points( group="openforcefield.smirnoff_forcefield_directory")): if type(entry_point) == str: pth = entry_point else: pth = entry_point.load()()[0] abspth = os.path.join(pth, filename) if verbose: self.logger.info("Searching {}".format(abspth)) if os.path.exists(abspth): self.abs_path = abspth if verbose: self.logger.info("Found {}".format(abspth)) found = True break if not found: raise Exception("Forcefield could not be found") if verbose: self.logger.info("loading {}".format(self.abs_path)) self.forcefield = OFF.ForceField(self.abs_path, disable_version_check=True, **ff_kwargs) logger.setLevel(level=level)
def test_force_field_serialization(): from openforcefield.typing.engines import smirnoff force_field = smirnoff.ForceField(get_data_filename('forcefield/smirnoff99Frosst.offxml')) serialized_force_field = serialize_force_field(force_field) deserialized_force_field = deserialize_force_field(serialized_force_field) original_generators = force_field.getGenerators() deserialized_generators = deserialized_force_field.getGenerators() assert len(original_generators) == len(deserialized_generators)
def _get_off_forcefield(self, hashstring, offxml): from openforcefield.typing.engines import smirnoff key = hashlib.sha256(hashstring.encode()).hexdigest() # get forcefield from cache, build new one if not present off_forcefield = self._get_cache(key) if key in self._CACHE else smirnoff.ForceField(offxml) # cache forcefield, no matter what # handles updating time touched, dropping items if cache too large self._cache_it(key, off_forcefield) return off_forcefield
def compute_estimate_async(): """Submit calculations to a running server instance""" from openforcefield.typing.engines import smirnoff setup_timestamp_logging() # Load in the data set of interest. data_set = ThermoMLDataSet.from_file(get_data_filename('properties/single_dielectric.xml')) # Load in the force field to use. force_field = smirnoff.ForceField(get_data_filename('forcefield/smirnoff99Frosst.offxml')) # new_property_0 = copy.deepcopy(data_set.properties['COCCO{1.0}'][0]) # new_property_0.thermodynamic_state.temperature -= 2.0 * unit.kelvin # new_property_0.id = str(uuid4()) # # data_set.properties['COCCO{1.0}'].append(new_property_0) # # new_property_1 = copy.deepcopy(data_set.properties['COCCO{1.0}'][0]) # new_property_1.thermodynamic_state.temperature += 2.0 * unit.kelvin # new_property_1.id = str(uuid4()) # # data_set.properties['COCCO{1.0}'].append(new_property_1) # Modify the submission options submission_options = PropertyEstimatorOptions() workflow_options = PropertyWorkflowOptions(PropertyWorkflowOptions.ConvergenceMode.RelativeUncertainty, relative_uncertainty_fraction=100000) submission_options.workflow_options = { 'Density': workflow_options, 'Dielectric': workflow_options, 'EnthalpyOfMixing': workflow_options } # submission_options.allowed_calculation_layers = ['SimulationLayer'] submission_options.allowed_calculation_layers = ['ReweightingLayer'] # Create the client object. property_estimator = client.PropertyEstimatorClient() # Submit the request to a running server. request = property_estimator.request_estimate(data_set, force_field, submission_options) logging.info('Request info: {}'.format(str(request))) # Wait for the results. result = request.results(synchronous=True) logging.info('The server has returned a response: {}'.format(result.json()))
def compute_estimate_sync(): """Submit calculations to a running server instance""" from openforcefield.typing.engines import smirnoff setup_timestamp_logging() # Load in the data set of interest. data_set = ThermoMLDataSet.from_file(get_data_filename('properties/single_density.xml')) # Load in the force field to use. force_field = smirnoff.ForceField(get_data_filename('forcefield/smirnoff99Frosst.offxml')) # Create the client object. property_estimator = client.PropertyEstimatorClient() # Submit the request to a running server, and wait for the results. result = property_estimator.request_estimate(data_set, force_field) logging.info('The server has returned a response: {}'.format(result))
def test_local_force_field_storage(): """A simple test to that force fields can be stored and retrieved using the local storage backend.""" from openforcefield.typing.engines import smirnoff force_field = smirnoff.ForceField( get_data_filename('forcefield/smirnoff99Frosst.offxml')) with tempfile.TemporaryDirectory() as temporary_directory: local_storage = LocalFileStorage(temporary_directory) local_storage.store_force_field('tmp_id', force_field) retrieved_force_field = local_storage.retrieve_force_field('tmp_id') serialized_force_field = serialize_force_field(force_field) serialized_retrieved_force_field = serialize_force_field( retrieved_force_field) assert json.dumps(serialized_force_field) == json.dumps( serialized_retrieved_force_field) local_storage_new = LocalFileStorage(temporary_directory) assert local_storage_new.has_force_field(force_field)
def test_estimate_request(): """Test sending an estimator request to a server.""" from openforcefield.typing.engines import smirnoff with tempfile.TemporaryDirectory() as temporary_directory: storage_directory = path.join(temporary_directory, 'storage') working_directory = path.join(temporary_directory, 'working') dummy_property = create_dummy_property(Density) dummy_data_set = PhysicalPropertyDataSet() dummy_data_set.properties[dummy_property.substance.identifier] = [ dummy_property ] force_field = smirnoff.ForceField( get_data_filename('forcefield/smirnoff99Frosst.offxml')) calculation_backend = DaskLocalClusterBackend(1, ComputeResources()) storage_backend = LocalFileStorage(storage_directory) PropertyEstimatorServer(calculation_backend, storage_backend, working_directory=working_directory) property_estimator = PropertyEstimatorClient() options = PropertyEstimatorOptions( allowed_calculation_layers=[TestCalculationLayer]) request = property_estimator.request_estimate(dummy_data_set, force_field, options) result = request.results(synchronous=True, polling_interval=0) assert not isinstance(result, PropertyEstimatorException)
def find_smirks_parameters(smiles_list, molecule_paths): """Finds the force field parameters which would be assigned to a list of molecules defined by the provided SMILES patterns. Parameters ---------- smiles_list: list of str The SMILES patterns of the target molecules molecule_paths: list of Path The list of molecules that correspond to the SMILES strings (to make it easier to see which molecules utilize which parameters) Returns ------- dict of str and list of str A dictionary with keys of SMIRKS patterns, and values of lists of SMILES patterns which would utilize those patterns, and the parameter ID in the force field. """ force_field = smirnoff.ForceField('smirnoff99Frosst-1.0.9.offxml') smiles_by_smirks = {} smiles_by_smirks["Bonds"] = {} smiles_by_smirks["Angles"] = {} smiles_by_smirks["ProperTorsions"] = {} smiles_by_smirks["vdW"] = {} smiles_by_smirks["ImproperTorsions"] = {} smiles_by_smirks["Electrostatics"] = {} # Populate the dictionary using the open force field toolkit. for index, smiles in enumerate(smiles_list): ifs = oechem.oemolistream() if not ifs.open(str(molecule_paths[index])): logging.error( f'Unable to open {molecule_paths[index]} for reading...') ifs.open(str(molecule_paths[index])) oe_mols = [] for mol in ifs.GetOEMols(): oe_mols.append(oechem.OEMol(mol)) oechem.OE3DToAtomStereo(oe_mols[0]) molecule = Molecule.from_openeye(oe_mols[0]) # molecule = Molecule.from_smiles(smiles, allow_undefined_stereo=True) topology = Topology.from_molecules([molecule]) molecule_force_list = force_field.label_molecules(topology) for molecule_index, molecule_forces in enumerate(molecule_force_list): print(f'Forces for molecule {molecule_index}') for force_name, force_dict in molecule_forces.items(): print(f"\n{force_name}:") for (atom_indices, parameter) in force_dict.items(): atomstr = '' for idx in atom_indices: atomstr += '%5s' % idx print("atoms: %s parameter_id: %s smirks %s" % ([ oe_mols[0].GetAtom(oechem.OEHasAtomIdx(i)).GetName() for i in atom_indices ], parameter.id, parameter.smirks)) # This is not catching _all_ the atoms that hit a certain parameter. # I think these need to be initialized in the outer loop. # Each parameter is getting a list of length 1. if parameter.id not in smiles_by_smirks[force_name]: smiles_by_smirks[force_name][parameter.id] = {} if "atom_indices" not in smiles_by_smirks[force_name]: smiles_by_smirks[force_name][ parameter.id]["atom_indices"] = [] if "atom_names" not in smiles_by_smirks[force_name]: smiles_by_smirks[force_name][ parameter.id]["atom_names"] = [] smiles_by_smirks[force_name][ parameter.id]["atom_indices"].append(atom_indices) smiles_by_smirks[force_name][ parameter.id]["atom_names"].append([ oe_mols[0].GetAtom( oechem.OEHasAtomIdx(i)).GetName() for i in atom_indices ]) smiles_by_smirks[force_name][ parameter.id]["smirks"] = parameter.smirks return smiles_by_smirks
def create_xml_system_files(molecule_mol2_filepath, tip3p_mol2_filepath, vacuum_pdb_filepath, solvated_pdb_filepath, vacuum_xml_filepath, solvated_xml_filepath): """Create vacuum and solvated OpenMM systems and save in XML format. Parameters ---------- molecule_mol2_filepath : str Path to the mol2 file describing the molecule. tip3p_mol2_filepath : str Path to the mol2 file describing the water molecule with TIP3P charges. vacuum_pdb_filepath : str Path to the PDB file for the molecule in vacuum. solvated_pdb_filepath : str Path to the PDB file for the solvated molecule. vacuum_xml_filepath : str Output path of the vacuum system. solvated_xml_filepath : str Output path of the solvated system. """ # Load TIP3P water into OpenEye molecule. water_oe_mol = load_oe_graph_mol(tip3p_mol2_filepath) # Load solvated molecule into OpeneEye molecule. molecule_oe_mol = load_oe_graph_mol(molecule_mol2_filepath) # Load forcefield. # TODO add HBonds constraint through createSystem when openforcefield#32 is implemented. ff = smirnoff.ForceField('forcefield/smirnoff99Frosst.ffxml', 'hbonds.ffxml', 'forcefield/tip3p.ffxml') # Load vacuum and solvated PDBFiles. pdb_file_vacuum = openmm.app.PDBFile(vacuum_pdb_filepath) pdb_file_solvated = openmm.app.PDBFile(solvated_pdb_filepath) # Create vacuum and solvated system. system_vacuum = ff.createSystem(pdb_file_vacuum.topology, molecules=[molecule_oe_mol], nonbondedMethod=smirnoff.NoCutoff) # TODO add HBonds constraints here when openforcefield#32 is implemented. system_solvated = ff.createSystem( pdb_file_solvated.topology, molecules=[molecule_oe_mol, water_oe_mol], nonbondedMethod=smirnoff.PME, nonbondedCutoff=1.1 * unit.nanometer, ewaldErrorTolerance=1e-4) #, constraints=smirnoff.HBonds) # Fix switching function. # TODO remove this when openforcefield#31 is fixed for force in system_solvated.getForces(): if isinstance(force, openmm.NonbondedForce): force.setUseSwitchingFunction(True) force.setSwitchingDistance(1.0 * unit.nanometer) # Save XML files. for system, xml_filepath in zip( [system_vacuum, system_solvated], [vacuum_xml_filepath, solvated_xml_filepath]): system_serialized = openmm.XmlSerializer.serialize(system) with open(xml_filepath, 'w') as f: f.write(system_serialized)
def _initialize(self): """Initializes the target. """ # Load in the ESP data store. esp_store = MoleculeESPStore( os.path.join(self.tgtdir, self.recharge_esp_store)) # Define the molecules to include in the training set. smiles = [smiles_pattern for smiles_pattern in esp_store.list()] # Determine which BCC parameters are being optimized. force_field = smirnoff.ForceField(os.path.join(self.FF.ffdir, self.FF.offxml), allow_cosmetic_attributes=True) bcc_handler = force_field.get_parameter_handler("ChargeIncrementModel") if bcc_handler.partial_charge_method.lower() != "am1elf10": raise NotImplementedError() # TODO: it is assumed that the MDL aromaticity model should be used # rather than the once specified in the FF as the model is not # currently exposed. See OpenFF toolkit issue #663. bcc_collection = from_smirnoff(bcc_handler) bcc_smirks = [bcc.smirks for bcc in bcc_collection.parameters] # Determine the indices of the BCC parameters being refit. bcc_to_parameter_index = {} for parameter_index, field_list in enumerate(self.FF.pfields): split_key = field_list[0].split("/") parameter_tag = split_key[0].strip() parameter_smirks = split_key[3].strip() if (parameter_tag != "ChargeIncrementModel" or field_list[3] != "charge_increment1"): continue bcc_index = bcc_smirks.index(parameter_smirks) bcc_to_parameter_index[bcc_index] = parameter_index fixed_parameters = [ i for i in range(len(bcc_smirks)) if i not in bcc_to_parameter_index ] self._parameter_to_bcc_map = np.array([ bcc_to_parameter_index[i] for i in range(len(bcc_collection.parameters)) if i not in fixed_parameters ]) charge_settings = ChargeSettings(theory="am1", symmetrize=True, optimize=True) # Pre-calculate the expensive operations which are needed to evaluate the # objective function, but do not depend on the current parameters. objective_terms = ESPOptimization.compute_objective_terms( smiles, esp_store, bcc_collection, fixed_parameters, charge_settings) self._design_matrix = np.vstack([ objective_term.design_matrix for objective_term in objective_terms ]) self._target_residuals = np.vstack([ objective_term.target_residuals for objective_term in objective_terms ]) # Track which residuals map to which molecule. residual_counter = 0 for smiles_pattern in smiles: esp_records = esp_store.retrieve(smiles_pattern) n_residuals = sum( len(esp_record.grid_coordinates) for esp_record in esp_records) self._molecule_residual_ranges[smiles_pattern] = np.array( [i + residual_counter for i in range(n_residuals)]) residual_counter += len( self._molecule_residual_ranges[smiles_pattern])
""" # # Load and parameterize the small molecule # # Load the small molecule from openforcefield.utils import get_data_file_path ligand_filename = get_data_file_path('molecules/toluene.mol2') molecule = Molecule.from_file(ligand_filename) # Load the smirnoff99Frosst force field from openforcefield.typing.engines import smirnoff forcefield = smirnoff.ForceField('test_forcefields/smirnoff99Frosst.offxml') # Create a ParmEd structure for the molecule molecule_structure = forcefield.create_parmed_structure( topology=molecule.to_topology(), positions=molecule.positions) print('Molecule:', molecule_structure) # # Load and parameterize the protein # # Load the protein topology protein_pdb_filename = get_data_file_path('proteins/T4-protein.pdb') protein_pdbfile = app.PDBFile(protein_pdb_filename) # Load the AMBER protein force field, along with a solvent force field
""" # # Load and parameterize the small molecule # # Load the small molecule from openforcefield.utils import get_data_file_path ligand_filename = get_data_file_path('molecules/toluene.mol2') molecule = Molecule.from_file(ligand_filename) # Load the smirnoff99Frosst force field from openforcefield.typing.engines import smirnoff forcefield = smirnoff.ForceField('smirnoff99Frosst.offxml') # Create a ParmEd structure for the molecule molecule_structure = forcefield.create_parmed_structure( topology=molecule.to_topology(), positions=molecule.positions) print('Molecule:', molecule_structure) # # Load and parameterize the protein # # Load the protein topology protein_pdb_filename = get_data_file_path('proteins/T4-protein.pdb') protein_pdbfile = app.PDBFile(protein_pdb_filename) # Load the AMBER protein force field, along with a solvent force field
def submit_jobs(self, mvals, AGrad=True, AHess=True): """ Submit jobs for evaluating the objective function Parameters ---------- mvals: np.ndarray mvals array containing the math values of the parameters AGrad: bool Flag for computing gradients of not AHess: bool Flag for computing hessian or not Notes ----- 1. This function is called before wq_complete() and get(). 2. This function should not block. """ # Make the force field based on the current values of the parameters. self.FF.make(mvals) force_field = smirnoff.ForceField(self.FF.offxml, allow_cosmetic_attributes=True) # strip out cosmetic attributes with tempfile.NamedTemporaryFile(mode="w", suffix=".offxml") as file: force_field.to_file(file.name, discard_cosmetic_attributes=True) force_field = smirnoff.ForceField(file.name) # Determine which gradients (if any) we should be estimating. parameter_gradient_keys = [] self._gradient_key_mappings = {} self._parameter_units = {} if AGrad is True: index_counter = 0 for field_list in self.FF.pfields: string_key = field_list[0] key_split = string_key.split("/") parameter_tag = key_split[0].strip() parameter_smirks = key_split[3].strip() parameter_attribute = key_split[2].strip() # Use the full attribute name (e.g. k1) for the gradient key. parameter_gradient_key = ParameterGradientKey( tag=parameter_tag, smirks=parameter_smirks, attribute=parameter_attribute, ) # Find the unit of the gradient parameter. parameter_value, is_cosmetic = self._parameter_value_from_gradient_key( parameter_gradient_key) if parameter_value is None or is_cosmetic: # We don't wan't gradients w.r.t. cosmetic parameters. continue parameter_unit = parameter_value.units parameter_gradient_keys.append(parameter_gradient_key) self._gradient_key_mappings[ parameter_gradient_key] = index_counter self._parameter_units[parameter_gradient_key] = parameter_unit index_counter += 1 # Submit the estimation request. self._pending_estimate_request, _ = self._client.request_estimate( property_set=self._reference_data_set, force_field_source=force_field, options=self._options.estimation_options, parameter_gradient_keys=parameter_gradient_keys, ) logger.info("Requesting the estimation of {} properties, and their " "gradients with respect to {} parameters.\n".format( len(self._reference_data_set), len(parameter_gradient_keys))) if (self._pending_estimate_request.results( True, polling_interval=self._options.polling_interval)[0] is None): raise RuntimeError( "No `EvaluatorServer` could be found to submit the calculations to. " "Please double check that a server is running, and that the connection " "settings specified in the input script are correct.")
from openforcefield.typing.engines import smirnoff from simtk import unit force_field = smirnoff.ForceField('smirnoff99Frosst_experimental.offxml') # t9 # [#1:1]-[#6X4:2]-[#6X4:3]-[#8X2:4] # H1-C1-C2-O2 # GAFF v2.1 # k = 0.16 per = 3 # SMIRNOFF99Frosst # k = 0.25 per = 1 # k = 0.00 per = 3 # # < Proper # smirks = "[#1:1]-[#6X4:2]-[#6X4:3]-[#8X2:4]" # id = "t9" # idivf1 = "1" # k1 = "0.000" # periodicity1 = "3" # phase1 = "0.0" # phase2 = "0.0" # k2 = "0.250" # periodicity2 = "1" # idivf2 = "1" / > parameter = force_field.get_parameter_handler( 'ProperTorsions').parameters["[#1:1]-[#6X4:2]-[#6X4:3]-[#8X2:4]"] assert (parameter.k[0] == 0.0 * unit.kilocalorie_per_mole) assert (parameter.k[1] == 0.250 * unit.kilocalorie_per_mole)
def associate(self, source): super().associate(source) if self.forcefield is None: self.forcefield = OFF.ForceField(self.abs_path, disable_version_check=True)