class ProductDesignSpace(Resource['ProductDesignSpace'], DesignSpace):
    """[ALPHA] An outer product of univariate dimensions, either continuous or enumerated.

    Parameters
    ----------
    name:str
        the name of the design space
    description:str
        the description of the design space
    dimensions: list[Dimension]
        univariate dimensions that are factors of the design space; can be enumerated or continuous

    """

    _response_key = None

    uid = properties.Optional(properties.UUID, 'id', serializable=False)
    name = properties.String('config.name')
    description = properties.Optional(properties.String(), 'config.description')
    dimensions = properties.List(properties.Object(Dimension), 'config.dimensions')
    typ = properties.String('config.type', default='Univariate', deserializable=False)
    status = properties.String('status', serializable=False)
    status_info = properties.Optional(
        properties.List(properties.String()),
        'status_info',
        serializable=False
    )
    archived = properties.Boolean('archived', default=False)
    experimental = properties.Boolean("experimental", serializable=False, default=True)
    experimental_reasons = properties.Optional(
        properties.List(properties.String()),
        'experimental_reasons',
        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='DESIGN_SPACE')
    schema_id = properties.UUID('schema_id', default=UUID('6c16d694-d015-42a7-b462-8ef299473c9a'))

    def __init__(self,
                 name: str,
                 description: str,
                 dimensions: List[Dimension],
                 session: Session = Session()):
        self.name: str = name
        self.description: str = description
        self.dimensions: List[Dimension] = dimensions
        self.session: Session = session

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

    def __str__(self):
        return '<ProductDesignSpace {!r}>'.format(self.name)
示例#2
0
class AIResourceMetadata():
    """Abstract class for representing common metadata for Resources."""

    created_by = properties.Optional(properties.UUID,
                                     'created_by',
                                     serializable=False)
    """:Optional[UUID]: id of the user who created the resource"""
    create_time = properties.Optional(properties.Datetime,
                                      'create_time',
                                      serializable=False)
    """:Optional[datetime]: date and time at which the resource was created"""

    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"""
    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"""

    archived = properties.Boolean('archived', default=False)
    """:bool: whether the resource is archived (hidden but not deleted)"""
    archived_by = properties.Optional(properties.UUID,
                                      'archived_by',
                                      serializable=False)
    """:Optional[UUID]: id of the user who archived the resource, if it has been archived"""
    archive_time = properties.Optional(properties.Datetime,
                                       'archive_time',
                                       serializable=False)
    """:Optional[datetime]: date and time at which the resource was archived,
    if it has been archived"""

    experimental = properties.Boolean("experimental",
                                      serializable=False,
                                      default=True)
    """:bool: whether the resource 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 resource is experimental"""

    status = properties.Optional(properties.String(),
                                 'status',
                                 serializable=False)
    """:Optional[str]: short description of the resource's status"""
    status_info = properties.Optional(properties.List(properties.String()),
                                      'status_info',
                                      serializable=False)
    """:Optional[List[str]]: human-readable explanations of the status"""
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 ComponentQuantityColumn(Serializable["ComponentQuantityColumn"], Column):
    """[ALPHA] Column that extracts the quantity of a given component.

    If the component is not present in the composition, then the value in the column will be 0.0.

    Parameters
    ----------
    data_source: str
        name of the variable to use when populating the column
    component_name: str
        name of the component from which to extract the quantity
    normalize: bool
        whether to normalize the quantity by the sum of all component amounts. Default is false

    """

    data_source = properties.String('data_source')
    component_name = properties.String("component_name")
    normalize = properties.Boolean("normalize")
    typ = properties.String('type',
                            default="component_quantity_column",
                            deserializable=False)

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

    def __init__(self,
                 *,
                 data_source: str,
                 component_name: str,
                 normalize: bool = False):
        self.data_source = data_source
        self.component_name = component_name
        self.normalize = normalize
示例#5
0
class MonteCarloProcessor(Serializable['GridProcessor'], Processor):
    """[ALPHA] Using a Monte Carlo optimizer to search for the best candidate.

    The moves that the MonteCarlo optimizer makes are inferred from the descriptors in the
    design space.

    Parameters
    ----------
    name: str
        name of the processor
    description: str
        description of the processor

    """

    uid = properties.Optional(properties.UUID, 'id', serializable=False)
    name = properties.String('config.name')
    description = properties.Optional(properties.String(),
                                      'config.description')
    typ = properties.String('config.type',
                            default='ContinuousSearch',
                            deserializable=False)
    status = properties.String('status', serializable=False)
    status_info = properties.Optional(properties.List(properties.String()),
                                      'status_info',
                                      serializable=False)
    experimental = properties.Boolean("experimental",
                                      serializable=False,
                                      default=True)
    experimental_reasons = properties.Optional(properties.List(
        properties.String()),
                                               'experimental_reasons',
                                               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('d8ddfe73-10f7-4456-9de9-9a1638bae403'))

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

    def __init__(self,
                 name: str,
                 description: str,
                 session: Optional[Session] = None):
        self.name: str = name
        self.description: str = description
        self.session: Optional[Session] = session

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

    def __str__(self):
        return '<MonteCarloProcessor {!r}>'.format(self.name)
示例#6
0
class ScalarRangeConstraint(Serializable['ScalarRangeConstraint'], Constraint):
    """[ALPHA] Represents an inequality constraint on a scalar-valued material attribute.

    Parameters
    ----------
    descriptor_key: str
        the key corresponding to a descriptor
    min: float
        the minimum value in the range
    max: float
        the maximum value in the range
    min_inclusive: bool
        if True, will include the min value in the range
    max_inclusive: bool
        if True, will include the max value in the range

    """

    descriptor_key = properties.String('descriptor_key')
    min = properties.Optional(properties.Float, 'min')
    max = properties.Optional(properties.Float, 'max')
    min_inclusive = properties.Boolean('min_inclusive')
    max_inclusive = properties.Boolean('max_inclusive')
    typ = properties.String('type', default='ScalarRange')

    def __init__(self,
                 descriptor_key: str,
                 max: Optional[float] = None,
                 min: Optional[float] = None,
                 min_inclusive: Optional[bool] = True,
                 max_inclusive: Optional[bool] = True,
                 session: Optional[Session] = None):
        self.descriptor_key = descriptor_key
        self.max = max
        self.min = min
        self.min_inclusive = min_inclusive
        self.max_inclusive = max_inclusive
        self.session: Optional[Session] = session

    def __str__(self):
        return '<ScalarRangeConstraint {!r}>'.format(self.descriptor_key)
