Release History

Releases follow the major.minor.micro scheme recommended by PEP440, where

  • major increments denote a change that may break API compatibility with previous major releases

  • minor increments add features but do not break API compatibility

  • micro increments represent bugfix releases or improvements in documentation

0.6.1 - Bugfixes

API-breaking changes

  • PR #558: Removes TopologyMolecule.topology_particle_start_index, since the :py:class`Topology <openforcefield.topology.Topology>` particle indexing system now orders :py:class`TopologyVirtualSites <openforcefield.topology.TopologyVirtualSite>` after all atoms. :py:meth`TopologyMolecule.topology_atom_start_index <openforcefield.topology.TopologyMolecule.topology_atom_start_index>` and :py:meth`TopologyMolecule.topology_virtual_site_start_index <openforcefield.topology.TopologyMolecule.topology_virtual_site_start_index>` are still available to access the appropriate values in the respective topology indexing systems.

  • PR #508: OpenEyeToolkitWrapper.compute_wiberg_bond_orders is now OpenEyeToolkitWrapper.assign_fractional_bond_orders. The charge_model keyword is now bond_order_model. The allowed values of this keyword have changed from am1 and pm3 to am1-wiberg and pm3-wiberg, respectively.

  • PR #508: Molecule.compute_wiberg_bond_orders is now Molecule.assign_fractional_bond_orders.

New features

Behavior changed

  • PR #558: The :py:class`Topology <openforcefield.topology.Topology>` particle indexing system now orders :py:class`TopologyVirtualSites <openforcefield.topology.TopologyVirtualSite>` after all atoms.

  • PR #469: When running Topology.to_openmm, unique atom names are generated if the provided atom names are not unique (overriding any existing atom names). This uniqueness extends only to atoms in the same molecule. To disable this behavior, set the kwarg ensure_unique_atom_names=False.

  • PR #472: The Molecule.__eq__ now uses the new Molecule.are_isomorphic to perform the similarity checking.

  • PR #472: The Topology.from_openmm and Topology.add_molecule now use the Molecule.are_isomorphic to match molecules.

  • PR #508: In order to provide the same results for the same chemical species, regardless of input conformation, fractional bond order calculation methods now default to ignore input conformers and generate a new conformer of the molecule before running semiempirical calculations. Users can override this behavior by specifying the keyword argument use_conformers=molecule.conformers

  • PR #544: Raises NotImplementedError when calling ParameterHandler.get_parameter, which is not yet implemented, but would previously silently return None.

  • PR #551: Implemented the ParameterHandler.get_parameter function.

Tests added

Bugfixes

  • PR #558: Fixes a bug where TopologyVirtualSite.atoms would not correctly apply TopologyMolecule atom ordering on top of the reference molecule ordering, in cases where the same molecule appears multiple times, but in a different order, in the same Topology.

  • Issue #460: Creates unique atom names in Topology.to_openmm if the existing ones are not unique. The lack of unique atom names had been causing problems in workflows involving downstream tools that expect unique atom names.

  • Issue #448: We can now make molecules from mapped smiles using Molecule.from_mapped_smiles where the order will correspond to the indeing used in the smiles. Molecules can also be re-indexed at any time using the Molecule.remap.

  • Issue #462: We can now instance the Molecule from a QCArchive entry record instance or dictionary representation.

  • Issue #412: We can now instance the Molecule using Molecule.from_mapped_smiles. This resolves an issue caused by RDKit considering atom map indices to be a distinguishing feature of an atom, which led to erroneous definition of chirality (as otherwise symmetric substituents would be seen as different). We anticipate that this will reduce the number of times you need to type allow_undefined_stereo=True when processing molecules that do not actually contain stereochemistrty.

  • Issue #513: The

    Molecule.to_rdkit now re-sets the aromaticity model after sanitizing the molecule.

  • Issue #500: The

    Molecule.find_rotatable_bonds has been added which returns a list of rotatable Bond instances for the molecule.

  • Issue #491: We can now parse large molecules without hitting a match limit cap.

  • Issue #474: We can now convert molecules to InChI and

    InChIKey and from InChI.

  • Issue #523: The
    py:meth

    Molecule.to_file <openforcefield.topology.Molecule.to_file> can now correctly write to MOL files in

    line with the support file type list.

