def test_base_layer():

    properties_to_estimate = [
        create_dummy_property(Density),
        create_dummy_property(Density),
    ]

    dummy_options = RequestOptions()

    batch = server.Batch()
    batch.queued_properties = properties_to_estimate
    batch.options = dummy_options
    batch.force_field_id = ""
    batch.options.calculation_schemas = {
        "Density": {
            "DummyCalculationLayer": CalculationLayerSchema()
        }
    }

    with tempfile.TemporaryDirectory() as temporary_directory:

        with temporarily_change_directory(temporary_directory):

            # Create a simple calculation backend to test with.
            test_backend = DaskLocalCluster()
            test_backend.start()

            # Create a simple storage backend to test with.
            test_storage = LocalFileStorage()

            layer_directory = "dummy_layer"
            makedirs(layer_directory)

            def dummy_callback(returned_request):

                assert len(returned_request.estimated_properties) == 1
                assert len(returned_request.exceptions) == 2

            dummy_layer = DummyCalculationLayer()

            dummy_layer.schedule_calculation(
                test_backend,
                test_storage,
                layer_directory,
                batch,
                dummy_callback,
                True,
            )
def test_workflow_schema_merging(
    calculation_layer, property_type, workflow_merge_function
):
    """Tests that two of the exact the same calculations get merged into one
    by the `WorkflowGraph`."""

    schema = registered_calculation_schemas[calculation_layer][property_type]

    if callable(schema):
        schema = schema()

    if not isinstance(schema, WorkflowCalculationSchema):
        pytest.skip("Not a `WorkflowCalculationSchema`.")

    property_class = getattr(openff.evaluator.properties, property_type)

    dummy_property = create_dummy_property(property_class)

    global_metadata = create_dummy_metadata(dummy_property, calculation_layer)

    workflow_a = Workflow(global_metadata, "workflow_a")
    workflow_a.schema = schema.workflow_schema

    workflow_b = Workflow(global_metadata, "workflow_b")
    workflow_b.schema = schema.workflow_schema

    workflow_graph = workflow_merge_function(workflow_a, workflow_b)

    workflow_graph_a = workflow_a.to_graph()
    workflow_graph_b = workflow_b.to_graph()

    dependants_graph_a = workflow_graph_a._protocol_graph._build_dependants_graph(
        workflow_graph_a.protocols, False, apply_reduction=True
    )
    dependants_graph_b = workflow_graph_b._protocol_graph._build_dependants_graph(
        workflow_graph_b.protocols, False, apply_reduction=True
    )

    ordered_dict_a = OrderedDict(sorted(dependants_graph_a.items()))
    ordered_dict_a = {key: sorted(value) for key, value in ordered_dict_a.items()}
    ordered_dict_b = OrderedDict(sorted(dependants_graph_b.items()))
    ordered_dict_b = {key: sorted(value) for key, value in ordered_dict_b.items()}

    merge_order_a = graph.topological_sort(ordered_dict_a)
    merge_order_b = graph.topological_sort(ordered_dict_b)

    assert len(workflow_graph.protocols) == len(workflow_a.protocols)

    for protocol_id in workflow_a.protocols:
        assert protocol_id in workflow_graph.protocols

    for protocol_id_A, protocol_id_B in zip(merge_order_a, merge_order_b):

        assert protocol_id_A == protocol_id_B

        assert (
            workflow_a.protocols[protocol_id_A].schema.json()
            == workflow_b.protocols[protocol_id_B].schema.json()
        )
Example #3
0
def test_properties_by_type():

    density = create_dummy_property(Density)
    dielectric = create_dummy_property(DielectricConstant)

    data_set = PhysicalPropertyDataSet()
    data_set.add_properties(density, dielectric)

    densities = [x for x in data_set.properties_by_type("Density")]
    assert len(densities) == 1
    assert densities[0] == density

    dielectrics = [
        x for x in data_set.properties_by_type("DielectricConstant")
    ]
    assert len(dielectrics) == 1
    assert dielectrics[0] == dielectric
Example #4
0
def test_sources_substances():

    physical_property = create_dummy_property(Density)

    data_set = PhysicalPropertyDataSet()
    data_set.add_properties(physical_property)

    assert next(iter(data_set.sources)) == physical_property.source
    assert next(iter(data_set.substances)) == physical_property.substance
