Skip to content

Commit 479a635

Browse files
Record the prevalence of disease/condition, still births, neonatal death, maternal mortality (#1772)
* Tried to make the log daily by introducing more conditions. * Monthly call from functions * removed unused variable for checks * removed unused variable for checks * removed unused variable for checks * isort * new write to log function just for prevalence calculations * new write to log function just for prevalence calculations. Now logs monthly * new write to log function just for prevalence calculations. Now logs monthly * Shorter run as test * Allow mockitis to be read in the GetPrevalence Class. Added report_prevalence function to the mockitis module * Set p(infection) of Mockitis to 1 and checked logging * In demography, fixed labels for direct/indirect/hiv/non hiv deaths * Changed malaria prevalence calculator to clinical and severe malaria infections * Changed schisto prevalence calculation to check for Low-infection or High-infection * Changed TB prevalence logging to only include active cases. "I think here we should log only active cases, this way we can compare with WHO reports / GBD etc. Also the way that we assign latent cases is not identical to other models, we don't have infections -> latent -> active so we would under-estimate the latent infections. Best to stick to symptomatic active cases only." * Now using (df['rt_inj_severity'] != 'none') again to record RTI injuries * Updated description of logger to show what is being saved where * Added report_prevalence to the skeleton module so that it's formally part of the definition of a disease module * Added option between daily, monthly, and yearly logging Added check to ensure prganancy is possible * Tidied test to have mockitis test (to check logging structures etc) as well as initial test to see if all expected modules have logged diseases * update for actual runs * isort * Added stacked plots over time and plots per 1000 population over time * Updated to create files for longterm_trends_all_diseases-2024-09-04T082106Z * Changed dates for longterm_trends_all_diseases-2024-09-04T082106Z * Added spacing of years so can toggle finer resolution * Improved docstring * New file calculating the prevalence of different conditions * isort * Condensed graph so Panel A is stacked bar charts of raw prevalence over time and B is the relative change since 2010 * Changed colours * Changed labels on plots * Included placeholder code for reordering; not yet working * Included placeholder code for reordering; not yet working * Added in WPP life expectancy to graph * Changed colours * Removed print statements * Added a gif of the population pyramids * Tidied graphs * Tidied graphs * Changed to a bar chart and ensured that colours matched * Removed print check * Removed colour generation * Removed axis * Now print all files * Added gif for line graph * Added checks for dummy runs in life expectancy calculations. Checks for infinities and replaces with NAN. * Changed timing * Have total minutes per treatment_id * Have graphs of minutes per treatment id * Have graphs of minutes per treatment id * Tidied up graphs * Changed to test new logs * test * test * return to actual params * return to actual params * trying * Loaded dataframes to access NEED TO cross ref with dataframe * Added loops over each event and cadre. Adding time to the cadre and the module dictionaries * Changed it back to be the first part of treatment id (as those are the short code treatment ids) * Changed it back to be the first part of treatment id (as those are the short code treatment ids) * Fixed legends and titles * Changed ASFR axis * Changed dates * Left-censured the x axis for the deaths and life expectancy graph * New dates * Edited for neatness * Modified for latest run input_file = '/Users/rem76/PycharmProjects/TLOmodel/outputs/rm916@ic.ac.uk/longterm_trends_all_diseases-2024-09-12T084811Z/0/8/longterm_trends_all_diseases-2024-09-12T084811Z.log' * Changed so graphs are from 2020 on * Remove the demography summary logger * edited for latest run * edited for latest run * Removed print statements Changed so that the MMR, Live Births etc returns None only if Simplified Births are used * Accidentally deleted scenario directory * changed date raneg * changed date raneg * resized figures * Changed prevalence calculation for RTI to ensure accident happened in last month * Changed prevalence calculation for RTI to ensure accident happened in last month. Fixed issue so that only comparing actual times (not NaT) * Aesthetic edits Added file for a network graph using pydot that shows interactions bewteen disease modules (based on tlo_module_graph.py) * Updated modules so that all INIT_DEPENDENCIES and OPTIONAL_INIT_DEPENDENCIES are declared * Updated modules so that all INIT_DEPENDENCIES and OPTIONAL_INIT_DEPENDENCIES and ADDITIONAL_DEPENDENCIES are declared * Updated modules so that all INIT_DEPENDENCIES and OPTIONAL_INIT_DEPENDENCIES and ADDITIONAL_DEPENDENCIES are declared * Updated modules so that all INIT_DEPENDENCIES and OPTIONAL_INIT_DEPENDENCIES and ADDITIONAL_DEPENDENCIES are declared * Updated modules so that all INIT_DEPENDENCIES and OPTIONAL_INIT_DEPENDENCIES and ADDITIONAL_DEPENDENCIES are declared * Updated modules so that all INIT_DEPENDENCIES and OPTIONAL_INIT_DEPENDENCIES and ADDITIONAL_DEPENDENCIES are declared * Updated modules so that all INIT_DEPENDENCIES and OPTIONAL_INIT_DEPENDENCIES and ADDITIONAL_DEPENDENCIES are declared * Updated modules so that all INIT_DEPENDENCIES and OPTIONAL_INIT_DEPENDENCIES and ADDITIONAL_DEPENDENCIES are declared * Moved all new dependencies to OPTIONAL_INIT_DEPENDENCIES * Type * Typo * Removed unnecessary subgraphs * Updated circular dependencies * Updated circular dependencies * Tried to add subgraph * Pregnancy modules are now diamonds * Changed to additional dependencies * Added subgraphs * graph of the property dependencies between modules * Have graph of properties as they relate to modules removed infection subgraph (temporarily) * Removed bad graph * Added subgraphs * Graph of properties from disease modules that contribute to other disease modules. Process: collects properties from each disease (+lifestyle) module, and compares them to the scripts of the remaining disease (+lifestyle) module. * Delete src/scripts/longterm_projections/property_dependency_graph.py Duplicate graph * isort * isort * Changed names of functions to avoid overlap * Updated docstring * Initial attempt at creating module-level property graphs * Fixed typo * Graphs for each individual module * Aesthetics - still needs colour * reduced duplication * Removed all additional dependencies * typo * Moved to get_properties folder * Tidied * Increased max date * Tidied and changed to 2059 * Increased max year for pop line * Increased axis for deaths over time * Improved plotting * changed normalization to 2020 * changed normalization to 2020 and improved plotting * aesthetics * plotting * Typo - left out fraction_of_last_age_survived in calculating probability of premature death * add lifestyle logging * shorter run + demography.detail to see if there is an issue in assumption of fraction of period survived * updated so that it looks at the entire code of whatever disease of interest, as previously was only looking at module classes and was therefore missing things like polling events * actual logging for demography detail * changed to latest short run * Investigation into differences in LE for 2010 - 2020. Could be because of below-1 mortality. Life table calculations assume that 50% of the age group is survived; from this analysis, looks like >60% of children die before 6 months, violating that assumption. Major driver could be encephalopathy? * removed unneccessary LE graph * More plots to investiagte proprtion of life groups lived * Sample LE estimates with one year age groups and 0.5 year at beginning. Unsure it did much * Can't get half-year age groups to work * Updated date * Scripts to try and investigate why RTI DALYs etc goes up, but there is a big decrease in demand on the healthcare system * revert to original * New notebook for investigating the differences in LE between our method and WPP * New notebook for investigating the differences in LE between our method and WPP * New notebook for investigating the differences in LE between our method and WPP * To investigate RTI * Formattin * Add in scenarios for baseline (business as usual), renamed perfect world and added in the HTM scale up. Working on lifestyle examinations * Added in two lifestyle scenarios: cancer and CMD. Hard to paramaterise * Fixed number_of_draws isort * 50% increase/decrease in probabilities instead of doubling? * Set up to run * Added MDA_event to try and ensure that MDA events are scheduled * Added MDA_event to try and ensure that MDA events are scheduled * Somehow prevalence logging for HIV was removed * Added sex- and age-specific prevalence logging Dictionary for each * Accidentally saved csv file * Removed the manual administration of mda event in the schisto * Added age and sex for mockitis * Dont need file * Deleted too much * Added age and sex breakdown * simplified * Updated test to account for fact it is now a dictionary * Don't need these files for this commit * Updated test to account for new dictionary structure * Used groupby instead of loops * Reverted back * Reverted changes that were being used to test. Noticed that dividing by fraction_of_last_age_survived at line 119 was lost in master * Deleted accidental duplication of files * Added empty dictionary * Ensured there was at least some dictionary to be referred to * Updated to match master * Updated to match master * Add record prevalence to wasting. Did for both moderate and severe wasting for below 5 y/o. * Add record age-specific prevalence to cervical cancer. * Add record age-specific prevalence to pregnancy supervisor. Just grouped all complications together - could disentangle. * update use of rfp * handling paramter value * roll back incidental changes in life_expectancy.py * avoid duplication of log_df_line_by_line function in healthburden.py * rename to show it's a private function * rename for clarity * correct signuature and docstring in skeleton.py * remove unused variable * no need to store prevalence_of_diseases on module * need to schedule the occurence of the event that does all the work! * direct pass the df to avoid saving on module * streamline logic for information collection and processing and removing special case conditions * update imports * handle arguement for frequency of updating * move dummy module to test suite get test on dummy module working refactor mechanics unify naming conventions * fully reguluarise returns into flatten returns to dict[str, float] format * allow nested dict * store population age/sex breakdown * log population age/sex breakdown * * use utility function for ease of refactoring (wherever possible) * use boolean property for RTI * simply refactoring logic * tidy pregnancy prevalence calculation and logic * Remove MMR etc from Demography file * Created new "DiseaseNumbers" module that records - at a set frequency - the number of individuals of each age and sex with a specific disease/condition. NB - no longer has a denominator, just raw numbers. This replaces the "report_prevalence" that was previously in the healthburden module. * Renamed module file Included file with parameters Redid test to not use HealthBurden Module any more * --fix flag * Added report_disease_numbers method * isort src tests * ruff check src tests --fix * Removed "prevalence" to "number" Fixed line formatting * Removed OPTIONAL_INIT_DEPENDENCIES = {"DiseaseNumbers"} as not called until after the initialisation * Add check of data structure. * Added more informative dictionary labels indicating what is being collected by each "report_disease_numbers" call. Additionally, changed get_counts_by_sex_and_age_group to ensure that different statuses are captured in the logging (e.g., noting whether it is clinical or severe malaria). * remove stray inverted comma * remove unneccessary whitespace * rollback incidental change * simplyy test: * don't write to the interal store twice * use global dates in format * remove optional_init_dependence * typo in member function of oseophageal cancer * * rename module to RecordSummaryStats * soft-code parameter and read-in from resourcefile * no need to worry about logging at end of the simulation or storing dates * collection of registered moudle should not include checks on callable member function as that obviates the check that follows * check on validity of parameter for logging frequency * use type checking to ensure return from 'report' function is a dict * * rename report_disease_numbers to report_summary_stats * update instructions in skeleton.py * more notes in skeleton.py * simplifying logging output by putting results from each disease module into separate key (and so becomes its own dataframe) * * Make all returns by of the form {stat: content} * Update utiltity function so that target is the set of things considered 'truthy' (a further layer of breakdown can still be achieved by repeating call to the functioin, by the additional layer on nesting by default seemed superfluous) * Roll back incidental changes and where the module doesn't actually do any reporting * Where that content is age/sex breakdown, let sex by the outer-key * standardise outet key style * roll back all changes to healtburden,py * in labour upodate: report_prevalence --> report_summmary_stats * in labour uodate metadata. * simplify schisto by using new utility function * strealine counting of report of i_s_b and make it robust to different repoting frequencies. * typo * linting: update imports * more linting * refactor and simplify check on types. (Needs to be very lightweight as its called so mnay times). Error portection is also there from the wrapping inside the try/except loop. Any make it optional by gating behind a parameter * remove unused import from record_summary_stats.py --------- Co-authored-by: RachelMurray-Watson <rmurwat@gmail.com> Co-authored-by: RachelMurray-Watson <106470783+RachelMurray-Watson@users.noreply.github.com>
1 parent ff41fa1 commit 479a635

27 files changed

Lines changed: 704 additions & 23 deletions
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:94601cde7187f0dc5a6c98c664ac0595651a3cc39b4118f9529031c27693b707
3+
size 63

src/tlo/analysis/utils.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from collections.abc import Mapping
1212
from pathlib import Path
1313
from types import MappingProxyType
14-
from typing import Callable, Dict, Iterable, List, Literal, Optional, TextIO, Tuple, Union
14+
from typing import Any, Callable, Dict, Iterable, List, Literal, Optional, TextIO, Tuple, Union
1515

1616
import git
1717
import matplotlib.colors as mcolors
@@ -1460,3 +1460,34 @@ def mix_scenarios(*dicts) -> Dict:
14601460
d[mod].update({param: value})
14611461

14621462
return d
1463+
1464+
1465+
def flatten_nested_dict(my_dict, sep='_'):
1466+
"""Flatten a nested dictionary into a single level dictionary."""
1467+
return pd.pandas.io.json._normalize.nested_to_record(my_dict, sep=sep)
1468+
1469+
1470+
def get_counts_by_sex_and_age_group(df: pd.DataFrame, property: str, targets: Optional[Tuple[Any]|str] = None) -> dict:
1471+
"""Returns dict giving counts (by sex and age-group) of alive individuals with truthy
1472+
values for that property (if no `target` is provided) or with a value included in `targets` (if a `target` is
1473+
provided).
1474+
1475+
Returns: {sex: {age_group: count}}
1476+
"""
1477+
1478+
if targets is None:
1479+
counts = df.loc[
1480+
df.is_alive & df[property]
1481+
].groupby(['sex', 'age_range']).size().unstack(fill_value=0)
1482+
1483+
elif isinstance(targets, tuple):
1484+
counts = df.loc[
1485+
df.is_alive & df[property].isin(targets)
1486+
].groupby(['sex', 'age_range']).size().unstack(fill_value=0)
1487+
1488+
elif isinstance(targets, str):
1489+
counts = df.loc[
1490+
df.is_alive & (df[property] == targets)
1491+
].groupby(['sex', 'age_range']).size().unstack(fill_value=0)
1492+
1493+
return counts.to_dict(orient='index')

src/tlo/methods/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ class Metadata(Enum):
66
USES_SYMPTOMMANAGER = auto() # The 'Symptom Manager' recognises modules with this label.
77
USES_HEALTHSYSTEM = auto() # The 'HealthSystem' recognises modules with this label.
88
USES_HEALTHBURDEN = auto() # The 'HealthBurden' module recognises modules with this label.
9+
REPORTS_DISEASE_NUMBERS = auto() # The 'DiseaseNumbers' module recognises modules with this label.

src/tlo/methods/alri.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import pandas as pd
3131

3232
from tlo import DAYS_IN_YEAR, DateOffset, Module, Parameter, Property, Types, logging
33+
from tlo.analysis.utils import get_counts_by_sex_and_age_group
3334
from tlo.events import Event, IndividualScopeEventMixin, PopulationScopeEventMixin, RegularEvent
3435
from tlo.lm import LinearModel, LinearModelType, Predictor
3536
from tlo.methods import Metadata
@@ -75,7 +76,8 @@ class Alri(Module, GenericFirstAppointmentsMixin):
7576
Metadata.DISEASE_MODULE,
7677
Metadata.USES_SYMPTOMMANAGER,
7778
Metadata.USES_HEALTHSYSTEM,
78-
Metadata.USES_HEALTHBURDEN
79+
Metadata.USES_HEALTHBURDEN,
80+
Metadata.REPORTS_DISEASE_NUMBERS
7981
}
8082

