class GemTableDataSource(Serializable['GemTableDataSource'], DataSource):
    """[ALPHA] A data source based on a GEM Table hosted on the data platform.

    Parameters
    ----------
    table_id: UUID
        Unique identifier for the GEM Table
    table_version: Union[str,int]
        Version number for the GEM Table, which starts at 1 rather than 0.
        Strings are cast to ints.
    formulation_descriptor: Optional[FormulationDescriptor]
        Optional descriptor used to store formulations emitted by the data source.

    """

    typ = properties.String('type',
                            default='hosted_table_data_source',
                            deserializable=False)
    table_id = properties.UUID("table_id")
    table_version = properties.Integer("table_version")
    formulation_descriptor = properties.Optional(
        properties.Object(FormulationDescriptor), "formulation_descriptor")

    def _attrs(self) -> List[str]:
        return ["table_id", "table_version", "typ"]

    def __init__(
            self,
            table_id: UUID,
            table_version: Union[int, str],
            formulation_descriptor: Optional[FormulationDescriptor] = None):
        self.table_id: UUID = table_id
        self.table_version: Union[int, str] = table_version
        self.formulation_descriptor: Optional[
            FormulationDescriptor] = formulation_descriptor
class NthBiggestComponentQuantityColumn(
        Serializable["NthBiggestComponentQuantityColumn"], Column):
    """[ALPHA] Quantity of the Nth biggest component.

    If there are fewer than N components in the composition, then this column will be empty.

    Parameters
    ----------
    data_source: str
        name of the variable to use when populating the column
    n: int
        index of the component quantity to extract, starting with 1 for the biggest
    normalize: bool
        whether to normalize the quantity by the sum of all component amounts. Default is false

    """

    data_source = properties.String('data_source')
    n = properties.Integer("n")
    normalize = properties.Boolean("normalize")
    typ = properties.String('type',
                            default="biggest_component_quantity_column",
                            deserializable=False)

    def _attrs(self) -> List[str]:
        return ["data_source", "n", "normalize", "typ"]

    def __init__(self, *, data_source: str, n: int, normalize: bool = False):
        self.data_source = data_source
        self.n = n
        self.normalize = normalize
class NthBiggestComponentNameColumn(
        Serializable["NthBiggestComponentNameColumn"], Column):
    """[ALPHA] Name of the Nth biggest component.

    If there are fewer than N components in the composition, then this column will be empty.

    Parameters
    ----------
    data_source: str
        name of the variable to use when populating the column
    n: int
        index of the component name to extract, starting with 1 for the biggest

    """

    data_source = properties.String('data_source')
    n = properties.Integer("n")
    typ = properties.String('type',
                            default="biggest_component_name_column",
                            deserializable=False)

    def _attrs(self) -> List[str]:
        return ["data_source", "n", "typ"]

    def __init__(self, *, data_source: str, n: int):
        self.data_source = data_source
        self.n = n
Example #4
0
class PredictedVsActualRealPoint(Serializable["PredictedVsActualRealPoint"]):
    """Predicted vs. actual data for a single real-valued data point."""

    uuid = properties.UUID("uuid")
    """:UUID: Unique Citrine id given to the candidate"""
    identifiers = properties.Set(properties.String, "identifiers")
    """:Set[str]: Set of globally unique identifiers given to the candidate"""
    trial = properties.Integer("trial")
    """:int: 1-based index of the trial this candidate belonged to"""
    fold = properties.Integer("fold")
    """:int: 1-based index of the fold this candidate belonged to"""
    predicted = properties.Object(RealMetricValue, "predicted")
    """:RealMetricValue: Predicted value"""
    actual = properties.Object(RealMetricValue, "actual")
    """:RealMetricValue: Actual value"""
    def __init__(self):
        pass  # pragma: no cover
