meta-edc 1.0.5__py3-none-any.whl → 1.0.7__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/admin/modeladmin_mixins.py +0 -1
- meta_analytics/dataframes/__init__.py +3 -0
- meta_analytics/dataframes/constants.py +1 -1
- meta_analytics/dataframes/enrolled/__init__.py +0 -1
- meta_analytics/dataframes/get_eos_df.py +15 -2
- meta_analytics/dataframes/get_glucose_df.py +149 -0
- meta_analytics/dataframes/get_glucose_fbg_df.py +27 -0
- meta_analytics/dataframes/get_glucose_fbg_ogtt_df.py +22 -0
- meta_analytics/dataframes/glucose_endpoints/endpoint_by_date.py +106 -120
- meta_analytics/dataframes/glucose_endpoints/glucose_endpoints_by_date.py +36 -227
- meta_analytics/dataframes/utils.py +18 -4
- meta_analytics/notebooks/hiv_regimens.ipynb +425 -0
- meta_analytics/notebooks/monitoring_report.ipynb +1561 -0
- meta_analytics/notebooks/pharmacy.ipynb +971 -0
- meta_analytics/utils.py +81 -0
- {meta_edc-1.0.5.dist-info → meta_edc-1.0.7.dist-info}/METADATA +5 -4
- {meta_edc-1.0.5.dist-info → meta_edc-1.0.7.dist-info}/RECORD +41 -27
- {meta_edc-1.0.5.dist-info → meta_edc-1.0.7.dist-info}/WHEEL +1 -1
- meta_edc-1.0.7.dist-info/licenses/AUTHORS.rst +8 -0
- meta_prn/models/end_of_study.py +0 -2
- meta_prn/models/loss_to_followup.py +0 -2
- meta_prn/models/pregnancy_notification.py +0 -2
- meta_reports/migrations/0054_auto_20250422_2003.py +81 -0
- meta_reports/migrations/0055_alter_glucosesummary_table.py +17 -0
- meta_reports/migrations/0056_auto_20250422_2214.py +54 -0
- meta_reports/migrations/0057_auto_20250422_2224.py +54 -0
- meta_reports/migrations/0058_auto_20250422_2232.py +54 -0
- meta_reports/models/dbviews/glucose_summary/unmanaged_model.py +13 -1
- meta_reports/models/dbviews/glucose_summary/view_definition.py +8 -5
- meta_subject/form_validators/glucose_form_validator.py +16 -1
- meta_subject/forms/study_medication_form.py +5 -3
- meta_subject/migrations/0221_auto_20250402_1913.py +42 -0
- meta_subject/migrations/0222_alter_historicalstudymedication_stock_codes_and_more.py +46 -0
- meta_subject/models/blood_results/blood_results_hba1c.py +0 -1
- meta_subject/models/blood_results/blood_results_ins.py +0 -1
- meta_subject/models/blood_results/blood_results_lft.py +0 -1
- meta_subject/models/delivery.py +0 -2
- meta_subject/models/followup_examination.py +0 -2
- meta_analytics/dataframes/enrolled/get_glucose_df.py +0 -122
- /meta_edc-1.0.5.dist-info/AUTHORS → /meta_analytics/dataframes/glucose_endpoints/utils.py +0 -0
- {meta_edc-1.0.5.dist-info → meta_edc-1.0.7.dist-info/licenses}/LICENSE +0 -0
- {meta_edc-1.0.5.dist-info → meta_edc-1.0.7.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,54 @@
|
|
1
|
+
# Generated by Django 6.0 on 2025-04-22 19:32
|
2
|
+
|
3
|
+
import django_db_views.migration_functions
|
4
|
+
import django_db_views.operations
|
5
|
+
from django.db import migrations
|
6
|
+
|
7
|
+
|
8
|
+
class Migration(migrations.Migration):
|
9
|
+
|
10
|
+
dependencies = [
|
11
|
+
("meta_reports", "0057_auto_20250422_2224"),
|
12
|
+
]
|
13
|
+
|
14
|
+
operations = [
|
15
|
+
django_db_views.operations.ViewRunPython(
|
16
|
+
code=django_db_views.migration_functions.ForwardViewMigration(
|
17
|
+
"select *, uuid() as id, now() as `created`, 'meta_reports.glucosesummaryview' as `report_model` from (SELECT v.subject_identifier, fbg_value, fbg_units, fbg_datetime, NULL AS `ogtt_value`, NULL AS `ogtt_units`, NULL AS `ogtt_datetime`, CASE WHEN fasting = 'fasting' THEN 'Yes' WHEN fasting = 'non_fasting' THEN 'No' ELSE fasting END AS `fasted`, fbg.site_id, v.visit_code, v.visit_code_sequence, v.report_datetime, v.appointment_id, eos.offstudy_datetime, fasting_duration_delta, 'meta_subject.glucosefbg' AS source FROM meta_subject_glucosefbg AS fbg LEFT JOIN meta_subject_subjectvisit AS v ON v.id = fbg.subject_visit_id LEFT JOIN meta_prn_endofstudy AS eos ON v.subject_identifier = eos.subject_identifier UNION SELECT v.subject_identifier, fbg_value, fbg_units, fbg_datetime, ogtt_value, ogtt_units, ogtt_datetime, CASE WHEN fasting = 'fasting' THEN 'Yes' WHEN fasting = 'non_fasting' THEN 'No' ELSE fasting END AS `fasted`, fbg.site_id, v.visit_code, v.visit_code_sequence, v.report_datetime, v.appointment_id, eos.offstudy_datetime, fasting_duration_delta, 'meta_subject.glucose' AS source FROM meta_subject_glucose AS fbg LEFT JOIN meta_subject_subjectvisit AS v ON v.id = fbg.subject_visit_id LEFT JOIN meta_prn_endofstudy AS eos ON v.subject_identifier = eos.subject_identifier) as A ORDER BY subject_identifier, site_id",
|
18
|
+
"meta_reports_glucosesummaryview",
|
19
|
+
engine="django.db.backends.mysql",
|
20
|
+
),
|
21
|
+
reverse_code=django_db_views.migration_functions.BackwardViewMigration(
|
22
|
+
"select *, uuid() as id, now() as `created`, 'meta_reports.glucosesummaryview' as `report_model` from (SELECT v.subject_identifier, fbg_value, fbg_datetime, NULL AS `ogtt_value`, NULL AS `ogtt_datetime`, CASE WHEN fasting = 'fasting' THEN 'Yes' WHEN fasting = 'non_fasting' THEN 'No' ELSE fasting END AS `fasted`, fbg.site_id, v.visit_code, v.visit_code_sequence, v.report_datetime, v.appointment_id, eos.offstudy_datetime, fasting_duration_delta, 'meta_subject.glucosefbg' AS source FROM meta_subject_glucosefbg AS fbg LEFT JOIN meta_subject_subjectvisit AS v ON v.id = fbg.subject_visit_id LEFT JOIN meta_prn_endofstudy AS eos ON v.subject_identifier = eos.subject_identifier UNION SELECT v.subject_identifier, fbg_value, fbg_datetime, ogtt_value, ogtt_datetime, CASE WHEN fasting = 'fasting' THEN 'Yes' WHEN fasting = 'non_fasting' THEN 'No' ELSE fasting END AS `fasted`, fbg.site_id, v.visit_code, v.visit_code_sequence, v.report_datetime, v.appointment_id, eos.offstudy_datetime, fasting_duration_delta, 'meta_subject.glucose' AS source FROM meta_subject_glucose AS fbg LEFT JOIN meta_subject_subjectvisit AS v ON v.id = fbg.subject_visit_id LEFT JOIN meta_prn_endofstudy AS eos ON v.subject_identifier = eos.subject_identifier) as A ORDER BY subject_identifier, site_id",
|
23
|
+
"meta_reports_glucosesummaryview",
|
24
|
+
engine="django.db.backends.mysql",
|
25
|
+
),
|
26
|
+
atomic=False,
|
27
|
+
),
|
28
|
+
django_db_views.operations.ViewRunPython(
|
29
|
+
code=django_db_views.migration_functions.ForwardViewMigration(
|
30
|
+
"select *, get_random_uuid() as id, now() as created, 'meta_reports.glucosesummaryview' as report_model from (SELECT v.subject_identifier, fbg_value, fbg_units, fbg_datetime, NULL AS \"ogtt_value\", NULL AS \"ogtt_units\", NULL AS \"ogtt_datetime\", CASE WHEN fasting = 'fasting' THEN 'Yes' WHEN fasting = 'non_fasting' THEN 'No' ELSE fasting END AS \"fasted\", fbg.site_id, v.visit_code, v.visit_code_sequence, v.report_datetime, v.appointment_id, eos.offstudy_datetime, fasting_duration_delta, 'meta_subject.glucosefbg' AS source FROM meta_subject_glucosefbg AS fbg LEFT JOIN meta_subject_subjectvisit AS v ON v.id = fbg.subject_visit_id LEFT JOIN meta_prn_endofstudy AS eos ON v.subject_identifier = eos.subject_identifier UNION SELECT v.subject_identifier, fbg_value, fbg_units, fbg_datetime, ogtt_value, ogtt_units, ogtt_datetime, CASE WHEN fasting = 'fasting' THEN 'Yes' WHEN fasting = 'non_fasting' THEN 'No' ELSE fasting END AS \"fasted\", fbg.site_id, v.visit_code, v.visit_code_sequence, v.report_datetime, v.appointment_id, eos.offstudy_datetime, fasting_duration_delta, 'meta_subject.glucose' AS source FROM meta_subject_glucose AS fbg LEFT JOIN meta_subject_subjectvisit AS v ON v.id = fbg.subject_visit_id LEFT JOIN meta_prn_endofstudy AS eos ON v.subject_identifier = eos.subject_identifier) as A ORDER BY subject_identifier, site_id",
|
31
|
+
"meta_reports_glucosesummaryview",
|
32
|
+
engine="django.db.backends.postgresql",
|
33
|
+
),
|
34
|
+
reverse_code=django_db_views.migration_functions.BackwardViewMigration(
|
35
|
+
"select *, get_random_uuid() as id, now() as created, 'meta_reports.glucosesummaryview' as report_model from (SELECT v.subject_identifier, fbg_value, fbg_datetime, NULL AS \"ogtt_value\", NULL AS \"ogtt_datetime\", CASE WHEN fasting = 'fasting' THEN 'Yes' WHEN fasting = 'non_fasting' THEN 'No' ELSE fasting END AS \"fasted\", fbg.site_id, v.visit_code, v.visit_code_sequence, v.report_datetime, v.appointment_id, eos.offstudy_datetime, fasting_duration_delta, 'meta_subject.glucosefbg' AS source FROM meta_subject_glucosefbg AS fbg LEFT JOIN meta_subject_subjectvisit AS v ON v.id = fbg.subject_visit_id LEFT JOIN meta_prn_endofstudy AS eos ON v.subject_identifier = eos.subject_identifier UNION SELECT v.subject_identifier, fbg_value, fbg_datetime, ogtt_value, ogtt_datetime, CASE WHEN fasting = 'fasting' THEN 'Yes' WHEN fasting = 'non_fasting' THEN 'No' ELSE fasting END AS \"fasted\", fbg.site_id, v.visit_code, v.visit_code_sequence, v.report_datetime, v.appointment_id, eos.offstudy_datetime, fasting_duration_delta, 'meta_subject.glucose' AS source FROM meta_subject_glucose AS fbg LEFT JOIN meta_subject_subjectvisit AS v ON v.id = fbg.subject_visit_id LEFT JOIN meta_prn_endofstudy AS eos ON v.subject_identifier = eos.subject_identifier) as A ORDER BY subject_identifier, site_id",
|
36
|
+
"meta_reports_glucosesummaryview",
|
37
|
+
engine="django.db.backends.postgresql",
|
38
|
+
),
|
39
|
+
atomic=False,
|
40
|
+
),
|
41
|
+
django_db_views.operations.ViewRunPython(
|
42
|
+
code=django_db_views.migration_functions.ForwardViewMigration(
|
43
|
+
"select *, uuid() as id, datetime() as created, 'meta_reports.glucosesummaryview' as report_model from (SELECT v.subject_identifier, fbg_value, fbg_units, fbg_datetime, NULL AS \"ogtt_value\", NULL AS \"ogtt_units\", NULL AS \"ogtt_datetime\", CASE WHEN fasting = 'fasting' THEN 'Yes' WHEN fasting = 'non_fasting' THEN 'No' ELSE fasting END AS \"fasted\", fbg.site_id, v.visit_code, v.visit_code_sequence, v.report_datetime, v.appointment_id, eos.offstudy_datetime, fasting_duration_delta, 'meta_subject.glucosefbg' AS source FROM meta_subject_glucosefbg AS fbg LEFT JOIN meta_subject_subjectvisit AS v ON v.id = fbg.subject_visit_id LEFT JOIN meta_prn_endofstudy AS eos ON v.subject_identifier = eos.subject_identifier UNION SELECT v.subject_identifier, fbg_value, fbg_units, fbg_datetime, ogtt_value, ogtt_units, ogtt_datetime, CASE WHEN fasting = 'fasting' THEN 'Yes' WHEN fasting = 'non_fasting' THEN 'No' ELSE fasting END AS \"fasted\", fbg.site_id, v.visit_code, v.visit_code_sequence, v.report_datetime, v.appointment_id, eos.offstudy_datetime, fasting_duration_delta, 'meta_subject.glucose' AS source FROM meta_subject_glucose AS fbg LEFT JOIN meta_subject_subjectvisit AS v ON v.id = fbg.subject_visit_id LEFT JOIN meta_prn_endofstudy AS eos ON v.subject_identifier = eos.subject_identifier) as A ORDER BY subject_identifier, site_id",
|
44
|
+
"meta_reports_glucosesummaryview",
|
45
|
+
engine="django.db.backends.sqlite3",
|
46
|
+
),
|
47
|
+
reverse_code=django_db_views.migration_functions.BackwardViewMigration(
|
48
|
+
"select *, uuid() as id, datetime() as created, 'meta_reports.glucosesummaryview' as report_model from (SELECT v.subject_identifier, fbg_value, fbg_datetime, NULL AS \"ogtt_value\", NULL AS \"ogtt_datetime\", CASE WHEN fasting = 'fasting' THEN 'Yes' WHEN fasting = 'non_fasting' THEN 'No' ELSE fasting END AS \"fasted\", fbg.site_id, v.visit_code, v.visit_code_sequence, v.report_datetime, v.appointment_id, eos.offstudy_datetime, fasting_duration_delta, 'meta_subject.glucosefbg' AS source FROM meta_subject_glucosefbg AS fbg LEFT JOIN meta_subject_subjectvisit AS v ON v.id = fbg.subject_visit_id LEFT JOIN meta_prn_endofstudy AS eos ON v.subject_identifier = eos.subject_identifier UNION SELECT v.subject_identifier, fbg_value, fbg_datetime, ogtt_value, ogtt_datetime, CASE WHEN fasting = 'fasting' THEN 'Yes' WHEN fasting = 'non_fasting' THEN 'No' ELSE fasting END AS \"fasted\", fbg.site_id, v.visit_code, v.visit_code_sequence, v.report_datetime, v.appointment_id, eos.offstudy_datetime, fasting_duration_delta, 'meta_subject.glucose' AS source FROM meta_subject_glucose AS fbg LEFT JOIN meta_subject_subjectvisit AS v ON v.id = fbg.subject_visit_id LEFT JOIN meta_prn_endofstudy AS eos ON v.subject_identifier = eos.subject_identifier) as A ORDER BY subject_identifier, site_id",
|
49
|
+
"meta_reports_glucosesummaryview",
|
50
|
+
engine="django.db.backends.sqlite3",
|
51
|
+
),
|
52
|
+
atomic=False,
|
53
|
+
),
|
54
|
+
]
|
@@ -9,14 +9,24 @@ class GlucoseSummary(QaReportModelMixin, DBView):
|
|
9
9
|
|
10
10
|
fbg_value = models.DecimalField(max_digits=8, decimal_places=2, null=True)
|
11
11
|
|
12
|
+
fbg_units = models.CharField(max_length=15, null=True)
|
13
|
+
|
12
14
|
fbg_datetime = models.DateTimeField(null=True)
|
13
15
|
|
14
16
|
ogtt_value = models.DecimalField(max_digits=8, decimal_places=2, null=True)
|
15
17
|
|
18
|
+
ogtt_units = models.CharField(max_length=15, null=True)
|
19
|
+
|
16
20
|
ogtt_datetime = models.DateTimeField(null=True)
|
17
21
|
|
18
22
|
fasted = models.CharField(max_length=15, null=True)
|
19
23
|
|
24
|
+
fasting_duration_delta = models.DurationField(
|
25
|
+
verbose_name="Fasting duration (hrs)", null=True
|
26
|
+
)
|
27
|
+
|
28
|
+
report_datetime = models.DateTimeField(null=True)
|
29
|
+
|
20
30
|
visit_code = models.CharField(max_length=25)
|
21
31
|
|
22
32
|
visit_code_sequence = models.IntegerField()
|
@@ -25,11 +35,13 @@ class GlucoseSummary(QaReportModelMixin, DBView):
|
|
25
35
|
|
26
36
|
offstudy_datetime = models.DateTimeField(null=True)
|
27
37
|
|
38
|
+
source = models.CharField(max_length=35, null=True)
|
39
|
+
|
28
40
|
view_definition = get_view_definition()
|
29
41
|
|
30
42
|
class Meta:
|
31
43
|
managed = False
|
32
|
-
db_table = "
|
44
|
+
db_table = "meta_reports_glucosesummaryview"
|
33
45
|
verbose_name = "Glucose Summary"
|
34
46
|
verbose_name_plural = "Glucose Summary"
|
35
47
|
default_permissions = qa_reports_permissions
|
@@ -3,22 +3,25 @@ from edc_qareports.sql_generator import SqlViewGenerator
|
|
3
3
|
|
4
4
|
def get_view_definition() -> dict:
|
5
5
|
subquery = """
|
6
|
-
select v.subject_identifier, fbg_value, fbg_datetime, null as `ogtt_value`, null as `
|
6
|
+
select v.subject_identifier, fbg_value, fbg_units, fbg_datetime, null as `ogtt_value`, null as `ogtt_units`,
|
7
|
+
null as `ogtt_datetime`,
|
7
8
|
case when fasting="fasting" then "Yes" when fasting="non_fasting" then "No" else fasting end as `fasted`,
|
8
|
-
fbg.site_id, v.visit_code, v.visit_code_sequence, v.appointment_id, eos.offstudy_datetime
|
9
|
+
fbg.site_id, v.visit_code, v.visit_code_sequence, v.report_datetime, v.appointment_id, eos.offstudy_datetime,
|
10
|
+
fasting_duration_delta, "meta_subject.glucosefbg" as source
|
9
11
|
from meta_subject_glucosefbg as fbg
|
10
12
|
left join meta_subject_subjectvisit as v on v.id=fbg.subject_visit_id
|
11
13
|
left join meta_prn_endofstudy as eos on v.subject_identifier=eos.subject_identifier
|
12
14
|
UNION
|
13
|
-
select v.subject_identifier, fbg_value, fbg_datetime, ogtt_value, ogtt_datetime,
|
15
|
+
select v.subject_identifier, fbg_value, fbg_units, fbg_datetime, ogtt_value, ogtt_units, ogtt_datetime,
|
14
16
|
case when fasting="fasting" then "Yes" when fasting="non_fasting" then "No" else fasting end as `fasted`,
|
15
|
-
fbg.site_id, v.visit_code, v.visit_code_sequence, v.appointment_id, eos.offstudy_datetime
|
17
|
+
fbg.site_id, v.visit_code, v.visit_code_sequence, v.report_datetime, v.appointment_id, eos.offstudy_datetime,
|
18
|
+
fasting_duration_delta, "meta_subject.glucose" as source
|
16
19
|
from meta_subject_glucose as fbg
|
17
20
|
left join meta_subject_subjectvisit as v on v.id=fbg.subject_visit_id
|
18
21
|
left join meta_prn_endofstudy as eos on v.subject_identifier=eos.subject_identifier
|
19
22
|
""" # noqa
|
20
23
|
sql_view = SqlViewGenerator(
|
21
|
-
report_model="meta_reports.
|
24
|
+
report_model="meta_reports.glucosesummaryview",
|
22
25
|
ordering=["subject_identifier", "site_id"],
|
23
26
|
)
|
24
27
|
return {
|
@@ -5,6 +5,8 @@ from edc_crf.crf_form_validator import CrfFormValidator
|
|
5
5
|
from edc_form_validators import INVALID_ERROR
|
6
6
|
from edc_glucose.form_validators import FbgOgttFormValidatorMixin
|
7
7
|
|
8
|
+
from meta_reports.models import GlucoseSummary
|
9
|
+
|
8
10
|
from ..constants import AMENDMENT_DATE
|
9
11
|
|
10
12
|
|
@@ -79,5 +81,18 @@ class GlucoseFormValidator(FbgOgttFormValidatorMixin, CrfFormValidator):
|
|
79
81
|
elif self.cleaned_data.get("fbg_value") >= Decimal("7.0") and self.cleaned_data.get(
|
80
82
|
"ogtt_value"
|
81
83
|
) < Decimal("11.1"):
|
82
|
-
|
84
|
+
# is there a previous FBG>=7.0 in sequence or do you need to repeat?
|
85
|
+
previous_obj = (
|
86
|
+
GlucoseSummary.objects.filter(
|
87
|
+
subject_identifier=self.subject_identifier,
|
88
|
+
fbg_datetime__lt=self.cleaned_data.get("fbg_datetime"),
|
89
|
+
)
|
90
|
+
.order_by("fbg_datetime")
|
91
|
+
.last()
|
92
|
+
)
|
93
|
+
if previous_obj and previous_obj.fbg_value >= Decimal("7.0"):
|
94
|
+
value = YES
|
95
|
+
else:
|
96
|
+
# you need to schedule a repeat
|
97
|
+
value = PENDING
|
83
98
|
return value
|
@@ -38,16 +38,18 @@ class StudyMedicationFormValidator(BaseStudyMedicationFormValidator):
|
|
38
38
|
|
39
39
|
def validate_stock_codes_are_dispensed(self):
|
40
40
|
if self.cleaned_data.get("stock_codes"):
|
41
|
-
pattern = re.compile("^([A-Z0-9]{6})(,[A-Z0-9]{6})*$")
|
41
|
+
# pattern = re.compile("^([A-Z0-9]{6})(,[A-Z0-9]{6})*$")
|
42
|
+
pattern = re.compile("^([A-Z0-9]{6})(\r\n[A-Z0-9]{6})*$")
|
42
43
|
if not pattern.match(self.cleaned_data.get("stock_codes")):
|
43
44
|
raise forms.ValidationError(
|
44
45
|
{
|
45
46
|
"stock_codes": (
|
46
|
-
"Invalid format. Enter one or more valid codes
|
47
|
+
"Invalid format. Enter one or more valid codes. "
|
48
|
+
"One code per line only. No commas, spaces, etc"
|
47
49
|
)
|
48
50
|
}
|
49
51
|
)
|
50
|
-
for stock_code in self.cleaned_data.get("stock_codes").split("
|
52
|
+
for stock_code in self.cleaned_data.get("stock_codes").split("\r\n"):
|
51
53
|
try:
|
52
54
|
Stock.objects.get(
|
53
55
|
code=stock_code,
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# Generated by Django 6.0 on 2025-04-02 16:13
|
2
|
+
from django.apps import apps as django_apps
|
3
|
+
from django.db import migrations
|
4
|
+
from django.db.migrations import RunPython
|
5
|
+
from edc_appointment.constants import MISSED_APPT
|
6
|
+
from edc_pdutils.dataframes import get_crf
|
7
|
+
from edc_utils import get_utcnow
|
8
|
+
from tqdm import tqdm
|
9
|
+
|
10
|
+
|
11
|
+
def update(apps, schema_editor):
|
12
|
+
"""Correct missed appointments incorrectly set to
|
13
|
+
appt_timing=ONTIME_APPT.
|
14
|
+
"""
|
15
|
+
appointment_model_cls = django_apps.get_model("edc_appointment.appointment")
|
16
|
+
df_missedvisit = get_crf(
|
17
|
+
"meta_subject.subjectvisitmissed",
|
18
|
+
subject_visit_model="meta_subject.subjectvisit",
|
19
|
+
)
|
20
|
+
df_subjects = df_missedvisit[df_missedvisit.appt_timing != MISSED_APPT][
|
21
|
+
["subject_identifier", "visit_code_str", "visit_code_sequence"]
|
22
|
+
].copy()
|
23
|
+
for tpl in tqdm(df_subjects.itertuples(), total=len(df_subjects)):
|
24
|
+
obj = appointment_model_cls.objects.get(
|
25
|
+
subject_identifier=tpl.subject_identifier,
|
26
|
+
visit_code=tpl.visit_code_str,
|
27
|
+
visit_code_sequence=tpl.visit_code_sequence,
|
28
|
+
)
|
29
|
+
obj.appt_timing = MISSED_APPT
|
30
|
+
obj.modified = get_utcnow()
|
31
|
+
obj.user_modified = "erikvw"
|
32
|
+
|
33
|
+
obj.save(update_fields=["appt_timing", "user_modified", "modified"])
|
34
|
+
|
35
|
+
|
36
|
+
class Migration(migrations.Migration):
|
37
|
+
|
38
|
+
dependencies = [
|
39
|
+
("meta_subject", "0220_historicalbloodresultsgludummy_bloodresultsgludummy"),
|
40
|
+
]
|
41
|
+
|
42
|
+
operations = [RunPython(update)]
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# Generated by Django 6.0 on 2025-04-15 22:06
|
2
|
+
|
3
|
+
import django.core.validators
|
4
|
+
from django.db import migrations, models
|
5
|
+
|
6
|
+
|
7
|
+
class Migration(migrations.Migration):
|
8
|
+
|
9
|
+
dependencies = [
|
10
|
+
("meta_subject", "0221_auto_20250402_1913"),
|
11
|
+
]
|
12
|
+
|
13
|
+
operations = [
|
14
|
+
migrations.AlterField(
|
15
|
+
model_name="historicalstudymedication",
|
16
|
+
name="stock_codes",
|
17
|
+
field=models.TextField(
|
18
|
+
blank=True,
|
19
|
+
help_text="Enter the medication bottle barcode or barcodes. Type one code per line",
|
20
|
+
max_length=30,
|
21
|
+
null=True,
|
22
|
+
validators=[
|
23
|
+
django.core.validators.RegexValidator(
|
24
|
+
message="Enter one or more valid codes, one code per line",
|
25
|
+
regex="^([A-Z0-9]{6})(\r\n[A-Z0-9]{6})*$",
|
26
|
+
)
|
27
|
+
],
|
28
|
+
),
|
29
|
+
),
|
30
|
+
migrations.AlterField(
|
31
|
+
model_name="studymedication",
|
32
|
+
name="stock_codes",
|
33
|
+
field=models.TextField(
|
34
|
+
blank=True,
|
35
|
+
help_text="Enter the medication bottle barcode or barcodes. Type one code per line",
|
36
|
+
max_length=30,
|
37
|
+
null=True,
|
38
|
+
validators=[
|
39
|
+
django.core.validators.RegexValidator(
|
40
|
+
message="Enter one or more valid codes, one code per line",
|
41
|
+
regex="^([A-Z0-9]{6})(\r\n[A-Z0-9]{6})*$",
|
42
|
+
)
|
43
|
+
],
|
44
|
+
),
|
45
|
+
),
|
46
|
+
]
|
meta_subject/models/delivery.py
CHANGED
@@ -16,8 +16,6 @@ from ..model_mixins import CrfWithActionModelMixin
|
|
16
16
|
class FollowupExamination(CrfWithActionModelMixin, BaseUuidModel):
|
17
17
|
action_name = FOLLOWUP_EXAMINATION_ACTION
|
18
18
|
|
19
|
-
tracking_identifier_prefix = "FU"
|
20
|
-
|
21
19
|
# 4a
|
22
20
|
symptoms = models.ManyToManyField(
|
23
21
|
Symptoms,
|
@@ -1,122 +0,0 @@
|
|
1
|
-
import numpy as np
|
2
|
-
import pandas as pd
|
3
|
-
from django_pandas.io import read_frame
|
4
|
-
from edc_pdutils.dataframes import get_eos, get_subject_consent, get_subject_visit
|
5
|
-
|
6
|
-
from meta_subject.models import Glucose, GlucoseFbg
|
7
|
-
|
8
|
-
|
9
|
-
def get_glucose_df() -> pd.DataFrame:
|
10
|
-
qs_glucose_fbg = GlucoseFbg.objects.all()
|
11
|
-
df_glucose_fbg = read_frame(qs_glucose_fbg)
|
12
|
-
df_glucose_fbg.rename(
|
13
|
-
columns={"fbg_fasting": "fasting", "subject_visit": "subject_visit_id"},
|
14
|
-
inplace=True,
|
15
|
-
)
|
16
|
-
|
17
|
-
df_glucose_fbg.loc[(df_glucose_fbg["fasting"] == "fasting"), "fasting"] = "Yes"
|
18
|
-
df_glucose_fbg.loc[(df_glucose_fbg["fasting"] == "non_fasting"), "fasting"] = "No"
|
19
|
-
df_glucose_fbg["fasting_hrs"] = np.nan
|
20
|
-
df_glucose_fbg["fasting_hrs"] = df_glucose_fbg["fasting_duration_delta"].apply(
|
21
|
-
lambda x: x.total_seconds() / 3600
|
22
|
-
)
|
23
|
-
df_glucose_fbg["fasting_hrs"] = df_glucose_fbg["fasting_hrs"].apply(
|
24
|
-
lambda x: 8.05 if not x else x
|
25
|
-
)
|
26
|
-
# df_glucose_fbg = df_glucose_fbg.loc[df_glucose_fbg["fasting_hrs"] >= 8.0]
|
27
|
-
# df_glucose_fbg.reset_index(drop=True, inplace=True)
|
28
|
-
df_glucose_fbg.loc[
|
29
|
-
:,
|
30
|
-
["ogtt_value", "ogtt_units", "ogtt_datetime"],
|
31
|
-
] = [np.nan, None, pd.NaT]
|
32
|
-
df_glucose_fbg["source"] = "meta_subject.glucosefbg"
|
33
|
-
|
34
|
-
qs_glucose = Glucose.objects.all()
|
35
|
-
df_glucose = read_frame(qs_glucose)
|
36
|
-
df_glucose.rename(columns={"subject_visit": "subject_visit_id"}, inplace=True)
|
37
|
-
df_glucose.loc[(df_glucose["fasting"] == "fasting"), "fasting"] = "Yes"
|
38
|
-
df_glucose.loc[(df_glucose["fasting"] == "non_fasting"), "fasting"] = "No"
|
39
|
-
df_glucose["fasting_hrs"] = np.nan
|
40
|
-
df_glucose["fasting_hrs"] = df_glucose[df_glucose["fasting"] == "Yes"][
|
41
|
-
"fasting_duration_delta"
|
42
|
-
].apply(lambda x: x.total_seconds() / 3600)
|
43
|
-
df_glucose["fasting_hrs"] = df_glucose["fasting_hrs"].apply(lambda x: 8.05 if not x else x)
|
44
|
-
# df_glucose = df_glucose.loc[df_glucose["fasting_hrs"] >= 8.0]
|
45
|
-
# df_glucose.reset_index(drop=True, inplace=True)
|
46
|
-
df_glucose["source"] = "meta_subject.glucose"
|
47
|
-
|
48
|
-
keep_cols = [
|
49
|
-
"subject_visit_id",
|
50
|
-
"fasting",
|
51
|
-
"fasting_hrs",
|
52
|
-
"fbg_value",
|
53
|
-
"fbg_units",
|
54
|
-
"fbg_datetime",
|
55
|
-
"ogtt_value",
|
56
|
-
"ogtt_units",
|
57
|
-
"ogtt_datetime",
|
58
|
-
"source",
|
59
|
-
"revision",
|
60
|
-
"report_datetime",
|
61
|
-
]
|
62
|
-
df_glucose = df_glucose[keep_cols]
|
63
|
-
df_glucose_fbg = df_glucose_fbg[keep_cols]
|
64
|
-
# df = pd.concat([df_glucose_fbg, df_glucose])
|
65
|
-
df = pd.merge(
|
66
|
-
df_glucose,
|
67
|
-
df_glucose_fbg,
|
68
|
-
on="subject_visit_id",
|
69
|
-
how="outer",
|
70
|
-
indicator=True,
|
71
|
-
suffixes=("", "_2"),
|
72
|
-
)
|
73
|
-
|
74
|
-
for suffix in ["", "_2"]:
|
75
|
-
cols = [f"fasting_hrs{suffix}", f"fbg_value{suffix}", f"ogtt_value{suffix}"]
|
76
|
-
df[cols] = df[cols].apply(pd.to_numeric)
|
77
|
-
cols = [f"fbg_datetime{suffix}", f"ogtt_datetime{suffix}"]
|
78
|
-
df[cols] = df[cols].apply(pd.to_datetime)
|
79
|
-
df.loc[
|
80
|
-
(df[f"fbg_units{suffix}"] != "mmol/L (millimoles/L)")
|
81
|
-
& (df[f"fbg_value{suffix}"] >= 0),
|
82
|
-
f"fbg_units{suffix}",
|
83
|
-
] = "mmol/L (millimoles/L)"
|
84
|
-
df.loc[
|
85
|
-
(df[f"ogtt_units{suffix}"] != "mmol/L (millimoles/L)")
|
86
|
-
& (df[f"ogtt_value{suffix}"] >= 0),
|
87
|
-
f"ogtt_units{suffix}",
|
88
|
-
] = "mmol/L (millimoles/L)"
|
89
|
-
# remove values if not fasted
|
90
|
-
# df.loc[(df[f"fasting{suffix}"] != YES), f"fbg_value{suffix}"] = np.nan
|
91
|
-
# df.loc[(df[f"fasting{suffix}"] != YES), f"ogtt_value{suffix}"] = np.nan
|
92
|
-
|
93
|
-
# reconcile all to single column
|
94
|
-
df.loc[(df["fbg_value"].isna()) & (df["fbg_value_2"].notna()), "fbg_value"] = df[
|
95
|
-
"fbg_value_2"
|
96
|
-
]
|
97
|
-
df.loc[(df["ogtt_value"].isna()) & (df["ogtt_value_2"].notna()), "ogtt_value"] = df[
|
98
|
-
"ogtt_value_2"
|
99
|
-
]
|
100
|
-
cols = [col for col in list(df.columns) if col.endswith("_2")]
|
101
|
-
df.drop(columns=cols, inplace=True)
|
102
|
-
cols = [col for col in list(df.columns) if col.endswith("_3")]
|
103
|
-
df.drop(columns=cols, inplace=True)
|
104
|
-
|
105
|
-
df_subject_visit = get_subject_visit("meta_subject.subjectvisit")
|
106
|
-
df_consent = get_subject_consent("meta_consent.subjectconsent")
|
107
|
-
df_eos = get_eos("meta_prn.endofstudy")
|
108
|
-
|
109
|
-
df = pd.merge(df_subject_visit, df, on="subject_visit_id", how="left")
|
110
|
-
df = pd.merge(df, df_consent, on="subject_identifier", how="left")
|
111
|
-
df = pd.merge(df, df_eos, on="subject_identifier", how="left")
|
112
|
-
|
113
|
-
df["visit_days"] = df["baseline_datetime"].rsub(df["visit_datetime"]).dt.days
|
114
|
-
df["fgb_days"] = df["baseline_datetime"].rsub(df["fbg_datetime"]).dt.days
|
115
|
-
df["ogtt_days"] = df["baseline_datetime"].rsub(df["ogtt_datetime"]).dt.days
|
116
|
-
df["visit_days"] = pd.to_numeric(df["visit_days"], downcast="integer")
|
117
|
-
df["fgb_days"] = pd.to_numeric(df["fgb_days"], downcast="integer")
|
118
|
-
df["ogtt_days"] = pd.to_numeric(df["ogtt_days"], downcast="integer")
|
119
|
-
|
120
|
-
df = df.sort_values(by=["subject_identifier", "visit_code"])
|
121
|
-
df.reset_index(drop=True, inplace=True)
|
122
|
-
return df
|
File without changes
|
File without changes
|
File without changes
|