meta-edc 1.0.7__py3-none-any.whl → 1.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- meta_ae/action_items.py +10 -2
- meta_ae/baker_recipes.py +1 -2
- meta_ae/tests/tests/test_actions.py +1 -2
- meta_analytics/notebooks/anu.ipynb +95 -0
- meta_analytics/notebooks/appointment_planning.ipynb +329 -0
- meta_analytics/notebooks/arvs.ipynb +103 -0
- meta_analytics/notebooks/cleaning/consent_v1_ext.ipynb +227 -0
- meta_analytics/notebooks/cleaning/offschedule_eos.ipynb +353 -0
- meta_analytics/notebooks/dsmc/renal_dysfunction.ipynb +435 -0
- meta_analytics/notebooks/endpoints/meta_endpoints_by_date.ipynb +664 -0
- meta_analytics/notebooks/followup_examination.ipynb +141 -0
- meta_analytics/notebooks/hba1c.ipynb +136 -0
- meta_analytics/notebooks/hiv_regimens.ipynb +122 -118
- meta_analytics/notebooks/incidence.ipynb +232 -0
- meta_analytics/notebooks/liver.ipynb +389 -0
- meta_analytics/notebooks/magreth.ipynb +645 -0
- meta_analytics/notebooks/monitoring_report.ipynb +435 -245
- meta_analytics/notebooks/pharmacy.ipynb +405 -306
- meta_analytics/notebooks/pharmacy_stock_202410.ipynb +306 -0
- meta_analytics/notebooks/steering.ipynb +61 -0
- meta_analytics/notebooks/undiagnosed/meta3_screening_consort_chart.ipynb +1176 -0
- meta_analytics/notebooks/undiagnosed/meta3_screening_undiagnosed.ipynb +519 -0
- meta_analytics/notebooks/undiagnosed/meta_screening_table2.ipynb +964 -0
- meta_analytics/notebooks/undiagnosed/screen_undiagnosed_or.ipynb +296 -0
- meta_analytics/notebooks/undiagnosed/screening.ipynb +273 -0
- meta_analytics/notebooks/undiagnosed/screening2.ipynb +958 -0
- meta_analytics/notebooks/undiagnosed/screening_undiagnosed_20241002.ipynb +958 -0
- meta_analytics/notebooks/ven.ipynb +191 -0
- meta_analytics/notebooks/vitals.ipynb +263 -0
- meta_edc/settings/debug.py +3 -2
- meta_edc/urls.py +1 -0
- {meta_edc-1.0.7.dist-info → meta_edc-1.1.0.dist-info}/METADATA +3 -3
- {meta_edc-1.0.7.dist-info → meta_edc-1.1.0.dist-info}/RECORD +55 -28
- {meta_edc-1.0.7.dist-info → meta_edc-1.1.0.dist-info}/WHEEL +1 -1
- meta_labs/reportables.py +14 -11
- meta_labs/tests/test_reportables.py +33 -12
- meta_pharmacy/notebooks/pharmacy.ipynb +41 -0
- meta_prn/migrations/0063_historicaloffstudymedication_singleton_field_and_more.py +37 -0
- meta_prn/migrations/0064_auto_20250602_2143.py +18 -0
- meta_prn/models/end_of_study.py +2 -0
- meta_prn/models/off_study_medication.py +2 -0
- meta_screening/eligibility/eligibility_part_three/base_eligibility_part_three.py +59 -47
- meta_screening/form_validators/screening_part_three.py +6 -1
- meta_screening/tests/meta_test_case_mixin.py +3 -0
- meta_screening/tests/tests/test_forms.py +9 -2
- meta_screening/tests/tests/test_screening_part_three.py +11 -14
- meta_subject/action_items.py +1 -2
- meta_subject/choices.py +2 -1
- meta_subject/forms/blood_results/blood_results_rft_form.py +60 -3
- meta_subject/migrations/0223_bloodresultsfbc_errors_bloodresultsgludummy_errors_and_more.py +83 -0
- meta_subject/migrations/0224_bloodresultsfbc_abnormal_summary_and_more.py +153 -0
- meta_subject/tests/tests/test_egfr.py +5 -5
- meta_analytics/dataframes/enrolled/__init__.py +0 -0
- {meta_edc-1.0.7.dist-info → meta_edc-1.1.0.dist-info}/licenses/AUTHORS.rst +0 -0
- {meta_edc-1.0.7.dist-info → meta_edc-1.1.0.dist-info}/licenses/LICENSE +0 -0
- {meta_edc-1.0.7.dist-info → meta_edc-1.1.0.dist-info}/top_level.txt +0 -0
@@ -2,8 +2,10 @@
|
|
2
2
|
"cells": [
|
3
3
|
{
|
4
4
|
"cell_type": "code",
|
5
|
-
"
|
5
|
+
"execution_count": null,
|
6
|
+
"id": "0",
|
6
7
|
"metadata": {},
|
8
|
+
"outputs": [],
|
7
9
|
"source": [
|
8
10
|
"%%capture\n",
|
9
11
|
"import os\n",
|
@@ -19,17 +21,17 @@
|
|
19
21
|
"pharmacy_folder = Path(os.environ[\"META_PHARMACY_FOLDER\"])\n",
|
20
22
|
"plus = activate(dotenv_file=env_file)\n",
|
21
23
|
"pd.set_option('future.no_silent_downcasting', True)"
|
22
|
-
]
|
23
|
-
"outputs": [],
|
24
|
-
"execution_count": null
|
24
|
+
]
|
25
25
|
},
|
26
26
|
{
|
27
27
|
"cell_type": "code",
|
28
|
-
"
|
28
|
+
"execution_count": null,
|
29
|
+
"id": "1",
|
29
30
|
"metadata": {},
|
31
|
+
"outputs": [],
|
30
32
|
"source": [
|
31
|
-
"\n",
|
32
33
|
"import pdfkit\n",
|
34
|
+
"from typing import Callable\n",
|
33
35
|
"from datetime import date\n",
|
34
36
|
"from edc_pdutils.dataframes import get_subject_visit\n",
|
35
37
|
"from meta_visit_schedule.constants import MONTH15, MONTH18, MONTH21, MONTH27, MONTH30, MONTH33, MONTH39\n",
|
@@ -43,33 +45,36 @@
|
|
43
45
|
"from edc_appointment.analytics import get_appointment_df\n",
|
44
46
|
"from edc_appointment.constants import NEW_APPT, CANCELLED_APPT, ONTIME_APPT, MISSED_APPT\n",
|
45
47
|
"from meta_consent.models import SubjectConsentV1Ext\n",
|
46
|
-
"from meta_analytics.dataframes import get_glucose_df\n",
|
48
|
+
"from meta_analytics.dataframes import get_glucose_df, get_screening_df\n",
|
47
49
|
"\n",
|
48
50
|
"from edc_appointment.constants import SCHEDULED_APPT, UNSCHEDULED_APPT # noqa\n",
|
49
|
-
"from edc_constants.constants import YES # noqa
|
50
|
-
]
|
51
|
-
"outputs": [],
|
52
|
-
"execution_count": null
|
51
|
+
"from edc_constants.constants import YES # noqa"
|
52
|
+
]
|
53
53
|
},
|
54
54
|
{
|
55
|
-
"metadata": {},
|
56
55
|
"cell_type": "code",
|
56
|
+
"execution_count": null,
|
57
|
+
"id": "2",
|
58
|
+
"metadata": {},
|
59
|
+
"outputs": [],
|
57
60
|
"source": [
|
58
61
|
"html_data = []\n",
|
59
|
-
"
|
60
|
-
"
|
61
|
-
"
|
62
|
+
"data_download_date= date(2025,6, 17)\n",
|
63
|
+
"cutoff_date = date(2025,6, 17)\n",
|
64
|
+
"end_of_trial_date= date(2026,7, 1)\n",
|
65
|
+
"document_title = f\"<h2>Monitoring Report: {cutoff_date.strftime('%B %Y')}</h2><h5>Data Download: {data_download_date.strftime('%d %B %Y')}</h5>\"\n",
|
62
66
|
"study_title = 'META3 - Metformin treatment for diabetes prevention in Africa'\n",
|
63
67
|
"pdf_filename = f\"monitoring_report_{cutoff_date.strftime('%Y%m%d')}.pdf\"\n"
|
64
|
-
]
|
65
|
-
"id": "b255fd34cd6f50c0",
|
66
|
-
"outputs": [],
|
67
|
-
"execution_count": null
|
68
|
+
]
|
68
69
|
},
|
69
70
|
{
|
70
|
-
"metadata": {},
|
71
71
|
"cell_type": "code",
|
72
|
+
"execution_count": null,
|
73
|
+
"id": "3",
|
74
|
+
"metadata": {},
|
75
|
+
"outputs": [],
|
72
76
|
"source": [
|
77
|
+
"# 105-30-0288-5 should also be late excluded based on the haemoglobin 4.8 presented at baseline\n",
|
73
78
|
"\n",
|
74
79
|
"df_visit = get_subject_visit(\"meta_subject.subjectvisit\")\n",
|
75
80
|
"late_exlusion_offstudy_reasons = ['Patient fulfilled late exclusion criteria (due to abnormal blood values or raised blood pressure at enrolment']\n",
|
@@ -117,27 +122,41 @@
|
|
117
122
|
" .pivot_table(columns=\"site_id\", values=0, observed=True)\n",
|
118
123
|
")\n",
|
119
124
|
"enrolled_pivot.columns.name=\"\"\n",
|
120
|
-
"enrolled_pivot[\"total\"] = enrolled_pivot[[\"10\", \"20\",\"30\",\"40\",\"60\"]].sum(axis=1)
|
121
|
-
|
122
|
-
],
|
123
|
-
"id": "215212f9d44e79df",
|
124
|
-
"outputs": [],
|
125
|
-
"execution_count": null
|
125
|
+
"enrolled_pivot[\"total\"] = enrolled_pivot[[\"10\", \"20\",\"30\",\"40\",\"60\"]].sum(axis=1)"
|
126
|
+
]
|
126
127
|
},
|
127
128
|
{
|
129
|
+
"cell_type": "code",
|
130
|
+
"execution_count": null,
|
131
|
+
"id": "4",
|
128
132
|
"metadata": {},
|
133
|
+
"outputs": [],
|
134
|
+
"source": [
|
135
|
+
"# df_eos.query(\"offstudy_reason.isin(@late_exlusion_offstudy_reasons)\")[[\"subject_identifier\", \"offstudy_datetime\", \"offstudy_reason\"]].to_stata(\n",
|
136
|
+
"# path=analysis_folder / \"late_exclusions.dta\",\n",
|
137
|
+
"# variable_labels={},\n",
|
138
|
+
"# version=118,\n",
|
139
|
+
"# write_index=False,\n",
|
140
|
+
"# )"
|
141
|
+
]
|
142
|
+
},
|
143
|
+
{
|
129
144
|
"cell_type": "code",
|
145
|
+
"execution_count": null,
|
146
|
+
"id": "5",
|
147
|
+
"metadata": {},
|
148
|
+
"outputs": [],
|
130
149
|
"source": [
|
131
150
|
"column_headers = {\"label\": \"Label\", \"visit_code\": \"Visit code\", \"10\": \"Hindu Mandal\", \"20\": \"Amana\", \"30\": \"Temeke\", \"40\": \"Mwananyamala\", \"60\": \"Mnazi Moja\", \"total\": \"Total\"}\n",
|
132
151
|
"column_headers_with_str = {\"label\": \"Label\", \"10_str\": \"Hindu Mandal\", \"20_str\": \"Amana\", \"30_str\": \"Temeke\", \"40_str\": \"Mwananyamala\", \"60_str\": \"Mnazi Moja\", \"total_str\": \"Total\"}"
|
133
|
-
]
|
134
|
-
"id": "fe90271ff1799692",
|
135
|
-
"outputs": [],
|
136
|
-
"execution_count": null
|
152
|
+
]
|
137
153
|
},
|
138
154
|
{
|
139
|
-
"metadata": {},
|
140
155
|
"cell_type": "code",
|
156
|
+
"execution_count": null,
|
157
|
+
"id": "6",
|
158
|
+
"metadata": {},
|
159
|
+
"outputs": [],
|
141
160
|
"source": [
|
142
161
|
"# Table 1a Visits completed to date\n",
|
143
162
|
"\n",
|
@@ -151,14 +170,14 @@
|
|
151
170
|
"df1.fillna(0, inplace=True)\n",
|
152
171
|
"df_attended = df1.copy().reset_index(drop=True)\n",
|
153
172
|
"df_attended = df_attended.fillna(0.0)"
|
154
|
-
]
|
155
|
-
"id": "9e3d608809eea5",
|
156
|
-
"outputs": [],
|
157
|
-
"execution_count": null
|
173
|
+
]
|
158
174
|
},
|
159
175
|
{
|
160
|
-
"metadata": {},
|
161
176
|
"cell_type": "code",
|
177
|
+
"execution_count": null,
|
178
|
+
"id": "7",
|
179
|
+
"metadata": {},
|
180
|
+
"outputs": [],
|
162
181
|
"source": [
|
163
182
|
"gt = df_as_great_table(\n",
|
164
183
|
" df_attended[[\"visit_code\", \"10\", \"20\", \"30\", \"40\", \"60\", \"total\"]],\n",
|
@@ -179,14 +198,14 @@
|
|
179
198
|
")\n",
|
180
199
|
"html_data.append(gt.as_raw_html())\n",
|
181
200
|
"gt.show()"
|
182
|
-
]
|
183
|
-
"id": "a43c2fbd8a7a692c",
|
184
|
-
"outputs": [],
|
185
|
-
"execution_count": null
|
201
|
+
]
|
186
202
|
},
|
187
203
|
{
|
188
|
-
"metadata": {},
|
189
204
|
"cell_type": "code",
|
205
|
+
"execution_count": null,
|
206
|
+
"id": "8",
|
207
|
+
"metadata": {},
|
208
|
+
"outputs": [],
|
190
209
|
"source": [
|
191
210
|
"# Table 1b Total scheduled appointments\n",
|
192
211
|
"df_appt_pivot = (\n",
|
@@ -226,14 +245,14 @@
|
|
226
245
|
")\n",
|
227
246
|
"html_data.append(gt.as_raw_html())\n",
|
228
247
|
"gt.show()"
|
229
|
-
]
|
230
|
-
"id": "70eb34a139ff7095",
|
231
|
-
"outputs": [],
|
232
|
-
"execution_count": null
|
248
|
+
]
|
233
249
|
},
|
234
250
|
{
|
235
|
-
"metadata": {},
|
236
251
|
"cell_type": "code",
|
252
|
+
"execution_count": null,
|
253
|
+
"id": "9",
|
254
|
+
"metadata": {},
|
255
|
+
"outputs": [],
|
237
256
|
"source": [
|
238
257
|
"# Table 1c Past scheduled appointments -- no information provided\n",
|
239
258
|
"df_appt_pivot = (\n",
|
@@ -272,14 +291,14 @@
|
|
272
291
|
")\n",
|
273
292
|
"html_data.append(gt.as_raw_html())\n",
|
274
293
|
"gt.show()"
|
275
|
-
]
|
276
|
-
"id": "f243552177b216d7",
|
277
|
-
"outputs": [],
|
278
|
-
"execution_count": null
|
294
|
+
]
|
279
295
|
},
|
280
296
|
{
|
281
|
-
"metadata": {},
|
282
297
|
"cell_type": "code",
|
298
|
+
"execution_count": null,
|
299
|
+
"id": "10",
|
300
|
+
"metadata": {},
|
301
|
+
"outputs": [],
|
283
302
|
"source": [
|
284
303
|
"# Table 1d Unscheduled appointments\n",
|
285
304
|
"df_appt = (\n",
|
@@ -338,14 +357,14 @@
|
|
338
357
|
")\n",
|
339
358
|
"html_data.append(gt.as_raw_html())\n",
|
340
359
|
"gt.show()"
|
341
|
-
]
|
342
|
-
"id": "6e55569e322370a",
|
343
|
-
"outputs": [],
|
344
|
-
"execution_count": null
|
360
|
+
]
|
345
361
|
},
|
346
362
|
{
|
347
|
-
"metadata": {},
|
348
363
|
"cell_type": "code",
|
364
|
+
"execution_count": null,
|
365
|
+
"id": "11",
|
366
|
+
"metadata": {},
|
367
|
+
"outputs": [],
|
349
368
|
"source": [
|
350
369
|
"# Table 1e Future scheduled appointments\n",
|
351
370
|
"df_appt_pivot = (\n",
|
@@ -384,14 +403,14 @@
|
|
384
403
|
")\n",
|
385
404
|
"html_data.append(gt.as_raw_html())\n",
|
386
405
|
"gt.show()"
|
387
|
-
]
|
388
|
-
"id": "8193005de33cae6f",
|
389
|
-
"outputs": [],
|
390
|
-
"execution_count": null
|
406
|
+
]
|
391
407
|
},
|
392
408
|
{
|
393
|
-
"metadata": {},
|
394
409
|
"cell_type": "code",
|
410
|
+
"execution_count": null,
|
411
|
+
"id": "12",
|
412
|
+
"metadata": {},
|
413
|
+
"outputs": [],
|
395
414
|
"source": [
|
396
415
|
"# Table 2 Visits Missed to Date as % of Visits Attended + Visits Missed\n",
|
397
416
|
"subject_count = (\n",
|
@@ -453,14 +472,14 @@
|
|
453
472
|
" df_result[col] = df_result.apply(lambda x: f\"{x[col]} ({x[col_perc]*100:.2f})\", axis=1)\n",
|
454
473
|
"df_result = df_result.reset_index().sort_values(by=[\"visit_code\"], ascending=True)\n",
|
455
474
|
"df_result = df_result.fillna(0.0)"
|
456
|
-
]
|
457
|
-
"id": "c86c5f0ffe59e951",
|
458
|
-
"outputs": [],
|
459
|
-
"execution_count": null
|
475
|
+
]
|
460
476
|
},
|
461
477
|
{
|
462
|
-
"metadata": {},
|
463
478
|
"cell_type": "code",
|
479
|
+
"execution_count": null,
|
480
|
+
"id": "13",
|
481
|
+
"metadata": {},
|
482
|
+
"outputs": [],
|
464
483
|
"source": [
|
465
484
|
"df_table = df_result[[\"visit_code\", \"10\", \"20\", \"30\", \"40\", \"60\", \"total\"]].copy()\n",
|
466
485
|
"gt = df_as_great_table(\n",
|
@@ -485,14 +504,14 @@
|
|
485
504
|
")\n",
|
486
505
|
"html_data.append(gt.as_raw_html())\n",
|
487
506
|
"gt.show()\n"
|
488
|
-
]
|
489
|
-
"id": "3cd8b1290091660c",
|
490
|
-
"outputs": [],
|
491
|
-
"execution_count": null
|
507
|
+
]
|
492
508
|
},
|
493
509
|
{
|
494
|
-
"metadata": {},
|
495
510
|
"cell_type": "code",
|
511
|
+
"execution_count": null,
|
512
|
+
"id": "14",
|
513
|
+
"metadata": {},
|
514
|
+
"outputs": [],
|
496
515
|
"source": [
|
497
516
|
"# Table 2b: Number of missed visits by participant\n",
|
498
517
|
"subject_count = (\n",
|
@@ -549,17 +568,17 @@
|
|
549
568
|
"html_data.append(gt.as_raw_html())\n",
|
550
569
|
"gt.show()\n",
|
551
570
|
"\n"
|
552
|
-
]
|
553
|
-
"id": "b18088e16e0bf7f7",
|
554
|
-
"outputs": [],
|
555
|
-
"execution_count": null
|
571
|
+
]
|
556
572
|
},
|
557
573
|
{
|
558
|
-
"metadata": {},
|
559
574
|
"cell_type": "code",
|
575
|
+
"execution_count": null,
|
576
|
+
"id": "15",
|
577
|
+
"metadata": {},
|
578
|
+
"outputs": [],
|
560
579
|
"source": [
|
561
580
|
"# func for tables 3,4,5\n",
|
562
|
-
"def get_row_df(row_df:pd.DataFrame, label:str)->pd.DataFrame:\n",
|
581
|
+
"def get_row_df(row_df:pd.DataFrame, label:str=None, **kwargs)->pd.DataFrame:\n",
|
563
582
|
" row_df = row_df.groupby(by=[\"site_id\"]).site_id.count().to_frame(name=\"n\")\n",
|
564
583
|
" row_df[\"label\"] = label\n",
|
565
584
|
" row_df = row_df.reset_index()\n",
|
@@ -573,49 +592,60 @@
|
|
573
592
|
" return row_df\n",
|
574
593
|
"\n",
|
575
594
|
"\n",
|
576
|
-
"def get_table_df(
|
595
|
+
"def get_table_df(\n",
|
596
|
+
" df_source:pd.DataFrame,\n",
|
597
|
+
" visit_code:float|None=None,\n",
|
598
|
+
" month_label:str|None=None,\n",
|
599
|
+
" visit_codes:list[float]|None=None,\n",
|
600
|
+
" get_row_func:Callable|None=None,\n",
|
601
|
+
" category_labels:list[str]|None=None,\n",
|
602
|
+
")->pd.DataFrame:\n",
|
603
|
+
" get_row_df_func = get_row_func or get_row_df\n",
|
577
604
|
" if visit_code:\n",
|
578
605
|
" df_month = df_source[df_source.visit_code==visit_code].copy()\n",
|
606
|
+
" elif visit_codes:\n",
|
607
|
+
" df_month = df_source[df_source.visit_code.isin(visit_codes)].copy()\n",
|
579
608
|
" elif month_label:\n",
|
580
609
|
" df_month = df_source.copy()\n",
|
581
610
|
"\n",
|
582
611
|
" \n",
|
583
612
|
" row_df = df_month.copy()\n",
|
584
|
-
" table_df =
|
613
|
+
" table_df = get_row_df_func(row_df, \"Total (n)\", category_labels=category_labels)\n",
|
585
614
|
" \n",
|
586
615
|
" row_df = df_month.query(\"ogtt_value<7.8 and fbg_value<6.1\").copy()\n",
|
587
|
-
" table_df = pd.concat([table_df,
|
616
|
+
" table_df = pd.concat([table_df, get_row_df_func(row_df, \"OGTT <7.8; FBG <6.1\", category_labels=category_labels)])\n",
|
588
617
|
" \n",
|
589
618
|
" row_df = df_month[(df_month.ogtt_value<7.8) & (df_month.fbg_value>=6.1) & (df_month.fbg_value<7.0)].copy()\n",
|
590
|
-
" table_df = pd.concat([table_df,
|
619
|
+
" table_df = pd.concat([table_df, get_row_df_func(row_df, \"OGTT <7.8; FBG >=6.1 <7.0\", category_labels=category_labels)])\n",
|
591
620
|
" \n",
|
592
621
|
" row_df = df_month[(df_month.ogtt_value<7.8) & (df_month.fbg_value>=7.0)].copy()\n",
|
593
|
-
" table_df = pd.concat([table_df,
|
622
|
+
" table_df = pd.concat([table_df, get_row_df_func(row_df, \"OGTT <7.8; FBG >=7.0\", category_labels=category_labels)])\n",
|
594
623
|
" \n",
|
595
624
|
" row_df = df_month[(df_month.ogtt_value>=7.8) & (df_month.ogtt_value<11.1) & (df_month.fbg_value<6.1)].copy()\n",
|
596
|
-
" table_df = pd.concat([table_df,
|
625
|
+
" table_df = pd.concat([table_df, get_row_df_func(row_df, \"OGTT ≥7.8 to <11.1; FBG <6.1\", category_labels=category_labels)])\n",
|
597
626
|
" \n",
|
598
627
|
" row_df = df_month[(df_month.ogtt_value>=7.8) & (df_month.ogtt_value<11.1) & (df_month.fbg_value>=6.1) & (df_month.fbg_value<7.0)].copy()\n",
|
599
|
-
" table_df = pd.concat([table_df,
|
628
|
+
" table_df = pd.concat([table_df, get_row_df_func(row_df, \"OGTT ≥7.8 to <11.1; FBG >=6.1 <7.0\", category_labels=category_labels)])\n",
|
600
629
|
" \n",
|
601
630
|
" row_df = df_month[(df_month.ogtt_value>=7.8) & (df_month.ogtt_value<11.1) & (df_month.fbg_value>=7.0)].copy()\n",
|
602
|
-
" table_df = pd.concat([table_df,
|
631
|
+
" table_df = pd.concat([table_df, get_row_df_func(row_df, \"OGTT ≥7.8 to <11.1; FBG >=7.0\", category_labels=category_labels)])\n",
|
603
632
|
" \n",
|
604
633
|
" row_df = df_month[(df_month.ogtt_value>=11.1) & (df_month.fbg_value<6.1)].copy()\n",
|
605
|
-
" table_df = pd.concat([table_df,
|
634
|
+
" table_df = pd.concat([table_df, get_row_df_func(row_df, \"OGTT ≥11.1; FBG <6.1\", category_labels=category_labels)])\n",
|
606
635
|
" \n",
|
607
636
|
" row_df = df_month[(df_month.ogtt_value>=11.1) & (df_month.fbg_value>=6.1) & (df_month.fbg_value<7.0)].copy()\n",
|
608
|
-
" table_df = pd.concat([table_df,
|
637
|
+
" table_df = pd.concat([table_df, get_row_df_func(row_df, \"OGTT ≥11.1; FBG >=6.1 <7.0\", category_labels=category_labels)])\n",
|
609
638
|
" \n",
|
610
639
|
" row_df = df_month[(df_month.ogtt_value>=11.1) & (df_month.fbg_value>=7.0)].copy()\n",
|
611
|
-
" table_df = pd.concat([table_df,
|
640
|
+
" table_df = pd.concat([table_df, get_row_df_func(row_df, \"OGTT ≥11.1; FBG >=7.0\", category_labels=category_labels)])\n",
|
612
641
|
"\n",
|
613
642
|
" row_df = df_month[(df_month.ogtt_value.isna())].copy()\n",
|
614
|
-
" table_df = pd.concat([table_df,
|
643
|
+
" table_df = pd.concat([table_df, get_row_df_func(row_df, \"Missing OGTT\", category_labels=category_labels)])\n",
|
615
644
|
" return table_df\n",
|
616
645
|
"\n",
|
617
646
|
"\n",
|
618
647
|
"def format_table_df(tbl_df, add_totals:bool|None=None):\n",
|
648
|
+
" \"\"\"Pivot on site\"\"\"\n",
|
619
649
|
" add_totals = True if add_totals is None else add_totals\n",
|
620
650
|
" tbl_df = tbl_df.fillna(0.0)\n",
|
621
651
|
" tbl_df[\"total\"] = tbl_df.iloc[:,1:].sum(axis=1)\n",
|
@@ -647,44 +677,201 @@
|
|
647
677
|
" cols = [\"label\", *[f\"{site}_str\" for site in [\"10\", \"20\", \"30\", \"40\", \"60\", \"total\"]]]\n",
|
648
678
|
" tbl_df1 = tbl_df[cols]\n",
|
649
679
|
" tbl_df1.loc[tbl_df.label==\"Total (n)\"] = tbl_df.iloc[0][[\"label\", \"10\", \"20\", \"30\", \"40\", \"60\", \"total\"]].to_list()\n",
|
650
|
-
" return tbl_df1"
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
680
|
+
" return tbl_df1\n",
|
681
|
+
"\n",
|
682
|
+
"def format_table_with_bmi_df(tbl_df, add_totals:bool|None=None, category_labels:list[str]=None):\n",
|
683
|
+
" \"\"\"Pivot on BMI categories\"\"\"\n",
|
684
|
+
"\n",
|
685
|
+
" add_totals = True if add_totals is None else add_totals\n",
|
686
|
+
" tbl_df = tbl_df.fillna(0.0)\n",
|
687
|
+
" tbl_df[\"total\"] = tbl_df.iloc[:,1:].sum(axis=1)\n",
|
688
|
+
" tbl_df = tbl_df.reset_index(drop=True)\n",
|
689
|
+
"\n",
|
690
|
+
" if add_totals:\n",
|
691
|
+
" df_last = tbl_df[1:].sum().to_frame()\n",
|
692
|
+
" df_last.loc[\"label\"] = np.nan\n",
|
693
|
+
" df_last = df_last.reset_index()\n",
|
694
|
+
" df_last.columns = [\"label\", \"value\"]\n",
|
695
|
+
" df_last = df_last.pivot_table(columns=\"label\", values=\"value\").reset_index(drop=True)\n",
|
696
|
+
" df_last.columns.name = \"\"\n",
|
697
|
+
" df_last[\"label\"] = \"Totals\"\n",
|
698
|
+
"\n",
|
699
|
+
" tbl_df = pd.concat([tbl_df, df_last])\n",
|
700
|
+
" tbl_df = tbl_df.reset_index(drop=True)\n",
|
701
|
+
"\n",
|
702
|
+
" tbl_df.columns = [\"label\", *category_labels, \"total\"]\n",
|
703
|
+
"\n",
|
704
|
+
" for label in [*category_labels, \"total\"]:\n",
|
705
|
+
" tbl_df[f\"{label}_perc\"] = (tbl_df[label]/tbl_df.iloc[0][label]) * 100 if tbl_df.iloc[0][label]>0 else 0\n",
|
706
|
+
" tbl_df[f\"{label}_perc_str\"] = tbl_df[f\"{label}_perc\"].map('{:.1f}'.format)\n",
|
707
|
+
"\n",
|
708
|
+
" for cat in [*category_labels, \"total\"]:\n",
|
709
|
+
" tbl_df[f\"{label}_str\"] = tbl_df[[f\"{label}\", f\"{label}_perc_str\"]].apply(lambda x: ' ('.join(x.astype(str)), axis=1)\n",
|
710
|
+
" tbl_df[f\"{label}_str\"] = tbl_df[f\"{label}_str\"] + \")\"\n",
|
711
|
+
"\n",
|
712
|
+
" cols = [\"label\", *[f\"{label}_str\" for label in [*category_labels, \"total\"]]]\n",
|
713
|
+
" tbl_df1 = tbl_df[cols]\n",
|
714
|
+
" tbl_df1.loc[tbl_df.label==\"Total (n)\"] = tbl_df.iloc[0][[\"label\", *category_labels, \"total\"]].to_list()\n",
|
715
|
+
" return tbl_df1\n",
|
716
|
+
"\n",
|
717
|
+
"\n",
|
718
|
+
"def get_row_by_df(row_df:pd.DataFrame, label:str, category_labels:list[str])->pd.DataFrame:\n",
|
719
|
+
" # if label not in category_labels:\n",
|
720
|
+
" # raise ValueError(f\"Invalid label. Expected one of {category_labels}. Got {label}.\")\n",
|
721
|
+
" row_df = row_df.groupby(by=[\"site_id\"]).site_id.count().to_frame(name=\"n\")\n",
|
722
|
+
" row_df[\"label\"] = label\n",
|
723
|
+
" row_df = row_df.reset_index()\n",
|
724
|
+
" row_df = row_df.pivot(index=\"label\", values=\"n\", columns=\"site_id\").reset_index()\n",
|
725
|
+
" row_df.columns.name = \"\"\n",
|
726
|
+
"\n",
|
727
|
+
" for label in category_labels:\n",
|
728
|
+
" if label not in row_df.columns:\n",
|
729
|
+
" row_df[label] = None\n",
|
730
|
+
" row_df = row_df.reset_index(drop=True)\n",
|
731
|
+
" return row_df"
|
732
|
+
]
|
655
733
|
},
|
656
734
|
{
|
735
|
+
"cell_type": "code",
|
736
|
+
"execution_count": null,
|
737
|
+
"id": "16",
|
657
738
|
"metadata": {},
|
739
|
+
"outputs": [],
|
740
|
+
"source": [
|
741
|
+
"def get_fbg_value(r):\n",
|
742
|
+
" if not pd.isna(r[\"converted_fbg2_value\"]):\n",
|
743
|
+
" return r[\"converted_fbg2_value\"]\n",
|
744
|
+
" return r[\"converted_fbg_value\"]\n",
|
745
|
+
"\n",
|
746
|
+
"def get_ogtt_value(r):\n",
|
747
|
+
" if not pd.isna(r[\"converted_ogtt2_value\"]):\n",
|
748
|
+
" return r[\"converted_ogtt2_value\"]\n",
|
749
|
+
" return r[\"converted_ogtt_value\"]\n"
|
750
|
+
]
|
751
|
+
},
|
752
|
+
{
|
658
753
|
"cell_type": "code",
|
754
|
+
"execution_count": null,
|
755
|
+
"id": "17",
|
756
|
+
"metadata": {},
|
757
|
+
"outputs": [],
|
659
758
|
"source": [
|
660
|
-
"# Table 3: OGTT and FBG at
|
661
|
-
"
|
759
|
+
"# Table 3: OGTT and FBG at Enrolment\n",
|
760
|
+
"\n",
|
761
|
+
"subjects = df_visit.subject_identifier.unique()\n",
|
762
|
+
"df_screening = get_screening_df().query(\"consented==True and subject_identifier.isin(@subjects)\")\n",
|
763
|
+
"df_screening[\"visit_code\"] = \"Enrol\"\n",
|
764
|
+
"df_screening[\"fbg_value\"] = df_screening.apply(get_fbg_value, axis=1)\n",
|
765
|
+
"df_screening[\"ogtt_value\"] = df_screening.apply(get_ogtt_value, axis=1)\n",
|
766
|
+
"df_screening[\"site_id\"] = df_screening.site.astype(int)\n",
|
767
|
+
"df_screening = df_screening.drop(columns=[\"site\"])\n",
|
768
|
+
"df_table3 = get_table_df(df_screening, month_label=\"enrol\")\n",
|
662
769
|
"df_table3 = format_table_df(df_table3)\n",
|
663
770
|
"df_table3 = df_table3.fillna(0.0)\n",
|
664
|
-
"gt = df_as_great_table(df_table3, title=\"Table
|
771
|
+
"gt = df_as_great_table(df_table3, title=\"Table 3a: OGTT and FBG at Screening / Enrolment\")\n",
|
772
|
+
"\n",
|
773
|
+
"column_headers_enrol = {k:v for k,v in column_headers_with_str.items() if k not in \"visit_code\"}\n",
|
665
774
|
"gt = (\n",
|
666
775
|
" gt\n",
|
667
|
-
" .cols_label(
|
776
|
+
" .cols_label(column_headers_enrol)\n",
|
668
777
|
" .cols_align(align=\"center\", columns=[\"10_str\", \"20_str\", \"30_str\", \"40_str\", \"60_str\", \"total_str\"])\n",
|
669
778
|
" .cols_align(align=\"left\", columns=[\"label\"])\n",
|
670
779
|
" .cols_width(cases={\"label\": \"35%\"})\n",
|
780
|
+
" .tab_source_note(source_note=\"Excluding patients eventually withdrawn for `late exclusion` criteria\")\n",
|
671
781
|
")\n",
|
672
782
|
"html_data.append(gt.as_raw_html())\n",
|
673
783
|
"gt.show()\n"
|
674
|
-
]
|
675
|
-
|
784
|
+
]
|
785
|
+
},
|
786
|
+
{
|
787
|
+
"cell_type": "code",
|
788
|
+
"execution_count": null,
|
789
|
+
"id": "18",
|
790
|
+
"metadata": {},
|
791
|
+
"outputs": [],
|
792
|
+
"source": [
|
793
|
+
"# bmi_categories:\n",
|
794
|
+
"# 1 calculated_bmi_value<25\n",
|
795
|
+
"# 2 calculated_bmi_value>=25 & calculated_bmi_value<30\n",
|
796
|
+
"# 3 calculated_bmi_value>=30\n",
|
797
|
+
"\n",
|
798
|
+
"\n",
|
799
|
+
"# subjects = df_visit.subject_identifier.unique()\n",
|
800
|
+
"# df_screening = get_screening_df().query(\"consented==True and subject_identifier.isin(@subjects)\")\n",
|
801
|
+
"# df_screening[\"visit_code\"] = \"Enrol\"\n",
|
802
|
+
"# df_screening[\"fbg_value\"] = df_screening.apply(get_fbg_value, axis=1)\n",
|
803
|
+
"# df_screening[\"ogtt_value\"] = df_screening.apply(get_ogtt_value, axis=1)\n",
|
804
|
+
"# df_screening[\"site_id\"] = df_screening.site.astype(int)\n",
|
805
|
+
"# df_screening = df_screening.drop(columns=[\"site\"])\n",
|
806
|
+
"# df_screening[\"bmi\"] = pd.NA\n",
|
807
|
+
"# df_screening.loc[df_screening[\"calculated_bmi_value\"] < 25.0, \"bmi\"] = \"bmi<25\"\n",
|
808
|
+
"# df_screening.loc[(df_screening[\"calculated_bmi_value\"]>=25.0) & (df_screening[\"calculated_bmi_value\"] < 30.0), \"bmi\"] = \"25<=bmi<30\"\n",
|
809
|
+
"# df_screening.loc[df_screening[\"calculated_bmi_value\"] > 30.0, \"bmi\"] = \"bmi>30\"\n",
|
810
|
+
"#\n",
|
811
|
+
"# category_labels = [ \"bmi<25\", \"25<=bmi<30\", \"bmi>=30\", \"Total (n)\"]\n",
|
812
|
+
"# df_table3 = get_table_df(df_screening, month_label=\"enrol\", get_row_func=get_row_by_df, category_labels=category_labels)\n",
|
813
|
+
"# df_table3 = format_table_with_bmi_df(df_table3, category_labels=category_labels)\n",
|
814
|
+
"# df_table3 = df_table3.fillna(0.0)\n",
|
815
|
+
"# gt = df_as_great_table(df_table3, title=\"Table 3b: OGTT/FBG by BMI at Screening / Enrolment\")\n",
|
816
|
+
"# column_headers_enrol = {\"bmi<25_str\":\"bmi<25\", \"25<=bmi<30_str\":\"25<=bmi<30\", \"bmi>30_str\":\"bmi>30\", \"total_str\": \"total\"}\n",
|
817
|
+
"# gt = (\n",
|
818
|
+
"# gt\n",
|
819
|
+
"# .cols_label(column_headers_enrol)\n",
|
820
|
+
"# .cols_align(align=\"center\", columns=[\"bmi<25_str\", \"25<=bmi<30_str\", \"bmi>30_str\", \"total_str\"])\n",
|
821
|
+
"# .cols_align(align=\"left\", columns=[\"label\"])\n",
|
822
|
+
"# .cols_width(cases={\"label\": \"35%\"})\n",
|
823
|
+
"# .tab_source_note(source_note=\"Excluding patients eventually withdrawn for `late exclusion` criteria\")\n",
|
824
|
+
"# )\n",
|
825
|
+
"# html_data.append(gt.as_raw_html())\n",
|
826
|
+
"# gt.show()\n",
|
827
|
+
"\n"
|
828
|
+
]
|
829
|
+
},
|
830
|
+
{
|
831
|
+
"cell_type": "code",
|
832
|
+
"execution_count": null,
|
833
|
+
"id": "19",
|
834
|
+
"metadata": {},
|
676
835
|
"outputs": [],
|
677
|
-
"
|
836
|
+
"source": [
|
837
|
+
"[col for col in df_screening.columns if \"bmi\" in col]"
|
838
|
+
]
|
678
839
|
},
|
679
840
|
{
|
841
|
+
"cell_type": "code",
|
842
|
+
"execution_count": null,
|
843
|
+
"id": "20",
|
680
844
|
"metadata": {},
|
845
|
+
"outputs": [],
|
846
|
+
"source": [
|
847
|
+
"# Table 4: OGTT and FBG at 12-month visit\n",
|
848
|
+
"df_table3 = get_table_df(df_glucose, visit_codes=[1120.0])\n",
|
849
|
+
"df_table3 = format_table_df(df_table3)\n",
|
850
|
+
"df_table3 = df_table3.fillna(0.0)\n",
|
851
|
+
"gt = df_as_great_table(df_table3, title=\"Table 4: OGTT and FBG at 12-month visit\")\n",
|
852
|
+
"gt = (\n",
|
853
|
+
" gt\n",
|
854
|
+
" .cols_label(column_headers_with_str)\n",
|
855
|
+
" .cols_align(align=\"center\", columns=[\"10_str\", \"20_str\", \"30_str\", \"40_str\", \"60_str\", \"total_str\"])\n",
|
856
|
+
" .cols_align(align=\"left\", columns=[\"label\"])\n",
|
857
|
+
" .cols_width(cases={\"label\": \"35%\"})\n",
|
858
|
+
")\n",
|
859
|
+
"html_data.append(gt.as_raw_html())\n",
|
860
|
+
"gt.show()\n"
|
861
|
+
]
|
862
|
+
},
|
863
|
+
{
|
681
864
|
"cell_type": "code",
|
865
|
+
"execution_count": null,
|
866
|
+
"id": "21",
|
867
|
+
"metadata": {},
|
868
|
+
"outputs": [],
|
682
869
|
"source": [
|
683
|
-
"# Table
|
870
|
+
"# Table 5: OGTT and FBG at 24-month visit\n",
|
684
871
|
"df_table4 = get_table_df(df_glucose, 1240.0)\n",
|
685
872
|
"df_table4 = format_table_df(df_table4)\n",
|
686
873
|
"df_table4 = df_table4.fillna(0.0)\n",
|
687
|
-
"gt = df_as_great_table(df_table4, title=\"Table
|
874
|
+
"gt = df_as_great_table(df_table4, title=\"Table 5: OGTT and FBG at 24-month visit\")\n",
|
688
875
|
"gt = (\n",
|
689
876
|
" gt\n",
|
690
877
|
" .cols_label(column_headers_with_str)\n",
|
@@ -694,20 +881,20 @@
|
|
694
881
|
")\n",
|
695
882
|
"html_data.append(gt.as_raw_html())\n",
|
696
883
|
"gt.show()"
|
697
|
-
]
|
698
|
-
"id": "ec0988364166e130",
|
699
|
-
"outputs": [],
|
700
|
-
"execution_count": null
|
884
|
+
]
|
701
885
|
},
|
702
886
|
{
|
703
|
-
"metadata": {},
|
704
887
|
"cell_type": "code",
|
888
|
+
"execution_count": null,
|
889
|
+
"id": "22",
|
890
|
+
"metadata": {},
|
891
|
+
"outputs": [],
|
705
892
|
"source": [
|
706
|
-
"# Table
|
893
|
+
"# Table 6: OGTT and FBG at 36-month visit\n",
|
707
894
|
"df_table5 = get_table_df(df_glucose, 1360.0)\n",
|
708
895
|
"df_table5 = format_table_df(df_table5)\n",
|
709
896
|
"df_table5 = df_table5.fillna(0.0)\n",
|
710
|
-
"gt = df_as_great_table(df_table5, title=\"Table
|
897
|
+
"gt = df_as_great_table(df_table5, title=\"Table 6: OGTT and FBG at 36-month visit\")\n",
|
711
898
|
"gt = (\n",
|
712
899
|
" gt\n",
|
713
900
|
" .cols_label(column_headers_with_str)\n",
|
@@ -717,21 +904,21 @@
|
|
717
904
|
")\n",
|
718
905
|
"html_data.append(gt.as_raw_html())\n",
|
719
906
|
"gt.show()"
|
720
|
-
]
|
721
|
-
"id": "59be72121202df15",
|
722
|
-
"outputs": [],
|
723
|
-
"execution_count": null
|
907
|
+
]
|
724
908
|
},
|
725
909
|
{
|
726
|
-
"metadata": {},
|
727
910
|
"cell_type": "code",
|
911
|
+
"execution_count": null,
|
912
|
+
"id": "23",
|
913
|
+
"metadata": {},
|
914
|
+
"outputs": [],
|
728
915
|
"source": [
|
729
|
-
"# Table
|
916
|
+
"# Table 7: Any OGTT>11.1 ever\n",
|
730
917
|
"row_df = df_glucose[df_glucose.ogtt_value>=11.1].copy()\n",
|
731
918
|
"table_df = get_row_df(row_df, \"Total (n)\")\n",
|
732
919
|
"df_table6 = format_table_df(table_df)\n",
|
733
920
|
"df_table = df_table6[:1].fillna(0.0).copy().reset_index(drop=True)\n",
|
734
|
-
"gt = df_as_great_table(df_table, title=\"Table
|
921
|
+
"gt = df_as_great_table(df_table, title=\"Table 7: Any OGTT>11.1 ever\")\n",
|
735
922
|
"gt = (\n",
|
736
923
|
" gt\n",
|
737
924
|
" .cols_label(column_headers_with_str)\n",
|
@@ -741,14 +928,14 @@
|
|
741
928
|
")\n",
|
742
929
|
"html_data.append(gt.as_raw_html())\n",
|
743
930
|
"gt.show()"
|
744
|
-
]
|
745
|
-
"id": "f016ddbe736c2f93",
|
746
|
-
"outputs": [],
|
747
|
-
"execution_count": null
|
931
|
+
]
|
748
932
|
},
|
749
933
|
{
|
750
|
-
"metadata": {},
|
751
934
|
"cell_type": "code",
|
935
|
+
"execution_count": null,
|
936
|
+
"id": "24",
|
937
|
+
"metadata": {},
|
938
|
+
"outputs": [],
|
752
939
|
"source": [
|
753
940
|
"# func for table 7\n",
|
754
941
|
"def get_table7_df(df_source:pd.DataFrame, visit_code:float)->pd.DataFrame:\n",
|
@@ -766,16 +953,16 @@
|
|
766
953
|
" row_df = df_month[(df_month.fbg_value>=7.0)].copy()\n",
|
767
954
|
" table_df = pd.concat([table_df, get_row_df(row_df, \"FBG >=7.0\")])\n",
|
768
955
|
" return table_df"
|
769
|
-
]
|
770
|
-
"id": "6193907cc12f5b5c",
|
771
|
-
"outputs": [],
|
772
|
-
"execution_count": null
|
956
|
+
]
|
773
957
|
},
|
774
958
|
{
|
775
|
-
"metadata": {},
|
776
959
|
"cell_type": "code",
|
960
|
+
"execution_count": null,
|
961
|
+
"id": "25",
|
962
|
+
"metadata": {},
|
963
|
+
"outputs": [],
|
777
964
|
"source": [
|
778
|
-
"# Table
|
965
|
+
"# Table 8: Interim FBG results\n",
|
779
966
|
"df_table7 = get_table7_df(df_glucose, 1150.0)\n",
|
780
967
|
"df_table7 = format_table_df(df_table7, add_totals=False)\n",
|
781
968
|
"df_table7[\"visit_code\"] = MONTH15\n",
|
@@ -807,17 +994,17 @@
|
|
807
994
|
"df_table = pd.concat([df_table7, df_table71, df_table72, df_table73, df_table74, df_table75, df_table76])\n",
|
808
995
|
"df_table = df_table.reset_index(drop=True)\n",
|
809
996
|
"df_table = df_table.fillna(0.0)"
|
810
|
-
]
|
811
|
-
"id": "16adb1f965081358",
|
812
|
-
"outputs": [],
|
813
|
-
"execution_count": null
|
997
|
+
]
|
814
998
|
},
|
815
999
|
{
|
816
|
-
"metadata": {},
|
817
1000
|
"cell_type": "code",
|
1001
|
+
"execution_count": null,
|
1002
|
+
"id": "26",
|
1003
|
+
"metadata": {},
|
1004
|
+
"outputs": [],
|
818
1005
|
"source": [
|
819
1006
|
"column_headers_with_str = {\"visit_code\": \"Visit Code\", **column_headers_with_str}\n",
|
820
|
-
"gt = df_as_great_table2(df_table, title=\"Table
|
1007
|
+
"gt = df_as_great_table2(df_table, title=\"Table 8: Interim FBG results\")\n",
|
821
1008
|
"gt = (\n",
|
822
1009
|
" gt\n",
|
823
1010
|
" .cols_label(column_headers_with_str)\n",
|
@@ -835,16 +1022,16 @@
|
|
835
1022
|
")\n",
|
836
1023
|
"html_data.append(gt.as_raw_html())\n",
|
837
1024
|
"gt.show()"
|
838
|
-
]
|
839
|
-
"id": "81bcfe52d364b646",
|
840
|
-
"outputs": [],
|
841
|
-
"execution_count": null
|
1025
|
+
]
|
842
1026
|
},
|
843
1027
|
{
|
844
|
-
"metadata": {},
|
845
1028
|
"cell_type": "code",
|
1029
|
+
"execution_count": null,
|
1030
|
+
"id": "27",
|
1031
|
+
"metadata": {},
|
1032
|
+
"outputs": [],
|
846
1033
|
"source": [
|
847
|
-
"# Table
|
1034
|
+
"# Table 9: Primary Endpoint met\n",
|
848
1035
|
"df_endpoint_grp = df_endpoint.groupby(by=[\"site_id\", \"endpoint_label\"]).size().to_frame().reset_index()\n",
|
849
1036
|
"df_endpoint_grp.columns = [\"site_id\", \"label\", \"endpoints\"]\n",
|
850
1037
|
"df_endpoint_pivot = df_endpoint_grp.pivot_table(index=\"label\", columns=\"site_id\", values=\"endpoints\").reset_index()\n",
|
@@ -857,7 +1044,7 @@
|
|
857
1044
|
"\n",
|
858
1045
|
"gt = df_as_great_table(\n",
|
859
1046
|
" df_endpoint_pivot,\n",
|
860
|
-
" title=\"Table
|
1047
|
+
" title=\"Table 9a: Primary Endpoint met\"\n",
|
861
1048
|
")\n",
|
862
1049
|
"gt = (\n",
|
863
1050
|
" gt\n",
|
@@ -868,26 +1055,28 @@
|
|
868
1055
|
")\n",
|
869
1056
|
"html_data.append(gt.as_raw_html())\n",
|
870
1057
|
"gt.show()"
|
871
|
-
]
|
872
|
-
"id": "37904c7ce49724e6",
|
873
|
-
"outputs": [],
|
874
|
-
"execution_count": null
|
1058
|
+
]
|
875
1059
|
},
|
876
1060
|
{
|
877
|
-
"metadata": {},
|
878
1061
|
"cell_type": "code",
|
879
|
-
"
|
880
|
-
"id": "
|
1062
|
+
"execution_count": null,
|
1063
|
+
"id": "28",
|
1064
|
+
"metadata": {},
|
881
1065
|
"outputs": [],
|
882
|
-
"
|
1066
|
+
"source": [
|
1067
|
+
"#read_frame(SubjectScheduleHistory.objects.filter(offschedule_model=\"meta_prn.offschedule\"), verbose=False).rename(columns={\"site\": \"site_id\"})"
|
1068
|
+
]
|
883
1069
|
},
|
884
1070
|
{
|
885
|
-
"metadata": {},
|
886
1071
|
"cell_type": "code",
|
1072
|
+
"execution_count": null,
|
1073
|
+
"id": "29",
|
1074
|
+
"metadata": {},
|
1075
|
+
"outputs": [],
|
887
1076
|
"source": [
|
888
1077
|
"from great_tables import html\n",
|
889
1078
|
"\n",
|
890
|
-
"# Table
|
1079
|
+
"# Table 9b: Primary Endpoint no EOS or DM Referral\n",
|
891
1080
|
"df_subjecthistory = read_frame(SubjectScheduleHistory.objects.filter(offschedule_model=\"meta_prn.offschedule\", offschedule_datetime__isnull=False), verbose=False).rename(columns={\"site\": \"site_id\"})\n",
|
892
1081
|
"df_subjecthistory[\"site_id\"] = df_subjecthistory[\"site_id\"].astype(str)\n",
|
893
1082
|
"df_endpoint_no_off = df_endpoint.merge(df_subjecthistory[[\"subject_identifier\", \"offschedule_datetime\"]], on=[\"subject_identifier\"], how=\"left\")\n",
|
@@ -907,7 +1096,7 @@
|
|
907
1096
|
"\n",
|
908
1097
|
"gt = df_as_great_table(\n",
|
909
1098
|
" df_endpoint_pivot,\n",
|
910
|
-
" title=\"Table
|
1099
|
+
" title=\"Table 9b: Primary Endpoint met -- participant not referred\"\n",
|
911
1100
|
")\n",
|
912
1101
|
"gt = (\n",
|
913
1102
|
" gt\n",
|
@@ -919,24 +1108,24 @@
|
|
919
1108
|
")\n",
|
920
1109
|
"html_data.append(gt.as_raw_html())\n",
|
921
1110
|
"gt.show()"
|
922
|
-
]
|
923
|
-
"id": "a74cd253ec5827f9",
|
924
|
-
"outputs": [],
|
925
|
-
"execution_count": null
|
1111
|
+
]
|
926
1112
|
},
|
927
1113
|
{
|
928
|
-
"metadata": {},
|
929
1114
|
"cell_type": "code",
|
930
|
-
"
|
931
|
-
"id": "
|
1115
|
+
"execution_count": null,
|
1116
|
+
"id": "30",
|
1117
|
+
"metadata": {},
|
932
1118
|
"outputs": [],
|
933
|
-
"
|
1119
|
+
"source": []
|
934
1120
|
},
|
935
1121
|
{
|
936
|
-
"metadata": {},
|
937
1122
|
"cell_type": "code",
|
1123
|
+
"execution_count": null,
|
1124
|
+
"id": "31",
|
1125
|
+
"metadata": {},
|
1126
|
+
"outputs": [],
|
938
1127
|
"source": [
|
939
|
-
"# Table
|
1128
|
+
"# Table 10: Incident Rate per 1000 person years\n",
|
940
1129
|
"\n",
|
941
1130
|
"def get_df_main(df_visit:pd.DataFrame, lower_days:float|None=None, upper_days:float|None=None):\n",
|
942
1131
|
" if not lower_days:\n",
|
@@ -989,14 +1178,14 @@
|
|
989
1178
|
" person_years_total = df_main.followup_years.sum()\n",
|
990
1179
|
" data.update({term:[person_years_total, subjects, events, *get_rate_and_ci(events, person_years_total)]})\n",
|
991
1180
|
" return data"
|
992
|
-
]
|
993
|
-
"id": "920db81ad440edab",
|
994
|
-
"outputs": [],
|
995
|
-
"execution_count": null
|
1181
|
+
]
|
996
1182
|
},
|
997
1183
|
{
|
998
|
-
"metadata": {},
|
999
1184
|
"cell_type": "code",
|
1185
|
+
"execution_count": null,
|
1186
|
+
"id": "32",
|
1187
|
+
"metadata": {},
|
1188
|
+
"outputs": [],
|
1000
1189
|
"source": [
|
1001
1190
|
"incidence_data = {}\n",
|
1002
1191
|
"incidence_data.update(get_incidence_data(\"total\", lower_days=-1, upper_days=10000))\n",
|
@@ -1017,18 +1206,18 @@
|
|
1017
1206
|
" data[\"upper_ci\"].append(v[5])\n",
|
1018
1207
|
"\n",
|
1019
1208
|
"df_table9 = pd.DataFrame(data={k:v for k,v in data.items() if k!=\"subjects\"})"
|
1020
|
-
]
|
1021
|
-
"id": "44651e865641b75d",
|
1022
|
-
"outputs": [],
|
1023
|
-
"execution_count": null
|
1209
|
+
]
|
1024
1210
|
},
|
1025
1211
|
{
|
1026
|
-
"metadata": {},
|
1027
1212
|
"cell_type": "code",
|
1213
|
+
"execution_count": null,
|
1214
|
+
"id": "33",
|
1215
|
+
"metadata": {},
|
1216
|
+
"outputs": [],
|
1028
1217
|
"source": [
|
1029
1218
|
"gt = df_as_great_table(\n",
|
1030
1219
|
" df_table9,\n",
|
1031
|
-
" title=\"Table
|
1220
|
+
" title=\"Table 10: Incident Rate per 1000 person years\",\n",
|
1032
1221
|
" subtitle=md(\"using randomisation to diabetes/last seen\"),\n",
|
1033
1222
|
")\n",
|
1034
1223
|
"gt = gt.fmt_number(columns=[\"person_years\", \"failures\", \"rate\", \"lower_ci\", \"upper_ci\"], decimals=2)\n",
|
@@ -1044,21 +1233,21 @@
|
|
1044
1233
|
")\n",
|
1045
1234
|
"gt.show()\n",
|
1046
1235
|
"html_data.append(gt.as_raw_html())"
|
1047
|
-
]
|
1048
|
-
"id": "da4e67d83522768a",
|
1049
|
-
"outputs": [],
|
1050
|
-
"execution_count": null
|
1236
|
+
]
|
1051
1237
|
},
|
1052
1238
|
{
|
1053
|
-
"metadata": {},
|
1054
1239
|
"cell_type": "code",
|
1240
|
+
"execution_count": null,
|
1241
|
+
"id": "34",
|
1242
|
+
"metadata": {},
|
1243
|
+
"outputs": [],
|
1055
1244
|
"source": [
|
1056
|
-
"# Table
|
1245
|
+
"# Table 11: Proportion meeting primary endpoint\n",
|
1057
1246
|
"df_table10 = pd.DataFrame(data=data)\n",
|
1058
1247
|
"df_table10[\"proportion\"] = df_table10[\"failures\"]/df_table10[\"subjects\"]*100\n",
|
1059
1248
|
"gt = df_as_great_table(\n",
|
1060
1249
|
" df_table10[[\"label\", \"subjects\", 'failures', \"proportion\"]],\n",
|
1061
|
-
" title=\"Table
|
1250
|
+
" title=\"Table 11: Proportion meeting primary endpoint\",\n",
|
1062
1251
|
")\n",
|
1063
1252
|
"gt = (\n",
|
1064
1253
|
" gt\n",
|
@@ -1070,23 +1259,25 @@
|
|
1070
1259
|
")\n",
|
1071
1260
|
"html_data.append(gt.as_raw_html())\n",
|
1072
1261
|
"gt.show()\n"
|
1073
|
-
]
|
1074
|
-
"id": "2376a30803fbc743",
|
1075
|
-
"outputs": [],
|
1076
|
-
"execution_count": null
|
1262
|
+
]
|
1077
1263
|
},
|
1078
1264
|
{
|
1079
|
-
"metadata": {},
|
1080
1265
|
"cell_type": "code",
|
1081
|
-
"
|
1082
|
-
"id": "
|
1266
|
+
"execution_count": null,
|
1267
|
+
"id": "35",
|
1268
|
+
"metadata": {},
|
1083
1269
|
"outputs": [],
|
1084
|
-
"
|
1270
|
+
"source": []
|
1085
1271
|
},
|
1086
1272
|
{
|
1087
|
-
"metadata": {},
|
1088
1273
|
"cell_type": "code",
|
1274
|
+
"execution_count": null,
|
1275
|
+
"id": "36",
|
1276
|
+
"metadata": {},
|
1277
|
+
"outputs": [],
|
1089
1278
|
"source": [
|
1279
|
+
"# TODO: EoS should be for all 1691, not 1631\n",
|
1280
|
+
"\n",
|
1090
1281
|
"# Table 11a: End of Study Table (for those who have completed an end of study form)\n",
|
1091
1282
|
"df_eos = get_eos_df()\n",
|
1092
1283
|
"offstudy_reasons = {\n",
|
@@ -1125,7 +1316,7 @@
|
|
1125
1316
|
"\n",
|
1126
1317
|
"gt = df_as_great_table(\n",
|
1127
1318
|
" df_eos_pivot,\n",
|
1128
|
-
" title=\"Table
|
1319
|
+
" title=\"Table 12a: End of study report\",\n",
|
1129
1320
|
" subtitle=md(\"for those who have completed an End of study report\"),\n",
|
1130
1321
|
")\n",
|
1131
1322
|
"gt = (\n",
|
@@ -1163,24 +1354,24 @@
|
|
1163
1354
|
")\n",
|
1164
1355
|
"html_data.append(gt.as_raw_html())\n",
|
1165
1356
|
"gt.show()\n"
|
1166
|
-
]
|
1167
|
-
"id": "37dcd320411bd9c5",
|
1168
|
-
"outputs": [],
|
1169
|
-
"execution_count": null
|
1357
|
+
]
|
1170
1358
|
},
|
1171
1359
|
{
|
1172
|
-
"metadata": {},
|
1173
1360
|
"cell_type": "code",
|
1174
|
-
"
|
1175
|
-
"id": "
|
1361
|
+
"execution_count": null,
|
1362
|
+
"id": "37",
|
1363
|
+
"metadata": {},
|
1176
1364
|
"outputs": [],
|
1177
|
-
"
|
1365
|
+
"source": []
|
1178
1366
|
},
|
1179
1367
|
{
|
1180
|
-
"metadata": {},
|
1181
1368
|
"cell_type": "code",
|
1369
|
+
"execution_count": null,
|
1370
|
+
"id": "38",
|
1371
|
+
"metadata": {},
|
1372
|
+
"outputs": [],
|
1182
1373
|
"source": [
|
1183
|
-
"# Table
|
1374
|
+
"# Table 12b: Study status\n",
|
1184
1375
|
"def get_schedule_df(df_subjecthistory:pd.DataFrame, onschedule_model:str, offschedule_model:str, mode:str)->pd.DataFrame:\n",
|
1185
1376
|
" columns = {k:f\"{k}_{mode}\" for k in [\"10\", \"20\", \"30\", \"40\", \"60\"]}\n",
|
1186
1377
|
" df_schedule = (\n",
|
@@ -1236,7 +1427,7 @@
|
|
1236
1427
|
"\n",
|
1237
1428
|
"gt = df_as_great_table(\n",
|
1238
1429
|
" df_status,\n",
|
1239
|
-
" title=\"Table
|
1430
|
+
" title=\"Table 12b: Study status\",\n",
|
1240
1431
|
" subtitle=md(\"Calculated from Offschedule form; not End of study report\"),\n",
|
1241
1432
|
")\n",
|
1242
1433
|
"# gt = gt.fmt_number(columns=[\"person_years\", \"failures\", \"rate\", \"lower_ci\", \"upper_ci\"], decimals=0)\n",
|
@@ -1300,16 +1491,16 @@
|
|
1300
1491
|
")\n",
|
1301
1492
|
"html_data.append(gt.as_raw_html())\n",
|
1302
1493
|
"gt.show()"
|
1303
|
-
]
|
1304
|
-
"id": "35840b9a7971e4cf",
|
1305
|
-
"outputs": [],
|
1306
|
-
"execution_count": null
|
1494
|
+
]
|
1307
1495
|
},
|
1308
1496
|
{
|
1309
|
-
"metadata": {},
|
1310
1497
|
"cell_type": "code",
|
1498
|
+
"execution_count": null,
|
1499
|
+
"id": "39",
|
1500
|
+
"metadata": {},
|
1501
|
+
"outputs": [],
|
1311
1502
|
"source": [
|
1312
|
-
"# Table
|
1503
|
+
"# Table 13: Loss to Follow Up\n",
|
1313
1504
|
"df_ltfu = read_frame(LossToFollowup.objects.all(), verbose=False).rename(columns={\"site\": \"site_id\"})\n",
|
1314
1505
|
"df_ltfu_pivot = (\n",
|
1315
1506
|
" df_ltfu\n",
|
@@ -1328,16 +1519,16 @@
|
|
1328
1519
|
"sum_row_df = pd.DataFrame(sum_row).T\n",
|
1329
1520
|
"df_ltfu_pivot = pd.concat([df_ltfu_pivot, sum_row_df], ignore_index=True)\n",
|
1330
1521
|
"df_ltfu_pivot\n"
|
1331
|
-
]
|
1332
|
-
"id": "534c51e7321e2ef3",
|
1333
|
-
"outputs": [],
|
1334
|
-
"execution_count": null
|
1522
|
+
]
|
1335
1523
|
},
|
1336
1524
|
{
|
1337
|
-
"metadata": {},
|
1338
1525
|
"cell_type": "code",
|
1526
|
+
"execution_count": null,
|
1527
|
+
"id": "40",
|
1528
|
+
"metadata": {},
|
1529
|
+
"outputs": [],
|
1339
1530
|
"source": [
|
1340
|
-
"# Table
|
1531
|
+
"# Table 13c: End of study report not submitted\n",
|
1341
1532
|
"\n",
|
1342
1533
|
"df1 = (\n",
|
1343
1534
|
" df_status\n",
|
@@ -1358,7 +1549,7 @@
|
|
1358
1549
|
"\n",
|
1359
1550
|
"gt = df_as_great_table(\n",
|
1360
1551
|
" df_eos_not_reported,\n",
|
1361
|
-
" title=\"Table
|
1552
|
+
" title=\"Table 13c: End of study report not submitted\",\n",
|
1362
1553
|
" subtitle=md(\"End of study report expected based on Offschedule form\"),\n",
|
1363
1554
|
")\n",
|
1364
1555
|
"gt = (\n",
|
@@ -1389,22 +1580,24 @@
|
|
1389
1580
|
")\n",
|
1390
1581
|
"html_data.append(gt.as_raw_html())\n",
|
1391
1582
|
"gt.show()\n"
|
1392
|
-
]
|
1393
|
-
"id": "25d05831ef76f267",
|
1394
|
-
"outputs": [],
|
1395
|
-
"execution_count": null
|
1583
|
+
]
|
1396
1584
|
},
|
1397
1585
|
{
|
1398
|
-
"metadata": {},
|
1399
1586
|
"cell_type": "code",
|
1400
|
-
"
|
1401
|
-
"id": "
|
1587
|
+
"execution_count": null,
|
1588
|
+
"id": "41",
|
1589
|
+
"metadata": {},
|
1402
1590
|
"outputs": [],
|
1403
|
-
"
|
1591
|
+
"source": [
|
1592
|
+
"# Table 14: Baseline Sample"
|
1593
|
+
]
|
1404
1594
|
},
|
1405
1595
|
{
|
1406
|
-
"metadata": {},
|
1407
1596
|
"cell_type": "code",
|
1597
|
+
"execution_count": null,
|
1598
|
+
"id": "42",
|
1599
|
+
"metadata": {},
|
1600
|
+
"outputs": [],
|
1408
1601
|
"source": [
|
1409
1602
|
"# Table 15: Consented to extended followup\n",
|
1410
1603
|
"df_consented = (\n",
|
@@ -1462,22 +1655,22 @@
|
|
1462
1655
|
")\n",
|
1463
1656
|
"html_data.append(gt.as_raw_html())\n",
|
1464
1657
|
"gt.show()"
|
1465
|
-
]
|
1466
|
-
"id": "8acd2dd7e5a958e9",
|
1467
|
-
"outputs": [],
|
1468
|
-
"execution_count": null
|
1658
|
+
]
|
1469
1659
|
},
|
1470
1660
|
{
|
1471
|
-
"metadata": {},
|
1472
1661
|
"cell_type": "code",
|
1473
|
-
"
|
1474
|
-
"id": "
|
1662
|
+
"execution_count": null,
|
1663
|
+
"id": "43",
|
1664
|
+
"metadata": {},
|
1475
1665
|
"outputs": [],
|
1476
|
-
"
|
1666
|
+
"source": []
|
1477
1667
|
},
|
1478
1668
|
{
|
1479
|
-
"metadata": {},
|
1480
1669
|
"cell_type": "code",
|
1670
|
+
"execution_count": null,
|
1671
|
+
"id": "44",
|
1672
|
+
"metadata": {},
|
1673
|
+
"outputs": [],
|
1481
1674
|
"source": [
|
1482
1675
|
"# gather raw html\n",
|
1483
1676
|
"raw_html = [f'<div class=\"page-break\">{s}</div>' for s in html_data]\n",
|
@@ -1496,14 +1689,14 @@
|
|
1496
1689
|
"\"\"\"\n",
|
1497
1690
|
"raw_html = ''.join(raw_html)\n",
|
1498
1691
|
"raw_html = f'<!DOCTYPE html>\\n<html lang=\"en\">\\n{style_css}\\n<head>\\n<meta charset=\"utf-8\"/>\\n</head>\\n<body>\\n' + document_title + raw_html + '\\n</body>\\n</html>\\n'"
|
1499
|
-
]
|
1500
|
-
"id": "a38e9d7ba59d063b",
|
1501
|
-
"outputs": [],
|
1502
|
-
"execution_count": null
|
1692
|
+
]
|
1503
1693
|
},
|
1504
1694
|
{
|
1505
|
-
"metadata": {},
|
1506
1695
|
"cell_type": "code",
|
1696
|
+
"execution_count": null,
|
1697
|
+
"id": "45",
|
1698
|
+
"metadata": {},
|
1699
|
+
"outputs": [],
|
1507
1700
|
"source": [
|
1508
1701
|
"# render html to PDF\n",
|
1509
1702
|
"pdfkit.from_string(raw_html, str(analysis_folder / pdf_filename),\n",
|
@@ -1523,18 +1716,15 @@
|
|
1523
1716
|
" 'no-outline': None,\n",
|
1524
1717
|
"},\n",
|
1525
1718
|
"verbose=True)"
|
1526
|
-
]
|
1527
|
-
"id": "792243aad557cc86",
|
1528
|
-
"outputs": [],
|
1529
|
-
"execution_count": null
|
1719
|
+
]
|
1530
1720
|
},
|
1531
1721
|
{
|
1532
|
-
"metadata": {},
|
1533
1722
|
"cell_type": "code",
|
1534
|
-
"
|
1535
|
-
"id": "
|
1723
|
+
"execution_count": null,
|
1724
|
+
"id": "46",
|
1725
|
+
"metadata": {},
|
1536
1726
|
"outputs": [],
|
1537
|
-
"
|
1727
|
+
"source": []
|
1538
1728
|
}
|
1539
1729
|
],
|
1540
1730
|
"metadata": {
|