示例#7
0
class LabelFractionConstraint(Serializable['LabelFractionConstraint'],
                              Constraint):
    """Represents a constraint on the total amount of ingredients with a given label.

    Parameters
    ----------
    formulation_descriptor: FormulationDescriptor
        descriptor to constrain
    label: str
        ingredient label to constrain
    min: float
        minimum value
    max: float
        maximum value
    is_required: bool, optional
        whether this ingredient is required.
        If ``True``, the label must be present and its value must be within the
        specified range. if ``False``, the label must be within the specified range only if
        it's present in the formulation, i.e., the value can be 0 or on the range ``[min, max]``.

    """

    formulation_descriptor = properties.Object(FormulationDescriptor,
                                               'formulation_descriptor')
    label = properties.String('label')
    min = properties.Optional(properties.Float, 'min')
    max = properties.Optional(properties.Float, 'max')
    is_required = properties.Boolean('is_required')
    typ = properties.String('type', default='LabelFractionConstraint')

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

    def __str__(self):
        return '<LabelFractionConstraint {!r}::{!r}>'.format(
            self.formulation_descriptor.key, self.label)
示例#8
0
class User(Resource['User']):
    """
    A Citrine User.

    Parameters
    ----------
    screen_name: str
        Screen name of the user.
    email: str
        Email address of the user.
    position: str
        Position of the user.
    is_admin: bool
        Whether or not the user is an administrator.
    session: Session, optional
        Citrine session used to connect to the database.

    """

    _resource_type = ResourceTypeEnum.USER

    uid = properties.Optional(properties.UUID, 'id')
    screen_name = properties.String('screen_name')
    position = properties.String('position')
    email = properties.String('email')
    is_admin = properties.Boolean('is_admin')

    def __init__(self,
                 screen_name: str,
                 email: str,
                 position: str,
                 is_admin: bool,
                 session: Optional[Session] = None):
        self.email: str = email
        self.position: str = position
        self.screen_name: str = screen_name
        self.is_admin: bool = is_admin
        self.session: Optional[Session] = session

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

    def get(self):
        """Retrieve a specific user from the database."""
        raise NotImplementedError("Get Not Implemented in Citrine Platform")
示例#9
0
class DesignWorkflow(Resource['DesignWorkflow'], Workflow):
    """[ALPHA] Object that generates scored materials that may approach higher values of the score.

    Parameters
    ----------
    name: str
        the name of the workflow
    design_space_id: UUID
        the UUID corresponding to the design space to use
    processor_id: Optional[UUID]
        the UUID corresponding to the processor to use
        if none is provided, one matching your design space will be automatically generated
    predictor_id: UUID
        the UUID corresponding to the predictor to use
    project_id: UUID
        the UUID corresponding to the project to use

    """

    uid = properties.Optional(properties.UUID, 'id', serializable=False)
    name = properties.String('display_name')
    status = properties.String('status', serializable=False)
    status_info = properties.Optional(properties.List(properties.String()),
                                      'status_info',
                                      serializable=False)
    experimental = properties.Boolean("experimental",
                                      serializable=False,
                                      default=True)
    experimental_reasons = properties.Optional(properties.List(
        properties.String()),
                                               'experimental_reasons',
                                               serializable=False)
    archived = properties.Boolean('archived', default=False)
    created_by = properties.Optional(properties.UUID,
                                     'created_by',
                                     serializable=False)
    create_time = properties.Optional(properties.Datetime,
                                      'create_time',
                                      serializable=False)
    design_space_id = properties.UUID('config.design_space_id')
    processor_id = properties.Optional(properties.UUID, 'config.processor_id')
    predictor_id = properties.UUID('config.predictor_id')
    module_type = properties.String('module_type', default='DESIGN_WORKFLOW')
    schema_id = properties.UUID(
        'schema_id', default=UUID('8af8b007-3e81-4185-82b2-6f62f4a2e6f1'))

    def __init__(self,
                 name: str,
                 design_space_id: UUID,
                 processor_id: Optional[UUID],
                 predictor_id: UUID,
                 project_id: Optional[UUID] = None,
                 session: Session = Session()):
        self.name = name
        self.design_space_id = design_space_id
        self.processor_id = processor_id
        self.predictor_id = predictor_id
        self.project_id = project_id
        self.session = session

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

    @property
    def executions(self) -> WorkflowExecutionCollection:
        """Return a resource representing all visible executions of this workflow."""
        if getattr(self, 'project_id', None) is None:
            raise AttributeError(
                'Cannot initialize execution without project reference!')
        return WorkflowExecutionCollection(self.project_id, self.uid,
                                           self.session)
示例#10
0
class PerformanceWorkflow(Resource['PerformanceWorkflow'], Workflow):
    """[ALPHA] Object that executes performance analysis on a given module.

    Parameters
    ----------
    name: str
        the name of the workflow
    analysis: CrossValidationAnalysisConfiguration
        the configuration object

    """

    uid = properties.Optional(properties.UUID, 'id', serializable=False)
    name = properties.String('display_name')
    status = properties.String('status', serializable=False)
    status_info = properties.Optional(properties.List(properties.String()),
                                      'status_info',
                                      serializable=False)
    experimental = properties.Boolean("experimental",
                                      serializable=False,
                                      default=True)
    experimental_reasons = properties.Optional(properties.List(
        properties.String()),
                                               'experimental_reasons',
                                               serializable=False)
    archived = properties.Boolean('archived', default=False)
    created_by = properties.Optional(properties.UUID,
                                     'created_by',
                                     serializable=False)
    create_time = properties.Optional(properties.Datetime,
                                      'create_time',
                                      serializable=False)
    analysis = properties.Object(CrossValidationAnalysisConfiguration,
                                 'config.analysis')
    module_type = properties.String('module_type',
                                    default='PERFORMANCE_WORKFLOW')
    schema_id = properties.UUID(
        'schema_id', default=UUID('1d213f0a-d07c-4f70-a4d0-bda3aa951ee0'))
    typ = properties.String('config.type',
                            default='PerformanceWorkflow',
                            deserializable=False)

    def __init__(self,
                 name: str,
                 analysis: CrossValidationAnalysisConfiguration,
                 project_id: Optional[UUID] = None,
                 session: Session = Session()):
        self.name = name
        self.analysis = analysis
        self.project_id = project_id
        self.session = session

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

    @property
    def executions(self) -> WorkflowExecutionCollection:
        """Return a resource representing all visible executions of this workflow."""
        if getattr(self, 'project_id', None) is None:
            raise AttributeError(
                'Cannot initialize execution without project reference!')
        return WorkflowExecutionCollection(self.project_id, self.uid,
                                           self.session)
