예제 #1
0
def test_invalid_constructor():
    """Test types for constructor."""
    with pytest.raises(ValueError):
        CategoricalBounds(categories="foo")

    with pytest.raises(ValueError):
        CategoricalBounds(categories={1, 2})
예제 #2
0
def test_contains():
    """Test basic contains logic."""
    bounds = CategoricalBounds(categories={"spam", "eggs"})
    assert bounds.contains(CategoricalBounds(categories={"spam"}))
    assert not bounds.contains(CategoricalBounds(categories={"spam", "foo"}))
    assert not bounds.contains(RealBounds(0.0, 2.0, ''))
    assert not bounds.contains(None)
    with pytest.raises(TypeError):
        bounds.contains({"spam", "eggs"})
예제 #3
0
def test_categories():
    """Test categories setter."""
    assert CategoricalBounds().categories == set()
    assert CategoricalBounds(categories={"foo", "bar"}).categories == {
        "foo", "bar"
    }
    assert CategoricalBounds(categories=["foo", "bar"]).categories == {
        "foo", "bar"
    }
예제 #4
0
def test_numpy():
    """Test that ndarrays, Series work as well."""
    assert len(array_like()) < 5  # In case we extend at some point

    if len(array_like()) > 2:  # Test numpy
        import numpy as np
        np_bounds = CategoricalBounds(np.array(["spam", "eggs"], dtype=object))
        np_copy = loads(dumps(np_bounds))
        assert np_copy == np_bounds

    if len(array_like()) > 3:  # Test numpy
        import pandas as pd
        pd_bounds = CategoricalBounds(pd.Series(["spam", "eggs"]))
        pd_copy = loads(dumps(pd_bounds))
        assert pd_copy == pd_bounds
예제 #5
0
def test_object_template_serde():
    """Test serde of an object template."""
    length_template = PropertyTemplate("Length", RealBounds(2.0, 3.5, 'cm'))
    sub_bounds = RealBounds(2.5, 3.0, 'cm')
    color_template = PropertyTemplate("Color", CategoricalBounds(["red", "green", "blue"]))
    # Properties are a mixture of property templates and [template, bounds], pairs
    block_template = MaterialTemplate("Block", properties=[[length_template, sub_bounds],
                                                           color_template])
    copy_template = MaterialTemplate.build(block_template.dump())
    assert copy_template == block_template

    # Tests below exercise similar code, but for measurement and process templates
    pressure_template = ConditionTemplate("pressure", RealBounds(0.1, 0.11, 'MPa'))
    index_template = ParameterTemplate("index", IntegerBounds(2, 10))
    meas_template = MeasurementTemplate("A measurement of length", properties=[length_template],
                                        conditions=[pressure_template], description="Description",
                                        parameters=[index_template], tags=["foo"])
    assert MeasurementTemplate.build(meas_template.dump()) == meas_template

    proc_template = ProcessTemplate("Make an object", parameters=[index_template],
                                    conditions=[pressure_template], allowed_labels=["Label"],
                                    allowed_names=["first sample", "second sample"])
    assert ProcessTemplate.build(proc_template.dump()) == proc_template

    # Check that serde still works if the template is a LinkByUID
    proc_template.conditions[0][0] = LinkByUID('id', pressure_template.uids['id'])
    assert ProcessTemplate.build(proc_template.dump()) == proc_template
예제 #6
0
def test_flatten_bounds():
    """Test that flatten works when the objects contain other objects."""
    bounds = CategoricalBounds(categories=["foo", "bar"])
    template = ProcessTemplate("spam",
                               conditions=[(ConditionTemplate(name="eggs",
                                                              bounds=bounds),
                                            bounds)])
    spec = ProcessSpec(name="spec", template=template)

    flat = flatten(spec)
    assert len(flat) == 2, "Expected 2 flattened objects"
예제 #7
0
def test_object_template_validation():
    """Test that attribute templates are validated against given bounds."""
    length_template = PropertyTemplate("Length", RealBounds(2.0, 3.5, 'cm'))
    dial_template = ConditionTemplate("dial", IntegerBounds(0, 5))
    color_template = ParameterTemplate(
        "Color", CategoricalBounds(["red", "green", "blue"]))

    with pytest.raises(ValueError):
        MaterialTemplate(
            "Block",
            properties=[[length_template,
                         RealBounds(3.0, 4.0, 'cm')]])

    with pytest.raises(ValueError):
        ProcessTemplate(
            "a process",
            conditions=[[color_template,
                         CategoricalBounds(["zz"])]])

    with pytest.raises(ValueError):
        MeasurementTemplate("A measurement",
                            parameters=[[dial_template,
                                         IntegerBounds(-3, -1)]])