Example #5
0
class WorkflowExecution(Resource['WorkflowExecution']):
    """[ALPHA] A Citrine Workflow Execution.

    Parameters
    ----------
    uid: str
        Unique identifier of the workflow execution
    project_id: str
        Unique identifier of the project that contains the workflow execution
    workflow_id: str
        Unique identifier of the workflow that was executed
    version_number: int
        Integer identifier that increases each time the workflow is executed.  The first execution
        has version_number = 1.

    """

    _response_key = 'WorkflowExecutions'

    uid = properties.UUID('id')
    project_id = properties.UUID('project_id', deserializable=False)
    workflow_id = properties.UUID('workflow_id', deserializable=False)
    version_number = properties.Integer("version_number")

    def __init__(
        self,
        uid: Optional[str] = None,
        project_id: Optional[str] = None,
        workflow_id: Optional[str] = None,
        session: Optional[Session] = None,
        version_number: Optional[int] = None,
    ):
        self.uid: str = uid
        self.project_id: str = project_id
        self.workflow_id: str = workflow_id
        self.session: Session = session
        self.version_number = version_number

    def __str__(self):
        return '<WorkflowExecution {!r}>'.format(str(self.uid))

    def _path(self):
        return '/projects/{project_id}/workflows/{workflow_id}/executions/{execution_id}'.format(
            **{
                "project_id": self.project_id,
                "workflow_id": self.workflow_id,
                "execution_id": self.uid
            })

    def status(self):
        """Get the current status of this execution."""
        response = self.session.get_resource(self._path() + "/status")
        return WorkflowExecutionStatus.build(response)

    def results(self):
        """Get the results of this execution."""
        return self.session.get_resource(self._path() + "/results")
Example #6
0
class DummyDescriptor(object):
    dummy_map = properties.Mapping(properties.Float(), properties.String)
    dummy_list = properties.List(properties.Float, properties.String)
    dummy_set = properties.Set(type(properties.Float()))
    link_or_else = properties.LinkOrElse()
    map_collection_key = properties.Mapping(
        properties.Optional(properties.String), properties.Integer)
    specified_mixed_list = properties.SpecifiedMixedList(
        [properties.Integer(default=100)])
Example #7
0
class PredictedVsActualCategoricalPoint(
        Serializable["PredictedVsActualCategoricalPoint"]):
    """Predicted vs. actual data for a single categorical data point."""

    uuid = properties.UUID("uuid")
    """:UUID: Unique Citrine id given to the candidate"""
    identifiers = properties.Set(properties.String, "identifiers")
    """:Set[str]: Set of globally unique identifiers given to the candidate"""
    trial = properties.Integer("trial")
    """:int: 1-based index of the trial this candidate belonged to"""
    fold = properties.Integer("fold")
    """:int: 1-based index of the fold this candidate belonged to"""
    predicted = properties.Mapping(properties.String, properties.Float,
                                   "predicted")
    """:Dict[str, float]: Predicted class probabilities defined as a map from each class name
    to its relative frequency"""
    actual = properties.Mapping(properties.String, properties.Float, "actual")
    """:Dict[str, float]: Actual class probabilities defined as a map from each class name
    to its relative frequency"""
    def __init__(self):
        pass  # pragma: no cover
class IngredientCountConstraint(Serializable['IngredientCountConstraint'], Constraint):
    """Represents a constraint on the total number of ingredients in a formulation.

    Parameters
    ----------
    formulation_descriptor: FormulationDescriptor
        descriptor to constrain
    min: int
        minimum ingredient count
    max: int
        maximum ingredient count
    label: Optional[str]
        Optional label to constrain.
        If specified, then only ingredients with the specified label will count towards the total.
        Default is ``None``; all ingredients count towards the total

    """

    formulation_descriptor = properties.Object(FormulationDescriptor, 'formulation_descriptor')
    min = properties.Integer('min')
    max = properties.Integer('max')
    label = properties.Optional(properties.String, 'label')
    typ = properties.String('type', default='IngredientCountConstraint')

    def __init__(self, *,
                 formulation_descriptor: FormulationDescriptor,
                 min: int,
                 max: int,
                 label: Optional[str] = None,
                 session: Optional[Session] = None):
        self.formulation_descriptor: FormulationDescriptor = formulation_descriptor
        self.min: int = min
        self.max: int = max
        self.label: Optional[str] = label
        self.session: Optional[Session] = session

    def __str__(self):
        return '<IngredientCountConstraint {!r}>'.format(self.formulation_descriptor.key)
