Source code for openff.bespokefit.executor.services.coordinator.utils
import hashlib
from typing import Optional
import redis
from openff.toolkit.typing.engines.smirnoff import ForceField
from openff.toolkit.utils.exceptions import ParameterLookupError
from openff.bespokefit.schema.fitting import BespokeOptimizationSchema
from openff.bespokefit.schema.results import BespokeOptimizationResults
def _hash_fitting_schema(fitting_schema: BespokeOptimizationSchema) -> str:
"""
Create a hash based on the whole fitting schema for any optimised parameters.
"""
hash_string = (
fitting_schema.smirk_settings.json() + fitting_schema.initial_force_field_hash
)
for stage in fitting_schema.stages:
# drop the reference data form each target and the parameters from each stage
hash_string += stage.json(
exclude={"targets": {"__all__": {"reference_data"}}, "parameters": ...}
)
hash_string = hashlib.sha512(hash_string.encode()).hexdigest()
return hash_string
[docs]def get_cached_parameters(
fitting_schema: BespokeOptimizationSchema, redis_connection: redis.Redis
) -> Optional[ForceField]:
"""
For the given fitting schema create a hash and check for a cached force field which contains a set of fit torsion parameters.
"""
hash_string = _hash_fitting_schema(fitting_schema=fitting_schema)
cached_ff = redis_connection.get(hash_string)
if cached_ff is not None:
return ForceField(cached_ff, allow_cosmetic_attributes=True)
return None
[docs]def cache_parameters(
results_schema: BespokeOptimizationResults, redis_connection: redis.Redis
) -> str:
"""
Cache any fitted torsion parameters saved in the final refit force field.
Returns:
The string the parameters are cached under
"""
hash_string = _hash_fitting_schema(fitting_schema=results_schema.input_schema)
cached_ff = redis_connection.get(hash_string)
if cached_ff is not None:
cached_force_field = ForceField(cached_ff)
else:
# create a new blank FF
cached_force_field = ForceField()
torsion_handler_cache = cached_force_field.get_parameter_handler("ProperTorsions")
refit_force_field = ForceField(results_schema.refit_force_field)
refit_torsions = refit_force_field.get_parameter_handler("ProperTorsions")
for stage in results_schema.input_schema.stages:
for parameter in stage.parameters:
try:
# the parameter maybe be in more than one stage so only save once
_ = torsion_handler_cache[parameter.smirks]
except ParameterLookupError:
# we need to add the parameter to the cache
torsion_handler_cache.add_parameter(
parameter=refit_torsions[parameter.smirks]
)
# now set the force field back in the cache
redis_connection.set(
hash_string, cached_force_field.to_string(discard_cosmetic_attributes=False)
)
return hash_string