def test_fields_from_property():
    """Test that several fields of the attribute are derived from the property."""
    prop_template = PropertyTemplate(name="cookie eating template",
                                     bounds=IntegerBounds(0, 1000))
    cond_template = ConditionTemplate(name="Hunger template",
                                      bounds=CategoricalBounds(
                                          ["hungry", "full", "peckish"]))
    prop = Property(name="number of cookies eaten",
                    template=prop_template,
                    origin='measured',
                    value=NominalInteger(27))
    cond = Condition(name="hunger level",
                     template=cond_template,
                     origin='specified',
                     value=NominalCategorical("hungry"))

    prop_and_conds = PropertyAndConditions(property=prop, conditions=[cond])
    assert prop_and_conds.name == prop.name
    assert prop_and_conds.template == prop.template
    assert prop_and_conds.origin == prop.origin
    assert prop_and_conds.value == prop.value
예제 #9
0
def make_templates():
    """Build all templates needed for the table."""
    tmpl = dict()

    # Attribute Templates
    attribute_feed = {
        "Formula": [
            PropertyTemplate,
            CompositionBounds(components=EmpiricalFormula.all_elements())
        ],
        "Crystallinity": [
            ConditionTemplate,
            CategoricalBounds(
                ['Amorphous', 'Polycrystalline', 'Single crystalline'])
        ],
        "Color": [
            PropertyTemplate,
            CategoricalBounds([
                'Amber', 'Black', 'Blue', 'Bluish', 'Bronze', 'Brown',
                'Brown-Black', 'Copper-Red', 'Dark Brown', 'Dark Gray',
                'Dark Green', 'Dark Red', 'Gray', 'Light Gray', 'Ocher',
                'Orange', 'Orange-Red', 'Pale Yellow', 'Red', 'Red-Yellow',
                'Violet', 'White', 'Yellow', 'Yellow-Orange', 'Yellow-White'
            ])
        ],
        "Band gap": [
            PropertyTemplate,
            RealBounds(lower_bound=0.001, upper_bound=100, default_units='eV')
        ],
        "Temperature": [
            ConditionTemplate,
            RealBounds(lower_bound=1, upper_bound=1000, default_units='K')
        ],
        "Temperature derivative of band gap": [
            PropertyTemplate,
            RealBounds(lower_bound=-0.01,
                       upper_bound=0.01,
                       default_units='eV/K')
        ],
        "Lasing": [PropertyTemplate,
                   CategoricalBounds(['True', 'False'])],
        "Cathodoluminescence":
        [PropertyTemplate,
         CategoricalBounds(['True', 'False'])],
        "Mechanical luminescence":
        [PropertyTemplate,
         CategoricalBounds(['True', 'False'])],
        "Photoluminescence":
        [PropertyTemplate,
         CategoricalBounds(['True', 'False'])],
        "Electroluminescence":
        [PropertyTemplate,
         CategoricalBounds(['True', 'False'])],
        "Thermoluminescence":
        [PropertyTemplate,
         CategoricalBounds(['True', 'False'])],
        "Morphology":
        [ConditionTemplate,
         CategoricalBounds(['Thin film', 'Bulk'])],
        "Electric field polarization": [
            ConditionTemplate,
            CategoricalBounds([
                'Parallel to A axis', 'Parallel to B axis',
                'Parallel to C axis', 'Perpendicular to B axis',
                'Perpendicular to C axis'
            ])
        ],
        "Phase": [
            ConditionTemplate,
            CategoricalBounds([
                'A', 'B', 'B1', 'B2', 'Fused quartz', 'Natural diamond',
                'Rutile', 'Sapphire', 'Synthetic quartz'
            ])
        ],
        "Crystal system": [
            ConditionTemplate,
            CategoricalBounds([
                'Cubic', 'Hexagonal', 'Orthorhombic', 'Tetragonal', 'Trigonal'
            ])
        ],
        "Transition": [
            ConditionTemplate,
            CategoricalBounds(['Direct', 'Excitonic', 'Indirect'])
        ],
        "Bands": [
            ConditionTemplate,
            CategoricalBounds([
                'G1 to X1', 'G15 to G1', 'G15 to X1', 'G25 to G1',
                'G25 to G12', 'G25 to G15', 'G6 to G8', 'G8 to G6+',
                'L6+ to L6-'
            ])
        ]
    }
    for (name, (typ, bounds)) in attribute_feed.items():
        assert name not in tmpl
        tmpl[name] = typ(name=name,
                         bounds=bounds,
                         uids={DEMO_SCOPE + '-template': name},
                         tags=['citrine::demo::template::attribute'])

    # Object Templates
    object_feed = {
        "Sample preparation": [ProcessTemplate, dict()],
        "Chemical": [MaterialTemplate, {
            "properties": [tmpl["Formula"]]
        }],
        "Band gap measurement": [
            MeasurementTemplate, {
                "properties": [
                    tmpl["Band gap"],
                    tmpl["Temperature derivative of band gap"], tmpl["Color"],
                    tmpl["Lasing"], tmpl["Cathodoluminescence"],
                    tmpl["Mechanical luminescence"], tmpl["Photoluminescence"],
                    tmpl["Electroluminescence"], tmpl["Thermoluminescence"]
                ],
                "conditions": [
                    tmpl["Temperature"], tmpl["Crystallinity"],
                    tmpl["Morphology"], tmpl["Electric field polarization"],
                    tmpl["Phase"], tmpl["Crystal system"], tmpl["Transition"],
                    tmpl["Bands"]
                ]
            }
        ],
    }
    for (name, (typ, kw_args)) in object_feed.items():
        assert name not in tmpl
        tmpl[name] = typ(name=name,
                         uids={DEMO_SCOPE + '-template': name},
                         tags=['citrine::demo::template::object'],
                         **kw_args)

    return tmpl