示例#11
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)
class Dataset(Resource['Dataset']):
    """
    A collection of data objects.

    Datasets are the basic unit of access control. A user with read access to a dataset can view
    every object in that dataset. A user with write access to a dataset can create, update,
    and delete objects in the dataset.

    Parameters
    ----------
    name: str
        Name of the dataset. Can be used for searching.
    summary: str
        A summary of this dataset.
    description: str
        Long-form description of the dataset.
    unique_name: Optional[str]
        An optional, globally unique name that can be used to retrieve the dataset.

    Attributes
    ----------
    uid: UUID
        Unique uuid4 identifier of this dataset.
    deleted: bool
        Flag indicating whether or not this dataset has been deleted.
    created_by: UUID
        ID of the user who created the dataset.
    updated_by: UUID
        ID of the user who last updated the dataset.
    deleted_by: UUID
        ID of the user who deleted the dataset, if it is deleted.
    create_time: int
        Time the dataset was created, in seconds since epoch.
    update_time: int
        Time the dataset was most recently updated, in seconds since epoch.
    delete_time: int
        Time the dataset was deleted, in seconds since epoch, if it is deleted.
    public: bool
        Flag indicating whether the dataset is publicly readable.

    """

    _response_key = 'dataset'
    _resource_type = ResourceTypeEnum.DATASET

    uid = properties.Optional(properties.UUID(), 'id')
    name = properties.String('name')
    unique_name = properties.Optional(properties.String(), 'unique_name')
    summary = properties.String('summary')
    description = properties.String('description')
    deleted = properties.Optional(properties.Boolean(), 'deleted')
    created_by = properties.Optional(properties.UUID(), 'created_by')
    updated_by = properties.Optional(properties.UUID(), 'updated_by')
    deleted_by = properties.Optional(properties.UUID(), 'deleted_by')
    create_time = properties.Optional(properties.Datetime(), 'create_time')
    update_time = properties.Optional(properties.Datetime(), 'update_time')
    delete_time = properties.Optional(properties.Datetime(), 'delete_time')
    public = properties.Optional(properties.Boolean(), 'public')

    def __init__(self,
                 name: str,
                 summary: str,
                 description: str,
                 unique_name: Optional[str] = None):
        self.name: str = name
        self.summary: str = summary
        self.description: str = description
        self.unique_name = unique_name

        # The attributes below should not be set by the user. Instead they will be updated as the
        # dataset interacts with the backend data service
        self.uid = None
        self.deleted = None
        self.created_by = None
        self.updated_by = None
        self.deleted_by = None
        self.create_time = None
        self.update_time = None
        self.delete_time = None
        self.public = None

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

    @property
    def property_templates(self) -> PropertyTemplateCollection:
        """Return a resource representing all property templates in this dataset."""
        return PropertyTemplateCollection(self.project_id, self.uid,
                                          self.session)

    @property
    def condition_templates(self) -> ConditionTemplateCollection:
        """Return a resource representing all condition templates in this dataset."""
        return ConditionTemplateCollection(self.project_id, self.uid,
                                           self.session)

    @property
    def parameter_templates(self) -> ParameterTemplateCollection:
        """Return a resource representing all parameter templates in this dataset."""
        return ParameterTemplateCollection(self.project_id, self.uid,
                                           self.session)

    @property
    def material_templates(self) -> MaterialTemplateCollection:
        """Return a resource representing all material templates in this dataset."""
        return MaterialTemplateCollection(self.project_id, self.uid,
                                          self.session)

    @property
    def measurement_templates(self) -> MeasurementTemplateCollection:
        """Return a resource representing all measurement templates in this dataset."""
        return MeasurementTemplateCollection(self.project_id, self.uid,
                                             self.session)

    @property
    def process_templates(self) -> ProcessTemplateCollection:
        """Return a resource representing all process templates in this dataset."""
        return ProcessTemplateCollection(self.project_id, self.uid,
                                         self.session)

    @property
    def process_runs(self) -> ProcessRunCollection:
        """Return a resource representing all process runs in this dataset."""
        return ProcessRunCollection(self.project_id, self.uid, self.session)

    @property
    def measurement_runs(self) -> MeasurementRunCollection:
        """Return a resource representing all measurement runs in this dataset."""
        return MeasurementRunCollection(self.project_id, self.uid,
                                        self.session)

    @property
    def material_runs(self) -> MaterialRunCollection:
        """Return a resource representing all material runs in this dataset."""
        return MaterialRunCollection(self.project_id, self.uid, self.session)

    @property
    def ingredient_runs(self) -> IngredientRunCollection:
        """Return a resource representing all ingredient runs in this dataset."""
        return IngredientRunCollection(self.project_id, self.uid, self.session)

    @property
    def process_specs(self) -> ProcessSpecCollection:
        """Return a resource representing all process specs in this dataset."""
        return ProcessSpecCollection(self.project_id, self.uid, self.session)

    @property
    def measurement_specs(self) -> MeasurementSpecCollection:
        """Return a resource representing all measurement specs in this dataset."""
        return MeasurementSpecCollection(self.project_id, self.uid,
                                         self.session)

    @property
    def material_specs(self) -> MaterialSpecCollection:
        """Return a resource representing all material specs in this dataset."""
        return MaterialSpecCollection(self.project_id, self.uid, self.session)

    @property
    def ingredient_specs(self) -> IngredientSpecCollection:
        """Return a resource representing all ingredient specs in this dataset."""
        return IngredientSpecCollection(self.project_id, self.uid,
                                        self.session)

    @property
    def files(self) -> FileCollection:
        """Return a resource representing all files in the dataset."""
        return FileCollection(self.project_id, self.uid, self.session)

    def _collection_for(self, data_concepts_resource):
        if isinstance(data_concepts_resource, MeasurementTemplate):
            return self.measurement_templates
        if isinstance(data_concepts_resource, MeasurementSpec):
            return self.measurement_specs
        if isinstance(data_concepts_resource, MeasurementRun):
            return self.measurement_runs

        if isinstance(data_concepts_resource, MaterialTemplate):
            return self.material_templates
        if isinstance(data_concepts_resource, MaterialSpec):
            return self.material_specs
        if isinstance(data_concepts_resource, MaterialRun):
            return self.material_runs

        if isinstance(data_concepts_resource, ProcessTemplate):
            return self.process_templates
        if isinstance(data_concepts_resource, ProcessSpec):
            return self.process_specs
        if isinstance(data_concepts_resource, ProcessRun):
            return self.process_runs

        if isinstance(data_concepts_resource, IngredientSpec):
            return self.ingredient_specs
        if isinstance(data_concepts_resource, IngredientRun):
            return self.ingredient_runs

        if isinstance(data_concepts_resource, PropertyTemplate):
            return self.property_templates
        if isinstance(data_concepts_resource, ParameterTemplate):
            return self.parameter_templates
        if isinstance(data_concepts_resource, ConditionTemplate):
            return self.condition_templates

    def register(self,
                 data_concepts_resource: ResourceType,
                 dry_run=False) -> ResourceType:
        """Register a data concepts resource to the appropriate collection."""
        return self._collection_for(data_concepts_resource)\
            .register(data_concepts_resource, dry_run=dry_run)

    def register_all(self,
                     data_concepts_resources: List[ResourceType],
                     dry_run=False) -> List[ResourceType]:
        """
        Register multiple data concepts resources to each of their appropriate collections.

        Does so in an order that is guaranteed to store all linked items before the item that
        references them.

        The uids of the input data concepts resources are updated with their on-platform uids.
        This supports storing an object that has a reference to an object that doesn't have a uid.

        Parameters
        ----------
        data_concepts_resources: List[ResourceType]
            The resources to register. Can be different types.

        dry_run: bool
            Whether to actually register the item or run a dry run of the register operation.
            Dry run is intended to be used for validation. Default: false

        Returns
        -------
        List[ResourceType]
            The registered versions

        """
        resources = list()
        by_type = defaultdict(list)
        for obj in data_concepts_resources:
            by_type[obj.typ].append(obj)
        typ_groups = sorted(list(by_type.values()),
                            key=lambda x: writable_sort_order(x[0]))
        batch_size = 50
        for typ_group in typ_groups:
            num_batches = len(typ_group) // batch_size
            for batch_num in range(num_batches + 1):
                batch = typ_group[batch_num * batch_size:(batch_num + 1) *
                                  batch_size]
                if batch:  # final batch is empty when batch_size divides len(typ_group)
                    registered = self._collection_for(batch[0])\
                        .register_all(batch, dry_run=dry_run)
                    for prewrite, postwrite in zip(batch, registered):
                        if isinstance(postwrite, BaseEntity):
                            prewrite.uids = postwrite.uids
                    resources.extend(registered)
        return resources

    def update(self, model: ResourceType) -> ResourceType:
        """Update a data concepts resource using the appropriate collection."""
        return self._collection_for(model).update(model)

    def delete(self,
               data_concepts_resource: ResourceType,
               dry_run=False) -> ResourceType:
        """Delete a data concepts resource to the appropriate collection."""
        uid = next(iter(data_concepts_resource.uids.items()), None)
        if uid is None:
            raise ValueError(
                "Only objects that contain identifiers can be deleted.")
        return self._collection_for(data_concepts_resource) \
            .delete(uid[1], scope=uid[0], dry_run=dry_run)

    def delete_contents(self,
                        *,
                        timeout: float = 2 * 60,
                        polling_delay: float = 1.0):
        """
        Delete all the GEMD objects from within a single Dataset.

        Parameters
        ----------
        timeout: float
            Amount of time to wait on the job (in seconds) before giving up.
            Note that this number has no effect on the underlying job itself,
            which can also time out server-side.

        polling_delay: float
            How long to delay between each polling retry attempt.

        Returns
        -------
        List[Tuple[LinkByUID, ApiError]]
            A list of (LinkByUID, api_error) for each failure to delete an object.
            Note that this method doesn't raise an exception if an object fails to be
            deleted.

        """
        path = 'projects/{project_id}/datasets/{dataset_uid}/contents'.format(
            dataset_uid=self.uid, project_id=self.project_id)

        response = self.session.delete_resource(path)
        job_id = response["job_id"]

        return _poll_for_async_batch_delete_result(self.project_id,
                                                   self.session, job_id,
                                                   timeout, polling_delay)

    def gemd_batch_delete(
            self,
            id_list: List[Union[LinkByUID, UUID, str, BaseEntity]],
            *,
            timeout: float = 2 * 60,
            polling_delay: float = 1.0) -> List[Tuple[LinkByUID, ApiError]]:
        """
        Remove a set of GEMD objects.

        You may provide GEMD objects that reference each other, and the objects
        will be removed in the appropriate order.

        A failure will be returned if the object cannot be deleted due to an external
        reference.

        All data objects must be associated with this dataset resource. You must also
        have write access on this dataset.

        If you wish to delete more than 50 objects, queuing of deletes requires that
        the types of objects be known, and thus you _must_ provide ids in the form
        of BaseEntities.

        Also note that Attribute Templates cannot be deleted at present.

        Parameters
        ----------
        id_list: List[Union[LinkByUID, UUID, str, BaseEntity]]
            A list of the IDs of data objects to be removed. They can be passed
            as a LinkByUID tuple, a UUID, a string, or the object itself. A UUID
            or string is assumed to be a Citrine ID, whereas a LinkByUID or
            BaseEntity can also be used to provide an external ID.

        Returns
        -------
        List[Tuple[LinkByUID, ApiError]]
            A list of (LinkByUID, api_error) for each failure to delete an object.
            Note that this method doesn't raise an exception if an object fails to be
            deleted.

        """
        return _async_gemd_batch_delete(id_list,
                                        self.project_id,
                                        self.session,
                                        self.uid,
                                        timeout=timeout,
                                        polling_delay=polling_delay)
