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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[submodule "submodules/cat_vrs"]
path = submodules/cat_vrs
url = https://github.com/ga4gh/cat-vrs
branch = 1.x
branch = 1.0.0-ballot.2024-11
5 changes: 3 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ keywords = [
requires-python = ">=3.10"
dynamic = ["version"]
dependencies = [
"ga4gh.vrs~=2.0.0a12",
"ga4gh.vrs==2.0.0a13",
"pydantic==2.*",
]

Expand Down Expand Up @@ -137,7 +137,8 @@ ignore = [
# S101 - assert
# B011 - assert-false
"tests/*" = ["ANN001", "ANN2", "ANN102", "S101", "B011"]
"src/ga4gh/cat_vrs/*models.py" = ["ANN102"]
"src/ga4gh/cat_vrs/models.py" = ["ANN102", "N815"]
"src/ga4gh/cat_vrs/recipes.py" = ["ANN102", "N815"]

[tool.setuptools.packages.find]
where = ["src"]
Expand Down
4 changes: 2 additions & 2 deletions src/ga4gh/cat_vrs/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""Package for Cat-VRS Python implementation"""

from . import profile_models as cat_vrs_models
from . import models, recipes

__all__ = ["cat_vrs_models"]
__all__ = ["models", "recipes"]
99 changes: 0 additions & 99 deletions src/ga4gh/cat_vrs/core_models.py

This file was deleted.

133 changes: 133 additions & 0 deletions src/ga4gh/cat_vrs/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
"""Define Pydantic models for GA4GH categorical variation objects.

See the `CatVar page <https://www.ga4gh.org/product/categorical-variation-catvar/>`_ on
the GA4GH website for more information.
"""

from enum import Enum
from typing import Literal

from ga4gh.core.models import (
ConceptMapping,
Entity,
MappableConcept,
iriReference,
)
from ga4gh.vrs.models import Allele, CopyChange, Range, SequenceLocation, Variation
from pydantic import BaseModel, Field, RootModel, field_validator


class Relation(str, Enum):
"""Defined relationships between members of the categorical variant and the defining
context.
"""

TRANSLATES_FROM = "translates_from"
LIFTOVER_TO = "liftover_to"
TRANSCRIBES_TO = "transcribes_to"


class DefiningAlleleConstraint(BaseModel):
"""The defining allele and its associated relationships that are congruent with
member variants.
"""

type: Literal["DefiningAlleleConstraint"] = Field(
"DefiningAlleleConstraint", description="MUST be 'DefiningAlleleConstraint'"
)
allele: Allele | iriReference
relations: list[MappableConcept] | None = Field(
None,
description="Defined relationships from which members relate to the defining allele.",
)


class DefiningLocationConstraint(BaseModel):
"""The defining location and its associated relationships that are congruent with
member locations.
"""

type: Literal["DefiningLocationConstraint"] = Field(
"DefiningLocationConstraint", description="MUST be 'DefiningLocationConstraint'"
)
location: SequenceLocation | iriReference
relations: list[MappableConcept] | None = Field(
None,
description="Defined relationships from which members relate to the defining location.",
)
matchCharacteristic: MappableConcept = Field(
...,
description="A characteristic of the location that is used to match the defining location to member locations.",
)


class CopyCountConstraint(BaseModel):
"""The exact or range of copies that members of this categorical variant must
satisfy.
"""

type: Literal["CopyCountConstraint"] = Field(
"CopyCountConstraint", description="MUST be 'CopyCountConstraint'"
)
copies: int | Range = Field(
...,
description="The precise value or range of copies members of this categorical variant must satisfy.",
)


class CopyChangeConstraint(BaseModel):
"""A representation of copy number change"""

type: Literal["CopyChangeConstraint"] = Field(
"CopyChangeConstraint", description="MUST be 'CopyChangeConstraint'"
)
copyChange: str = Field(
...,
description="The relative assessment of the change in copies that members of this categorical variant satisfies.",
)

@field_validator("copyChange")
@classmethod
def validate_copy_change(cls, v: str) -> str:
"""Validate copyChange property

:param v: copyChange value
:raises ValueError: If ``copyChange.code`` is not a valid CopyChange
:return: copyChange property
"""
try:
CopyChange(v)
except ValueError as e:
err_msg = f"copyChange, {v}, not one of {[cc.value for cc in CopyChange]}"
raise ValueError(err_msg) from e
return v


class Constraint(RootModel):
"""Constraints are used to construct an intensional semantics of categorical variant types."""

root: (
DefiningAlleleConstraint
| DefiningLocationConstraint
| CopyCountConstraint
| CopyChangeConstraint
) = Field(..., discriminator="type")


class CategoricalVariant(Entity):
"""A representation of a categorically-defined domain for variation, in which
individual Constraintual variation instances may be members of the domain.
"""

type: Literal["CategoricalVariant"] = Field(
"CategoricalVariant", description="MUST be 'CategoricalVariant'"
)
members: list[Variation | iriReference] | None = Field(
None,
description="A non-exhaustive list of VRS variation Constraints that satisfy the constraints of this categorical variant.",
)
constraints: list[Constraint] | None = None
mappings: list[ConceptMapping] | None = Field(
None,
description="A list of mappings to concepts in terminologies or code systems. Each mapping should include a coding and a relation.",
)
Loading
Loading