예제 #10
0
from taurus.entity.bounds.categorical_bounds import CategoricalBounds
from taurus.entity.bounds.real_bounds import RealBounds
from taurus.entity.value.uniform_real import UniformReal
from taurus.entity.template.attribute_template import AttributeTemplate
from taurus.entity.template.property_template import PropertyTemplate
from taurus.client.json_encoder import dumps, loads


class SampleAttributeTemplate(AttributeTemplate):
    """A class to flex the base attribute template."""

    typ = "sample_attribute_template"


cat_bounds = CategoricalBounds(categories={"a", "b", "c"})


def test_name_is_a_string():
    """Test that name is a string."""
    with pytest.raises(ValueError) as error:
        SampleAttributeTemplate(name=42, bounds=cat_bounds)

    assert "must be a string" in str(error.value)


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):
def test_property_template():
    """Test creation and serde of condition templates."""
    bounds = CategoricalBounds(['solid', 'liquid', 'gas'])
    template = PropertyTemplate("State", bounds=bounds, uids={'my_id': '0'})
    assert PropertyTemplate.build(template.dump()) == template
예제 #12
0
        name="kinematic viscosity",
        bounds=RealBounds(lower_bound=0.0, upper_bound=10.0**40, default_units="m^2 / s")
    )
}

known_conditions = {
    "temperature": ConditionTemplate(
        name="temperature",
        bounds=RealBounds(lower_bound=0.0, upper_bound=1000.0, default_units='K')
    )
}

known_parameters = {
    "knob_2_setting": ParameterTemplate(
        name="knob_2_setting",
        bounds=CategoricalBounds(categories={"low", "medium", "high"})
    )
}


def _parse_value(val):
    """Example field-parsing logic."""
    # If the string is complicated, split it up and try to get uncertainty and/or units
    if isinstance(val, str) and len(val.split()) > 1:
        toks = val.split()
        mean = float(toks[0])
        std = -1
        if toks[1] in {"+-", "+/-"}:
            std = float(toks[2])

        try:
예제 #13
0
def test_json():
    """Test that serialization works (categories is encoded as a list)."""
    bounds = CategoricalBounds(categories={"spam", "eggs"})
    copy = loads(dumps(bounds))
    assert copy == bounds