# PropertyEstimatorClient

class `propertyestimator.client.``PropertyEstimatorClient`(connection_options=<propertyestimator.client.ConnectionOptions object>)

  The PropertyEstimatorClient is the main object that users of the property estimator will interface with. It is responsible for requesting that a PropertyEstimatorServer estimates a set of physical properties, as well as querying for when those properties have been estimated.

  The PropertyEstimatorClient supports two main workflows: one where a PropertyEstimatorServer lives on a remote supercomputing cluster where all of the expensive calculations will be run, and one where the users local machine acts as both the server and the client, and all calculations will be performed locally.

  Warning

  While the API of this class in now close to being final, the internals and implementation are still heavily under development and is subject to rapid changes.

  Examples

  Setting up the client instance:

      >>> from propertyestimator.client import PropertyEstimatorClient
      >>> property_estimator = PropertyEstimatorClient()

  If the PropertyEstimatorServer is not running on the local machine, you will need to specify its address and the port that it is listening on:

      >>> from propertyestimator.client import ConnectionOptions
      >>>
      >>> connection_options = ConnectionOptions(server_address='server_address',
      >>>                                                         server_port=8000)
      >>> property_estimator = PropertyEstimatorClient(connection_options)

  To asynchronously submit a request to the running server using the default estimator options:

      >>> # Load in the data set of properties which will be used for comparisons
      >>> from propertyestimator.datasets import ThermoMLDataSet
      >>> data_set = ThermoMLDataSet.from_doi('10.1016/j.jct.2016.10.001')
      >>> # Filter the dataset to only include densities measured between 130-260 K
      >>> from propertyestimator.properties import Density
      >>>
      >>> data_set.filter_by_property_types(Density)
      >>> data_set.filter_by_temperature(min_temperature=130*unit.kelvin, max_temperature=260*unit.kelvin)
      >>>
      >>> # Load in the force field parameters
      >>> from openforcefield.typing.engines import smirnoff
      >>> from propertyestimator.forcefield import SmirnoffForceFieldSource
      >>> smirnoff_force_field = smirnoff.ForceField('smirnoff99Frosst-1.1.0.offxml')
      >>> force_field_source = SmirnoffForceFieldSource.from_object(smirnoff_force_field)
      >>>
      >>> request = property_estimator.request_estimate(data_set, force_field_source)

  The status of the request can be asynchronously queried by calling

      >>> results = request.results()

  or the main thread can be blocked until the results are available by calling

      >>> results = request.results(synchronous=True)

  How the property set will be estimated can easily be controlled by passing a PropertyEstimatorOptions object to the estimate commands.

  The calculations layers which will be used to estimate the properties can be controlled for example like so:

      >>> from propertyestimator.layers import ReweightingLayer, SimulationLayer
      >>>
      >>> options = PropertyEstimatorOptions(allowed_calculation_layers = [ReweightingLayer,
      >>>                                                                  SimulationLayer])
      >>>
      >>> request = property_estimator.request_estimate(data_set, force_field_source, options)

  Options for how properties should be estimated can be set on a per property, and per layer basis. For example, the relative uncertainty that properties should estimated to within by the SimulationLayer can be set as:

      >>> from propertyestimator.workflow import WorkflowOptions
      >>>
      >>> workflow_options = WorkflowOptions(WorkflowOptions.ConvergenceMode.RelativeUncertainty,
      >>>                                    relative_uncertainty_fraction=0.1)
      >>> options.workflow_options = {
      >>>     'Density': {'SimulationLayer': workflow_options},
      >>>     'Dielectric': {'SimulationLayer': workflow_options}
      >>> }

  Or alternatively, as absolute uncertainty tolerance can be set as:

      >>> density_options = WorkflowOptions(WorkflowOptions.ConvergenceMode.AbsoluteUncertainty,
      >>>                                   absolute_uncertainty=0.0002 * unit.gram / unit.milliliter)
      >>> dielectric_options = WorkflowOptions(WorkflowOptions.ConvergenceMode.AbsoluteUncertainty,
      >>>                                      absolute_uncertainty=0.02 * unit.dimensionless)
      >>>
      >>> options.workflow_options = {
      >>>     'Density': {'SimulationLayer': density_options},
      >>>     'Dielectric': {'SimulationLayer': dielectric_options}
      >>> }

  The gradients of the observables of interest with respect to a number of chosen parameters can be requested by passing a parameter_gradient_keys parameter. In the below example, gradients will be calculated with respect to both the bond length parameter for the [#6:1]-[#8:2] chemical environment, and the bond angle parameter for the [:1]-[#8:2]-[:3] chemical environment:

      >>> from propertyestimator.properties import ParameterGradientKey
      >>>
      >>> parameter_gradient_keys = [
      >>>     ParameterGradientKey('Bonds', '[#6:1]-[#8:2]', 'length')
      >>>     ParameterGradientKey('Angles', '[*:1]-[#8:2]-[*:3]', 'angle')
      >>> ]
      >>>
      >>> request = property_estimator.request_estimate(data_set, force_field_source, options, parameter_gradient_keys)
      >>>

  `__init__`(connection_options=<propertyestimator.client.ConnectionOptions object>)

    Constructs a new PropertyEstimatorClient object.

    Parameters

      connection_options (ConnectionOptions) – The options used when connecting to the calculation server.

  Methods

  `__init__`([connection_options]) | Constructs a new PropertyEstimatorClient object.
  `request_estimate`(property_set, …[, …]) | Requests that a PropertyEstimatorServer attempt to estimate the provided property set using the supplied force field and estimator options.

  Attributes

  `server_address` |
  `server_port` |

  class `Request`(request_id, connection_options, client=None)

    An object representation of a estimation request which has been sent to a PropertyEstimatorServer instance. This object can be used to query and retrieve the results of the request, or be stored to retrieve the request at some point in the future.

    property `id`

      The id of the submitted request.

      Type

        str

    property `server_address`

      The address of the server that the request was sent to.

      Type

        str

    property `server_port`

      The port that the server is listening on.

    `json`()

      Returns a JSON representation of the Request object.

      Returns

        The JSON representation of the Request object.

      Return type

        str

    classmethod `from_json`(json_string)

      Creates a new Request object from a JSON representation.

      Parameters

        json_string (str) – The JSON representation of the Request object.

      Returns

        The created Request object.

      Return type

        str

    `results`(synchronous=False, polling_interval=5)

      Retrieve the results of an estimate request.

      Parameters

        - synchronous (bool) – If true, this method will block the main thread until the server either returns a result or an error.

        - polling_interval (int) – If running synchronously, this is the time interval (seconds) between checking if the calculation has finished.

      Returns

        Returns either the results of the requested estimate, or any exceptions which were raised.

        If the method is run synchronously then this method will block the main thread until all of the requested properties have been estimated, or an exception is returned.

      Return type

        PropertyEstimatorResult or PropertyEstimatorException

  `request_estimate`(property_set, force_field_source, options=None, parameter_gradient_keys=None)

    Requests that a PropertyEstimatorServer attempt to estimate the provided property set using the supplied force field and estimator options.

    Parameters

      - property_set (PhysicalPropertyDataSet) – The set of properties to attempt to estimate.

      - force_field_source (ForceFieldSource or openforcefield.typing.engines.smirnoff.ForceField) – The source of the force field parameters to use for the calculations.

      - options (PropertyEstimatorOptions , optional) – A set of estimator options. If None, default options will be used.

      - parameter_gradient_keys (list of ParameterGradientKey, optional) – A list of references to all of the parameters which all observables should be differentiated with respect to.

    Returns

      An object which will provide access the the results of the request.

    Return type

      PropertyEstimatorClient.Request