Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/citrine/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "3.13.0"
__version__ = "3.14.0"
7 changes: 4 additions & 3 deletions src/citrine/informatics/predictors/__init__.py
Original file line number Diff line number Diff line change
@@ -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 *
Original file line number Diff line number Diff line change
@@ -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 '<AttributeAccumulationPredictor {!r}>'.format(self.name)
22 changes: 12 additions & 10 deletions src/citrine/informatics/predictors/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
19 changes: 19 additions & 0 deletions tests/informatics/test_predictors.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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 = '<AttributeAccumulationPredictor \'Attribute accumulation predictor\'>'
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
Expand Down