Source code for bioarch.trauma

#!/usr/bin/env python


import enum
from enum import Enum
import logging


import pandas as pd
from pandas.api.types import CategoricalDtype


from .left_right import LeftRight


logger = logging.getLogger(__name__)


[docs]@enum.unique class TraumaCategory(Enum): NOT_PRESENT = -1 # noqa: E221,E222 PARTIAL_BONE = 0.5 # noqa: E221,E222 NORMAL = 1 # noqa: E221,E222 INFECTION = 2 # noqa: E221,E222 FRACTURE = 3 # noqa: E221,E222 UNHEALED_FRACTURE = 4 # noqa: E221,E222 CRIBA = 5 # noqa: E221,E222 BLUNT_FORCE_TRAUMA = 6 # noqa: E221,E222 SHARP_FORCE_TRAUMA = 7 # noqa: E221,E222 TREPONATION = 8 # noqa: E221,E222 UNFUSED = 9 # noqa: E221,E222 BONY_GROWTH = 10 # noqa: E221,E222 FUSED = 11 # noqa: E221,E222 OSTEOCHONDRITIS_DESSICANS = 12 # noqa: E221,E222
[docs] @staticmethod def parse(value): if value is None: return None if type(value) == TraumaCategory: # pylint: disable=C0123 return value if isinstance(value, (float, int)): value = str(value) if not isinstance(value, str): raise ValueError(f'Failed to parse TraumaCategory: "{value}"') value = value.upper() for condition in TraumaCategory: if value == condition.name: return condition if value == str(condition.value): return condition if value in ('NA', 'N'): return TraumaCategory.NOT_PRESENT raise ValueError(f'Failed to parse TraumaCategory: "{value}"')
[docs] @staticmethod def avg(left, right): if left in (None, TraumaCategory.NOT_PRESENT): return right if right in (None, TraumaCategory.NOT_PRESENT): return left if left == right: return left raise NotImplementedError()
def __repr__(self): return f'{self.__class__.__name__}: {self}' def __str__(self): return self.name
[docs] @staticmethod def dtype(): return CategoricalDtype(categories=[s.name for s in TraumaCategory], ordered=False)
[docs]class Trauma(object): # pylint: disable=R0902 """docstring for Trauma""" def __init__(self, facial_bones: TraumaCategory, clavicle: LeftRight[TraumaCategory], scapula: LeftRight[TraumaCategory], humerus: LeftRight[TraumaCategory], ulna: LeftRight[TraumaCategory], radius: LeftRight[TraumaCategory], femur: LeftRight[TraumaCategory], tibia: LeftRight[TraumaCategory], fibula: LeftRight[TraumaCategory], ribs: TraumaCategory, vertabrae: TraumaCategory): self.facial_bones = facial_bones self.clavicle = clavicle self.scapula = scapula self.humerus = humerus self.ulna = ulna self.radius = radius self.femur = femur self.tibia = tibia self.fibula = fibula self.ribs = ribs self.vertabrae = vertabrae
[docs] @staticmethod def empty(): categories = [TraumaCategory.NOT_PRESENT] * 1 categories += [LeftRight(TraumaCategory.NOT_PRESENT, TraumaCategory.NOT_PRESENT)] * 8 categories += [TraumaCategory.NOT_PRESENT] * 2 return Trauma(*categories)
[docs] def to_pd_data_frame(self, index): d = { 'id': pd.Series([index]), } for l in ('clavicle', 'scapula', 'humerus', 'ulna', 'radius', 'femur', 'tibia', 'fibula'): val = getattr(self, l) if val is None: continue if val.left is not None: d[f'{l}_left_cat'] = pd.Series([val.left.name], copy=True, dtype=TraumaCategory.dtype()) # noqa: E241 d[f'{l}_left_val'] = pd.Series([val.left.value], copy=True) if val.right is not None: d[f'{l}_right_cat'] = pd.Series([val.right.name], copy=True, dtype=TraumaCategory.dtype()) # noqa: E241 d[f'{l}_right_val'] = pd.Series([val.right.value], copy=True) try: val_avg = val.avg() if val_avg is not None: d[f'{l}_avg_cat'] = pd.Series([val_avg.name], copy=True, dtype=TraumaCategory.dtype()) # noqa: E241 d[f'{l}_avg_val'] = pd.Series([val_avg.value], copy=True) except NotImplementedError: logger.info('Can not "avg" "%s": "%s"', l, self) for l in ('facial_bones', 'ribs', 'vertabrae'): val = getattr(self, l) if val is None: continue d[f'{l}_cat'] = pd.Series([val.name], copy=True, dtype=TraumaCategory.dtype()) # noqa: E241 d[f'{l}_val'] = pd.Series([val.value], copy=True) return pd.DataFrame.from_dict(d).set_index('id')
def __repr__(self): return f'{self.__class__.__name__}: {self}' def __str__(self): return f'facial_bones="{self.facial_bones}" clavicle="{self.clavicle}" ...'
if __name__ == "__main__": raise RuntimeError('No main available')