Beispiel #1
0
def test_equality():
    """Test that equality checks both bounds and units."""
    value1 = UniformReal(0, 1, '')
    value2 = UniformReal(0, 1, 'cm')
    value3 = UniformReal(0, 2, '')

    assert value1 == value1
    assert value1 != value2
    assert value1 != value3
    assert value1 != 0.5
Beispiel #2
0
def test_simple_deserialization(valid_data):
    """Ensure that a deserialized Process Spec looks sane."""
    process_spec: ProcessSpec = ProcessSpec.build(valid_data)
    assert process_spec.uids == {'id': valid_data['uids']['id']}
    assert process_spec.tags == ['baking::cakes', 'danger::low']
    assert process_spec.parameters[0] == Parameter(name='oven temp',
                                                   value=UniformReal(
                                                       195, 205, ''),
                                                   origin='specified')
    assert process_spec.conditions == []
    assert process_spec.template == \
           ProcessTemplate('the template', uids={'id': valid_data['template']['uids']['id']},
                           parameters=[
                               [ParameterTemplate('oven temp template',
                                                  bounds=RealBounds(175, 225, ''),
                                                  uids={'id': valid_data['template']['parameters'][0][0]['uids']['id']}),
                                RealBounds(175, 225, '')]
                           ],
                           description='a long description',
                           allowed_labels=['a', 'b'],
                           allowed_names=['a name'])
    assert process_spec.name == 'Process 1'
    assert process_spec.notes == 'make sure to use oven mitts'
    assert process_spec.file_links == [
        FileLink('cake_recipe.txt', 'www.baking.com')
    ]
    assert process_spec.typ == 'process_spec'
Beispiel #3
0
def test_access_data():
    """Demonstrate and test access patterns within the data island."""
    binders = {
        "Polyethylene Glycol 100M": 0.02,
        "Sodium lignosulfonate": 0.004,
        "Polyvinyl Acetate": 0.0001
    }
    powders = {"Al2O3": 0.96}
    island = make_data_island(
        density=1.0,
        bulk_modulus=300.0,
        firing_temperature=750.0,
        binders=binders,
        powders=powders,
        tag="Me"
    )

    # read the density value
    assert(island.measurements[0].properties[0].value == NominalReal(1.0, ''))
    # read the bulk modulus value
    assert(island.measurements[0].properties[1].value == NormalReal(300.0, 3.0, ''))
    # read the firing temperature
    assert(island.process.conditions[0].value == UniformReal(749.5, 750.5, 'degC'))
    assert(island.process.parameters[0].value == DiscreteCategorical({"hot": 1.0}))

    # read the quantity of alumina
    quantities = island.process.ingredients[0].material.process.conditions[0].value.quantities
    assert(list(
        keyfilter(lambda x: x == "Al2O3", quantities).values()
    )[0] == 0.96)

    # check that the serialization results in the correct number of objects in the preface
    # (note that neither measurements nor ingredients are serialized)
    assert(len(json.loads(dumps(island))["context"]) == 26)
Beispiel #4
0
def test_invalid_instance():
    """Calling make_instance on a non-spec should throw a TypeError."""
    not_specs = [
        MeasurementRun("meas"),
        Condition("cond"),
        UniformReal(0, 1, ''), 'foo', 10
    ]
    for not_spec in not_specs:
        with pytest.raises(TypeError):
            make_instance(not_spec)
def test_simple_deserialization(valid_data):
    """Ensure that a deserialized Process Run looks sane."""
    process_run: ProcessRun = ProcessRun.build(valid_data)
    assert process_run.uids == {'id': valid_data['uids']['id'], 'my_id': 'process1-v1'}
    assert process_run.tags == ['baking::cakes', 'danger::low']
    assert process_run.conditions[0] == Condition(name='oven temp',
                                                         value=NominalReal(203.0, ''),
                                                         origin='measured')
    assert process_run.parameters == []
    assert process_run.file_links == []
    assert process_run.template is None
    assert process_run.output_material is None
    assert process_run.spec == \
           ProcessSpec(name="Spec for proc 1",
                       uids={'id': valid_data['spec']['uids']['id']},
                       conditions=[Condition(name='oven temp', value=UniformReal(175, 225, ''),
                                             origin='specified')]
                       )
    assert process_run.name == 'Process 1'
    assert process_run.notes == 'make sure to use oven mitts'
    assert process_run.typ == 'process_run'
Beispiel #6
0
def test_bounds_order():
    """Lower bound must be <= upper bound."""
    UniformReal(4.4, 8.8, 'm')
    UniformReal(100.0, 100.0, 'm')
    with pytest.raises(AssertionError):
        UniformReal(23.2, 18.9, 'm')