8183
pathogens = {
@@ -1017,6 +1019,12 @@ def report_daly_values(self):
10171019
daly_values_by_pathogen = daly_values_by_pathogen.add_prefix('ALRI_')
10181020
return daly_values_by_pathogen
10191021

1022+
def report_summary_stats(self):
1023+
# This reports age- and sex-specific prevalence of ALRI for all individuals
1024+
df = self.sim.population.props
1025+
number_by_age_group_sex = get_counts_by_sex_and_age_group(df, 'ri_current_infection_status')
1026+
return {'number_current_ri': number_by_age_group_sex}
1027+
10201028
def over_ride_availability_of_certain_consumables(self):
10211029
"""Over-ride the availability of certain consumables, according the parameter values provided."""
10221030
p = self.parameters

src/tlo/methods/bladder_cancer.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import pandas as pd
1414

1515
from tlo import DateOffset, Module, Parameter, Property, Types, logging
16+
from tlo.analysis.utils import get_counts_by_sex_and_age_group
1617
from tlo.events import IndividualScopeEventMixin, PopulationScopeEventMixin, RegularEvent
1718
from tlo.lm import LinearModel, LinearModelType, Predictor
1819
from tlo.methods import Metadata
@@ -52,7 +53,8 @@ def __init__(self, name=None):
5253
Metadata.DISEASE_MODULE,
5354
Metadata.USES_SYMPTOMMANAGER,
5455
Metadata.USES_HEALTHSYSTEM,
55-
Metadata.USES_HEALTHBURDEN
56+
Metadata.USES_HEALTHBURDEN,
57+
Metadata.REPORTS_DISEASE_NUMBERS
5658
}
5759