Example added

  • PR #472: Adds an example notebook QCarchive_interface.ipynb <https://github.com/openforcefield/openforcefield/blob/master/examples/QCArchive_interface/QCarchive_interface.ipynb> which shows users how to instance the Molecule from a QCArchive entry level record and calculate the energy using RDKit through QCEngine.

0.6.0 - Library Charges

This release adds support for a new SMIRKS-based charge assignment method, Library Charges. The addition of more charge assignment methods opens the door for new types of experimentation, but also introduces several complex behaviors and failure modes. Accordingly, we have made changes to the charge assignment infrastructure to check for cases when partial charges do not sum to the formal charge of the molecule, or when no charge assignment method is able to generate charges for a molecule. More detailed explanation of the new errors that may be raised and keywords for overriding them are in the “Behavior Changed” section below.

With this release, we update test_forcefields/tip3p.offxml to be a working example of assigning LibraryCharges. However, we do not provide any force field files to assign protein residue LibraryCharges. If you are interested in translating an existing protein FF to SMIRNOFF format or developing a new one, please feel free to contact us on the Issue tracker or open a Pull Request.

New features

  • PR #433: Closes Issue #25 by adding initial support for the LibraryCharges tag in the SMIRNOFF specification using LibraryChargeHandler. For a molecule to have charges assigned using Library Charges, all of its atoms must be covered by at least one LibraryCharge. If an atom is covered by multiple LibraryCharge s, then the last LibraryCharge matched will be applied (per the hierarchy rules in the SMIRNOFF format).

    This functionality is thus able to apply per-residue charges similar to those in traditional protein force fields. At this time, there is no concept of “residues” or “fragments” during parametrization, so it is not possible to assign charges to some atoms in a molecule using LibraryCharge s, but calculate charges for other atoms in the same molecule using a different method. To assign charges to a protein, LibraryCharges SMARTS must be provided for the residues and protonation states in the molecule, as well as for any capping groups and post-translational modifications that are present.

    It is valid for LibraryCharge SMARTS to partially overlap one another. For example, a molecule consisting of atoms A-B-C connected by single bonds could be matched by a SMIRNOFF LibraryCharges section containing two LibraryCharge SMARTS: A-B and B-C. If listed in that order, the molecule would be assigned the A charge from the A-B LibraryCharge element and the B and C charges from the B-C element. In testing, these types of partial overlaps were found to frequently be sources of undesired behavior, so it is recommended that users define whole-molecule LibraryCharge SMARTS whenever possible.

  • PR #455: Addresses Issue #393 by adding ParameterHandler.attribute_is_cosmetic and ParameterType.attribute_is_cosmetic, which return True if the provided attribute name is defined for the queried object but does not correspond to an allowed value in the SMIRNOFF spec.

Behavior changed

  • PR #433: If a molecule can not be assigned charges by any charge-assignment method, an openforcefield.typing.engines.smirnoff.parameters.UnassignedMoleculeChargeException will be raised. Previously, creating a system without either ToolkitAM1BCCHandler or the charge_from_molecules keyword argument to ForceField.create_openmm_system would produce a system where the molecule has zero charge on all atoms. However, given that we will soon be adding more options for charge assignment, it is important that failures not be silent. Molecules with zero charge can still be produced by setting the Molecule.partial_charges array to be all zeroes, and including the molecule in the charge_from_molecules keyword argument to create_openmm_system.

  • PR #433: Due to risks introduced by permitting charge assignment using partially-overlapping LibraryCharge s, the toolkit will now raise a openforcefield.typing.engines.smirnoff.parameters.NonIntegralMoleculeChargeException if the sum of partial charges on a molecule are found to be more than 0.01 elementary charge units different than the molecule’s formal charge. This exception can be overridden by providing the allow_nonintegral_charges=True keyword argument to ForceField.create_openmm_system.

Tests added

  • PR #430: Added test for Wiberg Bond Order implemented in OpenEye Toolkits. Molecules taken from DOI:10.5281/zenodo.3405489 . Added by Sukanya Sasmal.

Bugfixes

  • PR #431: Fixes an issue where ToolkitWrapper objects would improperly search for functionality in the GLOBAL_TOOLKIT_REGISTRY, even though a specific ToolkitRegistry was requested for an operation.

  • PR #439: Fixes Issue #438, by replacing call to NetworkX Graph.node with call to Graph.nodes, per 2.4 migration guide.