示例#13
0
class PerformanceWorkflow(Resource['PerformanceWorkflow'], Workflow):
    """[DEPRECATED] Object that executes performance analysis on a given module.

    Parameters
    ----------
    name: str
        the name of the workflow
    analysis: CrossValidationAnalysisConfiguration
        the configuration object

    """

    name = properties.String('display_name')
    status = properties.String('status', serializable=False)
    status_info = properties.Optional(properties.List(properties.String()),
                                      'status_info',
                                      serializable=False)
    experimental = properties.Boolean("experimental",
                                      serializable=False,
                                      default=True)
    experimental_reasons = properties.Optional(properties.List(
        properties.String()),
                                               'experimental_reasons',
                                               serializable=False)
    archived = properties.Boolean('archived', default=False)
    created_by = properties.Optional(properties.UUID,
                                     'created_by',
                                     serializable=False)
    create_time = properties.Optional(properties.Datetime,
                                      'create_time',
                                      serializable=False)
    analysis = properties.Object(CrossValidationAnalysisConfiguration,
                                 'config.analysis')
    module_type = properties.String('module_type',
                                    default='PERFORMANCE_WORKFLOW')
    typ = properties.String('config.type',
                            default='PerformanceWorkflow',
                            deserializable=False)

    def __init__(self,
                 name: str,
                 analysis: CrossValidationAnalysisConfiguration,
                 project_id: Optional[UUID] = None,
                 session: Session = Session()):
        warn("{this_class} is deprecated. Please use {replacement} instead".
             format(this_class=self.__class__.name,
                    replacement=PredictorEvaluationWorkflow.__name__),
             category=DeprecationWarning)
        self.name = name
        self.analysis = analysis
        self.project_id = project_id
        self.session = session

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

    @property
    def executions(self) -> WorkflowExecutionCollection:
        """Return a resource representing all visible executions of this workflow."""
        if getattr(self, 'project_id', None) is None:
            raise AttributeError(
                'Cannot initialize execution without project reference!')
        return WorkflowExecutionCollection(self.project_id, self.uid,
                                           self.session)

    def in_progress(self) -> bool:
        """Whether workflow validation is in progress. Does not query state."""
        return self.status == "VALIDATING" or self.status == "CREATED"

    def succeeded(self) -> bool:
        """Whether workflow validation has completed successfully. Does not query state."""
        return self.status == "READY"

    def failed(self) -> bool:
        """Whether workflow validation has completed unsuccessfully. Does not query state."""
        return self.status == "INVALID" or self.status == "ERROR"
