diff --git a/src/citrine/__version__.py b/src/citrine/__version__.py index 62ee17b83..382c7be00 100644 --- a/src/citrine/__version__.py +++ b/src/citrine/__version__.py @@ -1 +1 @@ -__version__ = "3.13.0" +__version__ = "3.14.0" diff --git a/src/citrine/informatics/predictors/__init__.py b/src/citrine/informatics/predictors/__init__.py index e22ecf3d0..64daca963 100644 --- a/src/citrine/informatics/predictors/__init__.py +++ b/src/citrine/informatics/predictors/__init__.py @@ -1,15 +1,16 @@ # flake8: noqa from .predictor import * from .node import * +from .auto_ml_predictor import * +from .attribute_accumulation_predictor import * +from .chemical_formula_featurizer import * from .expression_predictor import * from .graph_predictor import * from .ingredient_fractions_predictor import * from .ingredients_to_formulation_predictor import * from .label_fractions_predictor import * from .molecular_structure_featurizer import * -from .chemical_formula_featurizer import * -from .simple_mixture_predictor import * -from .auto_ml_predictor import * from .mean_property_predictor import * +from .simple_mixture_predictor import * from .single_predict_request import * from .single_prediction import * diff --git a/src/citrine/informatics/predictors/attribute_accumulation_predictor.py b/src/citrine/informatics/predictors/attribute_accumulation_predictor.py new file mode 100644 index 000000000..963da002d --- /dev/null +++ b/src/citrine/informatics/predictors/attribute_accumulation_predictor.py @@ -0,0 +1,33 @@ +from typing import List + +from citrine._rest.resource import Resource +from citrine._serialization import properties as _properties +from citrine.informatics.descriptors import Descriptor +from citrine.informatics.predictors import PredictorNode + + +class AttributeAccumulationPredictor(Resource["AttributeAccumulationPredictor"], PredictorNode): + """A node to support propagating attributes through training. + + You should never have to add this node yourself: the backend should be able to automatically + create it when necessary. + """ + + attributes = _properties.List(_properties.Object(Descriptor), 'attributes') + sequential = _properties.Boolean('sequential') + + typ = _properties.String('type', default='AttributeAccumulation', deserializable=False) + + def __init__(self, + name: str, + *, + description: str, + attributes: List[Descriptor], + sequential: bool): + self.name = name + self.description = description + self.attributes = attributes + self.sequential = sequential + + def __str__(self): + return ''.format(self.name) diff --git a/src/citrine/informatics/predictors/node.py b/src/citrine/informatics/predictors/node.py index 637b43400..d20b6cdef 100644 --- a/src/citrine/informatics/predictors/node.py +++ b/src/citrine/informatics/predictors/node.py @@ -19,25 +19,27 @@ class PredictorNode(PolymorphicSerializable["PredictorNode"], Predictor): @classmethod def get_type(cls, data) -> Type['PredictorNode']: """Return the subtype.""" + from .auto_ml_predictor import AutoMLPredictor + from .attribute_accumulation_predictor import AttributeAccumulationPredictor + from .chemical_formula_featurizer import ChemicalFormulaFeaturizer from .expression_predictor import ExpressionPredictor - from .molecular_structure_featurizer import MolecularStructureFeaturizer + from .ingredient_fractions_predictor import IngredientFractionsPredictor from .ingredients_to_formulation_predictor import IngredientsToFormulationPredictor from .label_fractions_predictor import LabelFractionsPredictor - from .simple_mixture_predictor import SimpleMixturePredictor - from .ingredient_fractions_predictor import IngredientFractionsPredictor - from .auto_ml_predictor import AutoMLPredictor from .mean_property_predictor import MeanPropertyPredictor - from .chemical_formula_featurizer import ChemicalFormulaFeaturizer + from .molecular_structure_featurizer import MolecularStructureFeaturizer + from .simple_mixture_predictor import SimpleMixturePredictor type_dict = { "AnalyticExpression": ExpressionPredictor, - "MoleculeFeaturizer": MolecularStructureFeaturizer, + "AttributeAccumulation": AttributeAccumulationPredictor, + "AutoML": AutoMLPredictor, + "ChemicalFormulaFeaturizer": ChemicalFormulaFeaturizer, + "IngredientFractions": IngredientFractionsPredictor, "IngredientsToSimpleMixture": IngredientsToFormulationPredictor, - "MeanProperty": MeanPropertyPredictor, "LabelFractions": LabelFractionsPredictor, + "MeanProperty": MeanPropertyPredictor, + "MoleculeFeaturizer": MolecularStructureFeaturizer, "SimpleMixture": SimpleMixturePredictor, - "IngredientFractions": IngredientFractionsPredictor, - "ChemicalFormulaFeaturizer": ChemicalFormulaFeaturizer, - "AutoML": AutoMLPredictor, } typ = type_dict.get(data['type']) if typ is not None: diff --git a/tests/informatics/test_predictors.py b/tests/informatics/test_predictors.py index da98b2717..6eff41b5f 100644 --- a/tests/informatics/test_predictors.py +++ b/tests/informatics/test_predictors.py @@ -205,6 +205,16 @@ def ingredient_fractions_predictor() -> IngredientFractionsPredictor: ) +@pytest.fixture +def attribute_accumulation_predictor() -> AttributeAccumulationPredictor: + return AttributeAccumulationPredictor( + name="Attribute accumulation predictor", + description="Aid training", + attributes=[x, y], + sequential=True + ) + + def test_simple_report(graph_predictor): """Ensures we get a report from a simple predictor post_build call""" with pytest.raises(ValueError): @@ -458,6 +468,15 @@ def test_ingredient_fractions_property_initialization(ingredient_fractions_predi assert str(ingredient_fractions_predictor) == expected_str +def test_attribute_accumulation_property_initialization(attribute_accumulation_predictor): + """Make sure the correct fields go to the correct places for an attribute accumulation predictor.""" + assert attribute_accumulation_predictor.name == 'Attribute accumulation predictor' + assert attribute_accumulation_predictor.attributes == [x, y] + assert attribute_accumulation_predictor.sequential is True + expected_str = '' + assert str(attribute_accumulation_predictor) == expected_str + + def test_status(graph_predictor, valid_graph_predictor_data): """Ensure we can check the status of predictor validation.""" # A locally built predictor should be "False" for all status checks