Files modified

  • PR #433: Updates the previously-nonfunctional test_forcefields/tip3p.offxml to a functional state by updating it to the SMIRNOFF 0.3 specification, and specifying atomic charges using the LibraryCharges tag.

0.5.1 - Adding the parameter coverage example notebook

This release contains a new notebook example, check_parameter_coverage.ipynb, which loads sets of molecules, checks whether they are parameterizable, and generates reports of chemical motifs that are not. It also fixes several simple issues, improves warnings and docstring text, and removes unused files.

The parameter coverage example notebook goes hand-in-hand with the release candidate of our initial force field, openff-1.0.0-RC1.offxml , which will be temporarily available until the official force field release is made in October. Our goal in publishing this notebook alongside our first major refitting is to allow interested users to check whether there is parameter coverage for their molecules of interest. If the force field is unable to parameterize a molecule, this notebook will generate reports of the specific chemistry that is not covered. We understand that many organizations in our field have restrictions about sharing specific molecules, and the outputs from this notebook can easily be cropped to communicate unparameterizable chemistry without revealing the full structure.

The force field release candidate is in our new refit force field package, openforcefields. This package is now a part of the Open Force Field Toolkit conda recipe, along with the original smirnoff99Frosst line of force fields.

Once the openforcefields conda package is installed, you can load the release candidate using:

ff = ForceField('openff-1.0.0-RC1.offxml')

The release candidate will be removed when the official force field, openff-1.0.0.offxml, is released in early October.

Complete details about this release are below.

Example added

  • PR #419: Adds an example notebook check_parameter_coverage.ipynb which shows how to use the toolkit to check a molecule dataset for missing parameter coverage, and provides functionality to output tagged SMILES and 2D drawings of the unparameterizable chemistry.

New features

  • PR #419: Unassigned valence parameter exceptions now include a list of tuples of TopologyAtom which were unable to be parameterized (exception.unassigned_topology_atom_tuples) and the class of the ParameterHandler that raised the exception (exception.handler_class).

  • PR #425: Implements Trevor Gokey’s suggestion from Issue #411, which enables pickling of ForceFields and ParameterHandlers. Note that, while XML representations of ``ForceField``s are stable and conform to the SMIRNOFF specification, the pickled ``ForceField``s that this functionality enables are not guaranteed to be compatible with future toolkit versions.

Improved documentation and warnings

  • PR #425: Addresses Issue #410, by explicitly having toolkit warnings print Warning: at the beginning of each warning, and adding clearer language to the warning produced when the OpenEye Toolkits can not be loaded.

  • PR #425: Addresses Issue #421 by adding type/shape information to all Molecule partial charge and conformer docstrings.

  • PR #425: Addresses Issue #407 by providing a more extensive explanation of why we don’t use RDKit’s mol2 parser for molecule input.

Bugfixes

Files removed

  • PR #425: Addresses Issue #424 by deleting the unused files openforcefield/typing/engines/smirnoff/gbsaforces.py and openforcefield/tests/test_smirnoff.py. gbsaforces.py was only used internally and test_smirnoff.py tested unsupported functionality from before the 0.2.0 release.

0.5.0 - GBSA support and quality-of-life improvements

This release adds support for the GBSA tag in the SMIRNOFF specification. Currently, the HCT, OBC1, and OBC2 models (corresponding to AMBER keywords igb=1, 2, and 5, respectively) are supported, with the OBC2 implementation being the most flexible. Unfortunately, systems produced using these keywords are not yet transferable to other simulation packages via ParmEd, so users are restricted to using OpenMM to simulate systems with GBSA.

OFFXML files containing GBSA parameter definitions are available, and can be loaded in addition to existing parameter sets (for example, with the command ForceField('test_forcefields/smirnoff99Frosst.offxml', 'test_forcefields/GBSA_OBC1-1.0.offxml')). A manifest of new SMIRNOFF-format GBSA files is below.

Several other user-facing improvements have been added, including easier access to indexed attributes, which are now accessible as torsion.k1, torsion.k2, etc. (the previous access method torsion.k still works as well). More details of the new features and several bugfixes are listed below.

