meta-edc 1.0.7__py3-none-any.whl → 1.1.1__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/README.rst +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 +721 -448
- 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.1.dist-info}/METADATA +3 -3
- {meta_edc-1.0.7.dist-info → meta_edc-1.1.1.dist-info}/RECORD +62 -35
- {meta_edc-1.0.7.dist-info → meta_edc-1.1.1.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/admin/offschedule_pregnancy_admin.py +3 -3
- meta_prn/admin/onschedule_dm_referral_admin.py +5 -5
- meta_prn/form_validators/end_of_study.py +2 -2
- 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_reports/admin/last_imp_refill_admin.py +3 -2
- 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 +2 -3
- meta_subject/choices.py +2 -1
- meta_subject/form_validators/delivery_form_validator.py +1 -0
- meta_subject/forms/blood_results/blood_results_rft_form.py +60 -3
- meta_subject/forms/delivery_form.py +2 -0
- 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.1.dist-info}/licenses/AUTHORS.rst +0 -0
- {meta_edc-1.0.7.dist-info → meta_edc-1.1.1.dist-info}/licenses/LICENSE +0 -0
- {meta_edc-1.0.7.dist-info → meta_edc-1.1.1.dist-info}/top_level.txt +0 -0
@@ -2,10 +2,10 @@
|
|
2
2
|
"cells": [
|
3
3
|
{
|
4
4
|
"cell_type": "code",
|
5
|
-
"
|
6
|
-
"
|
7
|
-
|
8
|
-
|
5
|
+
"execution_count": null,
|
6
|
+
"id": "0",
|
7
|
+
"metadata": {},
|
8
|
+
"outputs": [],
|
9
9
|
"source": [
|
10
10
|
"%%capture\n",
|
11
11
|
"import os\n",
|
@@ -13,20 +13,20 @@
|
|
13
13
|
"import pandas as pd\n",
|
14
14
|
"from dj_notebook import activate\n",
|
15
15
|
"import numpy as np\n",
|
16
|
-
"from django_pandas.io import read_frame\n",
|
17
16
|
"\n",
|
18
17
|
"env_file = os.environ[\"META_ENV\"]\n",
|
19
18
|
"reports_folder = Path(os.environ[\"META_REPORTS_FOLDER\"])\n",
|
20
19
|
"analysis_folder = Path(os.environ[\"META_ANALYSIS_FOLDER\"])\n",
|
21
20
|
"pharmacy_folder = Path(os.environ[\"META_PHARMACY_FOLDER\"])\n",
|
22
21
|
"plus = activate(dotenv_file=env_file)"
|
23
|
-
]
|
24
|
-
"outputs": [],
|
25
|
-
"execution_count": null
|
22
|
+
]
|
26
23
|
},
|
27
24
|
{
|
28
|
-
"metadata": {},
|
29
25
|
"cell_type": "code",
|
26
|
+
"execution_count": null,
|
27
|
+
"id": "1",
|
28
|
+
"metadata": {},
|
29
|
+
"outputs": [],
|
30
30
|
"source": [
|
31
31
|
"from edc_pharmacy.analytics.dataframes import no_stock_for_subjects_df\n",
|
32
32
|
"from datetime import datetime\n",
|
@@ -46,15 +46,85 @@
|
|
46
46
|
"from edc_visit_schedule.site_visit_schedules import site_visit_schedules\n",
|
47
47
|
"from edc_pharmacy.models import Container\n",
|
48
48
|
"from great_tables import GT, html, loc, style\n",
|
49
|
-
"from PIL import Image\n"
|
50
|
-
|
51
|
-
|
49
|
+
"from PIL import Image\n",
|
50
|
+
"from edc_pdutils.dataframes.get_subject_visit import convert_visit_code_to_float\n"
|
51
|
+
]
|
52
|
+
},
|
53
|
+
{
|
54
|
+
"cell_type": "code",
|
55
|
+
"execution_count": null,
|
56
|
+
"id": "2",
|
57
|
+
"metadata": {},
|
52
58
|
"outputs": [],
|
53
|
-
"
|
59
|
+
"source": [
|
60
|
+
"from edc_model_to_dataframe import read_frame_edc\n",
|
61
|
+
"from meta_subject.models import FollowupExamination\n",
|
62
|
+
"\n",
|
63
|
+
"df = read_frame_edc(FollowupExamination.objects.all(), drop_sys_columns=True, drop_action_item_columns=True)\n",
|
64
|
+
"df = df.replace(\"none\", pd.NA)\n",
|
65
|
+
"df = df.replace(\"none\", pd.NA)\n",
|
66
|
+
"df = df.fillna(pd.NA)\n",
|
67
|
+
"convert_visit_code_to_float(df)"
|
68
|
+
]
|
54
69
|
},
|
55
70
|
{
|
71
|
+
"cell_type": "code",
|
72
|
+
"execution_count": null,
|
73
|
+
"id": "3",
|
56
74
|
"metadata": {},
|
75
|
+
"outputs": [],
|
76
|
+
"source": [
|
77
|
+
"from edc_analytics.stata import get_stata_labels_from_model\n",
|
78
|
+
"\n",
|
79
|
+
"df = df[[\"subject_identifier\", \"subject_visit_id\", \"report_datetime\", \"visit_code\", \"site_id\", \"site_name\", \"visit_reason\", \"symptoms\",\"symptoms_detail\", \"symptoms_sought_care\", \"symptoms_g3\", \"symptoms_g4\", \"comment\"]].copy().reset_index(drop=True)\n",
|
80
|
+
"\n",
|
81
|
+
"df = df.astype(\n",
|
82
|
+
" {col: \"Float64\" for col in df.select_dtypes(include=[\"float\", \"float64\"]).columns}\n",
|
83
|
+
")\n",
|
84
|
+
"df_meds = df.astype(\n",
|
85
|
+
" {col: \"Int64\" for col in df.select_dtypes(include=[\"int\", \"int64\"]).columns}\n",
|
86
|
+
")\n",
|
87
|
+
"df = df.astype(\n",
|
88
|
+
" {\n",
|
89
|
+
" col: \"datetime64[ns]\"\n",
|
90
|
+
" for col in df.select_dtypes(include=[\"datetime\", \"datetime64\"]).columns\n",
|
91
|
+
" }\n",
|
92
|
+
")\n",
|
93
|
+
"df = df.astype(\n",
|
94
|
+
" {\n",
|
95
|
+
" col: str\n",
|
96
|
+
" for col in df.select_dtypes(include=[\"object\"]).columns\n",
|
97
|
+
" }\n",
|
98
|
+
")\n",
|
99
|
+
"df = df.fillna(pd.NA)\n",
|
100
|
+
"\n",
|
101
|
+
"variable_labels = {}\n",
|
102
|
+
"variable_labels.update(**get_stata_labels_from_model(df, model=\"meta_subject.followupexamination\", suffix=None))\n",
|
103
|
+
"\n",
|
104
|
+
"df.to_stata(\n",
|
105
|
+
" path=analysis_folder / \"followupexamination.dta\",\n",
|
106
|
+
" variable_labels=variable_labels,\n",
|
107
|
+
" version=118,\n",
|
108
|
+
" write_index=False,\n",
|
109
|
+
")"
|
110
|
+
]
|
111
|
+
},
|
112
|
+
{
|
57
113
|
"cell_type": "code",
|
114
|
+
"execution_count": null,
|
115
|
+
"id": "4",
|
116
|
+
"metadata": {},
|
117
|
+
"outputs": [],
|
118
|
+
"source": [
|
119
|
+
"df"
|
120
|
+
]
|
121
|
+
},
|
122
|
+
{
|
123
|
+
"cell_type": "code",
|
124
|
+
"execution_count": null,
|
125
|
+
"id": "5",
|
126
|
+
"metadata": {},
|
127
|
+
"outputs": [],
|
58
128
|
"source": [
|
59
129
|
"\n",
|
60
130
|
"def get_great_table(df:pd.DataFrame, title:str, footnote:str|None=None):\n",
|
@@ -90,51 +160,61 @@
|
|
90
160
|
"\n",
|
91
161
|
"\n",
|
92
162
|
" )\n"
|
93
|
-
]
|
94
|
-
"id": "6d4f230107499268",
|
95
|
-
"outputs": [],
|
96
|
-
"execution_count": null
|
163
|
+
]
|
97
164
|
},
|
98
165
|
{
|
166
|
+
"cell_type": "code",
|
167
|
+
"execution_count": null,
|
168
|
+
"id": "6",
|
99
169
|
"metadata": {},
|
170
|
+
"outputs": [],
|
171
|
+
"source": [
|
172
|
+
"start_from_appt_date = datetime(2025,5,15)"
|
173
|
+
]
|
174
|
+
},
|
175
|
+
{
|
100
176
|
"cell_type": "code",
|
177
|
+
"execution_count": null,
|
178
|
+
"id": "7",
|
179
|
+
"metadata": {},
|
180
|
+
"outputs": [],
|
101
181
|
"source": [
|
102
182
|
"# get rando\n",
|
103
183
|
"df_rando = read_frame(RandomizationList.objects.values(\"subject_identifier\", \"assignment\").filter(subject_identifier__isnull=False))"
|
104
|
-
]
|
105
|
-
"id": "1a5c145dc73ae1ca",
|
106
|
-
"outputs": [],
|
107
|
-
"execution_count": null
|
184
|
+
]
|
108
185
|
},
|
109
186
|
{
|
110
|
-
"metadata": {},
|
111
187
|
"cell_type": "code",
|
188
|
+
"execution_count": null,
|
189
|
+
"id": "8",
|
190
|
+
"metadata": {},
|
191
|
+
"outputs": [],
|
112
192
|
"source": [
|
113
193
|
"# get appointments\n",
|
114
194
|
"df_appt = get_appointment_df()\n",
|
115
|
-
"print(f\"{len(df_appt[(df_appt.appt_status==NEW_APPT) & (df_appt.appt_datetime >=
|
116
|
-
]
|
117
|
-
"id": "c0f532dc5f20aef6",
|
118
|
-
"outputs": [],
|
119
|
-
"execution_count": null
|
195
|
+
"print(f\"{len(df_appt[(df_appt.appt_status==NEW_APPT) & (df_appt.appt_datetime >= start_from_appt_date) & (df_appt.appt_datetime < datetime(2026,3,1)) & (df_appt.visit_code!=1480.0)])} appointments after filtering\")"
|
196
|
+
]
|
120
197
|
},
|
121
198
|
{
|
122
|
-
"metadata": {},
|
123
199
|
"cell_type": "code",
|
200
|
+
"execution_count": null,
|
201
|
+
"id": "9",
|
202
|
+
"metadata": {},
|
203
|
+
"outputs": [],
|
124
204
|
"source": [
|
125
205
|
"# create a dataframe of subjects still on the 'schedule' schedule\n",
|
126
206
|
"# use SubjectScheduleHistory where offschedule_datetime is null\n",
|
127
207
|
"df_subject_schedule = read_frame(SubjectScheduleHistory.objects.values(\"subject_identifier\", \"visit_schedule_name\", \"schedule_name\", \"onschedule_datetime\", \"offschedule_datetime\").filter(offschedule_datetime__isnull=True, schedule_name=\"schedule\"))\n",
|
128
208
|
"\n",
|
129
209
|
"print(f\"{len(df_subject_schedule)} subjects currently onstudy\")"
|
130
|
-
]
|
131
|
-
"id": "dd5fd238c0160518",
|
132
|
-
"outputs": [],
|
133
|
-
"execution_count": null
|
210
|
+
]
|
134
211
|
},
|
135
212
|
{
|
136
|
-
"metadata": {},
|
137
213
|
"cell_type": "code",
|
214
|
+
"execution_count": null,
|
215
|
+
"id": "10",
|
216
|
+
"metadata": {},
|
217
|
+
"outputs": [],
|
138
218
|
"source": [
|
139
219
|
"# for now merge with the unfiltered df_appt\n",
|
140
220
|
"df_main = df_subject_schedule.merge(\n",
|
@@ -150,39 +230,41 @@
|
|
150
230
|
" (df_main.appt_status==NEW_APPT)\n",
|
151
231
|
"].copy()\n",
|
152
232
|
"print(f\"{len(df_main)} new appointments for subjects on study\")\n"
|
153
|
-
]
|
154
|
-
"id": "13739396761c72c",
|
155
|
-
"outputs": [],
|
156
|
-
"execution_count": null
|
233
|
+
]
|
157
234
|
},
|
158
235
|
{
|
159
|
-
"metadata": {},
|
160
236
|
"cell_type": "code",
|
237
|
+
"execution_count": null,
|
238
|
+
"id": "11",
|
239
|
+
"metadata": {},
|
240
|
+
"outputs": [],
|
161
241
|
"source": [
|
162
242
|
"# number of appointments before extended all subjects out to 48m\n",
|
163
243
|
"df_grouped = df_main[\n",
|
164
|
-
" (df_main.appt_datetime >=
|
244
|
+
" (df_main.appt_datetime >= start_from_appt_date) &\n",
|
165
245
|
" (df_main.appt_datetime < datetime(2026,3,1)) &\n",
|
166
246
|
" (df_main.visit_code!=1480.0)\n",
|
167
247
|
"].visit_code.value_counts().reset_index(name=\"appointments\").sort_values(by=\"visit_code\", ascending=True).reset_index(drop=True)\n",
|
168
248
|
"df_grouped[\"cumsum\"] = df_grouped.appointments.cumsum()\n",
|
169
249
|
"df_grouped[\"cumsum\"].max()\n"
|
170
|
-
]
|
171
|
-
"id": "fdf65539dce9fc30",
|
172
|
-
"outputs": [],
|
173
|
-
"execution_count": null
|
250
|
+
]
|
174
251
|
},
|
175
252
|
{
|
176
|
-
"metadata": {},
|
177
253
|
"cell_type": "code",
|
178
|
-
"
|
179
|
-
"id": "
|
254
|
+
"execution_count": null,
|
255
|
+
"id": "12",
|
256
|
+
"metadata": {},
|
180
257
|
"outputs": [],
|
181
|
-
"
|
258
|
+
"source": [
|
259
|
+
"df_main"
|
260
|
+
]
|
182
261
|
},
|
183
262
|
{
|
184
|
-
"metadata": {},
|
185
263
|
"cell_type": "code",
|
264
|
+
"execution_count": null,
|
265
|
+
"id": "13",
|
266
|
+
"metadata": {},
|
267
|
+
"outputs": [],
|
186
268
|
"source": [
|
187
269
|
"# now extend everyone to 48 months.\n",
|
188
270
|
"# Subjects are in the process of consenting for extended\n",
|
@@ -212,34 +294,36 @@
|
|
212
294
|
"# merge df_main back in\n",
|
213
295
|
"df_pivot = df_pivot.merge(df_main[[\"subject_identifier\", \"visit_code\", \"appt_datetime\", \"appt_status\"]], on=[\"subject_identifier\",\"visit_code\"], how=\"left\")\n",
|
214
296
|
"df_pivot"
|
215
|
-
]
|
216
|
-
"id": "9bd1bf18017c18f2",
|
217
|
-
"outputs": [],
|
218
|
-
"execution_count": null
|
297
|
+
]
|
219
298
|
},
|
220
299
|
{
|
221
|
-
"metadata": {},
|
222
300
|
"cell_type": "code",
|
223
|
-
"
|
224
|
-
"id": "
|
301
|
+
"execution_count": null,
|
302
|
+
"id": "14",
|
303
|
+
"metadata": {},
|
225
304
|
"outputs": [],
|
226
|
-
"
|
305
|
+
"source": [
|
306
|
+
"# len(df_pivot[(df_pivot.appt_datetime>=datetime(2025,1,1)) & (df_pivot.visit_code==MONTH48)])/3"
|
307
|
+
]
|
227
308
|
},
|
228
309
|
{
|
229
|
-
"metadata": {},
|
230
310
|
"cell_type": "code",
|
311
|
+
"execution_count": null,
|
312
|
+
"id": "15",
|
313
|
+
"metadata": {},
|
314
|
+
"outputs": [],
|
231
315
|
"source": [
|
232
316
|
"# extend no one!\n",
|
233
317
|
"# df_pivot = df_pivot[df_pivot.exists==1].copy()\n",
|
234
318
|
"# df_pivot.reset_index(drop=True, inplace=True)\n"
|
235
|
-
]
|
236
|
-
"id": "1e3098273f43e6b2",
|
237
|
-
"outputs": [],
|
238
|
-
"execution_count": null
|
319
|
+
]
|
239
320
|
},
|
240
321
|
{
|
241
|
-
"metadata": {},
|
242
322
|
"cell_type": "code",
|
323
|
+
"execution_count": null,
|
324
|
+
"id": "16",
|
325
|
+
"metadata": {},
|
326
|
+
"outputs": [],
|
243
327
|
"source": [
|
244
328
|
"# add appointments do not have an appt_datetime, so calculate\n",
|
245
329
|
"# using the visit schedule relative to baseline_datetime\n",
|
@@ -264,14 +348,14 @@
|
|
264
348
|
"df_pivot.loc[df_pivot.exists==0.0, \"appt_status\"] = NEW_APPT\n",
|
265
349
|
"\n",
|
266
350
|
"print(f\"{len(df_pivot)} appointments\")"
|
267
|
-
]
|
268
|
-
"id": "7483e4c8e47becc9",
|
269
|
-
"outputs": [],
|
270
|
-
"execution_count": null
|
351
|
+
]
|
271
352
|
},
|
272
353
|
{
|
273
|
-
"metadata": {},
|
274
354
|
"cell_type": "code",
|
355
|
+
"execution_count": null,
|
356
|
+
"id": "17",
|
357
|
+
"metadata": {},
|
358
|
+
"outputs": [],
|
275
359
|
"source": [
|
276
360
|
"# df_subject_appointments is a dataframe of appointments\n",
|
277
361
|
"# - only include NEW appointments\n",
|
@@ -280,51 +364,53 @@
|
|
280
364
|
"cutoff_date = datetime(2026,3,1)\n",
|
281
365
|
"df_subject_appointments = df_pivot[\n",
|
282
366
|
" (df_pivot.appt_status==NEW_APPT) &\n",
|
283
|
-
" (df_pivot.appt_datetime >=
|
367
|
+
" (df_pivot.appt_datetime >= start_from_appt_date) &\n",
|
284
368
|
" (df_pivot.appt_datetime < cutoff_date) &\n",
|
285
369
|
" (df_pivot.visit_code!=1480.0)\n",
|
286
370
|
"].copy()\n",
|
287
371
|
"print(f\"{len(df_subject_appointments)} appointments\")"
|
288
|
-
]
|
289
|
-
"id": "12f04c24f098e88f",
|
290
|
-
"outputs": [],
|
291
|
-
"execution_count": null
|
372
|
+
]
|
292
373
|
},
|
293
374
|
{
|
294
|
-
"metadata": {},
|
295
375
|
"cell_type": "code",
|
376
|
+
"execution_count": null,
|
377
|
+
"id": "18",
|
378
|
+
"metadata": {},
|
379
|
+
"outputs": [],
|
296
380
|
"source": [
|
297
381
|
"n = df_subject_appointments.subject_identifier.nunique()\n",
|
298
382
|
"print(f\"{n} subjects\")\n"
|
299
|
-
]
|
300
|
-
"id": "c32531751a339390",
|
301
|
-
"outputs": [],
|
302
|
-
"execution_count": null
|
383
|
+
]
|
303
384
|
},
|
304
385
|
{
|
305
|
-
"metadata": {},
|
306
386
|
"cell_type": "code",
|
307
|
-
"
|
308
|
-
"id": "
|
387
|
+
"execution_count": null,
|
388
|
+
"id": "19",
|
389
|
+
"metadata": {},
|
309
390
|
"outputs": [],
|
310
|
-
"
|
391
|
+
"source": [
|
392
|
+
"(len(df_subject_appointments[df_subject_appointments.appt_datetime>=datetime(2026,1,1)])/36)/5"
|
393
|
+
]
|
311
394
|
},
|
312
395
|
{
|
313
|
-
"metadata": {},
|
314
396
|
"cell_type": "code",
|
397
|
+
"execution_count": null,
|
398
|
+
"id": "20",
|
399
|
+
"metadata": {},
|
400
|
+
"outputs": [],
|
315
401
|
"source": [
|
316
402
|
"# summarize the appointments\n",
|
317
403
|
"df_summary = df_subject_appointments.visit_code.value_counts().reset_index(name=\"appointments\").sort_values(by=[\"visit_code\"], ascending=True)\n",
|
318
404
|
"df_summary[\"cumsum\"] = df_summary.appointments.cumsum()\n",
|
319
405
|
"df_summary"
|
320
|
-
]
|
321
|
-
"id": "f38ead26da10a1ef",
|
322
|
-
"outputs": [],
|
323
|
-
"execution_count": null
|
406
|
+
]
|
324
407
|
},
|
325
408
|
{
|
326
|
-
"metadata": {},
|
327
409
|
"cell_type": "code",
|
410
|
+
"execution_count": null,
|
411
|
+
"id": "21",
|
412
|
+
"metadata": {},
|
413
|
+
"outputs": [],
|
328
414
|
"source": [
|
329
415
|
"df = df_subject_appointments.assignment.value_counts(dropna=False).reset_index()\n",
|
330
416
|
"df.rename(columns={\"count\":\"appointments\"}, inplace=True)\n",
|
@@ -335,18 +421,18 @@
|
|
335
421
|
"# filter\n",
|
336
422
|
"df.loc[len(df)] = {\"appointments\": df.appointments.sum(), \"bottles\": df.bottles.sum(), \"tablets\": df.tablets.sum()}\n",
|
337
423
|
"df"
|
338
|
-
]
|
339
|
-
"id": "b6a56657d02b04ac",
|
340
|
-
"outputs": [],
|
341
|
-
"execution_count": null
|
424
|
+
]
|
342
425
|
},
|
343
426
|
{
|
344
|
-
"metadata": {},
|
345
427
|
"cell_type": "code",
|
428
|
+
"execution_count": null,
|
429
|
+
"id": "22",
|
430
|
+
"metadata": {},
|
431
|
+
"outputs": [],
|
346
432
|
"source": [
|
347
433
|
"gt = get_great_table(\n",
|
348
434
|
" df,\n",
|
349
|
-
" \"Table 1: IMP Bottles of 128 needed<BR><small>as of 2025-
|
435
|
+
" \"Table 1: IMP Bottles of 128 needed<BR><small>as of 2025-05-15</small>\",\n",
|
350
436
|
" footnote=(\n",
|
351
437
|
" \"<ol>\"\n",
|
352
438
|
" \"<li>assume all participants consent for extended followup.\"\n",
|
@@ -356,14 +442,14 @@
|
|
356
442
|
" \"</ol>\"\n",
|
357
443
|
" ))\n",
|
358
444
|
"gt.show()"
|
359
|
-
]
|
360
|
-
"id": "f9bffc9c05c7fd41",
|
361
|
-
"outputs": [],
|
362
|
-
"execution_count": null
|
445
|
+
]
|
363
446
|
},
|
364
447
|
{
|
365
|
-
"metadata": {},
|
366
448
|
"cell_type": "code",
|
449
|
+
"execution_count": null,
|
450
|
+
"id": "23",
|
451
|
+
"metadata": {},
|
452
|
+
"outputs": [],
|
367
453
|
"source": [
|
368
454
|
"\n",
|
369
455
|
"# save as png\n",
|
@@ -372,14 +458,14 @@
|
|
372
458
|
"image = Image.open(analysis_folder / \"pharmacy_tbl1.png\")\n",
|
373
459
|
"image = image.resize((image.width * 6, image.height * 6), Image.LANCZOS)\n",
|
374
460
|
"image.save(analysis_folder / \"pharmacy_tbl1.pdf\", \"PDF\", resolution=800, optimize=True, quality=95)"
|
375
|
-
]
|
376
|
-
"id": "53247d65d251bebb",
|
377
|
-
"outputs": [],
|
378
|
-
"execution_count": null
|
461
|
+
]
|
379
462
|
},
|
380
463
|
{
|
381
|
-
"metadata": {},
|
382
464
|
"cell_type": "code",
|
465
|
+
"execution_count": null,
|
466
|
+
"id": "24",
|
467
|
+
"metadata": {},
|
468
|
+
"outputs": [],
|
383
469
|
"source": [
|
384
470
|
"# now lets look at the stock\n",
|
385
471
|
"df_stock = read_frame(Stock.objects.values(\"code\", \"lot_id\", \"container__name\", \"confirmed\", \"allocated\", \"dispensed\", \"qty_in\", \"qty_out\", \"unit_qty_in\", \"unit_qty_out\").all(), verbose=False)\n",
|
@@ -390,14 +476,14 @@
|
|
390
476
|
"df_stock = df_stock.merge(df_lot[[\"lot_id\", \"assignment\"]], on=\"lot_id\", how=\"left\")\n",
|
391
477
|
"df_stock.rename(columns={\"container__name\":\"container\"}, inplace=True)\n",
|
392
478
|
"df_stock.reset_index(drop=True, inplace=True)"
|
393
|
-
]
|
394
|
-
"id": "6d280a4eeac931a0",
|
395
|
-
"outputs": [],
|
396
|
-
"execution_count": null
|
479
|
+
]
|
397
480
|
},
|
398
481
|
{
|
399
|
-
"metadata": {},
|
400
482
|
"cell_type": "code",
|
483
|
+
"execution_count": null,
|
484
|
+
"id": "25",
|
485
|
+
"metadata": {},
|
486
|
+
"outputs": [],
|
401
487
|
"source": [
|
402
488
|
"# merge in container columns\n",
|
403
489
|
"df_container = read_frame(Container.objects.all())\n",
|
@@ -407,60 +493,64 @@
|
|
407
493
|
"\n",
|
408
494
|
"# calculate bal\n",
|
409
495
|
"df_stock[\"bal\"] = df_stock[\"unit_qty_in\"] - df_stock[\"unit_qty_out\"]\n"
|
410
|
-
]
|
411
|
-
"id": "a11c4b67752b965d",
|
412
|
-
"outputs": [],
|
413
|
-
"execution_count": null
|
496
|
+
]
|
414
497
|
},
|
415
498
|
{
|
416
|
-
"metadata": {},
|
417
499
|
"cell_type": "code",
|
500
|
+
"execution_count": null,
|
501
|
+
"id": "26",
|
502
|
+
"metadata": {},
|
503
|
+
"outputs": [],
|
418
504
|
"source": [
|
419
505
|
"# show the balance of tablets decanted to bottles by assignment (on the EDC)\n",
|
420
506
|
"df2 = df_stock[df_stock.container_display_name==\"Bottle 128\"].groupby(by=[\"assignment\"]).bal.agg(\"sum\").reset_index()\n",
|
421
507
|
"df2.loc[len(df2)] = {\"bal\": df2.bal.sum()}\n",
|
422
508
|
"df2"
|
423
|
-
]
|
424
|
-
"id": "7e275d7fb827535b",
|
425
|
-
"outputs": [],
|
426
|
-
"execution_count": null
|
509
|
+
]
|
427
510
|
},
|
428
511
|
{
|
429
|
-
"metadata": {},
|
430
512
|
"cell_type": "code",
|
513
|
+
"execution_count": null,
|
514
|
+
"id": "27",
|
515
|
+
"metadata": {},
|
516
|
+
"outputs": [],
|
431
517
|
"source": [
|
432
518
|
"# some bottles, as of today, have not been captured in the system\n",
|
433
519
|
"# here is an estimate of what has been decanted into bottles but not labelled.\n",
|
434
520
|
"# in the system, these tablets would appear on the EDC as still in buckets\n",
|
435
521
|
"df3 = df2.copy()\n",
|
436
522
|
"df3 = df3.drop(len(df3) - 1)\n",
|
437
|
-
"placebo_unlabelled = 21*128*128\n",
|
438
|
-
"active_unlabelled = 25*191*128\n",
|
523
|
+
"placebo_unlabelled = 0 # 21*128*128\n",
|
524
|
+
"active_unlabelled = 0 # 25*191*128\n",
|
439
525
|
"\n",
|
440
526
|
"# adding in the estimates, this is about what we have bottled\n",
|
441
527
|
"df3.loc[df3.assignment==\"placebo\", \"bal\"] += placebo_unlabelled\n",
|
442
528
|
"df3.loc[df3.assignment==\"active\", \"bal\"] += active_unlabelled\n",
|
443
529
|
"df3.loc[len(df3)] = {\"bal\": df3.bal.sum()}\n",
|
444
530
|
"df3"
|
445
|
-
]
|
446
|
-
"id": "1d7134fe05417475",
|
447
|
-
"outputs": [],
|
448
|
-
"execution_count": null
|
531
|
+
]
|
449
532
|
},
|
450
533
|
{
|
451
|
-
"metadata": {},
|
452
534
|
"cell_type": "code",
|
535
|
+
"execution_count": null,
|
536
|
+
"id": "28",
|
537
|
+
"metadata": {},
|
538
|
+
"outputs": [],
|
453
539
|
"source": [
|
454
|
-
"gt = get_great_table(
|
540
|
+
"gt = get_great_table(\n",
|
541
|
+
" df3,\n",
|
542
|
+
" \"Table 2: IMP tablets in stock<BR><small>as of 2025-04-04</small>\",\n",
|
543
|
+
" # footnote=\"Includes recently decanted but unlabelled bottles\"\n",
|
544
|
+
" )\n",
|
455
545
|
"gt.show()"
|
456
|
-
]
|
457
|
-
"id": "7ab587c2d36d2e10",
|
458
|
-
"outputs": [],
|
459
|
-
"execution_count": null
|
546
|
+
]
|
460
547
|
},
|
461
548
|
{
|
462
|
-
"metadata": {},
|
463
549
|
"cell_type": "code",
|
550
|
+
"execution_count": null,
|
551
|
+
"id": "29",
|
552
|
+
"metadata": {},
|
553
|
+
"outputs": [],
|
464
554
|
"source": [
|
465
555
|
"# save as png\n",
|
466
556
|
"gt.save(analysis_folder / \"pharmacy_tbl2.png\")\n",
|
@@ -468,71 +558,71 @@
|
|
468
558
|
"image = Image.open(analysis_folder / \"pharmacy_tbl2.png\")\n",
|
469
559
|
"image = image.resize((image.width * 6, image.height * 6), Image.LANCZOS)\n",
|
470
560
|
"image.save(analysis_folder / \"pharmacy_tbl2.pdf\", \"PDF\", resolution=800, optimize=True, quality=95)"
|
471
|
-
]
|
472
|
-
"id": "68374d9f02546d6f",
|
473
|
-
"outputs": [],
|
474
|
-
"execution_count": null
|
561
|
+
]
|
475
562
|
},
|
476
563
|
{
|
477
|
-
"metadata": {},
|
478
564
|
"cell_type": "code",
|
565
|
+
"execution_count": null,
|
566
|
+
"id": "30",
|
567
|
+
"metadata": {},
|
568
|
+
"outputs": [],
|
479
569
|
"source": [
|
480
570
|
"# tablets: ordered\n",
|
481
571
|
"df_orderitems = read_frame(OrderItem.objects.all())\n",
|
482
572
|
"df_orderitems.qty.sum()"
|
483
|
-
]
|
484
|
-
"id": "9b67d6799735e116",
|
485
|
-
"outputs": [],
|
486
|
-
"execution_count": null
|
573
|
+
]
|
487
574
|
},
|
488
575
|
{
|
489
|
-
"metadata": {},
|
490
576
|
"cell_type": "code",
|
577
|
+
"execution_count": null,
|
578
|
+
"id": "31",
|
579
|
+
"metadata": {},
|
580
|
+
"outputs": [],
|
491
581
|
"source": [
|
492
582
|
"# tablets: received\n",
|
493
583
|
"df_received_items = read_frame(ReceiveItem.objects.all())\n",
|
494
584
|
"df_received_items.unit_qty.sum()"
|
495
|
-
]
|
496
|
-
"id": "af0868a54913329",
|
497
|
-
"outputs": [],
|
498
|
-
"execution_count": null
|
585
|
+
]
|
499
586
|
},
|
500
587
|
{
|
501
|
-
"metadata": {},
|
502
588
|
"cell_type": "code",
|
589
|
+
"execution_count": null,
|
590
|
+
"id": "32",
|
591
|
+
"metadata": {},
|
592
|
+
"outputs": [],
|
503
593
|
"source": [
|
504
594
|
"# tablets: received into stock\n",
|
505
595
|
"df_stock[df_stock.container_type==\"bucket\"].unit_qty_in.sum()"
|
506
|
-
]
|
507
|
-
"id": "82b0df34b49377f0",
|
508
|
-
"outputs": [],
|
509
|
-
"execution_count": null
|
596
|
+
]
|
510
597
|
},
|
511
598
|
{
|
512
|
-
"metadata": {},
|
513
599
|
"cell_type": "code",
|
600
|
+
"execution_count": null,
|
601
|
+
"id": "33",
|
602
|
+
"metadata": {},
|
603
|
+
"outputs": [],
|
514
604
|
"source": [
|
515
605
|
"# tablets: decanted from buckets into bottles\n",
|
516
606
|
"df_stock[df_stock.container_type==\"bucket\"].unit_qty_out.sum()"
|
517
|
-
]
|
518
|
-
"id": "1d1383219f8fd0a4",
|
519
|
-
"outputs": [],
|
520
|
-
"execution_count": null
|
607
|
+
]
|
521
608
|
},
|
522
609
|
{
|
523
|
-
"metadata": {},
|
524
610
|
"cell_type": "code",
|
611
|
+
"execution_count": null,
|
612
|
+
"id": "34",
|
613
|
+
"metadata": {},
|
614
|
+
"outputs": [],
|
525
615
|
"source": [
|
526
616
|
"# tablets: total in bottles\n",
|
527
617
|
"df_stock[df_stock.container_type==\"Bottle\"].unit_qty_in.sum()"
|
528
|
-
]
|
529
|
-
"id": "d928f610d5427f39",
|
530
|
-
"outputs": [],
|
531
|
-
"execution_count": null
|
618
|
+
]
|
532
619
|
},
|
533
620
|
{
|
534
|
-
"metadata": {},
|
535
621
|
"cell_type": "code",
|
622
|
+
"execution_count": null,
|
623
|
+
"id": "35",
|
624
|
+
"metadata": {},
|
625
|
+
"outputs": [],
|
536
626
|
"source": [
|
537
627
|
"# tablets: total bottles available / not yet dispensed BY ASSIGNMENT\n",
|
538
628
|
"# the total matches the total above for column \"bal\"\n",
|
@@ -554,50 +644,50 @@
|
|
554
644
|
"df6.loc[len(df6)] = {\"total\": df6.subtotal.sum()}\n",
|
555
645
|
"df6 = df6[[\"dispensed\", \"assignment\", \"unit_qty_in\", \"subtotal\", \"total\"]]\n",
|
556
646
|
"df6"
|
557
|
-
]
|
558
|
-
"id": "6600690d6e88a1b2",
|
559
|
-
"outputs": [],
|
560
|
-
"execution_count": null
|
647
|
+
]
|
561
648
|
},
|
562
649
|
{
|
563
|
-
"metadata": {},
|
564
650
|
"cell_type": "code",
|
565
|
-
"
|
566
|
-
"id": "
|
651
|
+
"execution_count": null,
|
652
|
+
"id": "36",
|
653
|
+
"metadata": {},
|
567
654
|
"outputs": [],
|
568
|
-
"
|
655
|
+
"source": []
|
569
656
|
},
|
570
657
|
{
|
571
|
-
"metadata": {},
|
572
658
|
"cell_type": "code",
|
573
|
-
"
|
574
|
-
"id": "
|
659
|
+
"execution_count": null,
|
660
|
+
"id": "37",
|
661
|
+
"metadata": {},
|
575
662
|
"outputs": [],
|
576
|
-
"
|
663
|
+
"source": []
|
577
664
|
},
|
578
665
|
{
|
579
|
-
"metadata": {},
|
580
666
|
"cell_type": "code",
|
581
|
-
"
|
582
|
-
"id": "
|
667
|
+
"execution_count": null,
|
668
|
+
"id": "38",
|
669
|
+
"metadata": {},
|
583
670
|
"outputs": [],
|
584
|
-
"
|
671
|
+
"source": []
|
585
672
|
},
|
586
673
|
{
|
587
|
-
"metadata": {},
|
588
674
|
"cell_type": "code",
|
675
|
+
"execution_count": null,
|
676
|
+
"id": "39",
|
677
|
+
"metadata": {},
|
678
|
+
"outputs": [],
|
589
679
|
"source": [
|
590
680
|
"from meta_visit_schedule.constants import MONTH36\n",
|
591
681
|
"\n",
|
592
682
|
"df_appt[(df_appt.visit_code_str==MONTH36) & (df_appt.appt_datetime >= datetime(2024,12,15)) & (df_appt.appt_status==NEW_APPT) & (df_appt.appt_datetime <= datetime(2026,2,28))]"
|
593
|
-
]
|
594
|
-
"id": "49a7b405b7973ae3",
|
595
|
-
"outputs": [],
|
596
|
-
"execution_count": null
|
683
|
+
]
|
597
684
|
},
|
598
685
|
{
|
599
|
-
"metadata": {},
|
600
686
|
"cell_type": "code",
|
687
|
+
"execution_count": null,
|
688
|
+
"id": "40",
|
689
|
+
"metadata": {},
|
690
|
+
"outputs": [],
|
601
691
|
"source": [
|
602
692
|
"def remove_subjects_where_stock_on_site(stock_request: StockRequest, df: pd.DataFrame):\n",
|
603
693
|
" stock_model_cls = django_apps.get_model(\"edc_pharmacy.Stock\")\n",
|
@@ -629,14 +719,14 @@
|
|
629
719
|
" df[\"stock_qty\"] = 0.0\n",
|
630
720
|
" df = df.reset_index(drop=True)\n",
|
631
721
|
" return df\n"
|
632
|
-
]
|
633
|
-
"id": "491b43957fe1c756",
|
634
|
-
"outputs": [],
|
635
|
-
"execution_count": null
|
722
|
+
]
|
636
723
|
},
|
637
724
|
{
|
638
|
-
"metadata": {},
|
639
725
|
"cell_type": "code",
|
726
|
+
"execution_count": null,
|
727
|
+
"id": "41",
|
728
|
+
"metadata": {},
|
729
|
+
"outputs": [],
|
640
730
|
"source": [
|
641
731
|
"def pad_with_null_rows(df, qty_needed):\n",
|
642
732
|
" padded_data = []\n",
|
@@ -649,44 +739,44 @@
|
|
649
739
|
" for product in products:\n",
|
650
740
|
" padded_data.append({'customer': customer, 'product_code': product})\n",
|
651
741
|
" return pd.DataFrame(padded_data)"
|
652
|
-
]
|
653
|
-
"id": "14fd36a1e0e158b9",
|
654
|
-
"outputs": [],
|
655
|
-
"execution_count": null
|
742
|
+
]
|
656
743
|
},
|
657
744
|
{
|
658
|
-
"metadata": {},
|
659
745
|
"cell_type": "code",
|
746
|
+
"execution_count": null,
|
747
|
+
"id": "42",
|
748
|
+
"metadata": {},
|
749
|
+
"outputs": [],
|
660
750
|
"source": [
|
661
751
|
"pk = \"5455cf66-b8e5-449c-a1e8-24d3325026d7\"\n",
|
662
752
|
"stock_request = StockRequest.objects.get(pk=pk)\n"
|
663
|
-
]
|
664
|
-
"id": "ee9423599bad2c6f",
|
665
|
-
"outputs": [],
|
666
|
-
"execution_count": null
|
753
|
+
]
|
667
754
|
},
|
668
755
|
{
|
669
|
-
"metadata": {},
|
670
756
|
"cell_type": "code",
|
757
|
+
"execution_count": null,
|
758
|
+
"id": "43",
|
759
|
+
"metadata": {},
|
760
|
+
"outputs": [],
|
671
761
|
"source": [
|
672
762
|
"df_subjects = get_next_scheduled_visit_for_subjects_df(stock_request)\n",
|
673
763
|
"df_subjects"
|
674
|
-
]
|
675
|
-
"id": "f5b22e507f36170d",
|
676
|
-
"outputs": [],
|
677
|
-
"execution_count": null
|
764
|
+
]
|
678
765
|
},
|
679
766
|
{
|
680
|
-
"metadata": {},
|
681
767
|
"cell_type": "code",
|
682
|
-
"
|
683
|
-
"id": "
|
768
|
+
"execution_count": null,
|
769
|
+
"id": "44",
|
770
|
+
"metadata": {},
|
684
771
|
"outputs": [],
|
685
|
-
"
|
772
|
+
"source": []
|
686
773
|
},
|
687
774
|
{
|
688
|
-
"metadata": {},
|
689
775
|
"cell_type": "code",
|
776
|
+
"execution_count": null,
|
777
|
+
"id": "45",
|
778
|
+
"metadata": {},
|
779
|
+
"outputs": [],
|
690
780
|
"source": [
|
691
781
|
"df = df_subjects.copy()\n",
|
692
782
|
"stock_model_cls = django_apps.get_model(\"edc_pharmacy.Stock\")\n",
|
@@ -705,22 +795,24 @@
|
|
705
795
|
" }\n",
|
706
796
|
")\n",
|
707
797
|
"df_stock"
|
708
|
-
]
|
709
|
-
"id": "164302f67cec31be",
|
710
|
-
"outputs": [],
|
711
|
-
"execution_count": null
|
798
|
+
]
|
712
799
|
},
|
713
800
|
{
|
714
|
-
"metadata": {},
|
715
801
|
"cell_type": "code",
|
716
|
-
"
|
717
|
-
"id": "
|
802
|
+
"execution_count": null,
|
803
|
+
"id": "46",
|
804
|
+
"metadata": {},
|
718
805
|
"outputs": [],
|
719
|
-
"
|
806
|
+
"source": [
|
807
|
+
"df.merge(df_stock, on=\"subject_identifier\", how=\"left\")"
|
808
|
+
]
|
720
809
|
},
|
721
810
|
{
|
722
|
-
"metadata": {},
|
723
811
|
"cell_type": "code",
|
812
|
+
"execution_count": null,
|
813
|
+
"id": "47",
|
814
|
+
"metadata": {},
|
815
|
+
"outputs": [],
|
724
816
|
"source": [
|
725
817
|
"if not df.empty and not df_stock.empty:\n",
|
726
818
|
" df_subject = df.copy()\n",
|
@@ -736,22 +828,24 @@
|
|
736
828
|
"df[\"stock_qty\"] = 0.0\n",
|
737
829
|
"df = df.reset_index(drop=True)\n",
|
738
830
|
"df"
|
739
|
-
]
|
740
|
-
"id": "ba3541a4e2cdfde6",
|
741
|
-
"outputs": [],
|
742
|
-
"execution_count": null
|
831
|
+
]
|
743
832
|
},
|
744
833
|
{
|
745
|
-
"metadata": {},
|
746
834
|
"cell_type": "code",
|
747
|
-
"
|
748
|
-
"id": "
|
835
|
+
"execution_count": null,
|
836
|
+
"id": "48",
|
837
|
+
"metadata": {},
|
749
838
|
"outputs": [],
|
750
|
-
"
|
839
|
+
"source": [
|
840
|
+
"df.loc[df.index.repeat(3)]"
|
841
|
+
]
|
751
842
|
},
|
752
843
|
{
|
753
|
-
"metadata": {},
|
754
844
|
"cell_type": "code",
|
845
|
+
"execution_count": null,
|
846
|
+
"id": "49",
|
847
|
+
"metadata": {},
|
848
|
+
"outputs": [],
|
755
849
|
"source": [
|
756
850
|
"if not df.empty and not df_stock.empty:\n",
|
757
851
|
" df = df.merge(df_stock, on=\"subject_identifier\", how=\"left\")\n",
|
@@ -760,25 +854,25 @@
|
|
760
854
|
"df[\"stock_qty\"] = 0.0\n",
|
761
855
|
"df = df.reset_index(drop=True)\n",
|
762
856
|
"df"
|
763
|
-
]
|
764
|
-
"id": "79507f3726dd23ac",
|
765
|
-
"outputs": [],
|
766
|
-
"execution_count": null
|
857
|
+
]
|
767
858
|
},
|
768
859
|
{
|
769
|
-
"metadata": {},
|
770
860
|
"cell_type": "code",
|
861
|
+
"execution_count": null,
|
862
|
+
"id": "50",
|
863
|
+
"metadata": {},
|
864
|
+
"outputs": [],
|
771
865
|
"source": [
|
772
866
|
"df = remove_subjects_where_stock_on_site(stock_request, df_subjects)\n",
|
773
867
|
"df"
|
774
|
-
]
|
775
|
-
"id": "a23aafeb660d5a9c",
|
776
|
-
"outputs": [],
|
777
|
-
"execution_count": null
|
868
|
+
]
|
778
869
|
},
|
779
870
|
{
|
780
|
-
"metadata": {},
|
781
871
|
"cell_type": "code",
|
872
|
+
"execution_count": null,
|
873
|
+
"id": "51",
|
874
|
+
"metadata": {},
|
875
|
+
"outputs": [],
|
782
876
|
"source": [
|
783
877
|
"df_instock = df[~df.code.isna()]\n",
|
784
878
|
"df_instock = df_instock.reset_index(drop=True)\n",
|
@@ -791,160 +885,165 @@
|
|
791
885
|
"].reset_index(drop=True)\n",
|
792
886
|
"df_nostock = df_nostock.sort_values(by=[\"subject_identifier\"])\n",
|
793
887
|
"df_nostock[\"code\"] = df_nostock[\"code\"].fillna(\"---\")\n"
|
794
|
-
]
|
795
|
-
"id": "f8e386caf276b53e",
|
796
|
-
"outputs": [],
|
797
|
-
"execution_count": null
|
888
|
+
]
|
798
889
|
},
|
799
890
|
{
|
800
|
-
"metadata": {},
|
801
891
|
"cell_type": "code",
|
802
|
-
"
|
803
|
-
"id": "
|
892
|
+
"execution_count": null,
|
893
|
+
"id": "52",
|
894
|
+
"metadata": {},
|
804
895
|
"outputs": [],
|
805
|
-
"
|
896
|
+
"source": []
|
806
897
|
},
|
807
898
|
{
|
808
|
-
"metadata": {},
|
809
899
|
"cell_type": "code",
|
810
|
-
"
|
811
|
-
"id": "
|
900
|
+
"execution_count": null,
|
901
|
+
"id": "53",
|
902
|
+
"metadata": {},
|
812
903
|
"outputs": [],
|
813
|
-
"
|
904
|
+
"source": []
|
814
905
|
},
|
815
906
|
{
|
816
|
-
"metadata": {},
|
817
907
|
"cell_type": "code",
|
818
|
-
"
|
819
|
-
"id": "
|
908
|
+
"execution_count": null,
|
909
|
+
"id": "54",
|
910
|
+
"metadata": {},
|
820
911
|
"outputs": [],
|
821
|
-
"
|
912
|
+
"source": [
|
913
|
+
"no_stock_for_subjects_df()"
|
914
|
+
]
|
822
915
|
},
|
823
916
|
{
|
824
|
-
"metadata": {},
|
825
917
|
"cell_type": "code",
|
826
|
-
"
|
827
|
-
"id": "
|
918
|
+
"execution_count": null,
|
919
|
+
"id": "55",
|
920
|
+
"metadata": {},
|
828
921
|
"outputs": [],
|
829
|
-
"
|
922
|
+
"source": [
|
923
|
+
"df_schedule = read_frame(SubjectScheduleHistory.objects.values(\"subject_identifier\", \"visit_schedule_name\",\"schedule_name\", \"offschedule_datetime\").all())\n"
|
924
|
+
]
|
830
925
|
},
|
831
926
|
{
|
832
|
-
"metadata": {},
|
833
927
|
"cell_type": "code",
|
928
|
+
"execution_count": null,
|
929
|
+
"id": "56",
|
930
|
+
"metadata": {},
|
931
|
+
"outputs": [],
|
834
932
|
"source": [
|
835
933
|
"df_schedule = df_schedule[(df_schedule.visit_schedule_name==\"visit_schedule\") & (df_schedule.schedule_name==\"schedule\") & df_schedule.offschedule_datetime.isna()]\n",
|
836
934
|
"df_schedule.reset_index(drop=True, inplace=True)"
|
837
|
-
]
|
838
|
-
"id": "621196fa35e00e9c",
|
839
|
-
"outputs": [],
|
840
|
-
"execution_count": null
|
935
|
+
]
|
841
936
|
},
|
842
937
|
{
|
843
|
-
"metadata": {},
|
844
938
|
"cell_type": "code",
|
939
|
+
"execution_count": null,
|
940
|
+
"id": "57",
|
941
|
+
"metadata": {},
|
942
|
+
"outputs": [],
|
845
943
|
"source": [
|
846
944
|
"df_stock = read_frame(Stock.objects.all(), verbose=False)\n",
|
847
945
|
"df_stock_on_site = df_stock[(df_stock.confirmed_at_site==True) & (df_stock.dispensed==False)].copy()\n",
|
848
946
|
"df_stock_on_site.reset_index(drop=True, inplace=True)\n",
|
849
947
|
"df_stock_on_site = df_stock_on_site.drop(columns=[\"subject_identifier\"])\n"
|
850
|
-
]
|
851
|
-
"id": "8abada4ffb0db4f0",
|
852
|
-
"outputs": [],
|
853
|
-
"execution_count": null
|
948
|
+
]
|
854
949
|
},
|
855
950
|
{
|
856
|
-
"metadata": {},
|
857
951
|
"cell_type": "code",
|
952
|
+
"execution_count": null,
|
953
|
+
"id": "58",
|
954
|
+
"metadata": {},
|
955
|
+
"outputs": [],
|
858
956
|
"source": [
|
859
957
|
"df_allocation = read_frame(Allocation.objects.values(\"id\", \"registered_subject\").all(), verbose=False)\n",
|
860
958
|
"df_rs = read_frame(RegisteredSubject.objects.values(\"id\", \"subject_identifier\").all(), verbose=False)\n",
|
861
959
|
"df_allocation = df_allocation.merge(df_rs[[\"id\", \"subject_identifier\"]], how=\"left\", left_on=\"registered_subject\", right_on=\"id\", suffixes=[\"_allocation\", \"_rs\"])"
|
862
|
-
]
|
863
|
-
"id": "624ebc7e51e679bd",
|
864
|
-
"outputs": [],
|
865
|
-
"execution_count": null
|
960
|
+
]
|
866
961
|
},
|
867
962
|
{
|
868
|
-
"metadata": {},
|
869
963
|
"cell_type": "code",
|
870
|
-
"
|
871
|
-
"id": "
|
964
|
+
"execution_count": null,
|
965
|
+
"id": "59",
|
966
|
+
"metadata": {},
|
872
967
|
"outputs": [],
|
873
|
-
"
|
968
|
+
"source": [
|
969
|
+
"df_stock_on_site = df_stock_on_site.merge(df_allocation[[\"id_allocation\", \"subject_identifier\"]], how=\"left\", left_on=\"allocation\", right_on=\"id_allocation\")"
|
970
|
+
]
|
874
971
|
},
|
875
972
|
{
|
876
|
-
"metadata": {},
|
877
973
|
"cell_type": "code",
|
974
|
+
"execution_count": null,
|
975
|
+
"id": "60",
|
976
|
+
"metadata": {},
|
977
|
+
"outputs": [],
|
878
978
|
"source": [
|
879
979
|
"df = pd.merge(df_schedule[[\"subject_identifier\", 'offschedule_datetime']], df_stock_on_site, on=\"subject_identifier\", how=\"left\")\n",
|
880
980
|
"df= df[df.code.isna()][[\"subject_identifier\", ]].sort_values(by=[\"subject_identifier\"]).reset_index(drop=True)"
|
881
|
-
]
|
882
|
-
"id": "1ab7350cfb29eab4",
|
883
|
-
"outputs": [],
|
884
|
-
"execution_count": null
|
981
|
+
]
|
885
982
|
},
|
886
983
|
{
|
887
|
-
"metadata": {},
|
888
984
|
"cell_type": "code",
|
985
|
+
"execution_count": null,
|
986
|
+
"id": "61",
|
987
|
+
"metadata": {},
|
988
|
+
"outputs": [],
|
889
989
|
"source": [
|
890
990
|
"df_appt = get_next_scheduled_visit_for_subjects_df()\n",
|
891
991
|
"df_appt = df_appt[[\"subject_identifier\", \"site_id\", \"visit_code\", \"appt_datetime\", \"baseline_datetime\"]].copy()\n",
|
892
992
|
"df_appt.reset_index(drop=True, inplace=True)"
|
893
|
-
]
|
894
|
-
"id": "f29cc9c6c1234c34",
|
895
|
-
"outputs": [],
|
896
|
-
"execution_count": null
|
993
|
+
]
|
897
994
|
},
|
898
995
|
{
|
899
|
-
"metadata": {},
|
900
996
|
"cell_type": "code",
|
997
|
+
"execution_count": null,
|
998
|
+
"id": "62",
|
999
|
+
"metadata": {},
|
1000
|
+
"outputs": [],
|
901
1001
|
"source": [
|
902
1002
|
"\n",
|
903
1003
|
"df = df.merge(df_appt, how=\"left\", on=\"subject_identifier\")\n",
|
904
1004
|
"df = df[(df.appt_datetime.notna())]\n",
|
905
1005
|
"df.reset_index(drop=True, inplace=True)"
|
906
|
-
]
|
907
|
-
"id": "9e3e3f429a1995ec",
|
908
|
-
"outputs": [],
|
909
|
-
"execution_count": null
|
1006
|
+
]
|
910
1007
|
},
|
911
1008
|
{
|
912
|
-
"metadata": {},
|
913
1009
|
"cell_type": "code",
|
1010
|
+
"execution_count": null,
|
1011
|
+
"id": "63",
|
1012
|
+
"metadata": {},
|
1013
|
+
"outputs": [],
|
914
1014
|
"source": [
|
915
1015
|
"utc_now = pd.Timestamp.utcnow().tz_localize(None)\n",
|
916
1016
|
"df[\"relative_days\"] = (df.appt_datetime - utc_now).dt.days\n",
|
917
1017
|
"df_final = df[(df.relative_days >= -105)].copy()\n",
|
918
1018
|
"df_final.reset_index(drop=True, inplace=True)\n",
|
919
1019
|
"df_final"
|
920
|
-
]
|
921
|
-
"id": "d6570f1e94ac23bb",
|
922
|
-
"outputs": [],
|
923
|
-
"execution_count": null
|
1020
|
+
]
|
924
1021
|
},
|
925
1022
|
{
|
926
|
-
"metadata": {},
|
927
1023
|
"cell_type": "code",
|
928
|
-
"
|
929
|
-
"id": "
|
1024
|
+
"execution_count": null,
|
1025
|
+
"id": "64",
|
1026
|
+
"metadata": {},
|
930
1027
|
"outputs": [],
|
931
|
-
"
|
1028
|
+
"source": [
|
1029
|
+
"RegisteredSubject.objects.filter(site_id=10)"
|
1030
|
+
]
|
932
1031
|
},
|
933
1032
|
{
|
934
|
-
"metadata": {},
|
935
1033
|
"cell_type": "code",
|
936
|
-
"
|
937
|
-
"id": "
|
1034
|
+
"execution_count": null,
|
1035
|
+
"id": "65",
|
1036
|
+
"metadata": {},
|
938
1037
|
"outputs": [],
|
939
|
-
"
|
1038
|
+
"source": []
|
940
1039
|
},
|
941
1040
|
{
|
942
|
-
"metadata": {},
|
943
1041
|
"cell_type": "code",
|
944
|
-
"
|
945
|
-
"id": "
|
1042
|
+
"execution_count": null,
|
1043
|
+
"id": "66",
|
1044
|
+
"metadata": {},
|
946
1045
|
"outputs": [],
|
947
|
-
"
|
1046
|
+
"source": []
|
948
1047
|
}
|
949
1048
|
],
|
950
1049
|
"metadata": {
|