Source code for ppsc.v202._individual

import enum
import typing

import phenopackets as pp202
from google.protobuf.message import Message

from ._base import TimeElement, OntologyClass
from .._api import MessageMixin
from .._timestamp import Timestamp
from ..parse import extract_message_scalar, extract_pb_message_scalar


[docs] class Sex(enum.Enum): """ An enumeration used to represent the sex of an individual. This element does not represent gender identity or :class:`KaryotypicSex`, but instead represents typical “phenotypic sex”, as would be determined by a midwife or physician at birth. """ # The `int` values correspond to protobuf fields in Phenopacket Schema. UNKNOWN_SEX = 0 """ Not assessed or not available. Maps to `NCIT:C17998 <https://www.ebi.ac.uk/ols/ontologies/ncit/terms?iri=http%3A%2F%2Fpurl.obolibrary.org%2Fobo%2FNCIT_C17998>`_ """ FEMALE = 1 """ Female sex. Maps to `NCIT:C46113 <https://www.ebi.ac.uk/ols/ontologies/ncit/terms?iri=http%3A%2F%2Fpurl.obolibrary.org%2Fobo%2FNCIT_C46113>`_. """ MALE = 2 """ Male sex. Maps to `NCIT:C46112 <https://www.ebi.ac.uk/ols/ontologies/ncit/terms?iri=http%3A%2F%2Fpurl.obolibrary.org%2Fobo%2FNCIT_C46112>`_ """ OTHER_SEX = 3 """ It is not possible to accurately assess the applicability of `MALE`/`FEMALE`. Maps to `NCIT:C45908 <https://www.ebi.ac.uk/ols/ontologies/ncit/terms?iri=http%3A%2F%2Fpurl.obolibrary.org%2Fobo%2FNCIT_C45908>`_ """
[docs] class KaryotypicSex(enum.Enum): # The `int` values correspond to protobuf fields in Phenopacket Schema. UNKNOWN_KARYOTYPE = 0 XX = 1 XY = 2 XO = 3 XXY = 4 XXX = 5 XXYY = 6 XXXY = 7 XXXX = 8 XYY = 9 OTHER_KARYOTYPE = 10
[docs] class VitalStatus(MessageMixin): """ TODO: add docs. """
[docs] class Status(enum.Enum): """ TODO: add docs. """ # The `int` values correspond to protobuf fields in Phenopacket Schema. UNKNOWN_STATUS = 0 ALIVE = 1 DECEASED = 2
def __init__( self, status: Status, time_of_death: typing.Optional[TimeElement] = None, cause_of_death: typing.Optional[OntologyClass] = None, survival_time_in_days: typing.Optional[int] = None, ): self._status = status self._time_of_death = time_of_death self._cause_of_death = cause_of_death self._survival_time_in_days = survival_time_in_days @property def status(self) -> Status: return self._status @status.setter def status(self, value: Status): self._status = value @property def time_of_death(self) -> typing.Optional[TimeElement]: return self._time_of_death @time_of_death.setter def time_of_death(self, value: typing.Optional[TimeElement]): self._time_of_death = value @time_of_death.deleter def time_of_death(self): self._time_of_death = None @property def cause_of_death(self) -> typing.Optional[OntologyClass]: return self._cause_of_death @cause_of_death.setter def cause_of_death(self, value: typing.Optional[OntologyClass]): self._cause_of_death = value @cause_of_death.deleter def cause_of_death(self): self._cause_of_death = None @property def survival_time_in_days(self) -> typing.Optional[int]: return self._survival_time_in_days @survival_time_in_days.setter def survival_time_in_days(self, value: typing.Optional[int]): self._survival_time_in_days = value @survival_time_in_days.deleter def survival_time_in_days(self): self._survival_time_in_days = None
[docs] @staticmethod def field_names() -> typing.Iterable[str]: return 'status', 'time_of_death', 'cause_of_death', 'survival_time_in_days'
[docs] @classmethod def required_fields(cls) -> typing.Sequence[str]: return 'status',
[docs] @classmethod def from_dict(cls, values: typing.Mapping[str, typing.Any]): if cls._all_required_fields_are_present(values): return VitalStatus( status=MessageMixin._extract_enum_field('status', VitalStatus.Status, values), time_of_death=extract_message_scalar('time_of_death', TimeElement, values), cause_of_death=extract_message_scalar('cause_of_death', OntologyClass, values), survival_time_in_days=int(values['survival_time_in_days']) if 'survival_time_in_days' in values else None, ) else: cls._complain_about_missing_field(values)
[docs] def to_message(self) -> Message: vs = pp202.VitalStatus( status=pp202.VitalStatus.Status.Value(self._status.name), ) if self._time_of_death is not None: vs.time_of_death.CopyFrom(self._time_of_death.to_message()) if self._cause_of_death is not None: vs.cause_of_death.CopyFrom(self._cause_of_death.to_message()) if self._survival_time_in_days is not None: vs.survival_time_in_days = self._survival_time_in_days return vs
[docs] @classmethod def message_type(cls) -> typing.Type[Message]: return pp202.VitalStatus
[docs] @classmethod def from_message(cls, msg: Message): if isinstance(msg, pp202.VitalStatus): return VitalStatus( status=VitalStatus.Status(msg.status), time_of_death=extract_pb_message_scalar('time_of_death', TimeElement, msg), cause_of_death=extract_pb_message_scalar('cause_of_death', OntologyClass, msg), survival_time_in_days=None if msg.survival_time_in_days == 0 else msg.survival_time_in_days, ) else: cls.complain_about_incompatible_msg_type(msg)
def __eq__(self, other): return isinstance(other, VitalStatus) \ and self._status == other._status \ and self._time_of_death == other._time_of_death \ and self._cause_of_death == other._cause_of_death \ and self._survival_time_in_days == other._survival_time_in_days def __repr__(self): return f'VitalStatus(' \ f'status={self._status}, ' \ f'time_of_death={self._time_of_death}, ' \ f'cause_of_death={self._cause_of_death}, ' \ f'survival_time_in_days={self._survival_time_in_days}' \ ')'
[docs] class Individual(MessageMixin): def __init__( self, id: str, alternate_ids: typing.Optional[typing.Iterable[str]] = None, date_of_birth: typing.Optional[Timestamp] = None, time_at_last_encounter: typing.Optional[TimeElement] = None, vital_status: typing.Optional[VitalStatus] = None, sex: typing.Optional[Sex] = None, karyotypic_sex: typing.Optional[KaryotypicSex] = None, gender: typing.Optional[OntologyClass] = None, taxonomy: typing.Optional[OntologyClass] = None, ): # TODO: validate self._id = id self._alt_ids = [] if alternate_ids is None else list(alternate_ids) self._date_of_birth = date_of_birth self._time_at_last_encounter = time_at_last_encounter self._vital_status = vital_status self._sex = sex self._karyotypic_sex = karyotypic_sex self._gender = gender self._taxonomy = taxonomy @property def id(self) -> typing.Optional[str]: return self._id @property def alternate_ids(self) -> typing.MutableSequence[str]: return self._alt_ids @property def date_of_birth(self) -> typing.Optional[Timestamp]: return self._date_of_birth @date_of_birth.setter def date_of_birth(self, value: typing.Optional[Timestamp]): self._date_of_birth = value @date_of_birth.deleter def date_of_birth(self): self._date_of_birth = None @property def time_at_last_encounter(self) -> typing.Optional[TimeElement]: return self._time_at_last_encounter @time_at_last_encounter.setter def time_at_last_encounter(self, value: typing.Optional[TimeElement]): self._time_at_last_encounter = value @time_at_last_encounter.deleter def time_at_last_encounter(self): self._time_at_last_encounter = None @property def vital_status(self) -> typing.Optional[VitalStatus]: return self._vital_status @vital_status.setter def vital_status(self, value: typing.Optional[VitalStatus]): self._vital_status = value @vital_status.deleter def vital_status(self): self._vital_status = None @property def sex(self) -> typing.Optional[Sex]: return self._sex @sex.setter def sex(self, value: typing.Optional[Sex]): self._sex = value @sex.deleter def sex(self): self._sex = None @property def karyotypic_sex(self) -> typing.Optional[KaryotypicSex]: return self._karyotypic_sex @karyotypic_sex.setter def karyotypic_sex(self, value: typing.Optional[KaryotypicSex]): self._karyotypic_sex = value @karyotypic_sex.deleter def karyotypic_sex(self): self._karyotypic_sex = None @property def gender(self) -> typing.Optional[OntologyClass]: return self._gender @gender.setter def gender(self, value: typing.Optional[OntologyClass]): self._gender = value @gender.deleter def gender(self): self._gender = None @property def taxonomy(self) -> typing.Optional[OntologyClass]: return self._taxonomy @taxonomy.setter def taxonomy(self, value: typing.Optional[OntologyClass]): self._taxonomy = value @taxonomy.deleter def taxonomy(self): self._taxonomy = None
[docs] @staticmethod def field_names() -> typing.Iterable[str]: return 'id', 'alternate_ids', 'date_of_birth', 'time_at_last_encounter', 'vital_status', 'sex', 'karyotypic_sex', 'gender', 'taxonomy'
[docs] @classmethod def required_fields(cls) -> typing.Sequence[str]: return 'id',
[docs] @classmethod def from_dict(cls, values: typing.Mapping[str, typing.Any]): if cls._all_required_fields_are_present(values): return Individual( id=values['id'], alternate_ids=MessageMixin._extract_optional_field('alternate_ids', values), date_of_birth=extract_message_scalar('date_of_birth', Timestamp, values), time_at_last_encounter=extract_message_scalar('time_at_last_encounter', TimeElement, values), vital_status=extract_message_scalar('vital_status', VitalStatus, values), sex=MessageMixin._extract_enum_field('sex', Sex, values), karyotypic_sex=MessageMixin._extract_enum_field('karyotypic_sex', KaryotypicSex, values), gender=extract_message_scalar('gender', OntologyClass, values), taxonomy=extract_message_scalar('taxonomy', OntologyClass, values), ) else: cls._complain_about_missing_field(values)
[docs] def to_message(self) -> Message: i = pp202.Individual( id=self._id, ) if len(self._alt_ids) != 0: i.alternate_ids.extend(self._alt_ids) if self._date_of_birth is not None: i.time_at_last_encounter.CopyFrom(self._date_of_birth.to_message()) if self._time_at_last_encounter is not None: i.time_at_last_encounter.CopyFrom(self._time_at_last_encounter.to_message()) if self._vital_status is not None: i.vital_status.CopyFrom(self._vital_status.to_message()) if self._sex is not None: i.sex = pp202.Sex.Value(self._sex.name) if self._karyotypic_sex is not None: i.karyotypic_sex = pp202.KaryotypicSex.Value(self._karyotypic_sex.name) if self._gender is not None: i.gender.CopyFrom(self._gender.to_message()) if self._taxonomy is not None: i.taxonomy.CopyFrom(self._taxonomy.to_message()) return i
[docs] @classmethod def message_type(cls) -> typing.Type[Message]: return pp202.Individual
[docs] @classmethod def from_message(cls, msg: Message): if isinstance(msg, pp202.Individual): return Individual( id=msg.id, alternate_ids=msg.alternate_ids, date_of_birth=extract_pb_message_scalar('date_of_birth', Timestamp, msg), time_at_last_encounter=extract_pb_message_scalar('time_at_last_encounter', TimeElement, msg), sex=Sex(msg.sex), karyotypic_sex=KaryotypicSex(msg.karyotypic_sex), vital_status=extract_pb_message_scalar('vital_status', VitalStatus, msg), gender=extract_pb_message_scalar('gender', OntologyClass, msg), taxonomy=extract_pb_message_scalar('taxonomy', OntologyClass, msg), ) else: cls.complain_about_incompatible_msg_type(msg)
def __eq__(self, other): return isinstance(other, Individual) \ and self._id == other._id \ and self._alt_ids == other._alt_ids \ and self._date_of_birth == other._date_of_birth \ and self._time_at_last_encounter == other._time_at_last_encounter \ and self._sex == other._sex \ and self._karyotypic_sex == other._karyotypic_sex \ and self._gender == other._gender \ and self._taxonomy == other._taxonomy def __repr__(self): return f'Individual(id={self._id},' \ f' alternate_ids={self._alt_ids},' \ f' date_of_birth={self._date_of_birth},' \ f' time_at_last_encounter={self._time_at_last_encounter},' \ f' sex={self._sex},' \ f' karyotypic_sex={self._karyotypic_sex},' \ f' gender={self._gender},' \ f' taxonomy={self._taxonomy},' \ ')'