示例#14
0
class Dataset(Resource['Dataset']):
    """
    A collection of data objects.

    Datasets are the basic unit of access control. A user with read access to a dataset can view
    every object in that dataset. A user with write access to a dataset can create, update,
    and delete objects in the dataset.

    Parameters
    ----------
    name: str
        Name of the dataset. Can be used for searching.
    summary: str
        A summary of this dataset.
    description: str
        Long-form description of the dataset.

    Attributes
    ----------
    uid: UUID
        Unique uuid4 identifier of this dataset.
    deleted: bool
        Flag indicating whether or not this dataset has been deleted.
    created_by: UUID
        ID of the user who created the dataset.
    updated_by: UUID
        ID of the user who last updated the dataset.
    deleted_by: UUID
        ID of the user who deleted the dataset, if it is deleted.
    create_time: int
        Time the dataset was created, in seconds since epoch.
    update_time: int
        Time the dataset was most recently updated, in seconds since epoch.
    delete_time: int
        Time the dataset was deleted, in seconds since epoch, if it is deleted.
    public: bool
        Flag indicating whether the dataset is publicly readable.

    """

    _response_key = 'dataset'

    uid = properties.Optional(properties.UUID(), 'id')
    name = properties.String('name')
    summary = properties.String('summary')
    description = properties.String('description')
    deleted = properties.Optional(properties.Boolean(), 'deleted')
    created_by = properties.Optional(properties.UUID(), 'created_by')
    updated_by = properties.Optional(properties.UUID(), 'updated_by')
    deleted_by = properties.Optional(properties.UUID(), 'deleted_by')
    create_time = properties.Optional(properties.Datetime(), 'create_time')
    update_time = properties.Optional(properties.Datetime(), 'update_time')
    delete_time = properties.Optional(properties.Datetime(), 'delete_time')
    public = properties.Optional(properties.Boolean(), 'public')

    def __init__(self, name: str, summary: str, description: str):
        self.name: str = name
        self.summary: str = summary
        self.description: str = description

        # The attributes below should not be set by the user. Instead they will be updated as the
        # dataset interacts with the backend data service
        self.uid = None
        self.deleted = None
        self.created_by = None
        self.updated_by = None
        self.deleted_by = None
        self.create_time = None
        self.update_time = None
        self.delete_time = None
        self.public = None

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

    @property
    def property_templates(self) -> PropertyTemplateCollection:
        """Return a resource representing all property templates in this dataset."""
        return PropertyTemplateCollection(self.project_id, self.uid, self.session)

    @property
    def condition_templates(self) -> ConditionTemplateCollection:
        """Return a resource representing all condition templates in this dataset."""
        return ConditionTemplateCollection(self.project_id, self.uid, self.session)

    @property
    def parameter_templates(self) -> ParameterTemplateCollection:
        """Return a resource representing all parameter templates in this dataset."""
        return ParameterTemplateCollection(self.project_id, self.uid, self.session)

    @property
    def material_templates(self) -> MaterialTemplateCollection:
        """Return a resource representing all material templates in this dataset."""
        return MaterialTemplateCollection(self.project_id, self.uid, self.session)

    @property
    def measurement_templates(self) -> MeasurementTemplateCollection:
        """Return a resource representing all measurement templates in this dataset."""
        return MeasurementTemplateCollection(self.project_id, self.uid, self.session)

    @property
    def process_templates(self) -> ProcessTemplateCollection:
        """Return a resource representing all process templates in this dataset."""
        return ProcessTemplateCollection(self.project_id, self.uid, self.session)

    @property
    def process_runs(self) -> ProcessRunCollection:
        """Return a resource representing all process runs in this dataset."""
        return ProcessRunCollection(self.project_id, self.uid, self.session)

    @property
    def measurement_runs(self) -> MeasurementRunCollection:
        """Return a resource representing all measurement runs in this dataset."""
        return MeasurementRunCollection(self.project_id, self.uid, self.session)

    @property
    def material_runs(self) -> MaterialRunCollection:
        """Return a resource representing all material runs in this dataset."""
        return MaterialRunCollection(self.project_id, self.uid, self.session)

    @property
    def ingredient_runs(self) -> IngredientRunCollection:
        """Return a resource representing all ingredient runs in this dataset."""
        return IngredientRunCollection(self.project_id, self.uid, self.session)

    @property
    def process_specs(self) -> ProcessSpecCollection:
        """Return a resource representing all process specs in this dataset."""
        return ProcessSpecCollection(self.project_id, self.uid, self.session)

    @property
    def measurement_specs(self) -> MeasurementSpecCollection:
        """Return a resource representing all measurement specs in this dataset."""
        return MeasurementSpecCollection(self.project_id, self.uid, self.session)

    @property
    def material_specs(self) -> MaterialSpecCollection:
        """Return a resource representing all material specs in this dataset."""
        return MaterialSpecCollection(self.project_id, self.uid, self.session)

    @property
    def ingredient_specs(self) -> IngredientSpecCollection:
        """Return a resource representing all ingredient specs in this dataset."""
        return IngredientSpecCollection(self.project_id, self.uid, self.session)

    @property
    def files(self) -> FileCollection:
        """Return a resource representing all files in the dataset."""
        return FileCollection(self.project_id, self.uid, self.session)

    def _collection_for(self, data_concepts_resource):
        if isinstance(data_concepts_resource, MeasurementTemplate):
            return self.measurement_templates
        if isinstance(data_concepts_resource, MeasurementSpec):
            return self.measurement_specs
        if isinstance(data_concepts_resource, MeasurementRun):
            return self.measurement_runs

        if isinstance(data_concepts_resource, MaterialTemplate):
            return self.material_templates
        if isinstance(data_concepts_resource, MaterialSpec):
            return self.material_specs
        if isinstance(data_concepts_resource, MaterialRun):
            return self.material_runs

        if isinstance(data_concepts_resource, ProcessTemplate):
            return self.process_templates
        if isinstance(data_concepts_resource, ProcessSpec):
            return self.process_specs
        if isinstance(data_concepts_resource, ProcessRun):
            return self.process_runs

        if isinstance(data_concepts_resource, IngredientSpec):
            return self.ingredient_specs
        if isinstance(data_concepts_resource, IngredientRun):
            return self.ingredient_runs

        if isinstance(data_concepts_resource, PropertyTemplate):
            return self.property_templates
        if isinstance(data_concepts_resource, ParameterTemplate):
            return self.parameter_templates
        if isinstance(data_concepts_resource, ConditionTemplate):
            return self.condition_templates

    def register(self, data_concepts_resource: ResourceType, dry_run=False) -> ResourceType:
        """Register a data concepts resource to the appropriate collection."""
        return self._collection_for(data_concepts_resource)\
            .register(data_concepts_resource, dry_run=dry_run)

    def register_all(self, data_concepts_resources: List[ResourceType],
                     dry_run=False) -> List[ResourceType]:
        """
        Register multiple data concepts resources to each of their appropriate collections.

        Does so in an order that is guaranteed to store all linked items before the item that
        references them.

        The uids of the input data concepts resources are updated with their on-platform uids.
        This supports storing an object that has a reference to an object that doesn't have a uid.

        Parameters
        ----------
        data_concepts_resources: List[ResourceType]
            The resources to register. Can be different types.

        dry_run: bool
            Whether to actually register the item or run a dry run of the register operation.
            Dry run is intended to be used for validation. Default: false

        Returns
        -------
        List[ResourceType]
            The registered versions

        """
        resources = list()
        by_type = defaultdict(list)
        for obj in data_concepts_resources:
            by_type[obj.typ].append(obj)
        typ_groups = sorted(list(by_type.values()), key=lambda x: writable_sort_order(x[0]))
        batch_size = 50
        for typ_group in typ_groups:
            num_batches = len(typ_group) // batch_size
            for batch_num in range(num_batches + 1):
                batch = typ_group[batch_num * batch_size: (batch_num + 1) * batch_size]
                if batch:  # final batch is empty when batch_size divides len(typ_group)
                    registered = self._collection_for(batch[0])\
                        .register_all(batch, dry_run=dry_run)
                    for prewrite, postwrite in zip(batch, registered):
                        if isinstance(postwrite, BaseEntity):
                            prewrite.uids = postwrite.uids
                    resources.extend(registered)
        return resources

    def delete(self, data_concepts_resource: ResourceType, dry_run=False) -> ResourceType:
        """Delete a data concepts resource to the appropriate collection."""
        uid = next(iter(data_concepts_resource.uids.items()), None)
        if uid is None:
            raise ValueError("Only objects that contain identifiers can be deleted.")
        return self._collection_for(data_concepts_resource) \
            .delete(uid[1], scope=uid[0], dry_run=dry_run)