5860
# Declare Causes of Death
@@ -635,6 +637,13 @@ def report_daly_values(self):
635637

636638
return disability_series_for_alive_persons
637639

640+
def report_summary_stats(self):
641+
# This reports age- and sex-specific prevalence of bladder cancer for all individuals
642+
df = self.sim.population.props
643+
number_by_age_group_sex = get_counts_by_sex_and_age_group(df, 'bc_status', ("tis_t1", "t2p", "metastatic"))
644+
return {'number_at_any_stage': number_by_age_group_sex}
645+
646+
638647
def do_at_generic_first_appt(
639648
self,
640649
person_id: int,

src/tlo/methods/breast_cancer.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import pandas as pd
1313

1414
from tlo import DateOffset, Module, Parameter, Property, Types, logging
15+
from tlo.analysis.utils import get_counts_by_sex_and_age_group
1516
from tlo.events import IndividualScopeEventMixin, PopulationScopeEventMixin, RegularEvent
1617
from tlo.lm import LinearModel, LinearModelType, Predictor
1718
from tlo.methods import Metadata
@@ -50,7 +51,8 @@ def __init__(self, name=None):
5051
Metadata.DISEASE_MODULE,
5152
Metadata.USES_SYMPTOMMANAGER,
5253
Metadata.USES_HEALTHSYSTEM,
53-
Metadata.USES_HEALTHBURDEN
54+
Metadata.USES_HEALTHBURDEN,
55+
Metadata.REPORTS_DISEASE_NUMBERS
5456
}
5557

