from __future__ import annotations
from typing import Any
from dae.person_sets import PersonSet, PersonSetCollection
from dae.variants.attributes import Sex
[docs]
class PeopleCounter:
"""Class representing a people counter JSON."""
def __init__(self, json: dict[str, int | str]) -> None:
self.person_set_name = json["column"]
self.people_male = json.get("people_male", 0)
self.people_female = json.get("people_female", 0)
self.people_unspecified = json.get("people_unspecified", 0)
self.people_total = json.get("people_total", 0)
[docs]
@staticmethod
def from_person_set(person_set: PersonSet) -> PeopleCounter:
"""Build people counter JSON from person set."""
matched_people = list(person_set.persons.values())
people_male = len(
list(filter(lambda p: p.sex == Sex.male, matched_people)),
)
people_female = len(
list(filter(lambda p: p.sex == Sex.female, matched_people)),
)
people_unspecified = len(
list(filter(lambda p: p.sex == Sex.unspecified, matched_people)),
)
people_total = len(matched_people)
assert (
people_total == people_male + people_female + people_unspecified
)
return PeopleCounter({
"column": person_set.name,
"people_male": people_male,
"people_female": people_female,
"people_unspecified": people_unspecified,
"people_total": people_total,
})
[docs]
def to_dict(self, rows: list) -> dict[str, int | str]:
people_counter_dict = {row: getattr(self, row) for row in rows}
people_counter_dict["column"] = self.person_set_name
return people_counter_dict
[docs]
def is_empty(self) -> bool:
return self.people_total == 0
[docs]
def is_empty_field(self, field: str) -> bool:
"""Return whether a given field has not counted a single variant."""
assert field in {
"people_male",
"people_female",
"people_unspecified",
"people_total",
}
return bool(getattr(self, field) == 0)
[docs]
class PeopleCounters:
"""Class representing people counters JSON."""
def __init__(self, json: dict[str, Any]) -> None:
self.group_name = json["group_name"]
self.columns = json["columns"]
self.rows = json["rows"]
self.counters = [PeopleCounter(d) for d in json["counters"]]
[docs]
@staticmethod
def from_person_set_collection(
person_set_collection: PersonSetCollection,
) -> PeopleCounters:
"""Create people counters JSON from dict of families."""
people_counters = [
PeopleCounter.from_person_set(person_set)
for person_set in person_set_collection.person_sets.values()
]
people_counters = list(
filter(
lambda people_counter: not people_counter.is_empty(),
people_counters,
),
)
group_name = person_set_collection.name
rows = [
"people_male",
"people_female",
"people_unspecified",
"people_total",
]
def is_row_empty(row: str) -> bool:
return all(
people_counter.is_empty_field(row)
for people_counter in people_counters
)
rows = [row for row in rows if not is_row_empty(row)]
column_names = [
pc.person_set_name for pc in people_counters
]
return PeopleCounters({
"group_name": group_name,
"columns": column_names,
"rows": rows,
"counters": [pc.to_dict(rows) for pc in people_counters],
})
[docs]
def to_dict(self) -> dict[str, Any]:
return {
"group_name": self.group_name,
"columns": self.columns,
"rows": self.rows,
"counters": [c.to_dict(self.rows) for c in self.counters],
}
[docs]
class PeopleReport:
"""Class representing people report JSON."""
def __init__(
self, json: list[dict[str, Any]],
) -> None:
self.people_counters = [PeopleCounters(d) for d in json]
[docs]
@staticmethod
def from_person_set_collections(
person_set_collections: list[PersonSetCollection],
) -> PeopleReport:
"""Create people report from list of person set collections."""
people_counters_collection = [
PeopleCounters.from_person_set_collection(person_set_collection)
for person_set_collection in person_set_collections
]
return PeopleReport(
[pc.to_dict() for pc in people_counters_collection],
)
[docs]
def to_dict(self) -> list[dict[str, Any]]:
return [pc.to_dict() for pc in self.people_counters]