示例#15
0
class ScalarRangeConstraint(Serializable['ScalarRangeConstraint'], Constraint):
    """Represents an inequality constraint on a scalar-valued material attribute.

    Parameters
    ----------
    descriptor_key: str
        the key corresponding to a descriptor
    lower_bound: float
        the minimum value in the range
    upper_bound: float
        the maximum value in the range
    lower_inclusive: bool
        if True, will include the lower bound value in the range (default: true)
    upper_inclusive: bool
        if True, will include the max value in the range (default: true)

    """

    descriptor_key = properties.String('descriptor_key')
    lower_bound = properties.Optional(properties.Float, 'min')
    upper_bound = properties.Optional(properties.Float, 'max')
    lower_inclusive = properties.Boolean('min_inclusive')
    upper_inclusive = properties.Boolean('max_inclusive')
    typ = properties.String('type', default='ScalarRange')

    def __init__(self,
                 descriptor_key: str,
                 lower_bound: Optional[float] = None,
                 upper_bound: Optional[float] = None,
                 lower_inclusive: Optional[bool] = None,
                 upper_inclusive: Optional[bool] = None,
                 min: Optional[float] = None,
                 max: Optional[float] = None,
                 min_inclusive: Optional[bool] = None,
                 max_inclusive: Optional[bool] = None,
                 session: Optional[Session] = None):
        if lower_bound is not None and min is not None:
            raise ValueError("Both lower_bound and min were specified.  "
                             "Please only specify lower_bound.")
        if upper_bound is not None and max is not None:
            raise ValueError("Both upper_bound and max were specified.  "
                             "Please only specify upper_bound.")
        if lower_inclusive is not None and min_inclusive is not None:
            raise ValueError(
                "Both lower_inclusive and min_inclusive were specified.  "
                "Please only specify lower_inclusive.")
        if upper_inclusive is not None and max_inclusive is not None:
            raise ValueError(
                "Both upper_inclusive and max_inclusive were specified.  "
                "Please only specify upper_inclusive.")
        if min is not None or max is not None:
            msg = "The min/max arguments for ScalarRangeConstraint are deprecated.  " \
                  "Please use lower_bound/upper_bound instead."
            warn(msg, DeprecationWarning)
        if min_inclusive is not None or max_inclusive is not None:
            msg = "The min_inclusive/max_inclusive arguments for ScalarRangeConstraint " \
                  "are deprecated.  " \
                  "Please use lower_inclusive/upper_inclusive instead."
            warn(msg, DeprecationWarning)

        self.descriptor_key = descriptor_key

        if lower_bound is not None:
            self.lower_bound = lower_bound
        else:
            self.lower_bound = min
        if upper_bound is not None:
            self.upper_bound = upper_bound
        else:
            self.upper_bound = max

        # we have to be careful with None and boolean values
        # None or False or True -> True, so that pattern doesn't work
        self.lower_inclusive = True
        if lower_inclusive is not None:
            self.lower_inclusive = lower_inclusive
        elif min_inclusive is not None:
            self.lower_inclusive = min_inclusive

        self.upper_inclusive = True
        if upper_inclusive is not None:
            self.upper_inclusive = upper_inclusive
        elif max_inclusive is not None:
            self.upper_inclusive = max_inclusive

        self.session: Optional[Session] = session

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

    @property
    def min(self):
        """[DEPRECATED] Alias for lower_bound."""
        warn(
            "ScalarRangeConstraint.min is deprecated.  Please use lower_bound instead",
            DeprecationWarning)
        return self.lower_bound

    @property
    def max(self):
        """[DEPRECATED] Alias for upper_bound."""
        warn(
            "ScalarRangeConstraint.max is deprecated.  Please use upper_bound instead",
            DeprecationWarning)
        return self.upper_bound

    @property
    def min_inclusive(self):
        """[DEPRECATED] Alias for lower_inclusive."""
        warn(
            "ScalarRangeConstraint.min_inclusive is deprecated.  "
            "Please use lower_inclusive instead", DeprecationWarning)
        return self.lower_inclusive

    @property
    def max_inclusive(self):
        """[DEPRECATED] Alias for upper_inclusive."""
        warn(
            "ScalarRangeConstraint.max_inclusive is deprecated.  "
            "Please use upper_inclusive instead", DeprecationWarning)
        return self.upper_inclusive