5658
# Declare Causes of Death
@@ -579,6 +581,13 @@ def report_daly_values(self):
579581

580582
return disability_series_for_alive_persons
581583

584+
def report_summary_stats(self):
585+
# This reports age- and sex-specific prevalence of breast cancer for all individuals
586+
df = self.sim.population.props
587+
number_by_age_group_sex = (
588+
get_counts_by_sex_and_age_group(df, 'brc_status', ("stage1", "stage2", "stage3", "stage4")))
589+
return {'number_at_any_stage': number_by_age_group_sex}
590+
582591
def do_at_generic_first_appt(
583592
self,
584593
person_id: int,

src/tlo/methods/cardio_metabolic_disorders.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import pandas as pd
2222

2323
from tlo import DAYS_IN_YEAR, DateOffset, Module, Parameter, Property, Types, logging
24+
from tlo.analysis.utils import get_counts_by_sex_and_age_group
2425
from tlo.events import Event, IndividualScopeEventMixin, PopulationScopeEventMixin, RegularEvent
2526
from tlo.lm import LinearModel, LinearModelType, Predictor
2627
from tlo.methods import Metadata
@@ -71,7 +72,8 @@ class CardioMetabolicDisorders(Module, GenericFirstAppointmentsMixin):
7172
Metadata.DISEASE_MODULE,
7273
Metadata.USES_SYMPTOMMANAGER,
7374
Metadata.USES_HEALTHSYSTEM,
74-
Metadata.USES_HEALTHBURDEN
75+
Metadata.USES_HEALTHBURDEN,
76+
Metadata.REPORTS_DISEASE_NUMBERS
7577
}
7678