class EnumeratedProcessor(Serializable['EnumeratedProcessor'], Processor):
    """Process a design space by enumerating up to `max_size` materials from the domain and processing each
    independently.

    Parameters
    ----------
    name: str
        name of the processor
    description: str
        description of the processor
    max_size: int
        maximum number of samples that can be enumerated over
    """

    uid = properties.Optional(properties.UUID, 'id', serializable=False)
    name = properties.String('config.name')
    description = properties.Optional(properties.String(),
                                      'config.description')
    max_size = properties.Integer('config.max_size')
    typ = properties.String('config.type',
                            default='Enumerated',
                            deserializable=False)
    status = properties.String('status', serializable=False)
    status_info = properties.Optional(properties.List(properties.String()),
                                      'status_info',
                                      serializable=False)

    # NOTE: These could go here or in _post_dump - it's unclear which is better right now
    module_type = properties.String('module_type', default='PROCESSOR')
    schema_id = properties.UUID(
        'schema_id', default=UUID('307b88a2-fd50-4d27-ae91-b8d6282f68f7'))

    def __init__(self,
                 name: str,
                 description: str,
                 max_size: Optional[int] = None,
                 session: Optional[Session] = None):
        self.name: str = name
        self.description: str = description
        self.max_size: int = max_size or 2**31 - 1  # = 2147483647 (max 32-bit integer)
        self.session: Optional[Session] = session

    def _post_dump(self, data: dict) -> dict:
        data['display_name'] = data['config']['name']
        return data

    def __str__(self):
        return '<EnumeratedProcessor {!r}>'.format(self.name)
Example #10
0
class GemTableDataSource(Serializable['GemTableDataSource'], DataSource):
    """A data source based on a GEM Table hosted on the data platform.

    Parameters
    ----------
    table_id: UUID
        Unique identifier for the GEM Table
    table_version: Union[str,int]
        Version number for the GEM Table. The first GEM table built from a configuration
        has version = 1. Strings are cast to ints.
    formulation_descriptor: Optional[FormulationDescriptor]
        Optional descriptor used to store formulations emitted by the data source.
        If the data source emits a formulation but this argument is not provided, then a
        default formulation descriptor will be generated. The formulations descriptor, and
        other descriptors, can be retrieved using
        :func:`~citrine.resources.descriptors.DescriptorMethods.descriptors_from_data_source`.

    """

    typ = properties.String('type', default='hosted_table_data_source', deserializable=False)
    table_id = properties.UUID("table_id")
    table_version = properties.Integer("table_version")
    formulation_descriptor = properties.Optional(
        properties.Object(FormulationDescriptor),
        "formulation_descriptor"
    )

    def _attrs(self) -> List[str]:
        return ["table_id", "table_version", "typ"]

    def __init__(self,
                 table_id: UUID,
                 table_version: Union[int, str],
                 formulation_descriptor: Optional[FormulationDescriptor] = None):
        self.table_id: UUID = table_id
        self.table_version: Union[int, str] = table_version
        self.formulation_descriptor: Optional[FormulationDescriptor] = formulation_descriptor
class CrossValidationEvaluator(Serializable["CrossValidationEvaluator"], PredictorEvaluator):
    """Evaluate a predictor via cross validation.

    Performs cross-validation on requested predictor responses and computes the requested metrics
    on each response. For a discussion of how many folds and trials to use,
    please see the :ref:`documentation<Cross-validation evaluator>`.

    In addition to a name, set of responses to validate, trials, folds and metrics to compute,
    this evaluator defines a set of descriptor keys to ignore when grouping.  Candidates with
    different values for ignored keys and identical values for all other predictor inputs will be
    placed in the same fold.  For example, if you are baking cakes with different ingredients and
    different oven temperatures and want to group together the data by the ingredients, then you
    can set `ignore_when_grouping={"oven temperature"}`. That way, two recipes that differ only in
    their oven temperature will always end up in the same fold.

    Parameters
    ----------
    name: str
        Name of the evaluator
    description: str
        Description of the evaluator
    responses: Set[str]
        Set of descriptor keys to evaluate
    n_folds: int
        Number of cross-validation folds
    n_trials: int
        Number of cross-validation trials, each contains ``n_folds`` folds
    metrics: Optional[Set[PredictorEvaluationMetric]]
        Optional set of metrics to compute for each response.
        Default is all metrics.
    ignore_when_grouping: Optional[Set[str]]
        Set of descriptor keys to group together.
        Candidates with different values for the given keys and identical values
        for all other descriptors will be in the same group.

    """

    def _attrs(self) -> List[str]:
        return ["typ", "name", "description",
                "responses", "n_folds", "n_trials", "metrics", "ignore_when_grouping"]

    name = properties.String("name")
    description = properties.String("description")
    _responses = properties.Set(properties.String, "responses")
    n_folds = properties.Integer("n_folds")
    n_trials = properties.Integer("n_trials")
    _metrics = properties.Optional(properties.Set(properties.Object(PredictorEvaluationMetric)),
                                   "metrics")
    ignore_when_grouping = properties.Optional(properties.Set(properties.String),
                                               "ignore_when_grouping")
    typ = properties.String("type", default="CrossValidationEvaluator", deserializable=False)

    def __init__(self, *,
                 name: str,
                 description: str = "",
                 responses: Set[str],
                 n_folds: int = 5,
                 n_trials: int = 3,
                 metrics: Optional[Set[PredictorEvaluationMetric]] = None,
                 ignore_when_grouping: Optional[Set[str]] = None):
        self.name: str = name
        self.description: str = description
        self._responses: Set[str] = responses
        self._metrics: Optional[Set[PredictorEvaluationMetric]] = metrics
        self.n_folds: int = n_folds
        self.n_trials: int = n_trials
        self.ignore_when_grouping: Optional[Set[str]] = ignore_when_grouping

    @property
    def responses(self) -> Set[str]:
        """Set of predictor responses cross-validated by the evaluator."""
        return self._responses

    @property
    def metrics(self) -> Set[PredictorEvaluationMetric]:
        """Set of metrics computed during cross-validation."""
        return self._metrics