New features

  • PR #363: Implements GBSAHandler, which supports the GBSA tag in the SMIRNOFF specification. Currently, only GBSAHandlers with gb_model="OBC2" support setting non-default values for the surface_area_penalty term (default 5.4*calories/mole/angstroms**2), though users can zero the SA term for OBC1 and HCT models by setting sa_model="None". No model currently supports setting solvent_radius to any value other than 1.4*angstroms. Files containing experimental SMIRNOFF-format implementations of HCT, OBC1, and OBC2 are included with this release (see below). Additional details of these models, including literature references, are available on the SMIRNOFF specification page.

    Warning

    The current release of ParmEd can not transfer GBSA models produced by the Open Force Field Toolkit to other simulation packages. These GBSA forces are currently only computable using OpenMM.

  • PR #363: When using Topology.to_openmm(), periodic box vectors are now transferred from the Open Force Field Toolkit Topology into the newly-created OpenMM Topology.

  • PR #377: Single indexed parameters in ParameterHandler and ParameterType can now be get/set through normal attribute syntax in addition to the list syntax.

  • PR #394: Include element and atom name in error output when there are missing valence parameters during molecule parameterization.

Bugfixes

Files added

  • PR #363: Adds test_forcefields/GBSA_HCT-1.0.offxml, test_forcefields/GBSA_OBC1-1.0.offxml, and test_forcefields/GBSA_OBC2-1.0.offxml, which are experimental implementations of GBSA models. These are primarily used in validation tests against OpenMM’s models, and their version numbers will increment if bugfixes are necessary.

0.4.1 - Bugfix Release

This update fixes several toolkit bugs that have been reported by the community. Details of these bugfixes are provided below.

It also refactors how ParameterType and ParameterHandler store their attributes, by introducing ParameterAttribute and IndexedParameterAttribute. These new attribute-handling classes provide a consistent backend which should simplify manipulation of parameters and implementation of new handlers.

Bug fixes

  • PR #329: Fixed a bug where the two BondType parameter attributes k and length were treated as indexed attributes. (k and length values that correspond to specific bond orders will be indexed under k_bondorder1, k_bondorder2, etc when implemented in the future)

  • PR #329: Fixed a bug that allowed setting indexed attributes to single values instead of strictly lists.

  • PR #370: Fixed a bug in the API where BondHandler, ProperTorsionHandler , and ImproperTorsionHandler exposed non-functional indexed parameters.

  • PR #351: Fixes Issue #344, in which the main FrozenMolecule constructor and several other Molecule-construction functions ignored or did not expose the allow_undefined_stereo keyword argument.

  • PR #351: Fixes a bug where a molecule which previously generated a SMILES using one cheminformatics toolkit returns the same SMILES, even though a different toolkit (which would generate a different SMILES for the molecule) is explicitly called.

  • PR #354: Fixes the error message that is printed if an unexpected parameter attribute is found while loading data into a ForceField (now instructs users to specify allow_cosmetic_attributes instead of permit_cosmetic_attributes)

  • PR #364: Fixes Issue #362 by modifying OpenEyeToolkitWrapper.from_smiles and RDKitToolkitWrapper.from_smiles to make implicit hydrogens explicit before molecule creation. These functions also now raise an error if the optional keyword hydrogens_are_explicit=True but the SMILES are interpreted by the backend cheminformatic toolkit as having implicit hydrogens.

  • PR #371: Fixes error when reading early SMIRNOFF 0.1 spec files enclosed by a top-level SMIRFF tag.

Note

The enclosing SMIRFF tag is present only in legacy files. Since developing a formal specification, the only acceptable top-level tag value in a SMIRNOFF data structure is SMIRNOFF.

Code enhancements

Force fields added

  • PR #368: Temporarily adds test_forcefields/smirnoff99frosst_experimental.offxml to address hierarchy problems, redundancies, SMIRKS pattern typos etc., as documented in issue #367. Will ultimately be propagated to an updated forcefield in the openforcefield/smirnoff99frosst repo.

  • PR #371: Adds test_forcefields/smirff99Frosst_reference_0_1_spec.offxml, a SMIRNOFF 0.1 spec file enclosed by the legacy SMIRFF tag. This file is used in backwards-compatibility testing.

0.4.0 - Performance optimizations and support for SMIRNOFF 0.3 specification

This update contains performance enhancements that significantly reduce the time to create OpenMM systems for topologies containing many molecules via ForceField.create_openmm_system.