Example #5
0
def test_launch_batch():

    # Set up a dummy data set
    data_set = PhysicalPropertyDataSet()
    data_set.add_properties(create_dummy_property(Density),
                            create_dummy_property(Density))

    batch = Batch()
    batch.force_field_id = ""
    batch.options = RequestOptions()
    batch.options.calculation_layers = ["QuickCalculationLayer"]
    batch.options.calculation_schemas = {
        "Density": {
            "QuickCalculationLayer": CalculationLayerSchema()
        }
    }
    batch.parameter_gradient_keys = []
    batch.queued_properties = [*data_set]
    batch.validate()

    with tempfile.TemporaryDirectory() as directory:

        with temporarily_change_directory(directory):

            with DaskLocalCluster() as calculation_backend:

                server = EvaluatorServer(
                    calculation_backend=calculation_backend,
                    working_directory=directory,
                )

                server._queued_batches[batch.id] = batch
                server._launch_batch(batch)

                while len(batch.queued_properties) > 0:
                    sleep(0.01)

                assert len(batch.estimated_properties) == 1
                assert len(batch.unsuccessful_properties) == 1
Example #6
0
def test_serialization():
    """A test to ensure that data sets are JSON serializable."""

    data_set = PhysicalPropertyDataSet()
    data_set.add_properties(create_dummy_property(Density))

    data_set_json = data_set.json()

    parsed_data_set = PhysicalPropertyDataSet.parse_json(data_set_json)
    assert len(data_set) == len(parsed_data_set)

    parsed_data_set_json = parsed_data_set.json()
    assert parsed_data_set_json == data_set_json
Example #7
0
def test_protocol_replacement(force_field_source, expected_protocol_type):

    data_set = PhysicalPropertyDataSet()

    for property_type in property_types:
        physical_property = create_dummy_property(property_type)
        data_set.add_properties(physical_property)

    options = EvaluatorClient.default_request_options(data_set,
                                                      force_field_source)
    options_json = options.json(format=True)

    assert options_json.find('BaseBuildSystem"') < 0
    assert options_json.find(expected_protocol_type) >= 0
Example #8
0
def test_physical_property_state_methods():

    dummy_property = create_dummy_property(Density)
    property_state = dummy_property.__getstate__()

    recreated_property = Density()
    recreated_property.__setstate__(property_state)

    recreated_state = recreated_property.__getstate__()

    original_json = json.dumps(property_state, cls=TypedJSONEncoder)
    recreated_json = json.dumps(recreated_state, cls=TypedJSONEncoder)

    assert original_json == recreated_json
def test_serialize_layer_result():
    """Tests that the `CalculationLayerResult` can be properly
    serialized and deserialized."""

    dummy_result = CalculationLayerResult()

    dummy_result.physical_property = create_dummy_property(Density)
    dummy_result.exceptions = [EvaluatorException()]

    dummy_result.data_to_store = [("dummy_object_path", "dummy_directory")]

    dummy_result_json = json.dumps(dummy_result, cls=TypedJSONEncoder)

    recreated_result = json.loads(dummy_result_json, cls=TypedJSONDecoder)
    recreated_result_json = json.dumps(recreated_result, cls=TypedJSONEncoder)

    assert recreated_result_json == dummy_result_json
