Source code for laser_measles.demographics.base

from collections import defaultdict
from pathlib import Path
from typing import Protocol

import polars as pl
from pydantic import BaseModel
from pydantic import field_validator
from shapefile import Reader


[docs] class DemographicsGeneratorProtocol(Protocol):
[docs] def generate_population(self) -> pl.DataFrame: ...
[docs] def generate_birth_rates(self) -> pl.DataFrame: ...
[docs] def generate_mortality_rates(self) -> pl.DataFrame: ...
[docs] class ShapefileProtocol(Protocol):
[docs] def add_dotname(self) -> None: ...
[docs] def get_dataframe(self) -> pl.DataFrame: ...
[docs] class BaseShapefile(BaseModel): shapefile: Path
[docs] @classmethod @field_validator("shapefile", mode="before") def convert_to_path(cls, v): p = Path(v) if not isinstance(v, Path) else v if not p.exists(): raise FileNotFoundError(f"Shapefile {p} does not exist") return p
[docs] def add_dotname(self) -> None: ...
[docs] def get_dataframe(self) -> pl.DataFrame: """ Get a Polars DataFrame containing the shapefile data and fields. Returns: A Polars DataFrame. """ with Reader(self.shapefile) as sf: # Get all records and shapes records = [] shapes = [] for shaperec in sf.iterShapeRecords(): records.append(shaperec.record) shapes.append(shaperec.shape) record_dict = defaultdict(list) for record in records: for key, value in record.as_dict().items(): record_dict[key].append(value) # Convert to DataFrame df = pl.DataFrame(record_dict) # Add shape column df = df.with_columns(pl.Series(name="shape", values=shapes)) return df