示例#16
0
class Dataset(Resource['Dataset']):
    """
    A collection of data objects.

    Datasets are the basic unit of access control. A user with read access to a dataset can view
    every object in that dataset. A user with write access to a dataset can create, update,
    and delete objects in the dataset.

    Parameters
    ----------
    name: str
        Name of the dataset. Can be used for searching.
    summary: str
        A summary of this dataset.
    description: str
        Long-form description of the dataset.

    Attributes
    ----------
    uid: UUID
        Unique uuid4 identifier of this dataset.
    deleted: bool
        Flag indicating whether or not this dataset has been deleted.
    created_by: UUID
        ID of the user who created the dataset.
    updated_by: UUID
        ID of the user who last updated the dataset.
    deleted_by: UUID
        ID of the user who deleted the dataset, if it is deleted.
    create_time: int
        Time the dataset was created, in seconds since epoch.
    update_time: int
        Time the dataset was most recently updated, in seconds since epoch.
    delete_time: int
        Time the dataset was deleted, in seconds since epoch, if it is deleted.

    """

    _response_key = 'dataset'

    uid = properties.Optional(properties.UUID(), 'id')
    name = properties.String('name')
    summary = properties.String('summary')
    description = properties.String('description')
    deleted = properties.Optional(properties.Boolean(), 'deleted')
    created_by = properties.Optional(properties.UUID(), 'created_by')
    updated_by = properties.Optional(properties.UUID(), 'updated_by')
    deleted_by = properties.Optional(properties.UUID(), 'deleted_by')
    create_time = properties.Optional(properties.Datetime(), 'create_time')
    update_time = properties.Optional(properties.Datetime(), 'update_time')
    delete_time = properties.Optional(properties.Datetime(), 'delete_time')

    def __init__(self, name: str, summary: str, description: str):
        self.name: str = name
        self.summary: str = summary
        self.description: str = description

        # The attributes below should not be set by the user. Instead they will be updated as the
        # dataset interacts with the backend data service
        self.uid = None
        self.deleted = None
        self.created_by = None
        self.updated_by = None
        self.deleted_by = None
        self.create_time = None
        self.update_time = None
        self.delete_time = None

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

    @property
    def property_templates(self) -> PropertyTemplateCollection:
        """Return a resource representing all property templates in this dataset."""
        return PropertyTemplateCollection(self.project_id, self.uid, self.session)

    @property
    def condition_templates(self) -> ConditionTemplateCollection:
        """Return a resource representing all condition templates in this dataset."""
        return ConditionTemplateCollection(self.project_id, self.uid, self.session)

    @property
    def parameter_templates(self) -> ParameterTemplateCollection:
        """Return a resource representing all parameter templates in this dataset."""
        return ParameterTemplateCollection(self.project_id, self.uid, self.session)

    @property
    def material_templates(self) -> MaterialTemplateCollection:
        """Return a resource representing all material templates in this dataset."""
        return MaterialTemplateCollection(self.project_id, self.uid, self.session)

    @property
    def measurement_templates(self) -> MeasurementTemplateCollection:
        """Return a resource representing all measurement templates in this dataset."""
        return MeasurementTemplateCollection(self.project_id, self.uid, self.session)

    @property
    def process_templates(self) -> ProcessTemplateCollection:
        """Return a resource representing all process templates in this dataset."""
        return ProcessTemplateCollection(self.project_id, self.uid, self.session)

    @property
    def process_runs(self) -> ProcessRunCollection:
        """Return a resource representing all process runs in this dataset."""
        return ProcessRunCollection(self.project_id, self.uid, self.session)

    @property
    def measurement_runs(self) -> MeasurementRunCollection:
        """Return a resource representing all measurement runs in this dataset."""
        return MeasurementRunCollection(self.project_id, self.uid, self.session)

    @property
    def material_runs(self) -> MaterialRunCollection:
        """Return a resource representing all material runs in this dataset."""
        return MaterialRunCollection(self.project_id, self.uid, self.session)

    @property
    def ingredient_runs(self) -> IngredientRunCollection:
        """Return a resource representing all ingredient runs in this dataset."""
        return IngredientRunCollection(self.project_id, self.uid, self.session)

    @property
    def process_specs(self) -> ProcessSpecCollection:
        """Return a resource representing all process specs in this dataset."""
        return ProcessSpecCollection(self.project_id, self.uid, self.session)

    @property
    def measurement_specs(self) -> MeasurementSpecCollection:
        """Return a resource representing all measurement specs in this dataset."""
        return MeasurementSpecCollection(self.project_id, self.uid, self.session)

    @property
    def material_specs(self) -> MaterialSpecCollection:
        """Return a resource representing all material specs in this dataset."""
        return MaterialSpecCollection(self.project_id, self.uid, self.session)

    @property
    def ingredient_specs(self) -> IngredientSpecCollection:
        """Return a resource representing all ingredient specs in this dataset."""
        return IngredientSpecCollection(self.project_id, self.uid, self.session)

    @property
    def files(self) -> FileCollection:
        """Return a resource representing all files in the dataset."""
        return FileCollection(self.project_id, self.uid, self.session)