Example #10
0
def test_nested_replicators():

    dummy_schema = WorkflowSchema()

    dummy_protocol = DummyReplicableProtocol("dummy_$(rep_a)_$(rep_b)")

    dummy_protocol.replicated_value_a = ReplicatorValue("rep_a")
    dummy_protocol.replicated_value_b = ReplicatorValue("rep_b")

    dummy_schema.protocol_schemas = [dummy_protocol.schema]

    replicator_a = ProtocolReplicator(replicator_id="rep_a")
    replicator_a.template_values = ["a", "b"]

    replicator_b = ProtocolReplicator(replicator_id="rep_b")
    replicator_b.template_values = [1, 2]

    dummy_schema.protocol_replicators = [replicator_a, replicator_b]

    dummy_schema.validate()

    dummy_property = create_dummy_property(Density)

    dummy_metadata = Workflow.generate_default_metadata(
        dummy_property, "smirnoff99Frosst-1.1.0.offxml", [])

    dummy_workflow = Workflow(dummy_metadata, "")
    dummy_workflow.schema = dummy_schema

    assert len(dummy_workflow.protocols) == 4

    assert dummy_workflow.protocols["dummy_0_0"].replicated_value_a == "a"
    assert dummy_workflow.protocols["dummy_0_1"].replicated_value_a == "a"

    assert dummy_workflow.protocols["dummy_1_0"].replicated_value_a == "b"
    assert dummy_workflow.protocols["dummy_1_1"].replicated_value_a == "b"

    assert dummy_workflow.protocols["dummy_0_0"].replicated_value_b == 1
    assert dummy_workflow.protocols["dummy_0_1"].replicated_value_b == 2

    assert dummy_workflow.protocols["dummy_1_0"].replicated_value_b == 1
    assert dummy_workflow.protocols["dummy_1_1"].replicated_value_b == 2

    print(dummy_workflow.schema)
Example #11
0
def test_default_options():
    """Test creating the default estimation options."""

    data_set = PhysicalPropertyDataSet()
    force_field_source = SmirnoffForceFieldSource.from_path(
        "smirnoff99Frosst-1.1.0.offxml")

    for property_type in property_types:
        physical_property = create_dummy_property(property_type)
        data_set.add_properties(physical_property)

    options = EvaluatorClient.default_request_options(data_set,
                                                      force_field_source)
    options.validate()

    assert len(options.calculation_layers) == 2
    assert len(options.calculation_schemas) == len(property_types)
    assert all(
        len(x) == len(options.calculation_layers)
        for x in options.calculation_schemas.values())
Example #12
0
def test_advanced_nested_replicators():

    dummy_schema = WorkflowSchema()

    replicator_a = ProtocolReplicator(replicator_id="replicator_a")
    replicator_a.template_values = ["a", "b"]

    replicator_b = ProtocolReplicator(
        replicator_id=f"replicator_b_{replicator_a.placeholder_id}")
    replicator_b.template_values = ProtocolPath(
        f"dummy_list[{replicator_a.placeholder_id}]", "global")

    dummy_protocol = DummyReplicableProtocol(f"dummy_"
                                             f"{replicator_a.placeholder_id}_"
                                             f"{replicator_b.placeholder_id}")

    dummy_protocol.replicated_value_a = ReplicatorValue(replicator_a.id)
    dummy_protocol.replicated_value_b = ReplicatorValue(replicator_b.id)

    dummy_schema.protocol_schemas = [dummy_protocol.schema]
    dummy_schema.protocol_replicators = [replicator_a, replicator_b]

    dummy_schema.validate()

    dummy_property = create_dummy_property(Density)
    dummy_metadata = Workflow.generate_default_metadata(
        dummy_property, "smirnoff99Frosst-1.1.0.offxml", [])
    dummy_metadata["dummy_list"] = [[1], [2]]

    dummy_workflow = Workflow(dummy_metadata, "")
    dummy_workflow.schema = dummy_schema

    assert len(dummy_workflow.protocols) == 2

    assert dummy_workflow.protocols["dummy_0_0"].replicated_value_a == "a"
    assert dummy_workflow.protocols["dummy_0_0"].replicated_value_b == 1

    assert dummy_workflow.protocols["dummy_1_0"].replicated_value_a == "b"
    assert dummy_workflow.protocols["dummy_1_0"].replicated_value_b == 2