class WorkflowExecution(Resource['WorkflowExecution'], Pageable):
    """[DEPRECATED] A Citrine Workflow Execution.

    Parameters
    ----------
    uid: str
        Unique identifier of the workflow execution
    project_id: str
        Unique identifier of the project that contains the workflow execution
    workflow_id: str
        Unique identifier of the workflow that was executed
    version_number: int
        Integer identifier that increases each time the workflow is executed.  The first execution
        has version_number = 1.

    """

    _response_key = 'WorkflowExecutions'
    _paginator: Paginator = Paginator()
    _collection_key = 'response'

    uid = properties.UUID('id')
    project_id = properties.UUID('project_id', deserializable=False)
    workflow_id = properties.UUID('workflow_id', deserializable=False)
    version_number = properties.Integer("version_number")

    def __init__(
        self,
        uid: Optional[str] = None,
        project_id: Optional[str] = None,
        workflow_id: Optional[str] = None,
        session: Optional[Session] = None,
        version_number: Optional[int] = None,
    ):
        msg = "{this_class} is deprecated. Please use {dw_replacement} instead for " \
            "Design Workflows and {pew_replacement} for Predictor Evaluation Workflows".format(
                this_class=self.__class__.__name__,
                dw_replacement=DesignExecution.__name__,
                pew_replacement=PredictorEvaluationExecution.__name__)
        warn(msg, category=DeprecationWarning)
        self.uid: str = uid
        self.project_id: str = project_id
        self.workflow_id: str = workflow_id
        self.session: Session = session
        self.version_number = version_number

    def __str__(self):
        return '<WorkflowExecution {!r}>'.format(str(self.uid))

    def _path(self):
        return '/projects/{project_id}/workflows/{workflow_id}/executions/{execution_id}'.format(
            **{
                "project_id": self.project_id,
                "workflow_id": self.workflow_id,
                "execution_id": self.uid
            })

    def status(self):
        """Get the current status of this execution."""
        response = self.session.get_resource(self._path() + "/status")
        return WorkflowExecutionStatus.build(response)

    def results(self):
        """Get the results of this execution."""
        return self.session.get_resource(self._path() + "/results")

    @classmethod
    def _build_candidates(
            cls,
            subset_collection: Iterable[dict]) -> Iterable[DesignCandidate]:
        for candidate in subset_collection:
            yield DesignCandidate.build(candidate)

    def candidates(
        self,
        page: Optional[int] = None,
        per_page: int = 100,
    ) -> Iterable[DesignCandidate]:
        """Fetch the Design Candidates for the particular execution, paginated.

        Gets candidates from the new candidates API for a workflow executed by the old api.
        New candidates are paginated and have structured types.
        """
        path = '/projects/{p_id}/design-workflows/{w_id}/executions/{e_id}/candidates'.format(
            p_id=self.project_id, w_id=self.workflow_id, e_id=self.uid)

        fetcher = partial(self._fetch_page, path=path)

        return self._paginator.paginate(
            page_fetcher=fetcher,
            collection_builder=self._build_candidates,
            page=page,
            per_page=per_page)
