clinicedc 2.0.11__py3-none-any.whl → 2.0.13__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.

Potentially problematic release.


This version of clinicedc might be problematic. Click here for more details.

Files changed (137) hide show
  1. {clinicedc-2.0.11.dist-info → clinicedc-2.0.13.dist-info}/METADATA +2 -1
  2. {clinicedc-2.0.11.dist-info → clinicedc-2.0.13.dist-info}/RECORD +137 -24
  3. edc_action_item/migrations/0017_auto_20190305_0123.py +1 -1
  4. edc_action_item/migrations/0030_edcpermissions.py +1 -1
  5. edc_action_item/migrations/0041_alter_actionitem_revision_alter_actiontype_revision_and_more.py +86 -0
  6. edc_adverse_event/migrations/0001_initial.py +1 -1
  7. edc_adverse_event/migrations/0002_auto_20190802_0059.py +1 -1
  8. edc_adverse_event/migrations/0008_auto_20220825_0451.py +1 -1
  9. edc_adverse_event/migrations/0009_auto_20220907_0157.py +1 -1
  10. edc_adverse_event/migrations/0017_alter_aeactionclassification_revision_and_more.py +77 -0
  11. edc_adverse_event/model_mixins/hospitaization/hospitalization_model_mixin.py +1 -3
  12. edc_analytics/__init__.py +3 -0
  13. edc_analytics/apps.py +8 -0
  14. edc_analytics/constants.py +26 -0
  15. edc_analytics/custom_tables/__init__.py +11 -0
  16. edc_analytics/custom_tables/age.py +72 -0
  17. edc_analytics/custom_tables/art.py +88 -0
  18. edc_analytics/custom_tables/bmi.py +125 -0
  19. edc_analytics/custom_tables/bp.py +103 -0
  20. edc_analytics/custom_tables/fasting.py +126 -0
  21. edc_analytics/custom_tables/fbg.py +98 -0
  22. edc_analytics/custom_tables/fbg_ogtt.py +384 -0
  23. edc_analytics/custom_tables/gender.py +12 -0
  24. edc_analytics/custom_tables/hba1c.py +87 -0
  25. edc_analytics/custom_tables/ogtt.py +95 -0
  26. edc_analytics/custom_tables/waist.py +105 -0
  27. edc_analytics/data.py +36 -0
  28. edc_analytics/row/__init__.py +4 -0
  29. edc_analytics/row/row_definition.py +43 -0
  30. edc_analytics/row/row_definitions.py +32 -0
  31. edc_analytics/row/row_statistics.py +88 -0
  32. edc_analytics/row/row_statistics_with_gender.py +115 -0
  33. edc_analytics/stata/__init__.py +1 -0
  34. edc_analytics/stata/get_stata_labels_from_model.py +44 -0
  35. edc_analytics/styler.py +93 -0
  36. edc_analytics/table.py +108 -0
  37. edc_analytics/urls.py +6 -0
  38. edc_appointment/migrations/0018_auto_20190305_0123.py +1 -1
  39. edc_appointment/migrations/0051_alter_appointment_revision_and_more.py +38 -0
  40. edc_auth/migrations/0001_squashed_0033_alter_userprofile_is_multisite_viewer.py +1 -1
  41. edc_auth/migrations/0012_auto_20191026_0034.py +1 -1
  42. edc_auth/migrations/0013_auto_20191026_0055.py +1 -1
  43. edc_auth/migrations/0025_permissions.py +1 -1
  44. edc_auth/migrations/0037_alter_edcpermissions_revision_alter_role_revision.py +38 -0
  45. edc_consent/migrations/0001_initial.py +1 -1
  46. edc_consent/migrations/0007_alter_edcpermissions_revision.py +26 -0
  47. edc_crf/migrations/0010_alter_crfstatus_revision.py +26 -0
  48. edc_dashboard/migrations/0001_initial.py +1 -1
  49. edc_dashboard/migrations/0007_alter_edcpermissions_revision.py +26 -0
  50. edc_data_manager/migrations/0001_initial.py +1 -1
  51. edc_data_manager/migrations/0025_edcpermissions.py +1 -1
  52. edc_data_manager/migrations/0042_alter_datadictionary_revision_and_more.py +98 -0
  53. edc_dx/__init__.py +6 -0
  54. edc_dx/apps.py +5 -0
  55. edc_dx/diagnoses.py +250 -0
  56. edc_dx/form_validators/__init__.py +2 -0
  57. edc_dx/form_validators/diagnosis_form_validator_mixin.py +54 -0
  58. edc_dx/form_validators/result_form_validator_mixin.py +65 -0
  59. edc_dx/utils.py +42 -0
  60. edc_dx_review/__init__.py +0 -0
  61. edc_dx_review/apps.py +5 -0
  62. edc_dx_review/auth_objects.py +13 -0
  63. edc_dx_review/auths.py +12 -0
  64. edc_dx_review/choices.py +24 -0
  65. edc_dx_review/constants.py +7 -0
  66. edc_dx_review/fieldsets.py +47 -0
  67. edc_dx_review/form_mixins/__init__.py +3 -0
  68. edc_dx_review/form_mixins/clinical_review_baseline_required_form_mixin.py +25 -0
  69. edc_dx_review/form_validator_mixins/__init__.py +6 -0
  70. edc_dx_review/form_validator_mixins/clinical_review_baseline_form_validator_mixin.py +7 -0
  71. edc_dx_review/form_validator_mixins/clinical_review_followup_form_validator_mixin.py +25 -0
  72. edc_dx_review/list_data.py +19 -0
  73. edc_dx_review/medical_date.py +195 -0
  74. edc_dx_review/migrations/0001_initial.py +307 -0
  75. edc_dx_review/migrations/0002_diagnosislocations_extra_value_and_more.py +32 -0
  76. edc_dx_review/migrations/0003_alter_diagnosislocations_options_and_more.py +148 -0
  77. edc_dx_review/migrations/0004_remove_diagnosislocations_edc_dx_revi_name_a39b40_idx_and_more.py +20 -0
  78. edc_dx_review/migrations/__init__.py +0 -0
  79. edc_dx_review/model_mixins/__init__.py +20 -0
  80. edc_dx_review/model_mixins/clinical_review_baseline_model_mixin.py +25 -0
  81. edc_dx_review/model_mixins/clinical_review_followup/__init__.py +5 -0
  82. edc_dx_review/model_mixins/clinical_review_followup/clinical_review_followup_chol_model_mixin.py +54 -0
  83. edc_dx_review/model_mixins/clinical_review_followup/clinical_review_followup_dm_model_mixin.py +54 -0
  84. edc_dx_review/model_mixins/clinical_review_followup/clinical_review_followup_hiv_model_mixin.py +54 -0
  85. edc_dx_review/model_mixins/clinical_review_followup/clinical_review_followup_htn_model_mixin.py +56 -0
  86. edc_dx_review/model_mixins/clinical_review_followup/clinical_review_followup_model_mixin.py +25 -0
  87. edc_dx_review/model_mixins/dx_location_model_mixin.py +17 -0
  88. edc_dx_review/model_mixins/factory/__init__.py +4 -0
  89. edc_dx_review/model_mixins/factory/baseline_review_model_mixin_factory.py +55 -0
  90. edc_dx_review/model_mixins/factory/calculate_date.py +43 -0
  91. edc_dx_review/model_mixins/factory/dx_initial_review_model_mixin_factory.py +97 -0
  92. edc_dx_review/model_mixins/factory/followup_review_model_mixin_factory.py +39 -0
  93. edc_dx_review/model_mixins/factory/rx_initial_review_model_mixin_factory.py +69 -0
  94. edc_dx_review/model_mixins/followup_review/__init__.py +2 -0
  95. edc_dx_review/model_mixins/followup_review/followup_review_model_mixin.py +22 -0
  96. edc_dx_review/model_mixins/followup_review/hiv_followup_review_model_mixin.py +32 -0
  97. edc_dx_review/model_mixins/initial_review/__init__.py +6 -0
  98. edc_dx_review/model_mixins/initial_review/chol_initial_review_model_mixin.py +34 -0
  99. edc_dx_review/model_mixins/initial_review/hiv_initial_model_mixins.py +119 -0
  100. edc_dx_review/model_mixins/initial_review/ncd_initial_review_model_mixin.py +42 -0
  101. edc_dx_review/models.py +20 -0
  102. edc_dx_review/radio_fields.py +30 -0
  103. edc_dx_review/utils.py +220 -0
  104. edc_export/migrations/0004_auto_20190305_0123.py +1 -1
  105. edc_export/migrations/0013_edcpermissions.py +1 -1
  106. edc_export/migrations/0024_alter_datarequest_revision_and_more.py +170 -0
  107. edc_facility/migrations/0005_healthfacility_healthfacilitytypes_and_more.py +1 -1
  108. edc_facility/migrations/0018_alter_healthfacility_revision_and_more.py +38 -0
  109. edc_form_runners/migrations/0006_alter_issue_revision.py +26 -0
  110. edc_identifier/migrations/0012_alter_identifiermodel_revision.py +26 -0
  111. edc_lab/migrations/0039_alter_aliquot_revision_alter_box_revision_and_more.py +269 -0
  112. edc_lab_dashboard/migrations/0006_alter_edcpermissions_revision.py +26 -0
  113. edc_label/migrations/0008_alter_zpllabeltemplates_revision.py +26 -0
  114. edc_listboard/migrations/0008_alter_listboard_revision.py +26 -0
  115. edc_locator/migrations/0042_alter_historicalsubjectlocator_revision_and_more.py +38 -0
  116. edc_metadata/migrations/0032_alter_crfmetadata_revision_and_more.py +38 -0
  117. edc_navbar/migrations/0010_alter_edcpermissions_revision.py +26 -0
  118. edc_notification/migrations/0012_alter_notification_revision.py +26 -0
  119. edc_offstudy/migrations/0025_alter_historicalsubjectoffstudy_revision_and_more.py +41 -0
  120. edc_pharmacy/migrations/0091_alter_allocation_revision_alter_assignment_revision_and_more.py +794 -0
  121. edc_protocol_incident/migrations/0026_alter_historicalprotocoldeviationviolation_revision_and_more.py +65 -0
  122. edc_pylabels/migrations/0014_alter_labelconfiguration_revision.py +26 -0
  123. edc_qareports/migrations/0021_alter_edcpermissions_revision_alter_note_revision.py +38 -0
  124. edc_randomization/migrations/0015_alter_edcpermissions_revision_and_more.py +50 -0
  125. edc_refusal/migrations/0014_alter_historicalsubjectrefusal_revision_and_more.py +38 -0
  126. edc_registration/migrations/0034_alter_historicalregisteredsubject_revision_and_more.py +41 -0
  127. edc_reportable/migrations/0008_alter_gradingdata_revision_and_more.py +110 -0
  128. edc_review_dashboard/migrations/0007_alter_edcpermissions_revision.py +26 -0
  129. edc_screening/migrations/0006_alter_edcpermissions_revision.py +26 -0
  130. edc_sites/migrations/0011_alter_edcpermissions_revision.py +26 -0
  131. edc_subject_dashboard/migrations/0006_alter_edcpermissions_revision.py +26 -0
  132. edc_unblinding/migrations/0016_alter_historicalunblindingrequest_revision_and_more.py +65 -0
  133. edc_visit_schedule/migrations/0021_alter_historicalonschedule_revision_and_more.py +89 -0
  134. edc_visit_tracking/migrations/0011_alter_historicalsubjectvisit_revision_and_more.py +65 -0
  135. edc_vitals/model_mixins/blood_pressure_model_mixin.py +1 -0
  136. {clinicedc-2.0.11.dist-info → clinicedc-2.0.13.dist-info}/WHEEL +0 -0
  137. {clinicedc-2.0.11.dist-info → clinicedc-2.0.13.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,126 @@
1
+ import pandas as pd
2
+ from edc_constants.constants import FEMALE, MALE
3
+
4
+ from ..constants import MEDIAN_IQR, N_ONLY, N_WITH_COL_PROP, N_WITH_ROW_PROP
5
+ from ..row import RowDefinition, RowDefinitions
6
+ from ..table import Table
7
+
8
+
9
+ class FastingFbgTable(Table):
10
+ def __init__(
11
+ self,
12
+ main_df: pd.DataFrame = None,
13
+ colname: str | None = None,
14
+ title: str | None = None,
15
+ ):
16
+ colname = colname or "fasting_fbg_hrs"
17
+ title = title or "Fasting duration (hrs)"
18
+ super().__init__(colname=colname, main_df=main_df, title=title)
19
+
20
+ @property
21
+ def row_definitions(self) -> RowDefinitions:
22
+ df_tmp = self.main_df.copy()
23
+ row_defs = RowDefinitions(reverse_rows=False)
24
+ row0 = RowDefinition(
25
+ title=self.title,
26
+ label=self.default_sublabel,
27
+ condition=(df_tmp["gender"].notna()),
28
+ columns={FEMALE: (N_ONLY, 2), MALE: (N_ONLY, 2), "All": (N_ONLY, 2)},
29
+ drop=False,
30
+ )
31
+ row_defs.add(row0)
32
+ columns = {
33
+ FEMALE: (MEDIAN_IQR, 2),
34
+ MALE: (MEDIAN_IQR, 2),
35
+ "All": (MEDIAN_IQR, 2),
36
+ }
37
+ row_defs.add(
38
+ RowDefinition(
39
+ colname=self.colname,
40
+ label="FBG fasted (hours), median (IQR)",
41
+ condition=(self.main_df[self.colname].notna()),
42
+ columns=columns,
43
+ drop=False,
44
+ )
45
+ )
46
+ columns = {
47
+ FEMALE: (N_WITH_COL_PROP, 2),
48
+ MALE: (N_WITH_COL_PROP, 2),
49
+ "All": (N_WITH_ROW_PROP, 2),
50
+ }
51
+ row_defs.add(
52
+ RowDefinition(
53
+ colname=self.colname,
54
+ label="FBG Fasted <8.0 hrs",
55
+ condition=(self.main_df[self.colname] < 8.0),
56
+ columns=columns,
57
+ drop=False,
58
+ )
59
+ )
60
+ row_defs.add(
61
+ RowDefinition(
62
+ colname=self.colname,
63
+ label="not measured",
64
+ condition=(self.main_df[self.colname].isna()),
65
+ columns=columns,
66
+ drop=False,
67
+ )
68
+ )
69
+ return row_defs
70
+
71
+
72
+ class FastingOgttTable(Table):
73
+ def __init__(self, main_df: pd.DataFrame = None):
74
+ super().__init__(colname="fasting_ogtt_hrs", main_df=main_df, title="")
75
+
76
+ @property
77
+ def row_definitions(self) -> RowDefinitions:
78
+ row_defs = RowDefinitions(reverse_rows=False)
79
+ columns = {
80
+ FEMALE: (MEDIAN_IQR, 2),
81
+ MALE: (MEDIAN_IQR, 2),
82
+ "All": (MEDIAN_IQR, 2),
83
+ }
84
+ row_defs.add(
85
+ RowDefinition(
86
+ colname=self.colname,
87
+ label="OGTT fasted (hours), median (IQR)",
88
+ condition=(self.main_df[self.colname].notna()),
89
+ columns=columns,
90
+ drop=False,
91
+ )
92
+ )
93
+ columns = {
94
+ FEMALE: (N_WITH_COL_PROP, 2),
95
+ MALE: (N_WITH_COL_PROP, 2),
96
+ "All": (N_WITH_ROW_PROP, 2),
97
+ }
98
+ row_defs.add(
99
+ RowDefinition(
100
+ colname=self.colname,
101
+ label="OGTT Fasted <8.0 hrs",
102
+ condition=(self.main_df[self.colname] < 8.0),
103
+ columns=columns,
104
+ drop=False,
105
+ )
106
+ )
107
+ row_defs.add(
108
+ RowDefinition(
109
+ colname=self.colname,
110
+ label="not measured",
111
+ condition=(self.main_df[self.colname].isna()),
112
+ columns=columns,
113
+ drop=False,
114
+ )
115
+ )
116
+ return row_defs
117
+
118
+
119
+ class FastingTable(Table):
120
+ def __init__(self, main_df: pd.DataFrame = None):
121
+ super().__init__(main_df=main_df, title="Fasting duration (hrs)")
122
+
123
+ def build_table_df(self) -> None:
124
+ df1 = FastingFbgTable(main_df=self.main_df).table_df
125
+ df2 = FastingOgttTable(main_df=self.main_df).table_df
126
+ self.table_df = pd.concat([df1, df2])
@@ -0,0 +1,98 @@
1
+ import pandas as pd
2
+ from edc_constants.constants import FEMALE, MALE
3
+
4
+ from ..constants import MEAN_95CI, N_ONLY, N_WITH_COL_PROP, N_WITH_ROW_PROP
5
+ from ..row import RowDefinition, RowDefinitions
6
+ from ..table import Table
7
+
8
+
9
+ class FbgTable(Table):
10
+ def __init__(self, main_df: pd.DataFrame = None):
11
+ super().__init__(colname="fbg", main_df=main_df, title="FBG (mmol/L) categories")
12
+
13
+ @property
14
+ def row_definitions(self) -> RowDefinitions:
15
+ df_tmp = self.main_df.copy()
16
+ row_defs = RowDefinitions(reverse_rows=False)
17
+ row0 = RowDefinition(
18
+ title=self.title,
19
+ label=self.default_sublabel,
20
+ condition=(df_tmp["gender"].notna()),
21
+ columns={FEMALE: (N_ONLY, 2), MALE: (N_ONLY, 2), "All": (N_ONLY, 2)},
22
+ drop=False,
23
+ )
24
+ row_defs.add(row0)
25
+
26
+ columns = {
27
+ FEMALE: (N_WITH_COL_PROP, 2),
28
+ MALE: (N_WITH_COL_PROP, 2),
29
+ "All": (N_WITH_ROW_PROP, 2),
30
+ }
31
+ row_defs.add(
32
+ RowDefinition(
33
+ colname=self.colname,
34
+ label="Not fasted",
35
+ condition=(self.main_df["fasting_fbg_hrs"] < 8.0),
36
+ columns=columns,
37
+ drop=True,
38
+ )
39
+ )
40
+
41
+ columns = {
42
+ FEMALE: (MEAN_95CI, 2),
43
+ MALE: (MEAN_95CI, 2),
44
+ "All": (MEAN_95CI, 2),
45
+ }
46
+ row_mean = RowDefinition(
47
+ colname=self.colname,
48
+ label="Mean (95% CI)",
49
+ condition=(self.main_df[self.colname].notna()),
50
+ columns=columns,
51
+ drop=False,
52
+ )
53
+ columns = {
54
+ FEMALE: (N_WITH_COL_PROP, 2),
55
+ MALE: (N_WITH_COL_PROP, 2),
56
+ "All": (N_WITH_ROW_PROP, 2),
57
+ }
58
+
59
+ row_defs.add(
60
+ RowDefinition(
61
+ colname=self.colname,
62
+ label="<6.1",
63
+ condition=(self.main_df[self.colname] < 6.1),
64
+ columns=columns,
65
+ drop=True,
66
+ )
67
+ )
68
+ row_defs.add(
69
+ RowDefinition(
70
+ colname=self.colname,
71
+ label="6.1-6.9",
72
+ condition=(self.main_df[self.colname] >= 6.1)
73
+ & (self.main_df[self.colname] < 7.0),
74
+ columns=columns,
75
+ drop=True,
76
+ )
77
+ )
78
+ row_defs.add(
79
+ RowDefinition(
80
+ colname=self.colname,
81
+ label="7.0 and above",
82
+ condition=(self.main_df[self.colname] >= 7.0),
83
+ columns=columns,
84
+ drop=True,
85
+ )
86
+ )
87
+ row_defs.add(
88
+ RowDefinition(
89
+ colname=self.colname,
90
+ label="not measured",
91
+ condition=(self.main_df[self.colname].isna()),
92
+ columns=columns,
93
+ drop=True,
94
+ )
95
+ )
96
+
97
+ row_defs.add(row_mean)
98
+ return row_defs
@@ -0,0 +1,384 @@
1
+ import pandas as pd
2
+ from edc_constants.constants import FEMALE, MALE
3
+
4
+ from ..constants import N_ONLY, N_WITH_COL_PROP, N_WITH_ROW_PROP
5
+ from ..row import RowDefinition, RowDefinitions
6
+ from ..table import Table
7
+
8
+
9
+ class FbgOgttTable1(Table):
10
+
11
+ fbg_colname = "fbg"
12
+ ogtt_colname = "ogtt"
13
+
14
+ def __init__(self, main_df: pd.DataFrame = None):
15
+ super().__init__(
16
+ colname="",
17
+ main_df=main_df,
18
+ title="OGTT & FBG (mmol/L) categories",
19
+ )
20
+
21
+ @property
22
+ def row_definitions(self) -> RowDefinitions:
23
+ df_tmp = self.main_df.copy()
24
+ row_defs = RowDefinitions(reverse_rows=False)
25
+ row0 = RowDefinition(
26
+ title=self.title,
27
+ label=self.default_sublabel,
28
+ condition=(df_tmp["gender"].notna()),
29
+ columns={FEMALE: (N_ONLY, 2), MALE: (N_ONLY, 2), "All": (N_ONLY, 2)},
30
+ drop=False,
31
+ )
32
+ row_defs.add(row0)
33
+ columns = {
34
+ FEMALE: (N_WITH_COL_PROP, 2),
35
+ MALE: (N_WITH_COL_PROP, 2),
36
+ "All": (N_WITH_ROW_PROP, 2),
37
+ }
38
+
39
+ row_defs.add(
40
+ RowDefinition(
41
+ colname=self.colname,
42
+ label="Not fasted",
43
+ condition=(
44
+ (self.main_df["fasting_fbg_hrs"] < 8.0)
45
+ | (self.main_df["fasting_ogtt_hrs"] < 8.0)
46
+ ),
47
+ columns=columns,
48
+ drop=True,
49
+ )
50
+ )
51
+
52
+ condition = (
53
+ (self.main_df[self.ogtt_colname] >= 11.1)
54
+ & (self.main_df[self.fbg_colname] >= 7.0)
55
+ & (self.main_df[self.ogtt_colname].notna())
56
+ & (self.main_df[self.fbg_colname].notna())
57
+ )
58
+ row_defs.add(
59
+ RowDefinition(
60
+ colname=self.colname,
61
+ label="OGTT ≥11.1 and FBG ≥7.0",
62
+ condition=condition,
63
+ columns=columns,
64
+ drop=True,
65
+ )
66
+ )
67
+
68
+ condition = (
69
+ ((df_tmp[self.ogtt_colname] >= 11.1) | (df_tmp[self.fbg_colname] >= 7.0))
70
+ & (df_tmp[self.fbg_colname].notna())
71
+ & (df_tmp[self.ogtt_colname].notna())
72
+ )
73
+
74
+ row_defs.add(
75
+ RowDefinition(
76
+ colname=self.colname,
77
+ label="OGTT ≥11.1 or FBG ≥7.0",
78
+ condition=condition,
79
+ columns=columns,
80
+ drop=True,
81
+ )
82
+ )
83
+
84
+ condition = (
85
+ ((df_tmp[self.fbg_colname] >= 6.1) | (df_tmp[self.ogtt_colname] >= 7.8))
86
+ & (df_tmp[self.fbg_colname].notna())
87
+ & (df_tmp[self.ogtt_colname].notna())
88
+ )
89
+ row_defs.add(
90
+ RowDefinition(
91
+ colname=self.colname,
92
+ label="OGTT ≥7.8 or FBG ≥6.1",
93
+ condition=condition,
94
+ columns=columns,
95
+ drop=True,
96
+ )
97
+ )
98
+
99
+ condition = (
100
+ ((df_tmp[self.fbg_colname] < 6.1) | (df_tmp[self.ogtt_colname] < 7.8))
101
+ & (df_tmp[self.fbg_colname].notna())
102
+ & (df_tmp[self.ogtt_colname].notna())
103
+ )
104
+ row_defs.add(
105
+ RowDefinition(
106
+ colname=self.colname,
107
+ label="OGTT <7.8 or FBG <6.1",
108
+ condition=condition,
109
+ columns=columns,
110
+ drop=True,
111
+ )
112
+ )
113
+
114
+ condition = (df_tmp[self.fbg_colname].notna()) & (df_tmp[self.ogtt_colname].notna())
115
+ row_defs.add(
116
+ RowDefinition(
117
+ colname=self.colname,
118
+ label="Other",
119
+ condition=condition,
120
+ columns=columns,
121
+ drop=True,
122
+ )
123
+ )
124
+
125
+ condition = (df_tmp[self.fbg_colname].notna()) & (df_tmp[self.ogtt_colname].isna())
126
+ row_defs.add(
127
+ RowDefinition(
128
+ colname=self.colname,
129
+ label="OGTT not measured",
130
+ condition=condition,
131
+ columns=columns,
132
+ drop=True,
133
+ )
134
+ )
135
+ condition = (df_tmp[self.fbg_colname].isna()) & (df_tmp[self.ogtt_colname].notna())
136
+ row_defs.add(
137
+ RowDefinition(
138
+ colname=self.colname,
139
+ label="FBG not measured",
140
+ condition=condition,
141
+ columns=columns,
142
+ drop=True,
143
+ )
144
+ )
145
+ condition = (df_tmp[self.fbg_colname].isna()) & (df_tmp[self.ogtt_colname].isna())
146
+ row_defs.add(
147
+ RowDefinition(
148
+ colname=self.colname,
149
+ label="not measured",
150
+ condition=condition,
151
+ columns=columns,
152
+ drop=True,
153
+ )
154
+ )
155
+ return row_defs
156
+
157
+
158
+ class FbgOgttTable2(Table):
159
+
160
+ fbg_colname = "fbg"
161
+ ogtt_colname = "ogtt"
162
+
163
+ def __init__(self, main_df: pd.DataFrame = None):
164
+ super().__init__(
165
+ colname="",
166
+ main_df=main_df,
167
+ title="OGTT & FBG (mmol/L) additional",
168
+ )
169
+
170
+ @property
171
+ def row_definitions(self) -> RowDefinitions:
172
+ df_tmp = self.main_df.copy()
173
+ row_defs = RowDefinitions(reverse_rows=False)
174
+ row0 = RowDefinition(
175
+ title=self.title,
176
+ label="Glucose levels, n (%)",
177
+ condition=(df_tmp["gender"].notna()),
178
+ columns={FEMALE: (N_ONLY, 2), MALE: (N_ONLY, 2), "All": (N_ONLY, 2)},
179
+ drop=False,
180
+ )
181
+ row_defs.add(row0)
182
+ columns = {
183
+ FEMALE: (N_WITH_COL_PROP, 2),
184
+ MALE: (N_WITH_COL_PROP, 2),
185
+ "All": (N_WITH_ROW_PROP, 2),
186
+ }
187
+
188
+ row_defs.add(
189
+ RowDefinition(
190
+ colname=self.colname,
191
+ label="Not fasted",
192
+ condition=(
193
+ (self.main_df["fasting_fbg_hrs"] < 8.0)
194
+ | (self.main_df["fasting_ogtt_hrs"] < 8.0)
195
+ ),
196
+ columns=columns,
197
+ drop=True,
198
+ )
199
+ )
200
+
201
+ condition = (
202
+ (self.main_df[self.fbg_colname] < 6.1)
203
+ & (self.main_df[self.ogtt_colname] < 7.8)
204
+ & (self.main_df[self.ogtt_colname].notna())
205
+ & (self.main_df[self.fbg_colname].notna())
206
+ )
207
+ row_defs.add(
208
+ RowDefinition(
209
+ colname=self.colname,
210
+ label="FBG <6.1 mmol/l and after OGTT <7.8 mmol/l",
211
+ condition=condition,
212
+ columns=columns,
213
+ drop=True,
214
+ )
215
+ )
216
+
217
+ condition = (
218
+ (self.main_df[self.fbg_colname] < 6.1)
219
+ & (self.main_df[self.ogtt_colname] >= 7.8)
220
+ & (self.main_df[self.ogtt_colname] < 11.1)
221
+ & (self.main_df[self.ogtt_colname].notna())
222
+ & (self.main_df[self.fbg_colname].notna())
223
+ )
224
+ row_defs.add(
225
+ RowDefinition(
226
+ colname=self.colname,
227
+ label="FBG <6.1 mmol/l and after OGTT 7.8–11.0 mmol/l",
228
+ condition=condition,
229
+ columns=columns,
230
+ drop=True,
231
+ )
232
+ )
233
+
234
+ condition = (
235
+ (self.main_df[self.fbg_colname] >= 6.1)
236
+ & (self.main_df[self.fbg_colname] < 7.0)
237
+ & (self.main_df[self.ogtt_colname] < 7.8)
238
+ & (self.main_df[self.ogtt_colname].notna())
239
+ & (self.main_df[self.fbg_colname].notna())
240
+ )
241
+ row_defs.add(
242
+ RowDefinition(
243
+ colname=self.colname,
244
+ label="FBG 6.1–6.9 mmol/l and after OGTT <7.8 mmol/l",
245
+ condition=condition,
246
+ columns=columns,
247
+ drop=True,
248
+ )
249
+ )
250
+
251
+ condition = (
252
+ (self.main_df[self.fbg_colname] >= 6.1)
253
+ & (self.main_df[self.fbg_colname] < 7.0)
254
+ & (self.main_df[self.ogtt_colname] >= 7.8)
255
+ & (self.main_df[self.ogtt_colname] < 11.1)
256
+ & (self.main_df[self.ogtt_colname].notna())
257
+ & (self.main_df[self.fbg_colname].notna())
258
+ )
259
+ row_defs.add(
260
+ RowDefinition(
261
+ colname=self.colname,
262
+ label="FBG 6.1–6.9 mmol/l and after OGTT 7.8–11.0 mmol/l",
263
+ condition=condition,
264
+ columns=columns,
265
+ drop=True,
266
+ )
267
+ )
268
+
269
+ condition = (
270
+ (self.main_df[self.fbg_colname] >= 6.1)
271
+ & (self.main_df[self.fbg_colname] < 7.0)
272
+ & (self.main_df[self.ogtt_colname] >= 11.1)
273
+ & (self.main_df[self.ogtt_colname].notna())
274
+ & (self.main_df[self.fbg_colname].notna())
275
+ )
276
+ row_defs.add(
277
+ RowDefinition(
278
+ colname=self.colname,
279
+ label="FBG 6.1–6.9 mmol/l and after OGTT ≥11.0 mmol/l",
280
+ condition=condition,
281
+ columns=columns,
282
+ drop=True,
283
+ )
284
+ )
285
+
286
+ condition = (
287
+ (self.main_df[self.fbg_colname] >= 7.0)
288
+ & (self.main_df[self.ogtt_colname] < 7.8)
289
+ & (self.main_df[self.ogtt_colname].notna())
290
+ & (self.main_df[self.fbg_colname].notna())
291
+ )
292
+ row_defs.add(
293
+ RowDefinition(
294
+ colname=self.colname,
295
+ label="FBG ≥7.0 mmol/l and after OGTT <7.8 mmol/l",
296
+ condition=condition,
297
+ columns=columns,
298
+ drop=True,
299
+ )
300
+ )
301
+
302
+ condition = (
303
+ (self.main_df[self.fbg_colname] >= 7.0)
304
+ & (self.main_df[self.ogtt_colname] >= 7.8)
305
+ & (self.main_df[self.ogtt_colname] < 11.1)
306
+ & (self.main_df[self.ogtt_colname].notna())
307
+ & (self.main_df[self.fbg_colname].notna())
308
+ )
309
+ row_defs.add(
310
+ RowDefinition(
311
+ colname=self.colname,
312
+ label="FBG ≥7.0 mmol/l and after OGTT 7.8–11.0 mmol/l",
313
+ condition=condition,
314
+ columns=columns,
315
+ drop=True,
316
+ )
317
+ )
318
+
319
+ condition = (
320
+ (self.main_df[self.fbg_colname] >= 7.0)
321
+ & (self.main_df[self.ogtt_colname] >= 11.1)
322
+ & (self.main_df[self.ogtt_colname].notna())
323
+ & (self.main_df[self.fbg_colname].notna())
324
+ )
325
+ row_defs.add(
326
+ RowDefinition(
327
+ colname=self.colname,
328
+ label="FBG ≥7.0 mmol/l and after OGTT ≥11.1 mmol/l",
329
+ condition=condition,
330
+ columns=columns,
331
+ drop=True,
332
+ )
333
+ )
334
+
335
+ condition = (self.main_df[self.ogtt_colname].notna()) | (
336
+ self.main_df[self.fbg_colname].isna()
337
+ )
338
+ row_defs.add(
339
+ RowDefinition(
340
+ colname=self.colname,
341
+ label="FBG not measured",
342
+ condition=condition,
343
+ columns=columns,
344
+ drop=True,
345
+ )
346
+ )
347
+
348
+ condition = (self.main_df[self.ogtt_colname].isna()) | (
349
+ self.main_df[self.fbg_colname].notna()
350
+ )
351
+ row_defs.add(
352
+ RowDefinition(
353
+ colname=self.colname,
354
+ label="OGTT not measured",
355
+ condition=condition,
356
+ columns=columns,
357
+ drop=True,
358
+ )
359
+ )
360
+
361
+ condition = (self.main_df[self.ogtt_colname].isna()) | (
362
+ self.main_df[self.fbg_colname].isna()
363
+ )
364
+ row_defs.add(
365
+ RowDefinition(
366
+ colname=self.colname,
367
+ label="not measured",
368
+ condition=condition,
369
+ columns=columns,
370
+ drop=True,
371
+ )
372
+ )
373
+ return row_defs
374
+
375
+
376
+ class FbgOgttTable(Table):
377
+
378
+ def __init__(self, main_df: pd.DataFrame = None):
379
+ super().__init__(colname="", main_df=main_df, title="")
380
+
381
+ def build_table_df(self) -> None:
382
+ df1 = FbgOgttTable1(main_df=self.main_df).table_df
383
+ df2 = FbgOgttTable2(main_df=self.main_df).table_df
384
+ self.table_df = pd.concat([df1, df2])
@@ -0,0 +1,12 @@
1
+ import pandas as pd
2
+
3
+ from ..table import Table
4
+
5
+
6
+ class GenderTable(Table):
7
+ def __init__(self, main_df: pd.DataFrame = None):
8
+ super().__init__(
9
+ colname="gender",
10
+ main_df=main_df,
11
+ title="Gender",
12
+ )
@@ -0,0 +1,87 @@
1
+ import pandas as pd
2
+ from edc_constants.constants import FEMALE, MALE
3
+
4
+ from ..constants import MEAN_95CI, N_ONLY, N_WITH_COL_PROP, N_WITH_ROW_PROP
5
+ from ..row import RowDefinition, RowDefinitions
6
+ from ..table import Table
7
+
8
+
9
+ class HbA1cTable(Table):
10
+ def __init__(self, main_df: pd.DataFrame = None):
11
+ super().__init__(
12
+ colname="hba1c_value",
13
+ main_df=main_df,
14
+ title="HbA1C (%) categories",
15
+ )
16
+
17
+ @property
18
+ def row_definitions(self) -> RowDefinitions:
19
+ df_tmp = self.main_df.copy()
20
+ row_defs = RowDefinitions(reverse_rows=False)
21
+ row0 = RowDefinition(
22
+ title=self.title,
23
+ label=self.default_sublabel,
24
+ condition=(df_tmp["gender"].notna()),
25
+ columns={FEMALE: (N_ONLY, 2), MALE: (N_ONLY, 2), "All": (N_ONLY, 2)},
26
+ drop=False,
27
+ )
28
+ row_defs.add(row0)
29
+
30
+ columns = {
31
+ FEMALE: (MEAN_95CI, 2),
32
+ MALE: (MEAN_95CI, 2),
33
+ "All": (MEAN_95CI, 2),
34
+ }
35
+ row_mean = RowDefinition(
36
+ colname=self.colname,
37
+ label="Mean (95% CI)",
38
+ condition=(self.main_df[self.colname].notna()),
39
+ columns=columns,
40
+ drop=False,
41
+ )
42
+
43
+ columns = {
44
+ FEMALE: (N_WITH_COL_PROP, 2),
45
+ MALE: (N_WITH_COL_PROP, 2),
46
+ "All": (N_WITH_ROW_PROP, 2),
47
+ }
48
+ row_defs.add(
49
+ RowDefinition(
50
+ colname=self.colname,
51
+ label="<6.0",
52
+ condition=(self.main_df[self.colname] < 6.0),
53
+ columns=columns,
54
+ drop=False,
55
+ )
56
+ )
57
+ row_defs.add(
58
+ RowDefinition(
59
+ colname=self.colname,
60
+ label="≥6.0 and ≤6.4",
61
+ condition=(
62
+ (self.main_df[self.colname] >= 6.0) & (self.main_df[self.colname] <= 6.4)
63
+ ),
64
+ columns=columns,
65
+ drop=False,
66
+ )
67
+ )
68
+ row_defs.add(
69
+ RowDefinition(
70
+ colname=self.colname,
71
+ label=">6.4",
72
+ condition=(self.main_df[self.colname] > 6.4),
73
+ columns=columns,
74
+ drop=False,
75
+ )
76
+ )
77
+ row_defs.add(
78
+ RowDefinition(
79
+ colname=self.colname,
80
+ label="not measured",
81
+ condition=(self.main_df[self.colname].isna()),
82
+ columns=columns,
83
+ drop=False,
84
+ )
85
+ )
86
+ row_defs.add(row_mean)
87
+ return row_defs