This update also introduces the SMIRNOFF 0.3 specification. The spec update is the result of discussions about how to handle the evolution of data and parameter types as further functional forms are added to the SMIRNOFF spec.

We provide methods to convert SMIRNOFF 0.1 and 0.2 forcefields written with the XML serialization (.offxml) to the SMIRNOFF 0.3 specification. These methods are called automatically when loading a serialized SMIRNOFF data representation written in the 0.1 or 0.2 specification. This functionality allows the toolkit to continue to read files containing SMIRNOFF 0.2 spec force fields, and also implements backwards-compatibility for SMIRNOFF 0.1 spec force fields.

Warning

The SMIRNOFF 0.1 spec did not contain fields for several energy-determining parameters that are exposed in later SMIRNOFF specs. Thus, when reading SMIRNOFF 0.1 spec data, the toolkit must make assumptions about the values that should be added for the newly-required fields. The values that are added include 1-2, 1-3 and 1-5 scaling factors, cutoffs, and long-range treatments for nonbonded interactions. Each assumption is printed as a warning during the conversion process. Please carefully review the warning messages to ensure that the conversion is providing your desired behavior.

SMIRNOFF 0.3 specification updates

  • The SMIRNOFF 0.3 spec introduces versioning for each individual parameter section, allowing asynchronous updates to the features of each parameter class. The top-level SMIRNOFF tag, containing information like aromaticity_model, Author, and Date, still has a version (currently 0.3). But, to allow for independent development of individual parameter types, each section (such as Bonds, Angles, etc) now has its own version as well (currently all 0.3).

  • All units are now stored in expressions with their corresponding values. For example, distances are now stored as 1.526*angstrom, instead of storing the unit separately in the section header.

  • The current allowed value of the potential field for ProperTorsions and ImproperTorsions tags is no longer charmm, but is rather k*(1+cos(periodicity*theta-phase)). It was pointed out to us that CHARMM-style torsions deviate from this formula when the periodicity of a torsion term is 0, and we do not intend to reproduce that behavior.

  • SMIRNOFF spec documentation has been updated with tables of keywords and their defaults for each parameter section and parameter type. These tables will track the allowed keywords and default behavior as updated versions of individual parameter sections are released.

Performance improvements and bugfixes

  • PR #329: Performance improvements when creating systems for topologies with many atoms.

  • PR #347: Fixes bug in charge assignment that occurs when charges are read from file, and reference and charge molecules have different atom orderings.