Example #13
0
def test_group_replicators():

    dummy_schema = WorkflowSchema()

    replicator_id = "replicator"

    dummy_replicated_protocol = DummyInputOutputProtocol(
        f"dummy_$({replicator_id})")
    dummy_replicated_protocol.input_value = ReplicatorValue(replicator_id)

    dummy_group = ProtocolGroup("dummy_group")
    dummy_group.add_protocols(dummy_replicated_protocol)

    dummy_protocol_single_value = DummyInputOutputProtocol(
        f"dummy_single_$({replicator_id})")
    dummy_protocol_single_value.input_value = ProtocolPath(
        "output_value", dummy_group.id, dummy_replicated_protocol.id)

    dummy_protocol_list_value = AddValues("dummy_list")
    dummy_protocol_list_value.values = ProtocolPath(
        "output_value", dummy_group.id, dummy_replicated_protocol.id)

    dummy_schema.protocol_schemas = [
        dummy_group.schema,
        dummy_protocol_single_value.schema,
        dummy_protocol_list_value.schema,
    ]

    replicator = ProtocolReplicator(replicator_id)

    replicator.template_values = [
        (1.0 * unit.kelvin).plus_minus(1.0 * unit.kelvin),
        (2.0 * unit.kelvin).plus_minus(2.0 * unit.kelvin),
    ]

    dummy_schema.protocol_replicators = [replicator]
    dummy_schema.validate()

    dummy_property = create_dummy_property(Density)

    dummy_metadata = Workflow.generate_default_metadata(
        dummy_property, "smirnoff99Frosst-1.1.0.offxml", [])

    dummy_workflow = Workflow(dummy_metadata, "")
    dummy_workflow.schema = dummy_schema

    assert len(dummy_workflow.protocols) == 4

    assert (dummy_workflow.protocols[dummy_group.id].protocols["dummy_0"].
            input_value.value == replicator.template_values[0].value)
    assert (dummy_workflow.protocols[dummy_group.id].protocols["dummy_1"].
            input_value.value == replicator.template_values[1].value)

    assert dummy_workflow.protocols[
        "dummy_single_0"].input_value == ProtocolPath("output_value",
                                                      dummy_group.id,
                                                      "dummy_0")
    assert dummy_workflow.protocols[
        "dummy_single_1"].input_value == ProtocolPath("output_value",
                                                      dummy_group.id,
                                                      "dummy_1")

    assert len(dummy_workflow.protocols["dummy_list"].values) == 2

    assert dummy_workflow.protocols["dummy_list"].values[0] == ProtocolPath(
        "output_value", dummy_group.id, "dummy_0")
    assert dummy_workflow.protocols["dummy_list"].values[1] == ProtocolPath(
        "output_value", dummy_group.id, "dummy_1")
def test_workflow_layer():
    """Test the `WorkflowLayer` calculation layer. As the `SimulationLayer`
    is the simplest implementation of the abstract layer, we settle for
    testing this."""

    properties_to_estimate = [
        create_dummy_property(Density),
        create_dummy_property(Density),
    ]

    # Create a very simple workflow which just returns some placeholder
    # value.
    estimated_value = Observable(
        (1 * unit.kelvin).plus_minus(0.1 * unit.kelvin))
    protocol_a = DummyProtocol("protocol_a")
    protocol_a.input_value = estimated_value

    schema = WorkflowSchema()
    schema.protocol_schemas = [protocol_a.schema]
    schema.final_value_source = ProtocolPath("output_value", protocol_a.id)

    layer_schema = SimulationSchema()
    layer_schema.workflow_schema = schema

    options = RequestOptions()
    options.add_schema("SimulationLayer", "Density", layer_schema)

    batch = server.Batch()
    batch.queued_properties = properties_to_estimate
    batch.options = options

    with tempfile.TemporaryDirectory() as directory:

        with temporarily_change_directory(directory):

            # Create a directory for the layer.
            layer_directory = "simulation_layer"
            os.makedirs(layer_directory)

            # Set-up a simple storage backend and add a force field to it.
            force_field = SmirnoffForceFieldSource.from_path(
                "smirnoff99Frosst-1.1.0.offxml")

            storage_backend = LocalFileStorage()
            batch.force_field_id = storage_backend.store_force_field(
                force_field)

            # Create a simple calculation backend to test with.
            with DaskLocalCluster() as calculation_backend:

                def dummy_callback(returned_request):

                    assert len(returned_request.estimated_properties) == 2
                    assert len(returned_request.exceptions) == 0

                simulation_layer = SimulationLayer()

                simulation_layer.schedule_calculation(
                    calculation_backend,
                    storage_backend,
                    layer_directory,
                    batch,
                    dummy_callback,
                    True,
                )
Example #15
0
def test_physical_property_id_generation():

    dummy_property_1 = create_dummy_property(Density)
    dummy_property_2 = create_dummy_property(Density)

    assert dummy_property_1.id != dummy_property_2.id