Example #13
0
class MeanPropertyPredictor(Resource['MeanPropertyPredictor'], Predictor,
                            AIResourceMetadata):
    """A predictor interface that computes mean component properties.

    .. seealso::
       If you are using a deprecated generalized mean property predictor please see
       :class:`~citrine.informatics.predictors.generalized_mean_property_predictor.GeneralizedMeanPropertyPredictor`
       for details on how to migrate to the new format.

    Parameters
    ----------
    name: str
        name of the configuration
    description: str
        description of the predictor
    input_descriptor: FormulationDescriptor
        descriptor that represents the input formulation
    properties: List[RealDescriptor]
        List of descriptors to featurize
    p: int
        Power of the `generalized mean <https://en.wikipedia.org/wiki/Generalized_mean>`_.
        Only integer powers are supported.
    impute_properties: bool
        Whether to impute missing ingredient properties.
        If ``False`` all ingredients must define values for all featurized properties.
        Otherwise, the row will not be featurized.
        If ``True`` and no ``default_properties`` are specified, then the average over the
        entire dataset is used.
        If ``True`` and a default is specified in ``default_properties``, then the specified
        default is used in place of missing values.
    label: Optional[str]
        Optional label
    training_data: Optional[List[DataSource]]
        Sources of training data. Each can be either a CSV or an GEM Table. Candidates from
        multiple data sources will be combined into a flattened list and de-duplicated by uid and
        identifiers. De-duplication is performed if a uid or identifier is shared between two or
        more rows. The content of a de-duplicated row will contain the union of data across all
        rows that share the same uid or at least 1 identifier. Training data is unnecessary if the
        predictor is part of a graph that includes all training data required by this predictor.
    default_properties: Optional[Mapping[str, float]]
        Default values to use for imputed properties.
        Defaults are specified as a map from descriptor key to its default value.
        If not specified and ``impute_properties == True`` the average over the entire dataset
        will be used to fill in missing values. Any specified defaults will be used in place of
        the average over the dataset. ``impute_properties`` must be ``True`` if
        ``default_properties`` are provided.

    """

    _resource_type = ResourceTypeEnum.MODULE

    input_descriptor = _properties.Object(FormulationDescriptor,
                                          'config.input')
    properties = _properties.List(_properties.Object(RealDescriptor),
                                  'config.properties')
    p = _properties.Integer('config.p')
    training_data = _properties.List(_properties.Object(DataSource),
                                     'config.training_data')
    impute_properties = _properties.Boolean('config.impute_properties')
    default_properties = _properties.Optional(
        _properties.Mapping(_properties.String, _properties.Float),
        'config.default_properties')
    label = _properties.Optional(_properties.String, 'config.label')

    typ = _properties.String('config.type',
                             default='MeanProperty',
                             deserializable=False)
    module_type = _properties.String('module_type', default='PREDICTOR')

    def __init__(self,
                 name: str,
                 description: str,
                 input_descriptor: FormulationDescriptor,
                 properties: List[RealDescriptor],
                 p: int,
                 impute_properties: bool,
                 default_properties: Optional[Mapping[str, float]] = None,
                 label: Optional[str] = None,
                 training_data: Optional[List[DataSource]] = None,
                 archived: bool = False):
        self.name: str = name
        self.description: str = description
        self.input_descriptor: FormulationDescriptor = input_descriptor
        self.properties: List[RealDescriptor] = properties
        self.p: int = p
        self.training_data: List[DataSource] = self._wrap_training_data(
            training_data)
        self.impute_properties: bool = impute_properties
        self.default_properties: Optional[Mapping[str,
                                                  float]] = default_properties
        self.label: Optional[str] = label
        self.archived: bool = archived

    def _post_dump(self, data: dict) -> dict:
        data['display_name'] = data['config']['name']
        return data

    def __str__(self):
        return '<MeanPropertyPredictor {!r}>'.format(self.name)
