openforcefield / openff-evaluator

A physical property evaluation toolkit from the Open Forcefield Consortium.
https://docs.openforcefield.org/projects/evaluator
MIT License
54 stars 18 forks source link

Specifying water models for SFE calculations #566

Closed barmoral closed 1 month ago

barmoral commented 1 month ago

Describe the bug I am not being able to specify water model to use in previous versions of OpenFF packages.

To Reproduce from openff import toolkit, evaluator from openff.toolkit.typing.engines.smirnoff import forcefield, ForceField from openff.evaluator.forcefield import SmirnoffForceFieldSource force_field_path = ForceField("openff-2.0.0.offxml","tip3p.offxml") force_field_source = SmirnoffForceFieldSource.from_object(force_field_path)

Output { "name": "SMIRNOFFVersionError", "message": "SMIRNOFF offxml file was written with version 0.4, but this version of ForceField only supports version 0.3 to version 0.3", "stack": "--------------------------------------------------------------------------- TypeError Traceback (most recent call last) File ~/miniconda3/envs/old-evaluator-test3/lib/python3.9/site-packages/openff/toolkit/typing/engines/smirnoff/parameters.py:462, in ParameterAttribute._call_converter(self, value, instance) 460 try: 461 # Static function. --> 462 return self._converter(value) 463 except TypeError: 464 # Instance method.

TypeError: version() missing 2 required positional arguments: 'attr' and 'new_version'

During handling of the above exception, another exception occurred:

SMIRNOFFVersionError Traceback (most recent call last) Cell In[2], line 2 1 ### load FF ----> 2 force_field_path = ForceField(\"openff-2.0.0.offxml\",\"tip3p.offxml\") 3 force_field_source = SmirnoffForceFieldSource.from_object(force_field_path)

File ~/miniconda3/envs/old-evaluator-test3/lib/python3.9/site-packages/openff/toolkit/typing/engines/smirnoff/forcefield.py:320, in ForceField.init(self, aromaticity_model, parameter_handler_classes, parameter_io_handler_classes, disable_version_check, allow_cosmetic_attributes, load_plugins, *sources) 317 self._register_parameter_io_handler_classes(parameter_io_handler_classes) 319 # Parse all sources containing SMIRNOFF parameter definitions --> 320 self.parse_sources(sources, allow_cosmetic_attributes=allow_cosmetic_attributes)

File ~/miniconda3/envs/old-evaluator-test3/lib/python3.9/site-packages/openff/toolkit/typing/engines/smirnoff/forcefield.py:873, in ForceField.parse_sources(self, sources, allow_cosmetic_attributes) 871 for source in sources: 872 smirnoff_data = self.parse_smirnoff_from_source(source) --> 873 self._load_smirnoff_data( 874 smirnoff_data, allow_cosmetic_attributes=allow_cosmetic_attributes 875 )

File ~/miniconda3/envs/old-evaluator-test3/lib/python3.9/site-packages/openff/toolkit/typing/engines/smirnoff/forcefield.py:1027, in ForceField._load_smirnoff_data(self, smirnoff_data, allow_cosmetic_attributes) 1023 parameter_list_dict = {parameter_list_tagname: parameter_list_dict} 1025 # Retrieve or create parameter handler, passing in section_dict to check for 1026 # compatibility if a handler for this parameter name already exists -> 1027 handler = self.get_parameter_handler( 1028 parameter_name, 1029 section_dict, 1030 allow_cosmetic_attributes=allow_cosmetic_attributes, 1031 ) 1032 handler._add_parameters( 1033 parameter_list_dict, allow_cosmetic_attributes=allow_cosmetic_attributes 1034 )

File ~/miniconda3/envs/old-evaluator-test3/lib/python3.9/site-packages/openff/toolkit/typing/engines/smirnoff/forcefield.py:755, in ForceField.get_parameter_handler(self, tagname, handler_kwargs, allow_cosmetic_attributes) 752 # If no handler kwargs were provided, skip the compatibility check 753 if handler_kwargs != {}: 754 # Initialize a new instance of this parameter handler class with the given kwargs --> 755 new_handler = ph_class( 756 **handler_kwargs, 757 allow_cosmetic_attributes=allow_cosmetic_attributes, 758 skip_version_check=skip_version_check, 759 ) 760 old_handler.check_handler_compatibility(new_handler) 761 return_handler = old_handler

File ~/miniconda3/envs/old-evaluator-test3/lib/python3.9/site-packages/openff/toolkit/typing/engines/smirnoff/parameters.py:1925, in ParameterHandler.init(self, allow_cosmetic_attributes, skip_version_check, kwargs) 1922 self._parameters = ParameterList() 1924 # Initialize ParameterAttributes and cosmetic attributes. -> 1925 super().init(allow_cosmetic_attributes=allow_cosmetic_attributes, kwargs)

File ~/miniconda3/envs/old-evaluator-test3/lib/python3.9/site-packages/openff/toolkit/typing/engines/smirnoff/parameters.py:889, in _ParameterAttributeHandler.init(self, allow_cosmetic_attributes, **kwargs) 887 for key, val in smirnoff_data.items(): 888 if key in allowed_attributes: --> 889 setattr(self, key, val) 890 # Handle all unknown kwargs as cosmetic so we can write them back out 891 elif allow_cosmetic_attributes:

File ~/miniconda3/envs/old-evaluator-test3/lib/python3.9/site-packages/openff/toolkit/typing/engines/smirnoff/parameters.py:1202, in _ParameterAttributeHandler.setattr(self, key, value) 1197 raise MissingIndexedAttributeError( 1198 f\"'{key}' is out of bounds for indexed attribute '{attr_name}'\" 1199 ) 1201 # Forward the request to the next class in the MRO. -> 1202 super().setattr(key, value)

File ~/miniconda3/envs/old-evaluator-test3/lib/python3.9/site-packages/openff/toolkit/typing/engines/smirnoff/parameters.py:411, in ParameterAttribute.set(self, instance, value) 409 def set(self, instance, value): 410 # Convert and validate the value. --> 411 value = self._convert_and_validate(instance, value) 412 setattr(instance, self._name, value)

File ~/miniconda3/envs/old-evaluator-test3/lib/python3.9/site-packages/openff/toolkit/typing/engines/smirnoff/parameters.py:429, in ParameterAttribute._convert_and_validate(self, instance, value) 427 value = self._validate_units(value) 428 # Call the custom converter before setting the value. --> 429 value = self._call_converter(value, instance) 430 return value

File ~/miniconda3/envs/old-evaluator-test3/lib/python3.9/site-packages/openff/toolkit/typing/engines/smirnoff/parameters.py:465, in ParameterAttribute._call_converter(self, value, instance) 462 return self._converter(value) 463 except TypeError: 464 # Instance method. --> 465 return self._converter(instance, self, value) 466 return value

File ~/miniconda3/envs/old-evaluator-test3/lib/python3.9/site-packages/openff/toolkit/typing/engines/smirnoff/parameters.py:1886, in ParameterHandler.version(self, attr, new_version) 1878 # Use PEP-440 compliant version number comparison, if requested 1879 if ( 1880 packaging.version.parse(str(new_version)) 1881 > packaging.version.parse(str(self._MAX_SUPPORTED_SECTION_VERSION)) (...) 1884 < packaging.version.parse(str(self._MIN_SUPPORTED_SECTION_VERSION)) 1885 ): -> 1886 raise SMIRNOFFVersionError( 1887 f\"SMIRNOFF offxml file was written with version {new_version}, but this version \" 1888 f\"of ForceField only supports version {self._MIN_SUPPORTED_SECTION_VERSION} \" 1889 f\"to version {self._MAX_SUPPORTED_SECTION_VERSION}\" 1890 ) 1891 return new_version

SMIRNOFFVersionError: SMIRNOFF offxml file was written with version 0.4, but this version of ForceField only supports version 0.3 to version 0.3" }

Computing environment (please complete the following information):

Additional context I need to use previous versions of evaluator and other OpenFF packages for calculating solvation free energies, which requires the deprecated yank package.

mattwthompson commented 1 month ago

I have an idea what's going on here and it's pretty messy with different versions of software and sections of the force field.

However, If you just need vanilla TIP3P parameters, you actually don't need to load a separate file at all. Sage includes them. Try simply loading ForceField("openff-2.0.0.offxml") and let me know how that works

barmoral commented 1 month ago

Thank you for your response Matt. Your method works with TIP3P, but I am interested in testing 7 water models. I was able to solve this problem with @lilyminium 's help, who suggested using sed in a bash function as follows.

function convert_ff_to_v3 () {
    FF="forcefields/v3/$1"
    cp forcefields/$1 $FF
    sed -i 's/    <vdW version="0.4" potential="Lennard-Jones-12-6" combining_rules="Lorentz-Berthelot" scale12="0.0" scale13="0.0" scale14="0.5" scale15="1.0" cutoff="9.0 \* angstrom \*\* 1" switch_width="1.0 \* angstrom \*\* 1" periodic_method="cutoff" nonperiodic_method="no-cutoff">/    <vdW version="0.3" potential="Lennard-Jones-12-6" combining_rules="Lorentz-Berthelot" scale12="0.0" scale13="0.0" scale14="0.5" scale15="1.0" cutoff="9.0 \* angstrom" switch_width="1.0 \* angstrom" method="cutoff">/g' $FF
    sed -i 's/    <Electrostatics version="0.4" scale12="0.0" scale13="0.0" scale14="0.8333333333" scale15="1.0" cutoff="9.0 \* angstrom \*\* 1" switch_width="0.0 \* angstrom \*\* 1" periodic_potential="Ewald3D-ConductingBoundary" nonperiodic_potential="Coulomb" exception_potential="Coulomb">/    <Electrostatics version="0.3" scale12="0.0" scale13="0.0" scale14="0.8333333333" scale15="1.0" cutoff="9.0 \* angstrom" switch_width="0.0 \* angstrom" method="PME">/g' $FF
    echo "converted $FF"
} 
mattwthompson commented 1 month ago

Great! That's what the problem was and, in typical Lily fashion, a super slick way to solve it.