示例#17
0
class EnumeratedProcessor(Serializable['EnumeratedProcessor'], Processor):
    """[ALPHA] 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_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)
    archived = properties.Boolean('archived', default=False)
    experimental = properties.Boolean("experimental",
                                      serializable=False,
                                      default=True)
    experimental_reasons = properties.Optional(properties.List(
        properties.String()),
                                               'experimental_reasons',
                                               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 _attrs(self) -> List[str]:
        return ["name", "description", "max_size", "typ"]

    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)
示例#18
0
class EnumeratedDesignSpace(Resource['EnumeratedDesignSpace'], DesignSpace):
    """[ALPHA] An explicit enumeration of candidate materials to score.

    Note that every candidate must have exactly the descriptors in the list populated
    (no more, no less) in order to be included.

    Parameters
    ----------
    name:str
        the name of the design space
    description:str
        the description of the design space
    descriptors: list[Descriptor]
        the list of descriptors included in the candidates of the design space
    data: list[dict]
        list of dicts of the shape `{<descriptor_key>: <descriptor_value>}`
        where each dict corresponds to a candidate in the design space

    """

    _response_key = None

    uid = properties.Optional(properties.UUID, 'id', serializable=False)
    name = properties.String('config.name')
    description = properties.Optional(properties.String(), 'config.description')
    descriptors = properties.List(properties.Object(Descriptor), 'config.descriptors')
    data = properties.List(properties.Mapping(properties.String, properties.Raw), 'config.data')

    typ = properties.String('config.type', default='EnumeratedDesignSpace', deserializable=False)
    status = properties.String('status', serializable=False)
    status_info = properties.Optional(
        properties.List(properties.String()),
        'status_info',
        serializable=False
    )
    archived = properties.Boolean('archived', default=False)
    experimental = properties.Boolean("experimental", serializable=False, default=True)
    experimental_reasons = properties.Optional(
        properties.List(properties.String()),
        'experimental_reasons',
        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='DESIGN_SPACE')
    schema_id = properties.UUID('schema_id', default=UUID('f3907a58-aa46-462c-8837-a5aa9605e79e'))

    def __init__(self,
                 name: str,
                 description: str,
                 descriptors: List[Descriptor],
                 data: List[Mapping[str, Any]],
                 session: Session = Session()):
        self.name: str = name
        self.description: str = description
        self.descriptors: List[Descriptor] = descriptors
        self.data: List[Mapping[str, Any]] = data
        self.session: Session = session

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

    def __str__(self):
        return '<EnumeratedDesignSpace {!r}>'.format(self.name)
示例#19
0
class GridProcessor(Serializable['GridProcessor'], Processor):
    """[ALPHA] Generates samples from the outer product of finite dimensions, then scans over them.

    To create a finite set of materials from continuous dimensions, a uniform grid is created
    between the lower and upper bounds of the descriptor.
    The number of points along each dimension is specified by `grid_sizes`.

    Parameters
    ----------
    name: str
        name of the processor
    description: str
        description of the processor
    grid_sizes: dict[str, int]
        the number of points to select along each dimension of the grid, by dimension name

    """

    uid = properties.Optional(properties.UUID, 'id', serializable=False)
    name = properties.String('config.name')
    description = properties.Optional(properties.String(),
                                      'config.description')
    typ = properties.String('config.type',
                            default='Grid',
                            deserializable=False)
    grid_sizes = properties.Mapping(properties.String, properties.Integer,
                                    'config.grid_dimensions')
    status = properties.String('status', serializable=False)
    status_info = properties.Optional(properties.List(properties.String()),
                                      'status_info',
                                      serializable=False)
    archived = properties.Boolean('archived', default=False)
    experimental = properties.Boolean("experimental",
                                      serializable=False,
                                      default=True)
    experimental_reasons = properties.Optional(properties.List(
        properties.String()),
                                               'experimental_reasons',
                                               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('272791a5-5468-4344-ac9f-2811d9266a4d'))

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

    def __init__(self,
                 name: str,
                 description: str,
                 grid_sizes: Mapping[str, int],
                 session: Optional[Session] = None):
        self.name: str = name
        self.description: str = description
        self.grid_sizes: Mapping[str, int] = grid_sizes
        self.session: Optional[Session] = session

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

    def __str__(self):
        return '<GridProcessor {!r}>'.format(self.name)
示例#20
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)