New features

  • PR #311: Several new experimental functions.

    • Adds convert_0_2_smirnoff_to_0_3, which takes a SMIRNOFF 0.2-spec data dict, and updates it to 0.3. This function is called automatically when creating a ForceField from a SMIRNOFF 0.2 spec OFFXML file.

    • Adds convert_0_1_smirnoff_to_0_2, which takes a SMIRNOFF 0.1-spec data dict, and updates it to 0.2. This function is called automatically when creating a ForceField from a SMIRNOFF 0.1 spec OFFXML file.

    • NOTE: The format of the “SMIRNOFF data dict” above is likely to change significantly in the future. Users that require a stable serialized ForceField object should use the output of ForceField.to_string('XML') instead.

    • Adds ParameterHandler and ParameterType add_cosmetic_attribute and delete_cosmetic_attribute functions. Once created, cosmetic attributes can be accessed and modified as attributes of the underlying object (eg. ParameterType.my_cosmetic_attrib = 'blue') These functions are experimental, and we are interested in feedback on how cosmetic attribute handling could be improved. (See Issue #338) Note that if a new cosmetic attribute is added to an object without using these functions, it will not be recognized by the toolkit and will not be written out during serialization.

    • Values for the top-level Author and Date tags are now kept during SMIRNOFF data I/O. If multiple data sources containing these fields are read, the values are concatenated using “AND” as a separator.

API-breaking changes

  • ForceField.to_string and ForceField.to_file have had the default value of their discard_cosmetic_attributes kwarg set to False.

  • ParameterHandler and ParameterType constructors now expect the version kwarg (per the SMIRNOFF spec change above) This requirement can be skipped by providing the kwarg skip_version_check=True

  • ParameterHandler and ParameterType functions no longer handle X_unit attributes in SMIRNOFF data (per the SMIRNOFF spec change above).

  • The scripts in utilities/convert_frosst are now deprecated. This functionality is important for provenance and will be migrated to the openforcefield/smirnoff99Frosst repository in the coming weeks.

  • ParameterType ._SMIRNOFF_ATTRIBS is now ParameterType ._REQUIRED_SPEC_ATTRIBS, to better parallel the structure of the ParameterHandler class.

  • ParameterType ._OPTIONAL_ATTRIBS is now ParameterType ._OPTIONAL_SPEC_ATTRIBS, to better parallel the structure of the ParameterHandler class.

  • Added class-level dictionaries ParameterHandler ._DEFAULT_SPEC_ATTRIBS and ParameterType ._DEFAULT_SPEC_ATTRIBS.

0.3.0 - API Improvements

Several improvements and changes to public API.

New features

  • PR #292: Implement Topology.to_openmm and remove ToolkitRegistry.toolkit_is_available

  • PR #322: Install directories for the lookup of OFFXML files through the entry point group openforcefield.smirnoff_forcefield_directory. The ForceField class doesn’t search in the data/forcefield/ folder anymore (now renamed data/test_forcefields/), but only in data/.

API-breaking Changes

  • PR #278: Standardize variable/method names

  • PR #291: Remove ForceField.load/to_smirnoff_data, add ForceField.to_file/string and ParameterHandler.add_parameters. Change behavior of ForceField.register_X_handler functions.

Bugfixes

  • PR #327: Fix units in tip3p.offxml (note that this file is still not loadable by current toolkit)

  • PR #325: Fix solvent box for provided test system to resolve periodic clashes.

  • PR #325: Add informative message containing Hill formula when a molecule can’t be matched in Topology.from_openmm.

  • PR #325: Provide warning or error message as appropriate when a molecule is missing stereochemistry.

  • PR #316: Fix formatting issues in GBSA section of SMIRNOFF spec

  • PR #308: Cache molecule SMILES to improve system creation speed

  • PR #306: Allow single-atom molecules with all zero coordinates to be converted to OE/RDK mols

  • PR #313: Fix issue where constraints are applied twice to constrained bonds

0.2.2 - Bugfix release

This release modifies an example to show how to parameterize a solvated system, cleans up backend code, and makes several improvements to the README.

Bugfixes

  • PR #279: Cleanup of unused code/warnings in main package __init__

  • PR #259: Update T4 Lysozyme + toluene example to show how to set up solvated systems

  • PR #256 and PR #274: Add functionality to ensure that links in READMEs resolve successfully

0.2.1 - Bugfix release

This release features various documentation fixes, minor bugfixes, and code cleanup.

Bugfixes

  • PR #267: Add neglected <ToolkitAM1BCC> documentation to the SMIRNOFF 0.2 spec

  • PR #258: General cleanup and removal of unused/inaccessible code.

  • PR #244: Improvements and typo fixes for BRD4:inhibitor benchmark

0.2.0 - Initial RDKit support

This version of the toolkit introduces many new features on the way to a 1.0.0 release.

New features

  • Major overhaul, resulting in the creation of the SMIRNOFF 0.2 specification and its XML representation

  • Updated API and infrastructure for reference SMIRNOFF ForceField implementation

  • Implementation of modular ParameterHandler classes which process the topology to add all necessary forces to the system.

  • Implementation of modular ParameterIOHandler classes for reading/writing different serialized SMIRNOFF forcefield representations

  • Introduction of Molecule and Topology classes for representing molecules and biomolecular systems

  • New ToolkitWrapper interface to RDKit, OpenEye, and AmberTools toolkits, managed by ToolkitRegistry

  • API improvements to more closely follow PEP8 guidelines

  • Improved documentation and examples

0.1.0

This is an early preview release of the toolkit that matches the functionality described in the preprint describing the SMIRNOFF v0.1 force field format: [DOI].

New features

This release features additional documentation, code comments, and support for automated testing.

Bugfixes

Treatment of improper torsions

A significant (though currently unused) problem in handling of improper torsions was corrected. Previously, non-planar impropers did not behave correctly, as six-fold impropers have two potential chiralities. To remedy this, SMIRNOFF impropers are now implemented as three-fold impropers with consistent chirality. However, current force fields in the SMIRNOFF format had no non-planar impropers, so this change is mainly aimed at future work.