Beispiel #7
0
    assert frying.ingredients == []

    oil.process = frying
    assert oil.process == frying
    assert boiling.ingredients == [potatoes]
    assert frying.ingredients == [oil]

    potatoes.process = frying
    assert potatoes.process == frying
    assert boiling.ingredients == []
    assert set(frying.ingredients) == {oil, potatoes}


VALID_QUANTITIES = [
    NominalReal(14.0, ''),
    UniformReal(0.5, 0.6, 'm'),
    NormalReal(-0.3, 0.6, "kg")
]

INVALID_QUANTITIES = [
    NominalCategorical("blue"),
    NominalInteger(5),
    EmpiricalFormula("CH4"),
    0.33,
    "0.5"
]


@pytest.mark.parametrize("valid_quantity", VALID_QUANTITIES)
def test_valid_quantities(valid_quantity):
    """
Beispiel #8
0
def test_invalid_bounds():
    """Test that invalid bounds throw the appropriate error."""
    with pytest.raises(ValueError):
        SampleAttributeTemplate(name="name")  # Must have a bounds
    with pytest.raises(TypeError):
        SampleAttributeTemplate(name="name", bounds=UniformReal(0, 1, ''))
Beispiel #9
0
def make_data_island(density, bulk_modulus, firing_temperature, binders, powders, tag=None):
    """Helper function to create a relatively involved data island."""
    binder_specs = keymap(lambda x: MaterialSpec(name=x), binders)
    powder_specs = keymap(lambda x: MaterialSpec(name=x), powders)

    binder_runs = keymap(lambda x: MaterialRun(spec=x), binder_specs)
    powder_runs = keymap(lambda x: MaterialRun(spec=x), powder_specs)

    all_input_materials = keymap(lambda x: x.spec.name, merge(binder_runs, powder_runs))
    mixing_composition = Condition(
        name="composition",
        value=NominalComposition(all_input_materials)
    )
    mixing_process = ProcessRun(
        tags=["mixing"],
        conditions=[mixing_composition]
    )
    binder_ingredients = []
    for run in binder_runs:
        binder_ingredients.append(
            IngredientRun(
                material=run,
                process=mixing_process,
                mass_fraction=NominalReal(binders[run.spec.name], ''),
            )
        )

    powder_ingredients = []
    for run in powder_runs:
        powder_ingredients.append(
            IngredientRun(
                material=run,
                process=mixing_process,
                mass_fraction=NominalReal(powders[run.spec.name], ''),
            )
        )

    green_sample = MaterialRun(process=mixing_process)

    measured_firing_temperature = Condition(
        name="Firing Temperature",
        value=UniformReal(firing_temperature - 0.5, firing_temperature + 0.5, 'degC'),
        template=firing_temperature_template
    )

    specified_firing_setting = Parameter(
        name="Firing setting",
        value=DiscreteCategorical("hot")
    )
    firing_spec = ProcessSpec(template=firing_template)
    firing_process = ProcessRun(
        conditions=[measured_firing_temperature],
        parameters=[specified_firing_setting],
        spec=firing_spec
    )
    IngredientRun(
        green_sample,
        process=firing_process,
        mass_fraction=NormalReal(1.0, 0.0, ''),
        volume_fraction=NormalReal(1.0, 0.0, ''),
        number_fraction=NormalReal(1.0, 0.0, '')
    )

    measured_density = Property(
        name="Density",
        value=NominalReal(density, ''),
        template=density_template
    )
    measured_modulus = Property(
        name="Bulk modulus",
        value=NormalReal(bulk_modulus, bulk_modulus / 100.0, '')
    )
    measurement_spec = MeasurementSpec(template=measurement_template)
    measurement = MeasurementRun(
        properties=[measured_density, measured_modulus],
        spec=measurement_spec
    )

    tags = [tag] if tag else []

    material_spec = MaterialSpec(template=material_template)
    material_run = MaterialRun(process=firing_process, tags=tags, spec=material_spec)
    measurement.material = material_run
    return material_run
Beispiel #10
0
def make_cake(seed=None):
    """Define all objects that go into making a demo cake."""
    if seed is not None:
        random.seed(seed)
    ######################################################################
    # Parent Objects
    tmpl = make_cake_templates()
    cake_spec = make_cake_spec()

    ######################################################################
    # Objects
    cake = make_instance(cake_spec)
    operators = ['gwash', 'jadams', 'thomasj', 'jmadison', 'jmonroe']
    cake.process.source = PerformedSource(performed_by=random.choice(operators),
                                          performed_date='2015-03-14')
    # Replace Abstract/In General
    queue = [cake]
    while queue:
        item = queue.pop(0)
        item.name = item.name.replace('Abstract ', '').replace(', in General', '')
        if item.spec.tags is not None:
            item.tags = list(item.spec.tags)
        if item.spec.notes:  # None or empty string
            item.notes = 'The spec says "{}"'.format(item.spec.notes)

        if isinstance(item, MaterialRun):
            queue.append(item.process)
        elif isinstance(item, ProcessRun):
            queue.extend(item.ingredients)
            if item.template.name == "Procurement":
                item.source = PerformedSource(performed_by='hamilton',
                                              performed_date='2015-02-17')
            else:
                item.source = cake.process.source
        elif isinstance(item, IngredientRun):
            queue.append(item.material)
            fuzz = 0.95 + 0.1 * random.random()
            if item.spec.absolute_quantity is not None:
                item.absolute_quantity = \
                    NormalReal(mean=fuzz * item.spec.absolute_quantity.nominal,
                               std=0.05 * item.spec.absolute_quantity.nominal,
                               units=item.spec.absolute_quantity.units)
            if item.spec.volume_fraction is not None:
                item.volume_fraction = \
                    NormalReal(mean=fuzz * item.spec.volume_fraction.nominal,
                               std=0.05 * item.spec.volume_fraction.nominal,
                               units=item.spec.volume_fraction.units)
            if item.spec.mass_fraction is not None:
                item.mass_fraction = \
                    UniformReal(lower_bound=(fuzz - 0.05) * item.spec.mass_fraction.nominal,
                                upper_bound=(fuzz + 0.05) * item.spec.mass_fraction.nominal,
                                units=item.spec.mass_fraction.units)
            if item.spec.number_fraction is not None:
                item.number_fraction = \
                    NormalReal(mean=fuzz * item.spec.number_fraction.nominal,
                               std=0.05 * item.spec.number_fraction.nominal,
                               units=item.spec.number_fraction.units)

        else:
            raise TypeError("Unexpected object in the queue")

    frosting = \
        next(x.material for x in cake.process.ingredients if 'rosting' in x.name)
    baked = \
        next(x.material for x in cake.process.ingredients if 'aked' in x.name)

    # Add measurements
    cake_taste = MeasurementRun(name='Final Taste', material=cake)
    cake_appearance = MeasurementRun(name='Final Appearance', material=cake)
    frosting_taste = MeasurementRun(name='Frosting Taste', material=frosting)
    frosting_sweetness = MeasurementRun(name='Frosting Sweetness', material=frosting)

    # and spec out the measurements
    cake_taste.spec = MeasurementSpec(name='Taste')
    cake_appearance.spec = MeasurementSpec(name='Appearance')
    frosting_taste.spec = cake_taste.spec  # Taste
    frosting_sweetness.spec = MeasurementSpec(name='Sweetness')

    ######################################################################
    # Let's add some attributes
    baked.process.conditions.append(Condition(name='Cooking time',
                                              template=tmpl['Cooking time'],
                                              origin=Origin.MEASURED,
                                              value=NominalReal(nominal=48, units='min')))
    baked.spec.process.conditions.append(Condition(name='Cooking time',
                                                   template=tmpl['Cooking time'],
                                                   origin=Origin.SPECIFIED,
                                                   value=NormalReal(mean=50, std=5, units='min')))
    baked.process.conditions.append(Condition(name='Oven temperature',
                                              origin="measured",
                                              value=NominalReal(nominal=362, units='degF')))
    baked.spec.process.parameters.append(Parameter(name='Oven temperature setting',
                                                   template=tmpl['Oven temperature setting'],
                                                   origin="specified",
                                                   value=NominalReal(nominal=350, units='degF')))
    cake_taste.properties.append(Property(name='Tastiness',
                                          origin=Origin.MEASURED,
                                          template=tmpl['Tastiness'],
                                          value=NominalInteger(nominal=5)))
    cake_appearance.properties.append(Property(name='Visual Appeal',
                                               origin=Origin.MEASURED,
                                               value=NominalInteger(nominal=5)))
    frosting_taste.properties.append(Property(name='Tastiness',
                                              origin=Origin.MEASURED,
                                              template=tmpl['Tastiness'],
                                              value=NominalInteger(nominal=4)))
    frosting_sweetness.properties.append(Property(name='Sweetness (Sucrose-basis)',
                                                  origin=Origin.MEASURED,
                                                  value=NominalReal(nominal=1.7, units='')))

    baked.process.spec.template = tmpl['Baking in an oven']
    cake_taste.spec.template = tmpl['Taste test']
    frosting_taste.spec.template = tmpl['Taste test']

    cake.spec.template = tmpl['Dessert']
    frosting.spec.template = tmpl['Dessert']

    # Code to force all scopes to 'id'
    set_uuids([cake, cake_taste, cake_appearance, frosting_taste, frosting_sweetness], name='id')
    id_queue = [x for x in cake.process.ingredients]
    while id_queue:
        x = id_queue.pop(0)
        set_uuids([x], name='id')
        id_queue += x.material.process.ingredients

    return cake