Skip to content

Samples

pydatalab.models.samples

Sample (Item) pydantic-model

A model for representing an experimental sample.

Source code in pydatalab/models/samples.py
class Sample(Item):
    """A model for representing an experimental sample."""

    type: str = Field("samples", const="samples", pattern="^samples$")

    chemform: Optional[str] = Field(example=["Na3P", "LiNiO2@C"])
    """A string representation of the chemical formula or composition associated with this sample."""

    synthesis_constituents: List[Constituent] = Field([])
    """A list of references to constituent materials giving the amount and relevant inlined details of consituent items."""

    synthesis_description: Optional[str]
    """Free-text details of the procedure applied to synthesise the sample"""

    @root_validator
    def add_missing_synthesis_relationships(cls, values):
        """Add any missing sample synthesis constituents to parent relationships"""
        from pydatalab.models.relationships import RelationshipType, TypedRelationship

        constituents_set = set()
        if values.get("synthesis_constituents") is not None:
            existing_parent_relationship_ids = set()
            if values.get("relationships") is not None:
                existing_parent_relationship_ids = {
                    relationship.item_id or relationship.refcode
                    for relationship in values["relationships"]
                    if relationship.relation == RelationshipType.PARENT
                }
            else:
                values["relationships"] = []

            for constituent in values.get("synthesis_constituents", []):
                # If this is an inline relationship, just skip it
                if isinstance(constituent.item, InlineSubstance):
                    continue
                if (
                    constituent.item.item_id not in existing_parent_relationship_ids
                    and constituent.item.refcode not in existing_parent_relationship_ids
                ):
                    relationship = TypedRelationship(
                        relation=RelationshipType.PARENT,
                        item_id=constituent.item.item_id,
                        type=constituent.item.type,
                        description="Is a constituent of",
                    )
                    values["relationships"].append(relationship)

                # Accumulate all constituent IDs in a set to filter those that have been deleted
                constituents_set.add(constituent.item.item_id)

        # Finally, filter out any parent relationships with item that were removed
        # from the synthesis constituents
        values["relationships"] = [
            rel
            for rel in values["relationships"]
            if not (
                rel.item_id not in constituents_set
                and rel.relation == RelationshipType.PARENT
                and rel.type in ("samples", "starting_materials")
            )
        ]

        return values

__slots__ special

chemform: str pydantic-field

synthesis_constituents: List[pydatalab.models.utils.Constituent] pydantic-field

synthesis_description: str pydantic-field

add_missing_synthesis_relationships(values) classmethod

Add any missing sample synthesis constituents to parent relationships

Source code in pydatalab/models/samples.py
@root_validator
def add_missing_synthesis_relationships(cls, values):
    """Add any missing sample synthesis constituents to parent relationships"""
    from pydatalab.models.relationships import RelationshipType, TypedRelationship

    constituents_set = set()
    if values.get("synthesis_constituents") is not None:
        existing_parent_relationship_ids = set()
        if values.get("relationships") is not None:
            existing_parent_relationship_ids = {
                relationship.item_id or relationship.refcode
                for relationship in values["relationships"]
                if relationship.relation == RelationshipType.PARENT
            }
        else:
            values["relationships"] = []

        for constituent in values.get("synthesis_constituents", []):
            # If this is an inline relationship, just skip it
            if isinstance(constituent.item, InlineSubstance):
                continue
            if (
                constituent.item.item_id not in existing_parent_relationship_ids
                and constituent.item.refcode not in existing_parent_relationship_ids
            ):
                relationship = TypedRelationship(
                    relation=RelationshipType.PARENT,
                    item_id=constituent.item.item_id,
                    type=constituent.item.type,
                    description="Is a constituent of",
                )
                values["relationships"].append(relationship)

            # Accumulate all constituent IDs in a set to filter those that have been deleted
            constituents_set.add(constituent.item.item_id)

    # Finally, filter out any parent relationships with item that were removed
    # from the synthesis constituents
    values["relationships"] = [
        rel
        for rel in values["relationships"]
        if not (
            rel.item_id not in constituents_set
            and rel.relation == RelationshipType.PARENT
            and rel.type in ("samples", "starting_materials")
        )
    ]

    return values