Skip to content

Commit 9c3c39b

Browse files
authored
Put into Health System Summary logger the annual summary of 'Fraction Time Used' broken down by officer type and facility level (#1321)
1 parent 82a02e9 commit 9c3c39b

File tree

1 file changed

+43
-13
lines changed

1 file changed

+43
-13
lines changed

src/tlo/methods/healthsystem.py

+43-13
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from collections.abc import Iterable
88
from itertools import repeat
99
from pathlib import Path
10-
from typing import Dict, List, NamedTuple, Optional, Tuple
10+
from typing import Dict, List, NamedTuple, Optional, Tuple, Union
1111

1212
import numpy as np
1313
import pandas as pd
@@ -928,7 +928,7 @@ def _rescale_capabilities_to_capture_effective_capability(self):
928928
# Only rescale if rescaling factor is greater than 1 (i.e. don't reduce
929929
# available capabilities if these were under-used the previous year).
930930
rescaling_factor = self._summary_counter.frac_time_used_by_officer_type_and_level(
931-
officer_type, level
931+
officer_type=officer_type, level=level
932932
)
933933
if rescaling_factor > 1 and rescaling_factor != float("inf"):
934934
self._daily_capabilities[officer] *= rescaling_factor
@@ -1678,7 +1678,7 @@ def write_to_never_ran_hsi_log(
16781678
def log_current_capabilities_and_usage(self):
16791679
"""
16801680
This will log the percentage of the current capabilities that is used at each Facility Type, according the
1681-
`runnning_total_footprint`.
1681+
`runnning_total_footprint`. This runs every day.
16821682
"""
16831683
current_capabilities = self.capabilities_today
16841684
total_footprint = self.running_total_footprint
@@ -2506,7 +2506,6 @@ def _reset_internal_stores(self) -> None:
25062506

25072507
self._frac_time_used_overall = [] # Running record of the usage of the healthcare system
25082508
self._sum_of_daily_frac_time_used_by_officer_type_and_level = Counter()
2509-
25102509
self._squeeze_factor_by_hsi_event_name = defaultdict(list) # Running record the squeeze-factor applying to each
25112510
# treatment_id. Key is of the form:
25122511
# "<TREATMENT_ID>:<HSI_EVENT_NAME>"
@@ -2561,7 +2560,7 @@ def record_hs_status(
25612560
self._sum_of_daily_frac_time_used_by_officer_type_and_level[officer_type_facility_level] += fraction_time
25622561

25632562
def write_to_log_and_reset_counters(self):
2564-
"""Log summary statistics reset the data structures."""
2563+
"""Log summary statistics reset the data structures. This usually occurs at the end of the year."""
25652564

25662565
logger_summary.info(
25672566
key="HSI_Event",
@@ -2600,16 +2599,47 @@ def write_to_log_and_reset_counters(self):
26002599
},
26012600
)
26022601

2603-
self._reset_internal_stores()
2604-
2605-
def frac_time_used_by_officer_type_and_level(self, officer_type, level):
2606-
"""Average fraction of time used by officer type and level since last reset."""
2607-
# Use len(self._frac_time_used_overall) as proxy for number of days in past year.
2608-
return (
2609-
self._sum_of_daily_frac_time_used_by_officer_type_and_level[officer_type, level]
2610-
/ len(self._frac_time_used_overall)
2602+
# Log mean of 'fraction time used by officer type and facility level' from daily entries from the previous
2603+
# year.
2604+
logger_summary.info(
2605+
key="Capacity_By_OfficerType_And_FacilityLevel",
2606+
description="The fraction of healthcare worker time that is used each day, averaged over this "
2607+
"calendar year, for each officer type at each facility level.",
2608+
data=flatten_multi_index_series_into_dict_for_logging(
2609+
self.frac_time_used_by_officer_type_and_level()),
26112610
)
26122611

2612+
self._reset_internal_stores()
2613+
2614+
def frac_time_used_by_officer_type_and_level(
2615+
self,
2616+
officer_type: Optional[str]=None,
2617+
level: Optional[str]=None,
2618+
) -> Union[float, pd.Series]:
2619+
"""Average fraction of time used by officer type and level since last reset.
2620+
If `officer_type` and/or `level` is not provided (left to default to `None`) then a pd.Series with a multi-index
2621+
is returned giving the result for all officer_types/levels."""
2622+
2623+
if (officer_type is not None) and (level is not None):
2624+
return (
2625+
self._sum_of_daily_frac_time_used_by_officer_type_and_level[officer_type, level]
2626+
/ len(self._frac_time_used_overall)
2627+
# Use len(self._frac_time_used_overall) as proxy for number of days in past year.
2628+
)
2629+
else:
2630+
# Return multiple in the form of a pd.Series with multiindex
2631+
mean_frac_time_used = {
2632+
(_officer_type, _level): v / len(self._frac_time_used_overall)
2633+
for (_officer_type, _level), v in self._sum_of_daily_frac_time_used_by_officer_type_and_level.items()
2634+
if (_officer_type == officer_type or officer_type is None) and (_level == level or level is None)
2635+
}
2636+
return pd.Series(
2637+
index=pd.MultiIndex.from_tuples(
2638+
mean_frac_time_used.keys(),
2639+
names=['OfficerType', 'FacilityLevel']
2640+
),
2641+
data=mean_frac_time_used.values()
2642+
).sort_index()
26132643

26142644
class HealthSystemChangeParameters(Event, PopulationScopeEventMixin):
26152645
"""Event that causes certain internal parameters of the HealthSystem to be changed; specifically:

0 commit comments

Comments
 (0)