Example #14
0
class EnumeratedProcessor(Resource['EnumeratedProcessor'], Processor,
                          AIResourceMetadata):
    """Process a design space by enumerating up to a fixed number of samples from the domain.

    Each sample is processed independently.

    Parameters
    ----------
    name: str
        name of the processor
    description: str
        description of the processor
    max_candidates: int
        maximum number of samples that can be enumerated over (default: 1000)

    """

    _resource_type = ResourceTypeEnum.MODULE

    max_candidates = properties.Integer('config.max_size')

    typ = properties.String('config.type',
                            default='Enumerated',
                            deserializable=False)
    module_type = properties.String('module_type', default='PROCESSOR')

    def _attrs(self) -> List[str]:
        return ["name", "description", "max_size", "typ"]

    def __init__(self,
                 name: str,
                 description: str,
                 max_candidates: Optional[int] = None,
                 max_size: Optional[int] = None,
                 session: Optional[Session] = None):
        if max_candidates is not None and max_size is not None:
            raise ValueError(
                "Both max_candidates and max_size were specified.  "
                "Please only specify max_candidates.")
        if max_size is not None:
            warn(
                "The max_size argument is deprecated.  Please use max_candidates instead.",
                DeprecationWarning)
        self.name: str = name
        self.description: str = description
        self.max_candidates: int = max_candidates or max_size or 1000
        self.session: Optional[Session] = session

    def _post_dump(self, data: dict) -> dict:
        data['display_name'] = data['config']['name']
        return data

    def __str__(self):
        return '<EnumeratedProcessor {!r}>'.format(self.name)

    @property
    def max_size(self):
        """[DEPRECATED] Alias for max_candidates."""
        warn(
            "EnumeratedProcessor.max_size is deprecated.  Please use max_candidates instead",
            DeprecationWarning)
        return self.max_candidates
class CrossValidationAnalysisConfiguration(
        Serializable['CrossValidationAnalysisConfiguration']):
    """[DEPRECATED] Configuration settings for running cross-validation in a performance workflow.

    Parameters
    ----------
    name : str
        Name of the analysis configuration
    description: str
        Description of the analysis configuration
    n_folds: int
        Number of folds
    n_trials: int
        Number of cross-validation trials to run, each with ``n_folds`` folds
    max_rows: int
        Maximum number of training candidates to use during cross-validation
    seed: int, optional
        Seed used to generate random test/train splits.
        If not provided, a random seed is used.
    group_by_keys: List[str], optional
        Set of keys used to group candidates.
        If present, candidates are grouped by the hash of
        ``(key, value)`` pairs computed on the given keys.
        If not provided, candidates are not grouped.
    responses: List[str], optional
        Set of descriptor keys to cross-validate.
        All requested responses must be present as an output of the predictor being analyzed.
        If not provided cross-validation metrics will be computed for all predictor responses.
        These cross-validated responses are removed from the data during the analysis,
        so which responses are requested can affect the performance metrics if the predictor
        contains latent variables. For example, if only the final output (leaf) responses are
        requested, latent variables are not removed during cross-validation. In this case the
        actual (and not predicted) values for latent variables are fed into the models used
        to compute leaf responses. Often this will manifest as a lower model error for the
        final response, compared to the model error computed when latent variables are requested
        and hence removed from the data. Note, if no responses are specified all leaf and
        latent variables are removed from the data during cross-validation.

    """

    name = properties.String('name')
    description = properties.String('description')
    n_folds = properties.Integer('n_folds')
    n_trials = properties.Integer('n_trials')
    seed = properties.Optional(properties.Integer, 'seed')
    group_by_keys = properties.Optional(properties.List(properties.String),
                                        'group_by_keys')
    responses = properties.Optional(properties.List(properties.String),
                                    'responses')
    max_rows = properties.Integer('max_rows')
    typ = properties.String('type',
                            default='CrossValidationAnalysis',
                            deserializable=False)

    def __init__(
        self,
        name: str,
        description: str,
        n_folds: int,
        n_trials: int,
        max_rows: int,
        seed: Optional[int] = None,
        group_by_keys: Optional[List[str]] = None,
        responses: Optional[List[str]] = None,
    ):
        warn("{this_class} is deprecated. Please use {replacement} instead".
             format(this_class=self.__class__.name,
                    replacement=CrossValidationEvaluator.__name__))
        self.name = name
        self.description = description
        self.n_folds = n_folds
        self.n_trials = n_trials
        self.seed = seed
        self.group_by_keys = group_by_keys
        self.max_rows = max_rows
        self.responses = responses