7779
# Declare Causes of Death
@@ -848,6 +850,16 @@ def left_censor(obs, window_open):
848850

849851
return dw
850852

853+
def report_summary_stats(self):
854+
"""Report age- and sex-specific prevalence of diseases to the HealthBurden module"""
855+
df = self.sim.population.props
856+
number_by_age_group_sex_dict = {}
857+
858+
for condition in self.conditions:
859+
number_by_age_group_sex_dict[f'number with {condition}'] = \
860+
get_counts_by_sex_and_age_group(df, f'nc_{condition}')
861+
return number_by_age_group_sex_dict
862+
851863
def on_hsi_alert(self, person_id, treatment_id):
852864
"""
853865
This is called whenever there is an HSI event commissioned by one of the other disease modules.

src/tlo/methods/cervical_cancer.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import pandas as pd
1313

1414
from tlo import DAYS_IN_YEAR, DateOffset, Module, Parameter, Property, Types, logging
15+
from tlo.analysis.utils import get_counts_by_sex_and_age_group
1516
from tlo.events import Event, IndividualScopeEventMixin, PopulationScopeEventMixin, RegularEvent
1617
from tlo.lm import LinearModel, LinearModelType, Predictor
1718
from tlo.methods import Metadata
@@ -44,7 +45,8 @@ class CervicalCancer(Module, GenericFirstAppointmentsMixin):
4445
Metadata.DISEASE_MODULE,
4546
Metadata.USES_SYMPTOMMANAGER,
4647
Metadata.USES_HEALTHSYSTEM,
47-
Metadata.USES_HEALTHBURDEN
48+
Metadata.USES_HEALTHBURDEN,
49+
Metadata.REPORTS_DISEASE_NUMBERS
4850
}
4951

5052
# Declare Causes of Death
@@ -745,6 +747,17 @@ def report_daly_values(self):
745747

746748
return disability_series_for_alive_persons
747749

750+
def report_summary_stats(self):
751+
df = self.sim.population.props
752+
number_by_age_group_sex = (
753+
get_counts_by_sex_and_age_group(df,
754+
'ce_hpv_cc_status',
755+
("cin1", "cin2", "cin3",
756+
"stage1","stage2a", "stage2b", "stage3", "stage4")
757+
)
758+
)
759+
return {'number_at_any_stage': number_by_age_group_sex}
760+
748761
def do_at_generic_first_appt(
749762
self,
750763
person_id: int,

src/tlo/methods/copd.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66
import pandas as pd
77

88
from tlo import Module, Parameter, Property, Types, logging
9-
from tlo.analysis.utils import flatten_multi_index_series_into_dict_for_logging
9+
from tlo.analysis.utils import (
10+
flatten_multi_index_series_into_dict_for_logging,
11+
get_counts_by_sex_and_age_group,
12+
)
1013
from tlo.events import Event, IndividualScopeEventMixin, PopulationScopeEventMixin, RegularEvent
1114
from tlo.lm import LinearModel, LinearModelType, Predictor
1215
from tlo.methods import Metadata
@@ -42,6 +45,7 @@ class Copd(Module, GenericFirstAppointmentsMixin):
4245
Metadata.USES_SYMPTOMMANAGER,
4346
Metadata.USES_HEALTHSYSTEM,
4447
Metadata.USES_HEALTHBURDEN,
48+
Metadata.REPORTS_DISEASE_NUMBERS
4549
}
4650

4751
CAUSES_OF_DEATH = {
@@ -218,6 +222,12 @@ def report_daly_values(self):
218222
df = self.sim.population.props
219223
return df.loc[df.is_alive, 'ch_lungfunction'].map(self.models.disability_weight_given_lungfunction)
220224

225+
def report_summary_stats(self):
226+
# This reports age- and sex-specific prevalence of COPD for all individuals
227+
df = self.sim.population.props
228+
number_by_age_group_sex = get_counts_by_sex_and_age_group(df, 'ch_lungfunction', (4, 5, 6))
229+
return {'number_with_poor_ch_lungfunction': number_by_age_group_sex}
230+
221231
def define_symptoms(self):
222232
"""Define and register Symptoms"""
223233
self.sim.modules['SymptomManager'].register_symptom(

src/tlo/methods/depression.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ def __init__(self, name=None):
4747
Metadata.DISEASE_MODULE,
4848
Metadata.USES_SYMPTOMMANAGER,
4949
Metadata.USES_HEALTHSYSTEM,
50-
Metadata.USES_HEALTHBURDEN
50+
Metadata.USES_HEALTHBURDEN,
51+
Metadata.REPORTS_DISEASE_NUMBERS
5152
}
5253

5354
# Declare Causes of Death
@@ -595,6 +596,23 @@ def right_censor(obs, window_close):
595596

596597
return av_daly_wt_last_month
597598

599+
def report_summary_stats(self):
600+
# This reports age- and sex-specific prevalence of depression for all individuals
601+
df = self.sim.population.props
602+
any_depr_in_the_last_month = df[
603+
(df['is_alive']) &
604+
(~pd.isnull(df['de_date_init_most_rec_depr'])) &
605+
(df['de_date_init_most_rec_depr'] <= self.sim.date) &
606+
(
607+
(pd.isnull(df['de_date_depr_resolved'])) |
608+
(df['de_date_depr_resolved'] >= (self.sim.date - DateOffset(months=1)))
609+
)
610+
]
611+
number_depressed = (
612+
any_depr_in_the_last_month.groupby(['sex', 'age_range']).size().unstack(fill_value=0)
613+
).to_dict(orient='index')
614+
return {'number_with_depressive_episode_in_past_month': number_depressed}
615+
598616
def _check_for_suspected_depression(
599617
self, symptoms: List[str], treatment_id: str, has_even_been_diagnosed: bool
600618
):

0 commit comments

Comments
 (0)