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.
Files changed (42) hide show
  1. meta_ae/admin/modeladmin_mixins.py +0 -1
  2. meta_analytics/dataframes/__init__.py +3 -0
  3. meta_analytics/dataframes/constants.py +1 -1
  4. meta_analytics/dataframes/enrolled/__init__.py +0 -1
  5. meta_analytics/dataframes/get_eos_df.py +15 -2
  6. meta_analytics/dataframes/get_glucose_df.py +149 -0
  7. meta_analytics/dataframes/get_glucose_fbg_df.py +27 -0
  8. meta_analytics/dataframes/get_glucose_fbg_ogtt_df.py +22 -0
  9. meta_analytics/dataframes/glucose_endpoints/endpoint_by_date.py +106 -120
  10. meta_analytics/dataframes/glucose_endpoints/glucose_endpoints_by_date.py +36 -227
  11. meta_analytics/dataframes/utils.py +18 -4
  12. meta_analytics/notebooks/hiv_regimens.ipynb +425 -0
  13. meta_analytics/notebooks/monitoring_report.ipynb +1561 -0
  14. meta_analytics/notebooks/pharmacy.ipynb +971 -0
  15. meta_analytics/utils.py +81 -0
  16. {meta_edc-1.0.5.dist-info → meta_edc-1.0.7.dist-info}/METADATA +5 -4
  17. {meta_edc-1.0.5.dist-info → meta_edc-1.0.7.dist-info}/RECORD +41 -27
  18. {meta_edc-1.0.5.dist-info → meta_edc-1.0.7.dist-info}/WHEEL +1 -1
  19. meta_edc-1.0.7.dist-info/licenses/AUTHORS.rst +8 -0
  20. meta_prn/models/end_of_study.py +0 -2
  21. meta_prn/models/loss_to_followup.py +0 -2
  22. meta_prn/models/pregnancy_notification.py +0 -2
  23. meta_reports/migrations/0054_auto_20250422_2003.py +81 -0
  24. meta_reports/migrations/0055_alter_glucosesummary_table.py +17 -0
  25. meta_reports/migrations/0056_auto_20250422_2214.py +54 -0
  26. meta_reports/migrations/0057_auto_20250422_2224.py +54 -0
  27. meta_reports/migrations/0058_auto_20250422_2232.py +54 -0
  28. meta_reports/models/dbviews/glucose_summary/unmanaged_model.py +13 -1
  29. meta_reports/models/dbviews/glucose_summary/view_definition.py +8 -5
  30. meta_subject/form_validators/glucose_form_validator.py +16 -1
  31. meta_subject/forms/study_medication_form.py +5 -3
  32. meta_subject/migrations/0221_auto_20250402_1913.py +42 -0
  33. meta_subject/migrations/0222_alter_historicalstudymedication_stock_codes_and_more.py +46 -0
  34. meta_subject/models/blood_results/blood_results_hba1c.py +0 -1
  35. meta_subject/models/blood_results/blood_results_ins.py +0 -1
  36. meta_subject/models/blood_results/blood_results_lft.py +0 -1
  37. meta_subject/models/delivery.py +0 -2
  38. meta_subject/models/followup_examination.py +0 -2
  39. meta_analytics/dataframes/enrolled/get_glucose_df.py +0 -122
  40. /meta_edc-1.0.5.dist-info/AUTHORS → /meta_analytics/dataframes/glucose_endpoints/utils.py +0 -0
  41. {meta_edc-1.0.5.dist-info → meta_edc-1.0.7.dist-info/licenses}/LICENSE +0 -0
  42. {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 = "glucose_summary_view"
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 `ogtt_datetime`,
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.glucose_summary_view",
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
- value = PENDING
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 separated by comma"
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
+ ]
@@ -18,7 +18,6 @@ class BloodResultsHba1c(
18
18
  BaseUuidModel,
19
19
  ):
20
20
  action_name = BLOOD_RESULTS_HBA1C_ACTION
21
- tracking_identifier_prefix = "HA"
22
21
  lab_panel = hba1c_panel
23
22
 
24
23
  requisition = models.ForeignKey(
@@ -18,7 +18,6 @@ class BloodResultsIns(
18
18
  BaseUuidModel,
19
19
  ):
20
20
  action_name = BLOOD_RESULTS_INSULIN_ACTION
21
- tracking_identifier_prefix = "IN"
22
21
  lab_panel = insulin_panel
23
22
 
24
23
  requisition = models.ForeignKey(
@@ -31,7 +31,6 @@ class BloodResultsLft(
31
31
  BaseUuidModel,
32
32
  ):
33
33
  action_name = BLOOD_RESULTS_LFT_ACTION
34
- tracking_identifier_prefix = "LF"
35
34
  lab_panel = lft_panel
36
35
 
37
36
  requisition = models.ForeignKey(
@@ -38,8 +38,6 @@ class Delivery(
38
38
 
39
39
  action_name = DELIVERY_ACTION
40
40
 
41
- tracking_identifier_prefix = "DL"
42
-
43
41
  report_datetime = models.DateTimeField(
44
42
  verbose_name="Report Date and Time", default=get_utcnow
45
43
  )
@@ -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