Example #16
0
class DesignExecution(Resource['DesignExecution'], Pageable,
                      AsynchronousObject):
    """The execution of a DesignWorkflow.

    Possible statuses are INPROGRESS, SUCCEEDED, and FAILED.
    Design executions also have a ``status_description`` field with more information.

    Parameters
    ----------
    project_id: str
        Unique identifier of the project that contains the workflow execution

    """

    _paginator: Paginator = Paginator()
    _collection_key = 'response'

    uid: UUID = properties.UUID('id', serializable=False)
    """:UUID: Unique identifier of the workflow execution"""
    workflow_id = properties.UUID('workflow_id', serializable=False)
    """:UUID: Unique identifier of the workflow that was executed"""
    version_number = properties.Integer("version_number", serializable=False)
    """:int: Integer identifier that increases each time the workflow is executed. The first
    execution has version_number = 1."""

    status = properties.Optional(properties.String(),
                                 'status',
                                 serializable=False)
    """:Optional[str]: short description of the execution's status"""
    status_description = properties.Optional(properties.String(),
                                             'status_description',
                                             serializable=False)
    """:Optional[str]: more detailed description of the execution's status"""
    status_info = properties.Optional(properties.List(properties.String()),
                                      'status_info',
                                      serializable=False)
    """:Optional[List[str]]: human-readable explanations of the status"""
    experimental = properties.Boolean("experimental",
                                      serializable=False,
                                      default=True)
    """:bool: whether the execution is experimental (newer, less well-tested functionality)"""
    experimental_reasons = properties.Optional(properties.List(
        properties.String()),
                                               'experimental_reasons',
                                               serializable=False)
    """:Optional[List[str]]: human-readable reasons why the execution is experimental"""
    created_by = properties.Optional(properties.UUID,
                                     'created_by',
                                     serializable=False)
    """:Optional[UUID]: id of the user who created the resource"""
    updated_by = properties.Optional(properties.UUID,
                                     'updated_by',
                                     serializable=False)
    """:Optional[UUID]: id of the user who most recently updated the resource,
    if it has been updated"""
    create_time = properties.Optional(properties.Datetime,
                                      'create_time',
                                      serializable=False)
    """:Optional[datetime]: date and time at which the resource was created"""
    update_time = properties.Optional(properties.Datetime,
                                      'update_time',
                                      serializable=False)
    """:Optional[datetime]: date and time at which the resource was most recently updated,
    if it has been updated"""

    score = properties.Object(Score, 'score')
    """:Score: score by which this execution was evaluated"""
    descriptors = properties.List(properties.Object(Descriptor), 'descriptors')
    """:List[Descriptor]: all of the descriptors in the candidates generated by this execution"""
    def __init__(self):
        """This shouldn't be called, but it defines members that are set elsewhere."""
        self.project_id: Optional[UUID] = None  # pragma: no cover
        self.session: Optional[Session] = None  # pragma: no cover

    def __str__(self):
        return '<DesignExecution {!r}>'.format(str(self.uid))

    def _path(self):
        return '/projects/{project_id}/design-workflows/{workflow_id}/executions/{execution_id}' \
            .format(project_id=self.project_id,
                    workflow_id=self.workflow_id,
                    execution_id=self.uid)

    def in_progress(self) -> bool:
        """Whether design execution is in progress. Does not query state."""
        return self.status == "INPROGRESS"

    def succeeded(self) -> bool:
        """Whether design execution has completed successfully. Does not query state."""
        return self.status == "SUCCEEDED"

    def failed(self) -> bool:
        """Whether design execution has completed unsuccessfully. Does not query state."""
        return self.status == "FAILED"

    @classmethod
    def _build_candidates(
            cls,
            subset_collection: Iterable[dict]) -> Iterable[DesignCandidate]:
        for candidate in subset_collection:
            yield DesignCandidate.build(candidate)

    def candidates(
        self,
        page: Optional[int] = None,
        per_page: int = 100,
    ) -> Iterable[DesignCandidate]:
        """Fetch the Design Candidates for the particular execution, paginated."""
        path = self._path() + '/candidates'

        fetcher = partial(self._fetch_page, path=path)

        return self._paginator.paginate(
            page_fetcher=fetcher,
            collection_builder=self._build_candidates,
            page=page,
            per_page=per_page)