From f4e5adaf07440226fb7716e026f3248a332d4e8b Mon Sep 17 00:00:00 2001 From: Tim Hallett <39991060+tbhallett@users.noreply.github.com> Date: Tue, 10 Oct 2023 07:42:04 +0100 Subject: [PATCH 1/5] Fix to `summarize` (#1150) --- src/tlo/analysis/utils.py | 23 +++++------ tests/test_analysis.py | 85 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 12 deletions(-) diff --git a/src/tlo/analysis/utils.py b/src/tlo/analysis/utils.py index 2504493a4d..089230f581 100644 --- a/src/tlo/analysis/utils.py +++ b/src/tlo/analysis/utils.py @@ -311,24 +311,23 @@ def summarize(results: pd.DataFrame, only_mean: bool = False, collapse_columns: Finds mean value and 95% interval across the runs for each draw. """ - summary = pd.DataFrame( - columns=pd.MultiIndex.from_product( - [ - results.columns.unique(level='draw'), - ["mean", "lower", "upper"] - ], - names=['draw', 'stat']), - index=results.index + summary = pd.concat( + { + 'mean': results.groupby(axis=1, by='draw', sort=False).mean(), + 'lower': results.groupby(axis=1, by='draw', sort=False).quantile(0.025), + 'upper': results.groupby(axis=1, by='draw', sort=False).quantile(0.975), + }, + axis=1 ) - - summary.loc[:, (slice(None), "mean")] = results.groupby(axis=1, by='draw').mean().values - summary.loc[:, (slice(None), "lower")] = results.groupby(axis=1, by='draw').quantile(0.025).values - summary.loc[:, (slice(None), "upper")] = results.groupby(axis=1, by='draw').quantile(0.975).values + summary.columns = summary.columns.swaplevel(1, 0) + summary.columns.names = ['draw', 'stat'] + summary = summary.sort_index(axis=1) if only_mean and (not collapse_columns): # Remove other metrics and simplify if 'only_mean' across runs for each draw is required: om: pd.DataFrame = summary.loc[:, (slice(None), "mean")] om.columns = [c[0] for c in om.columns.to_flat_index()] + om.columns.name = 'draw' return om elif collapse_columns and (len(summary.columns.levels[0]) == 1): diff --git a/tests/test_analysis.py b/tests/test_analysis.py index d511d237d6..547a8f33d5 100644 --- a/tests/test_analysis.py +++ b/tests/test_analysis.py @@ -22,6 +22,7 @@ order_of_coarse_appt, order_of_short_treatment_ids, parse_log_file, + summarize, unflatten_flattened_multi_index_in_logging, ) from tlo.events import PopulationScopeEventMixin, RegularEvent @@ -431,3 +432,87 @@ def test_scenario_switcher(seed): # Spot check for health care seeking being forced to occur for all symptoms hcs = sim.modules['HealthSeekingBehaviour'].force_any_symptom_to_lead_to_healthcareseeking assert isinstance(hcs, bool) and hcs + + +def test_summarize(): + """Check that the summarize utility function works as expected.""" + + results_multiple_draws = pd.DataFrame( + columns=pd.MultiIndex.from_tuples([ + ('DrawA', 'DrawA_Run1'), + ('DrawA', 'DrawA_Run2'), + ('DrawB', 'DrawB_Run1'), + ('DrawB', 'DrawB_Run2')], + names=('draw', 'run')), + index=['TimePoint0', 'TimePoint1'], + data=np.array([ + [0, 20, 1000, 2000], + [0, 20, 1000, 2000], + ]) + ) + + results_one_draw = pd.DataFrame( + columns=pd.MultiIndex.from_tuples([ + ('DrawA', 'DrawA_Run1'), + ('DrawA', 'DrawA_Run2')], + names=('draw', 'run')), + index=['TimePoint0', 'TimePoint1'], + data=np.array([ + [0, 20], + [0, 20] + ]), + ) + + # Without collapsing and all stats provided + pd.testing.assert_frame_equal( + pd.DataFrame( + columns=pd.MultiIndex.from_tuples([ + ('DrawA', 'lower'), + ('DrawA', 'mean'), + ('DrawA', 'upper'), + ("DrawB", "lower"), + ("DrawB", "mean"), + ("DrawB", "upper")], + names=('draw', 'stat')), + index=['TimePoint0', 'TimePoint1'], + data=np.array([ + [0.5, 10.0, 19.5, 1025.0, 1500.0, 1975.0], + [0.5, 10.0, 19.5, 1025.0, 1500.0, 1975.0], + ]) + ), + summarize(results_multiple_draws) + ) + + # Without collapsing and only mean + pd.testing.assert_frame_equal( + pd.DataFrame( + columns=pd.Index([ + 'DrawA', + 'DrawB'], + name='draw'), + index=['TimePoint0', 'TimePoint1'], + data=np.array([ + [10.0, 1500.0], + [10.0, 1500.0] + ]) + ), + summarize(results_multiple_draws, only_mean=True) + ) + + # With collapsing (as only one draw) + pd.testing.assert_frame_equal( + pd.DataFrame( + columns=pd.Index( + ['lower', + 'mean', + 'upper'], + name='stat' + ), + index=['TimePoint0', 'TimePoint1'], + data=np.array([ + [0.5, 10.0, 19.5], + [0.5, 10.0, 19.5], + ]) + ), + summarize(results_one_draw, collapse_columns=True) + ) From bcbb8d9ecb63b2f5b14c130f76f3554861cd6096 Mon Sep 17 00:00:00 2001 From: Asif Tamuri Date: Tue, 10 Oct 2023 17:26:51 +0100 Subject: [PATCH 2/5] Supply container type explicitly for new version of Azure Batch SDK (#1155) --- src/tlo/cli.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tlo/cli.py b/src/tlo/cli.py index 2cc0f448b5..f0e811e93b 100644 --- a/src/tlo/cli.py +++ b/src/tlo/cli.py @@ -180,6 +180,7 @@ def batch_submit(ctx, scenario_file, asserts_on, keep_pool_alive): # Create container configuration, prefetching Docker images from the container registry container_conf = batch_models.ContainerConfiguration( + type="dockerCompatible", container_image_names=[image_name], container_registries=[container_registry], ) From 8e61e8a14717ef95121dd60b189ca9fd30065a06 Mon Sep 17 00:00:00 2001 From: Tim Hallett <39991060+tbhallett@users.noreply.github.com> Date: Tue, 10 Oct 2023 20:24:48 +0100 Subject: [PATCH 3/5] Fix in handling of `Causes` (#1153) --- src/tlo/methods/causes.py | 6 ++++-- src/tlo/methods/healthburden.py | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/tlo/methods/causes.py b/src/tlo/methods/causes.py index ba92417563..91fd559a89 100644 --- a/src/tlo/methods/causes.py +++ b/src/tlo/methods/causes.py @@ -3,6 +3,7 @@ """ from collections import defaultdict +from copy import copy from typing import Union import pandas as pd @@ -67,8 +68,9 @@ def check_cause(_cause: Cause, _acceptable_causes: set): f"Conflict in declared cause {tlo_cause} by {m.name}. " \ f"A different specification has already been registered." - # If ok, update these causes to the master dict of all causes of death - collected_causes.update({tlo_cause: cause}) + # If ok, update these causes to the master dict of all causes of death (copies to prevent any + # accidental editing of the modules' declarations). + collected_causes[tlo_cause] = copy(cause) # Check that each gbd_cause is not defined in respect of more than one label gbd_causes = dict() # dict() diff --git a/src/tlo/methods/healthburden.py b/src/tlo/methods/healthburden.py index 7cb64e878e..c3f9617456 100644 --- a/src/tlo/methods/healthburden.py +++ b/src/tlo/methods/healthburden.py @@ -2,6 +2,7 @@ This Module runs the counting of Life-years Lost, Life-years Lived with Disability, and Disability-Adjusted Life-years (DALYS). """ +from copy import copy from pathlib import Path from typing import Dict @@ -179,7 +180,8 @@ def merge_dicts_of_causes(d1: Dict, d2: Dict) -> Dict: for _tlo_cause_name, _cause in d.items(): if _cause.label not in labels_seen: # If label is not already included, add this cause to the merged dict - merged_causes[_tlo_cause_name] = _cause + merged_causes[_tlo_cause_name] = copy(_cause) # Use copy to avoid the merged dict being linked + # to the passed arguments labels_seen[_cause.label] = _tlo_cause_name else: # If label is already included, merge the gbd_causes into the cause defined. From 09487cadd7db7921e12f0f692226402bd2cd6090 Mon Sep 17 00:00:00 2001 From: Matt Graham Date: Wed, 11 Oct 2023 08:24:35 +0100 Subject: [PATCH 4/5] Automatically generate contributor lists in documentation and citation file (#1128) * Add initial contributors YAML file * Automatically generate contributors docs page * Automatically update CITATION.cff file * Fix indentation in workflow file * Remove unnecessary line break + tweak order * Regenerate CITATION.cff * Remove to check comments from verified entries * Updating ORCID for Ines + remove to check comments * Regenerate CITATION.cff * Add option to check differences to script * Add citation file checks to tox environment * Removing update citation workflow Added as a check instead * Update website link * Update contributors.yaml * Remove "to check" comments from verified entries * Update citation file * Remove further "to check" comments + update citation * Remove custom css for rtd tables (fixes broken sphinx style) * Remove unused .css --------- Co-authored-by: Asif Tamuri --- CITATION.cff | 152 +++++++++--- MANIFEST.in | 4 +- contributors.yaml | 275 ++++++++++++++++++++++ docs/_static/theme_overrides.css | 16 -- docs/authors.rst | 48 ---- docs/conf.py | 6 - docs/contributors.rst | 6 + docs/index.rst | 2 +- docs/requirements.txt | 1 + docs/tlo_contributors.py | 116 +++++++++ src/scripts/automation/update_citation.py | 102 ++++++++ tox.ini | 15 +- 12 files changed, 640 insertions(+), 103 deletions(-) create mode 100644 contributors.yaml delete mode 100644 docs/_static/theme_overrides.css delete mode 100644 docs/authors.rst create mode 100644 docs/contributors.rst create mode 100644 docs/tlo_contributors.py create mode 100644 src/scripts/automation/update_citation.py diff --git a/CITATION.cff b/CITATION.cff index dcc367cc9a..36048f67e8 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -1,36 +1,130 @@ -# This CITATION.cff file was generated with cffinit. -# Visit https://bit.ly/cffinit to generate yours today! - +# Author list automatically generated from contributors.yaml by running +# python src/scripts/automation/update_citation.py +# Any manual updates to author list here may be overwritten cff-version: 1.2.0 title: The Thanzi La Onse Model version: 1.0.0 -message: >- - If you use this software, please cite it using the - metadata from this file. +message: If you use this software, please cite it using the metadata from this file. type: software authors: - - name: Thanzi La Onse Model Development Team - address: >- - Imperial College London; University College London; - Kamuzu University of Health Sciences; University of - York - website: https://www.tlomodel.org/authors.html -repository-code: 'https://github.com/UCL/TLOmodel' -url: 'https://tlomodel.org' -abstract: >- - Our fundamental aim is to develop the use of - epidemiological and economic science to effect a - step-change in the way that health priorities are - addressed through policy interventions in low-income - countries. We are doing this by developing a model that - represents explicitly the generation of health gains in a - population, which can be used to examine the effect of - resource allocation, management and clinical practice, in - order to contribute to informing decision-making. +- given-names: Timothy + family-names: Hallett + orcid: https://orcid.org/0000-0002-9681-0424 + affiliation: Imperial College London + website: https://www.imperial.ac.uk/people/timothy.hallett +- given-names: Andrew + family-names: Phillips + orcid: https://orcid.org/0000-0003-2384-4807 + affiliation: University College London + website: https://profiles.ucl.ac.uk/5430 +- given-names: Asif + family-names: Tamuri + orcid: https://orcid.org/0000-0001-6633-3789 + affiliation: University College London + website: https://www.homepages.ucl.ac.uk/~ucbtaut/ +- given-names: Tim + family-names: Colbourn + orcid: https://orcid.org/0000-0002-6917-6552 + affiliation: University College London + website: https://profiles.ucl.ac.uk/3084 +- given-names: Joseph + family-names: Collins + orcid: https://orcid.org/0000-0003-4801-7218 + affiliation: University College London + website: https://profiles.ucl.ac.uk/70734 +- given-names: Iwona + family-names: Hawryluk + orcid: https://orcid.org/0000-0001-6919-4366 + affiliation: Imperial College London + website: https://www.imperial.ac.uk/people/i.hawryluk19 +- given-names: Britta + family-names: Jewell + orcid: https://orcid.org/0000-0003-4275-8509 + website: https://www.imperial.ac.uk/people/b.jewell +- given-names: Ines + family-names: Li Lin + orcid: https://orcid.org/0000-0002-1945-3208 + affiliation: University College London +- given-names: Tara + family-names: Mangal + orcid: https://orcid.org/0000-0001-9222-8632 + affiliation: Imperial College London + website: https://www.imperial.ac.uk/people/t.mangal +- given-names: Robbie + family-names: Manning-Smith + orcid: https://orcid.org/0000-0002-9457-2821 + affiliation: University College London +- given-names: Sakshi + family-names: Mohan + orcid: https://orcid.org/0000-0002-1268-1769 + affiliation: University of York + website: https://www.york.ac.uk/che/staff/research/sakshi-mohan/ +- given-names: Wingston + family-names: Ng'ambi + orcid: https://orcid.org/0000-0003-3967-905X + affiliation: Kamuzu University of Health Sciences + website: https://www.linkedin.com/in/wingston-ng-ambi-7950707b +- given-names: Bingling + family-names: She + orcid: https://orcid.org/0000-0001-5976-8987 + affiliation: Imperial College London + website: https://www.imperial.ac.uk/people/b.she +- given-names: Matthew + family-names: Gillman +- given-names: Mosè + family-names: Giordano + orcid: https://orcid.org/0000-0002-7218-2873 + affiliation: University College London + website: https://giordano.github.io/ +- given-names: Matthew + family-names: Graham + orcid: https://orcid.org/0000-0001-9104-7960 + affiliation: University College London + website: https://matt-graham.github.io +- given-names: Emmanuel + family-names: Mnjowe + affiliation: Kamuzu University of Health Sciences + website: https://www.linkedin.com/in/emmanuel-mnjowe-067481162 +- given-names: Stefan + family-names: Piatek + orcid: https://orcid.org/0000-0002-3028-5292 + affiliation: University College London + website: https://profiles.ucl.ac.uk/67238 +- given-names: Jonathan + family-names: Cooper + orcid: https://orcid.org/0000-0001-6009-3542 + affiliation: University College London + website: https://profiles.ucl.ac.uk/59377 +- given-names: Dimitra + family-names: Salmanidou + orcid: https://orcid.org/0000-0002-2147-0787 + affiliation: University College London + website: https://www.researchgate.net/profile/Dimitra-Salmanidou +- given-names: William + family-names: Graham + orcid: https://orcid.org/0000-0003-0058-263X + affiliation: University College London + website: https://willgraham01.github.io/ +- given-names: Margherita + family-names: Molaro + orcid: https://orcid.org/0000-0002-1841-4274 + affiliation: Imperial College London +- given-names: Eva + family-names: Janoušková + orcid: https://orcid.org/0000-0002-4104-0119 + affiliation: University College London +repository-code: https://github.com/UCL/TLOmodel +url: https://tlomodel.org +abstract: Our fundamental aim is to develop the use of epidemiological and economic + science to effect a step-change in the way that health priorities are addressed + through policy interventions in low-income countries. We are doing this by developing + a model that represents explicitly the generation of health gains in a population, + which can be used to examine the effect of resource allocation, management and clinical + practice, in order to contribute to informing decision-making. keywords: - - Epidemiology - - Healthcare Systems - - Health-Economics - - Simulation Modelling - - Individual-based Modelling +- Epidemiology +- Healthcare Systems +- Health-Economics +- Simulation Modelling +- Individual-based Modelling license: MIT diff --git a/MANIFEST.in b/MANIFEST.in index 66f89377b9..42e867e258 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -10,6 +10,7 @@ include tox.ini include tlo.example.conf include CITATION.cff include LICENSE.txt +include contributors.yaml exclude .editorconfig recursive-exclude .ci * @@ -23,8 +24,9 @@ exclude docs/reference/tlo.rst exclude docs/reference/modules.rst exclude docs/_*.rst exclude docs/hsi_events.csv +exclude docs/_contributors_list.html global-exclude *.py[cod] __pycache__ *.so *.dylib .ipynb_checkpoints/** *~ # exclude profiling scripts from minimal build -recursive-exclude profiling * \ No newline at end of file +recursive-exclude profiling * diff --git a/contributors.yaml b/contributors.yaml new file mode 100644 index 0000000000..1ea698d181 --- /dev/null +++ b/contributors.yaml @@ -0,0 +1,275 @@ +- given-names: Timothy + family-names: Hallett + orcid: "https://orcid.org/0000-0002-9681-0424" + affiliation: "Imperial College London" + website: "https://www.imperial.ac.uk/people/timothy.hallett" + github-username: tbhallett + role: Joint lead epidemiology + contributions: + - Epidemiology and modelling + - Software development +- given-names: Andrew + family-names: Phillips + orcid: "https://orcid.org/0000-0003-2384-4807" + affiliation: "University College London" + website: "https://profiles.ucl.ac.uk/5430" + github-username: andrew-phillips-1 + role: Joint lead epidemiology + contributions: + - Epidemiology and modelling + - Software development +- given-names: Asif + family-names: Tamuri + orcid: "https://orcid.org/0000-0001-6633-3789" + affiliation: "University College London" + website: "https://www.homepages.ucl.ac.uk/~ucbtaut/" + github-username: tamuri + role: "Lead developer" + contributions: + - Software development +- given-names: Joseph + family-names: Mfutso-Bengo + orcid: "https://orcid.org/0000-0001-9396-3700" + affiliation: "Kamuzu University of Health Sciences" + website: "https://www.researchgate.net/profile/Joseph-Mfutso-Bengo" + role: "Lead policy translation" + contributions: + - Policy translation +- given-names: Tim + family-names: Colbourn + orcid: "https://orcid.org/0000-0002-6917-6552" + affiliation: "University College London" + website: "https://profiles.ucl.ac.uk/3084" + github-username: timcolbourn + contributions: + - Epidemiology and modelling + - Software development +- given-names: Joseph + family-names: Collins + orcid: "https://orcid.org/0000-0003-4801-7218" + affiliation: "University College London" + website: "https://profiles.ucl.ac.uk/70734" + github-username: joehcollins + contributions: + - Epidemiology and modelling + - Software development +- given-names: Iwona + family-names: Hawryluk + orcid: "https://orcid.org/0000-0001-6919-4366" + affiliation: "Imperial College London" + website: "https://www.imperial.ac.uk/people/i.hawryluk19" + github-username: ihwaryluk + contributions: + - Epidemiology and modelling + - Software development +- given-names: Britta + family-names: Jewell + orcid: "https://orcid.org/0000-0003-4275-8509" + website: https://www.imperial.ac.uk/people/b.jewell + github-username: brittajewell + contributions: + - Epidemiology and modelling + - Software development +- given-names: Ines + family-names: Li Lin + orcid: "https://orcid.org/0000-0002-1945-3208" + affiliation: "University College London" + github-username: inesll + contributions: + - Epidemiology and modelling + - Software development +- given-names: Tara + family-names: Mangal + orcid: "https://orcid.org/0000-0001-9222-8632" + affiliation: "Imperial College London" + website: "https://www.imperial.ac.uk/people/t.mangal" + github-username: tdm32 + contributions: + - Epidemiology and modelling + - Software development +- given-names: Robbie + family-names: Manning-Smith + orcid: "https://orcid.org/0000-0002-9457-2821" + affiliation: "University College London" + github-username: RobertManningSmith + contributions: + - Epidemiology and modelling + - Software development +- given-names: Sakshi + family-names: Mohan + orcid: "https://orcid.org/0000-0002-1268-1769" + affiliation: University of York + website: "https://www.york.ac.uk/che/staff/research/sakshi-mohan/" + github-username: sakshimohan + contributions: + - Epidemiology and modelling + - Health economics + - Software development +- given-names: Wingston + family-names: Ng'ambi + orcid: "https://orcid.org/0000-0003-3967-905X" + affiliation: "Kamuzu University of Health Sciences" + website: "https://www.linkedin.com/in/wingston-ng-ambi-7950707b" + github-username: winnga + contributions: + - Epidemiology and modelling + - Software development +- given-names: Bingling + family-names: She + orcid: "https://orcid.org/0000-0001-5976-8987" + affiliation: "Imperial College London" + website: "https://www.imperial.ac.uk/people/b.she" + github-username: BinglingICL + contributions: + - Epidemiology and modelling + - Software development +- given-names: Matthew + family-names: Gillman + github-username: mattagape + contributions: + - Software development +- given-names: Mosè + family-names: Giordano + orcid: "https://orcid.org/0000-0002-7218-2873" + affiliation: "University College London" + website: "https://giordano.github.io/" + github-username: giordano + contributions: + - Software development +- given-names: Matthew + family-names: Graham + orcid: "https://orcid.org/0000-0001-9104-7960" + affiliation: "University College London" + website: "https://matt-graham.github.io" + github-username: matt-graham + contributions: + - Software development +- given-names: Emmanuel + family-names: Mnjowe + affiliation: "Kamuzu University of Health Sciences" + website: "https://www.linkedin.com/in/emmanuel-mnjowe-067481162" + github-username: mnjowe + contributions: + - Epidemiology and modelling + - Software development +- given-names: Stefan + family-names: Piatek + orcid: "https://orcid.org/0000-0002-3028-5292" + affiliation: "University College London" + website: "https://profiles.ucl.ac.uk/67238" + github-username: stefpiatek + contributions: + - Software development +- given-names: Jonathan + family-names: Cooper + orcid: "https://orcid.org/0000-0001-6009-3542" + affiliation: "University College London" + website: "https://profiles.ucl.ac.uk/59377" + github-username: jonc125 + contributions: + - Software development +- given-names: Dimitra + family-names: Salmanidou + orcid: "https://orcid.org/0000-0002-2147-0787" + affiliation: "University College London" + website: "https://www.researchgate.net/profile/Dimitra-Salmanidou" + github-username: dimitrasal + contributions: + - Software development +- given-names: William + family-names: Graham + orcid: "https://orcid.org/0000-0003-0058-263X" + affiliation: "University College London" + website: "https://willgraham01.github.io/" + github-username: willGraham01 + contributions: + - Software development +- given-names: Margherita + family-names: Molaro + orcid: "https://orcid.org/0000-0002-1841-4274" + affiliation: "Imperial College London" + github-username: marghe-molaro + contributions: + - Epidemiology and modelling + - Software development +- given-names: Eva + family-names: Janoušková + orcid: "https://orcid.org/0000-0002-4104-0119" + affiliation: "University College London" + github-username: EvaJanouskova + contributions: + - Epidemiology and modelling + - Software development +- given-names: Alison + family-names: Rodger + orcid: "https://orcid.org/0000-0001-8817-4651" + affiliation: University College London + website: "https://profiles.ucl.ac.uk/954" + contributions: + - Clinical consultant +- given-names: Paul + family-names: Revill + orcid: "https://orcid.org/0000-0001-8632-0600" + affiliation: University of York + website: "https://www.york.ac.uk/che/staff/research/paul-revill/" + github-username: paulrevill + contributions: + - Health economics +- given-names: Wiktoria + family-names: Tafesse + orcid: "https://orcid.org/0000-0002-0076-8285" + affiliation: University of York + website: "https://www.york.ac.uk/che/staff/research/wiktoria-tafesse/" + github-username: wiktafesse + contributions: + - Health economics +- given-names: Kate + family-names: Bilsborrow + affiliation: "Imperial College London" + website: "https://www.imperial.ac.uk/people/k.bilsborrow" + github-username: imperialkate + contributions: + - Project management +- given-names: Newton + family-names: Chagoma + orcid: "https://orcid.org/0000-0003-0752-1696" + affiliation: "University of York" + website: "https://www.york.ac.uk/che/staff/students/newton-chagoma/" + github-username: nchagoma503 + contributions: + - Health economics +- given-names: Martin + family-names: Chalkley + orcid: "https://orcid.org/0000-0002-1091-8259" + affiliation: "University of York" + website: "https://www.york.ac.uk/che/staff/research/martin-chalkley/" + github-username: mjchalkley + contributions: + - Health economics +- given-names: Nimalan + family-names: Arinaminpathy + orcid: "https://orcid.org/0000-0001-9502-6876" + affiliation: "Imperial College London" + website: "https://www.imperial.ac.uk/people/nim.pathy" +- given-names: Amelia + family-names: Crampin + orcid: "https://orcid.org/0000-0002-1513-4330" + affiliation: "London School of Hygiene and Tropical Medicine" + website: "https://www.lshtm.ac.uk/aboutus/people/crampin.mia" +- given-names: Jonathan + family-names: Roberts + website: "https://uk.linkedin.com/in/jonathanroberts93" +- given-names: Mikaela + family-names: Smit + orcid: "https://orcid.org/0000-0001-8530-748X" + affiliation: "Imperial College London" + website: "https://www.imperial.ac.uk/people/mikaela.smit" +- given-names: Juan + family-names: Vesga + orcid: "https://orcid.org/0000-0003-1103-9587" + affiliation: "London School of Hygiene and Tropical Medicine" + website: "https://www.researchgate.net/profile/Juan-Vesga-3" +- given-names: Leila + family-names: Uwais + website: "https://uk.linkedin.com/in/leila-uwais-597705142" + github-username: Leila-Uwais diff --git a/docs/_static/theme_overrides.css b/docs/_static/theme_overrides.css deleted file mode 100644 index 7e334043c0..0000000000 --- a/docs/_static/theme_overrides.css +++ /dev/null @@ -1,16 +0,0 @@ -/* override table width restrictions - -From https://rackerlabs.github.io/docs-rackspace/tools/rtd-tables.html -*/ -@media screen and (min-width: 767px) { - - .wy-table-responsive table td { - /* !important prevents the common CSS stylesheets from overriding - this as on RTD they are loaded after this stylesheet */ - white-space: normal !important; - } - - .wy-table-responsive { - overflow: visible !important; - } -} diff --git a/docs/authors.rst b/docs/authors.rst deleted file mode 100644 index 33b9d6f712..0000000000 --- a/docs/authors.rst +++ /dev/null @@ -1,48 +0,0 @@ -======= -Authors -======= - -Scientific Leads -================ -* `Timothy Hallett `_ (Joint-Lead Epidemiology) -* `Andrew Phillips `_ (Joint-Lead Epidemiology) -* `Asif Tamuri `_ (Lead Developer) -* `Joseph Mfutso-Bengo `_ (Lead Policy Translation) - -Epidemiologists/Modellers -========================= -* `Tim Colbourn `_ -* `Joseph Collins `_ -* `Iwona Hawryluk `_ -* `Eva Janoušková `_ -* `Britta Jewell `_ -* `Ines Lin `_ -* `Tara Mangal `_ -* `Robbie Manning-Smith `_ -* `Sakshi Mohan `_ -* `Wingston Ng'ambi `_ -* `Bingling She `_ - - - -Software Developers -===================== -* `Matthew Gill `_ -* `Mosè Giordano `_ -* `Matt Graham `_ -* `Emmanuel Mnjowe `_ -* `Stef Piatek `_ - - -Clinical Consultant -===================== -* `Alison Rodger `_ - - -Acknowledgements -================= -* `Nimalan Arinaminpathy `_ -* `Amelia Crampin `_ -* Jonathan Roberts -* `Mikaela Smit `_ -* `Juan Vesga `_ diff --git a/docs/conf.py b/docs/conf.py index 2ba69eb2d4..2720a40b41 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -68,12 +68,6 @@ rawfiles = ['.github'] -html_context = { - 'css_files': [ - '_static/theme_overrides.css', # override wide tables in RTD theme - ], - } - napoleon_use_ivar = True napoleon_use_rtype = False napoleon_use_param = False diff --git a/docs/contributors.rst b/docs/contributors.rst new file mode 100644 index 0000000000..2d1cea7a2f --- /dev/null +++ b/docs/contributors.rst @@ -0,0 +1,6 @@ +============ +Contributors +============ + +.. raw:: html + :file: _contributors_list.html diff --git a/docs/index.rst b/docs/index.rst index 5e8589f24c..6ca4b1e966 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -42,5 +42,5 @@ Contents reference/index background publications - authors + contributors contributing diff --git a/docs/requirements.txt b/docs/requirements.txt index 37da9aeedf..2fa8d486e3 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,2 +1,3 @@ sphinx>=1.3 sphinx-rtd-theme +pyyaml diff --git a/docs/tlo_contributors.py b/docs/tlo_contributors.py new file mode 100644 index 0000000000..680418efa5 --- /dev/null +++ b/docs/tlo_contributors.py @@ -0,0 +1,116 @@ +import argparse +from collections import defaultdict +from pathlib import Path + +import yaml + + +def homepage_link_html(homepage_url): + homepage_icon_url = ( + "https://raw.githubusercontent.com/primer/octicons/main/icons/home-16.svg" + ) + return ( + f"" + f"Homepage" + "" + ) + + +def orcid_link_html(orcid): + orcid_icon_url = "https://info.orcid.org/wp-content/uploads/2019/11/orcid_16x16.png" + return ( + f"" + f"ORCID logo" + "" + ) + + +def github_link_html(github_username): + github_icon_url = "https://raw.githubusercontent.com/primer/octicons/main/icons/mark-github-16.svg" + return ( + f"" + f"GitHub mark" + "" + ) + + +def contributor_html(contributor): + name_string = f"{contributor['given-names']} {contributor['family-names']}" + if "website" in contributor: + html_string = f"{name_string} " + else: + html_string = f"{name_string} " + if "role" in contributor: + html_string += f" ({contributor['role']}) " + if "orcid" in contributor: + html_string += orcid_link_html(contributor["orcid"]) + if "github-username" in contributor: + html_string += github_link_html(contributor["github-username"]) + return html_string + + +def contributor_list_html(contributors, sort_key="family-names"): + sorted_contributors = sorted(contributors, key=lambda c: c[sort_key]) + list_items = [ + f"
  • {contributor_html(contributor)}
  • " + for contributor in sorted_contributors + ] + return "
      \n " + "\n ".join(list_items) + "\n
    " + + +def categorized_contributor_lists_html( + contributors, category_predicates, sort_key="family-names" +): + categorized_contributors = defaultdict(list) + for contributor in contributors: + for category, predicate in category_predicates.items(): + if predicate(contributor): + categorized_contributors[category].append(contributor) + break + assert len(contributors) == sum(len(c) for c in categorized_contributors.values()) + html_string = "" + for category in category_predicates.keys(): + html_string += f"

    {category}

    \n" + html_string += f"{contributor_list_html(categorized_contributors[category])}\n" + return html_string + + +if __name__ == "__main__": + docs_directory = Path(__file__).parent + root_directory = docs_directory.parent + parser = argparse.ArgumentParser( + description="Generate contributors list as HTML file" + ) + parser.add_argument( + "--contributors-file-path", + type=Path, + default=root_directory / "contributors.yaml", + help="Path to YAML file defining contributors data", + ) + parser.add_argument( + "--output-file-path", + type=Path, + default=docs_directory / "_contributors_list.html", + help="Path to write output file to", + ) + args = parser.parse_args() + assert args.contributors_file_path.exists() + with open(args.contributors_file_path, "r") as f: + contributors = yaml.safe_load(f) + contribution_categories = ( + "Epidemiology and modelling", + "Health economics", + "Software development", + "Clinical consultant", + "Project management", + ) + category_predicates = { + "Scientific leads": lambda c: "lead" in c.get("role", "").lower(), + **{ + category: lambda c, d=category: d in c.get("contributions", ()) + for category in contribution_categories + }, + "Acknowledgements": lambda c: True, + } + with open(args.output_file_path, "w") as f: + f.write(categorized_contributor_lists_html(contributors, category_predicates)) diff --git a/src/scripts/automation/update_citation.py b/src/scripts/automation/update_citation.py new file mode 100644 index 0000000000..30a091e031 --- /dev/null +++ b/src/scripts/automation/update_citation.py @@ -0,0 +1,102 @@ +"""Update citation file from contributors list or check if fill will be updated.""" + +import argparse +import difflib +from pathlib import Path + +import yaml + +CFF_PERSON_ALLOWED_KEYS = ( + "address", + "affiliation", + "alias", + "city", + "country", + "email", + "family-names", + "fax", + "given-names", + "name-particle", + "name-suffix", + "orcid", + "post-code", + "region", + "tel", + "website", +) + + +def strip_non_cff_fields(person): + return { + key: value for key, value in person.items() if key in CFF_PERSON_ALLOWED_KEYS + } + + +def strip_and_filter_contributors(contributors): + return [ + strip_non_cff_fields(contributor) + for contributor in contributors + if "Software development" in contributor.get("contributions", ()) + ] + + +if __name__ == "__main__": + root_directory = Path(__file__).parent.parent.parent.parent + parser = argparse.ArgumentParser( + description="Update author list in citation file format (CFF) file" + ) + parser.add_argument( + "--contributors-file-path", + type=Path, + default=root_directory / "contributors.yaml", + help="Path to YAML file defining contributors data", + ) + parser.add_argument( + "--citation-file-path", + type=Path, + default=root_directory / "CITATION.cff", + help="Path to existing citation file to update", + ) + parser.add_argument( + "--check", + action="store_true", + help=( + "Whether to check if citation file will be updated without modifying file " + "and raise an error if so." + ), + ) + args = parser.parse_args() + assert args.contributors_file_path.exists() + with open(args.contributors_file_path, "r") as f: + contributors = yaml.safe_load(f) + assert args.citation_file_path.exists() + with open(args.citation_file_path, "r") as f: + citation = yaml.safe_load(f) + f.seek(0) + original_citation_lines = f.readlines() + citation["authors"] = strip_and_filter_contributors(contributors) + comment = ( + "# Author list automatically generated from contributors.yaml by running\n" + "# python src/scripts/automation/update_citation.py\n" + "# Any manual updates to author list here may be overwritten\n" + ) + yaml_string = yaml.dump(citation, sort_keys=False, allow_unicode=True, indent=2) + updated_citation_lines = (comment + yaml_string).splitlines(keepends=True) + if args.check: + citation_diff = "".join( + difflib.unified_diff( + original_citation_lines, + updated_citation_lines, + fromfile=f"original ({args.citation_file_path})", + tofile="updated", + ) + ) + if citation_diff != "": + raise RuntimeError( + f"Citation file at {args.citation_file_path} would be updated:\n\n" + + citation_diff + + f"\nRe-run script {__file__} to update." + ) + else: + with open(args.citation_file_path, "w") as f: + f.writelines(updated_citation_lines) diff --git a/tox.ini b/tox.ini index 0b55afb84d..8c816c2500 100644 --- a/tox.ini +++ b/tox.ini @@ -8,12 +8,12 @@ envlist = py38, report, docs, - profile + profile, py{38,39,310,311}-pandas{12,15,20} [testenv] basepython = - {py38,docs,profile}: {env:TOXPYTHON:python3.8} + {py38,docs,profile,citation}: {env:TOXPYTHON:python3.8} {clean,check,report,codecov,spell}: {env:TOXPYTHON:python3} py39: {env:TOXPYTHON:python3.9} py310: {env:TOXPYTHON:python3.10} @@ -63,6 +63,8 @@ commands = python docs/tlo_methods_rst.py ; Generate data sources page python docs/tlo_data_sources.py + ; Generate contributors page + python docs/tlo_contributors.py ; Generate HSI events listing python src/tlo/analysis/hsi_events.py --output-file docs/_hsi_events.rst --output-format rst-list python src/tlo/analysis/hsi_events.py --output-file docs/hsi_events.csv --output-format csv @@ -77,6 +79,8 @@ deps = pygments isort twine + pyyaml + cffconvert skip_install = true commands = python setup.py sdist --formats=gztar @@ -84,6 +88,8 @@ commands = check-manifest {toxinidir} flake8 src tests setup.py isort --check-only --diff src tests setup.py + python {toxinidir}/src/scripts/automation/update_citation.py --check + cffconvert --validate [testenv:codecov] deps = @@ -110,3 +116,8 @@ commands = commands = coverage erase skip_install = true deps = coverage + +[testenv:citation] +commands = python {toxinidir}/src/scripts/automation/update_citation.py +skip_install = true +deps = pyyaml From 72aaf8707bb4a798ea3728627d3eb2d281e4671c Mon Sep 17 00:00:00 2001 From: Tim Hallett <39991060+tbhallett@users.noreply.github.com> Date: Wed, 11 Oct 2023 09:34:37 +0100 Subject: [PATCH 5/5] Declare cause of disability in the Depression module as 'Depressive Disorders' (#1152) * declare correct cause of disability in the depression module * use "safe divide" to avoid warnings about divisions by zero. * merge COPIES of dictionary rather than actual dictionaries, to avoid writing to arguments * Return collected causes that are NOT linked to the original declaration (to allow editing of these without writing to the original hard-coded declaration in the module) * remove old comment * typo --- src/tlo/methods/depression.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/tlo/methods/depression.py b/src/tlo/methods/depression.py index f20434c3cf..8f5fd9661c 100644 --- a/src/tlo/methods/depression.py +++ b/src/tlo/methods/depression.py @@ -49,7 +49,7 @@ def __init__(self, name=None, resourcefilepath=None): # Declare Causes of Disability CAUSES_OF_DISABILITY = { - 'SevereDepression': Cause(gbd_causes='Self-harm', label='Depression / Self-harm') + 'SevereDepression': Cause(gbd_causes='Depressive disorders', label='Depression / Self-harm') } # Module parameters @@ -740,17 +740,21 @@ def apply(self, population): def zero_out_nan(x): return x if not np.isnan(x) else 0 + def safe_divide(x, y): + return x / y if y > 0.0 else 0.0 + dict_for_output = { - 'prop_ge15_depr': zero_out_nan(n_ge15_depr / n_ge15), - 'prop_ge15_m_depr': zero_out_nan(n_ge15_m_depr / n_ge15_m), - 'prop_ge15_f_depr': zero_out_nan(n_ge15_f_depr / n_ge15_f), - 'prop_ever_depr': zero_out_nan(n_ever_depr / n_ge15), - 'prop_age_50_ever_depr': zero_out_nan(n_age_50_ever_depr / n_age_50), - 'p_ever_diagnosed_depression_if_ever_depressed': zero_out_nan(n_ever_diagnosed_depression / n_ever_depr), - 'prop_antidepr_if_curr_depr': zero_out_nan(n_antidepr_depr / n_ge15_depr), - 'prop_antidepr_if_ever_depr': zero_out_nan(n_antidepr_ever_depr / n_ever_depr), - 'prop_ever_talk_ther_if_ever_depr': zero_out_nan(n_ever_talk_ther / n_ever_depr), - 'prop_ever_self_harmed': zero_out_nan(n_ever_self_harmed / n_ever_depr), + 'prop_ge15_depr': zero_out_nan(safe_divide(n_ge15_depr, n_ge15)), + 'prop_ge15_m_depr': zero_out_nan(safe_divide(n_ge15_m_depr, n_ge15_m)), + 'prop_ge15_f_depr': zero_out_nan(safe_divide(n_ge15_f_depr, n_ge15_f)), + 'prop_ever_depr': zero_out_nan(safe_divide(n_ever_depr, n_ge15)), + 'prop_age_50_ever_depr': zero_out_nan(safe_divide(n_age_50_ever_depr, n_age_50)), + 'p_ever_diagnosed_depression_if_ever_depressed': + zero_out_nan(safe_divide(n_ever_diagnosed_depression, n_ever_depr)), + 'prop_antidepr_if_curr_depr': zero_out_nan(safe_divide(n_antidepr_depr, n_ge15_depr)), + 'prop_antidepr_if_ever_depr': zero_out_nan(safe_divide(n_antidepr_ever_depr, n_ever_depr)), + 'prop_ever_talk_ther_if_ever_depr': zero_out_nan(safe_divide(n_ever_talk_ther, n_ever_depr)), + 'prop_ever_self_harmed': zero_out_nan(safe_divide(n_ever_self_harmed, n_ever_depr)), } logger.info(key='summary_stats', data=dict_for_output)