meta-edc 1.2.6__py3-none-any.whl → 1.2.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.

Potentially problematic release.


This version of meta-edc might be problematic. Click here for more details.

Files changed (40) hide show
  1. meta_analytics/dataframes/constants.py +3 -1
  2. meta_analytics/dataframes/get_glucose_df.py +13 -3
  3. meta_analytics/dataframes/glucose_endpoints/endpoint_by_date.py +27 -5
  4. meta_analytics/dataframes/glucose_endpoints/glucose_endpoints_by_date.py +61 -8
  5. meta_analytics/dataframes/screening/get_screening_df.py +1 -5
  6. meta_consent/migrations/0035_alter_historicalsubjectconsent_consent_definition_name_and_more.py +43 -0
  7. meta_dashboard/navbars.py +2 -6
  8. meta_dashboard/urls.py +5 -5
  9. meta_dashboard/views/screening/listboard_view.py +2 -3
  10. meta_dashboard/views/subject/dashboard/dashboard_view.py +4 -5
  11. meta_dashboard/views/subject/listboard/listboard_view.py +2 -3
  12. meta_edc/settings/debug.py +2 -2
  13. {meta_edc-1.2.6.dist-info → meta_edc-1.2.7.dist-info}/METADATA +5 -5
  14. {meta_edc-1.2.6.dist-info → meta_edc-1.2.7.dist-info}/RECORD +40 -28
  15. {meta_edc-1.2.6.dist-info → meta_edc-1.2.7.dist-info}/WHEEL +1 -1
  16. meta_prn/forms/offschedule_form.py +25 -0
  17. meta_screening/admin/subject_screening_admin.py +4 -3
  18. meta_subject/admin/__init__.py +2 -0
  19. meta_subject/admin/glucose_fbg_admin.py +12 -1
  20. meta_subject/admin/hiv_exit_review_admin.py +49 -0
  21. meta_subject/form_validators/__init__.py +4 -0
  22. meta_subject/form_validators/glucose_fbg_form_validator.py +77 -0
  23. meta_subject/form_validators/glucose_form_validator.py +10 -82
  24. meta_subject/form_validators/hiv_exit_review_form_validator.py +18 -0
  25. meta_subject/form_validators/mixins.py +95 -0
  26. meta_subject/forms/__init__.py +2 -0
  27. meta_subject/forms/glucose_fbg_form.py +1 -46
  28. meta_subject/forms/hiv_exit_review_form.py +13 -0
  29. meta_subject/migrations/0235_glucosefbg_endpoint_today_and_more.py +606 -0
  30. meta_subject/migrations/0236_alter_historicalhivexitreview_other_current_arv_regimen_and_more.py +58 -0
  31. meta_subject/migrations/0237_historicalhivexitreview_singleton_field_and_more.py +68 -0
  32. meta_subject/migrations/0238_historicalhivexitreview_available_and_more.py +88 -0
  33. meta_subject/model_mixins/__init__.py +2 -0
  34. meta_subject/model_mixins/arv_history_model_mixin.py +3 -44
  35. meta_subject/model_mixins/arv_review_model_mixin.py +53 -0
  36. meta_subject/models/__init__.py +2 -0
  37. meta_subject/models/glucose_fbg.py +15 -1
  38. meta_subject/models/hiv_exit_review.py +44 -0
  39. meta_visit_schedule/visit_schedules/phase_three/crfs.py +14 -0
  40. {meta_edc-1.2.6.dist-info → meta_edc-1.2.7.dist-info}/licenses/LICENSE +0 -0
@@ -2,10 +2,11 @@ CASE_EOS = 7
2
2
  CASE_FBGS_WITH_FIRST_OGTT = 2
3
3
  CASE_FBGS_WITH_SECOND_OGTT = 3
4
4
  CASE_FBG_ONLY = 4
5
+ CASE_FBG_VERY_HIGH = 5
5
6
  CASE_OGTT = 1
6
7
  EOS_DM_MET = "EOS - Patient developed diabetes"
7
8
  OGTT_THRESHOLD_MET = "OGTT >= 11.1"
8
-
9
+ FBG_BEYOND_THRESHOLD = 20.0
9
10
  endpoint_columns = [
10
11
  "subject_identifier",
11
12
  "site_id",
@@ -29,5 +30,6 @@ endpoint_cases = {
29
30
  CASE_FBGS_WITH_FIRST_OGTT: "FBG >= 7 x 2, first OGTT<=11.1",
30
31
  CASE_FBGS_WITH_SECOND_OGTT: "FBG >= 7 x 2, second OGTT<=11.1",
31
32
  CASE_FBG_ONLY: "FBG >= 7 x 2, OGTT not considered",
33
+ # CASE_FBG_VERY_HIGH: f"FBG>={FBG_BEYOND_THRESHOLD}",
32
34
  CASE_EOS: EOS_DM_MET,
33
35
  }
@@ -7,13 +7,23 @@ from edc_pdutils.dataframes import get_eos, get_subject_consent, get_subject_vis
7
7
  from meta_subject.models import Glucose, GlucoseFbg
8
8
 
9
9
 
10
- def get_glucose_df() -> pd.DataFrame:
10
+ def get_glucose_df(subject_identifiers: list[str] | None = None) -> pd.DataFrame:
11
11
  subject_visit_df = (
12
- get_subject_visit("meta_subject.subjectvisit")
12
+ get_subject_visit("meta_subject.subjectvisit", subject_identifiers)
13
13
  .rename(columns={"id": "subject_visit_id"})
14
14
  .query("appt_timing!=@MISSED_APPT")
15
15
  )
16
- df_glucose_fbg = read_frame(GlucoseFbg.objects.all(), verbose=False).rename(
16
+ if subject_identifiers:
17
+ df_glucose_fbg = read_frame(
18
+ GlucoseFbg.objects.filter(
19
+ subject_visit__subject_identifier__in=subject_identifiers
20
+ ),
21
+ verbose=False,
22
+ )
23
+ else:
24
+ df_glucose_fbg = read_frame(GlucoseFbg.objects.all(), verbose=False)
25
+
26
+ df_glucose_fbg = df_glucose_fbg.rename(
17
27
  columns={"fasting": "fasted", "subject_visit": "subject_visit_id"},
18
28
  )
19
29
  df_glucose_fbg["fasting_hrs"] = np.nan
@@ -67,9 +67,11 @@ class CaseData:
67
67
  self.previous_fasted = self.df.loc[self.index - 1, "fasted"]
68
68
 
69
69
  def case_two(self) -> bool:
70
- """ "FBG >= 7 x 2, first OGTT<=11.1"""
70
+ """FBG >= 7 x 2, first OGTT<=11.1"""
71
71
  return bool(
72
- self.fbg_value >= self.fbg_threshold
72
+ pd.notna(self.next_fbg_datetime)
73
+ and pd.notna(self.fbg_datetime)
74
+ and self.fbg_value >= self.fbg_threshold
73
75
  and self.next_fbg_value >= self.fbg_threshold
74
76
  and 0.0 < self.ogtt_value < self.ogtt_threshold
75
77
  and self.fasted == YES
@@ -78,9 +80,11 @@ class CaseData:
78
80
  )
79
81
 
80
82
  def case_three(self) -> bool:
81
- """ "FBG >= 7 x 2, second OGTT<=11.1"""
83
+ """FBG >= 7 x 2, second OGTT<=11.1"""
82
84
  return bool(
83
- self.fbg_value >= self.fbg_threshold
85
+ pd.notna(self.next_fbg_datetime)
86
+ and pd.notna(self.fbg_datetime)
87
+ and self.fbg_value >= self.fbg_threshold
84
88
  and self.next_fbg_value >= self.fbg_threshold
85
89
  and 0.0 < self.next_ogtt_value < self.ogtt_threshold
86
90
  and self.fasted == YES
@@ -91,7 +95,9 @@ class CaseData:
91
95
  def case_two_reversed(self) -> bool:
92
96
  """Same as case 2, but with the previous FBG reading."""
93
97
  return bool(
94
- self.fbg_value >= self.fbg_threshold
98
+ pd.notna(self.next_fbg_datetime)
99
+ and pd.notna(self.fbg_datetime)
100
+ and self.fbg_value >= self.fbg_threshold
95
101
  and self.previous_fbg_value >= self.fbg_threshold
96
102
  and 0.0 < self.previous_ogtt_value < self.ogtt_threshold
97
103
  and self.fasted == YES
@@ -99,6 +105,19 @@ class CaseData:
99
105
  and (self.fbg_datetime.date() - self.previous_fbg_datetime.date()).days > 6
100
106
  )
101
107
 
108
+ # def case_four(self) -> bool:
109
+ # """FBG >= 20.0"""
110
+ # return bool(
111
+ # pd.notna(self.next_fbg_datetime)
112
+ # and pd.notna(self.fbg_datetime)
113
+ # and self.fbg_value >= self.fbg_threshold
114
+ # and self.next_fbg_value >= self.fbg_threshold
115
+ # and 0.0 < self.next_ogtt_value < self.ogtt_threshold
116
+ # and self.fasted == YES
117
+ # and self.next_fasted == YES
118
+ # and (self.next_fbg_datetime.date() - self.fbg_datetime.date()).days > 6
119
+ # )
120
+
102
121
 
103
122
  class EndpointByDate:
104
123
  """Given all timepoints for a subject, flag the first timepoint
@@ -113,6 +132,9 @@ class EndpointByDate:
113
132
  * case 2. FBG >= 7 x 2, first OGTT<11.1
114
133
  * case 3. FBG >= 7 x 2, second OGTT<11.1
115
134
 
135
+ If the endpoint is reached by FBG+OGTT, the date of endpoint is
136
+ always the date of the second measurement.
137
+
116
138
  Additional criteria considered:
117
139
  1. any threshhold FBG must be taken while fasted (fasted=YES)
118
140
  2. threshhold FBG readings must be consecutive (no
@@ -6,9 +6,11 @@ from edc_constants.constants import NULL_STRING, YES
6
6
 
7
7
  from ..constants import (
8
8
  CASE_EOS,
9
+ CASE_FBG_ONLY,
9
10
  CASE_FBGS_WITH_FIRST_OGTT,
10
11
  CASE_FBGS_WITH_SECOND_OGTT,
11
12
  CASE_OGTT,
13
+ FBG_BEYOND_THRESHOLD,
12
14
  endpoint_cases,
13
15
  endpoint_columns,
14
16
  )
@@ -40,6 +42,7 @@ class GlucoseEndpointsByDate:
40
42
  """
41
43
 
42
44
  fbg_threshhold = 7.0
45
+ fbg_beyond_threshold = FBG_BEYOND_THRESHOLD
43
46
  ogtt_threshhold = 11.1
44
47
  endpoint_cls = EndpointByDate
45
48
  keep_cols = [ # noqa: RUF012
@@ -77,13 +80,15 @@ class GlucoseEndpointsByDate:
77
80
  ]
78
81
  self.endpoint_cases = {k: v for k, v in endpoint_cases.items() if k in self.case_list}
79
82
 
80
- self.df = get_glucose_df().copy()
83
+ self.df = get_glucose_df(subject_identifiers=self.subject_identifiers).copy()
81
84
 
82
85
  # label rows by type of glu tests (ones with value)
83
86
  self.df["test"] = self.df.apply(get_test_string, axis=1)
84
87
 
85
- self.df = self.df.sort_values(by=["subject_identifier", "fbg_datetime"]).reset_index(
86
- drop=True
88
+ self.df = (
89
+ self.df.query("not (fbg_value.isna() and ogtt_value.isna())")
90
+ .sort_values(by=["subject_identifier", "fbg_datetime"])
91
+ .reset_index(drop=True)
87
92
  )
88
93
  self.working_df = self.df.copy()
89
94
  self.working_df["endpoint"] = 0
@@ -91,11 +96,11 @@ class GlucoseEndpointsByDate:
91
96
 
92
97
  def run(self):
93
98
  self.process_by_ogtt_only()
99
+ # self.process_by_fbg_only()
94
100
  subject_identifiers_df = get_unique_subject_identifiers(self.df)
95
101
  for _, row in subject_identifiers_df.iterrows():
96
- subject_df = self.get_subject_df(row["subject_identifier"])
97
102
  subject_df = self.endpoint_cls(
98
- subject_df=subject_df,
103
+ subject_df=self.get_subject_df(row["subject_identifier"]),
99
104
  fbg_threshhold=self.fbg_threshhold,
100
105
  ogtt_threshhold=self.ogtt_threshhold,
101
106
  ).subject_df
@@ -105,6 +110,53 @@ class GlucoseEndpointsByDate:
105
110
  self.post_check_endpoint()
106
111
  self.merge_with_final_endpoints()
107
112
 
113
+ def process_by_fbg_only(self):
114
+ """Flag subjects that met endpoint by hitting the absurd FBG
115
+
116
+ Not used yet. Waiting for confirmation from Anu.
117
+ """
118
+ subject_endpoint_df = self.working_df.loc[
119
+ (self.working_df["fbg_value"] >= self.fbg_beyond_threshold)
120
+ # & (self.working_df["fasted"] == YES)
121
+ ].copy()
122
+
123
+ subject_endpoint_df = (
124
+ subject_endpoint_df.sort_values(by=["subject_identifier", "fbg_datetime"])
125
+ .reset_index(drop=True)
126
+ .drop_duplicates(subset=["subject_identifier"], keep="first")
127
+ .reset_index(drop=True)
128
+ )
129
+ if not subject_endpoint_df.empty:
130
+ # flag the selected endpoint rows as endpoints
131
+ subject_endpoint_df["endpoint"] = 1
132
+ subject_endpoint_df["endpoint_label"] = self.endpoint_cases[CASE_OGTT]
133
+ subject_endpoint_df["endpoint_type"] = CASE_FBG_ONLY
134
+ subject_endpoint_df["interval_in_days"] = np.nan
135
+
136
+ # add back the others rows for these subjects
137
+ subjects_df = self.working_df.loc[
138
+ (
139
+ self.working_df["subject_identifier"].isin(
140
+ subject_endpoint_df["subject_identifier"]
141
+ )
142
+ & ~(
143
+ self.working_df["fbg_datetime"].isin(
144
+ subject_endpoint_df["fbg_datetime"]
145
+ )
146
+ )
147
+ )
148
+ ].copy()
149
+ subjects_df = subjects_df.reset_index(drop=True)
150
+ subjects_df["endpoint"] = np.nan
151
+ subjects_df["endpoint_label"] = None
152
+ subjects_df["endpoint_type"] = None
153
+ subjects_df["interval_in_days"] = np.nan
154
+ subjects_df = pd.concat([subjects_df, subject_endpoint_df])
155
+ subjects_df = subjects_df.reset_index(drop=True)
156
+
157
+ self.append_subject_to_endpoint_df(subjects_df[endpoint_columns])
158
+ self.remove_subjects_from_working_df(subjects_df)
159
+
108
160
  def process_by_ogtt_only(self):
109
161
  """Flag subjects that met endpoint by hitting the OGTT
110
162
  threshold.
@@ -126,7 +178,7 @@ class GlucoseEndpointsByDate:
126
178
  """
127
179
  subject_endpoint_df = self.working_df.loc[
128
180
  (self.working_df["ogtt_value"] >= self.ogtt_threshhold)
129
- & (self.working_df["ogtt_value"] < 9999.99)
181
+ & (self.working_df["ogtt_value"] <= 9999.99)
130
182
  & (self.working_df["fasted"] == YES)
131
183
  & (self.working_df["fbg_value"].notna())
132
184
  ].copy()
@@ -292,8 +344,9 @@ class GlucoseEndpointsByDate:
292
344
  how="left",
293
345
  suffixes=("", "_y"),
294
346
  )
295
- self.df = self.df.sort_values(by=["subject_identifier", "fbg_datetime"])
296
- self.df = self.df.reset_index(drop=True)
347
+ self.df = self.df.sort_values(by=["subject_identifier", "fbg_datetime"]).reset_index(
348
+ drop=True
349
+ )
297
350
 
298
351
  def to_model(self):
299
352
  """Write endpoint_only_df to the Endpoints model"""
@@ -124,16 +124,12 @@ def get_screening_df(df: pd.DataFrame | None = None) -> pd.DataFrame:
124
124
  df_physical_exam = read_frame(qs_physical_exam)
125
125
  # merge w/ subject visit to get subject_identifier
126
126
  df_physical_exam = df_physical_exam.merge(
127
- df_physical_exam,
128
127
  df_subject_visit[
129
128
  ["subject_visit", "subject_identifier", "visit_code", "visit_code_sequence"]
130
129
  ],
131
130
  on="subject_visit",
132
131
  how="left",
133
- )
134
- df_physical_exam = df_physical_exam[
135
- ["subject_identifier", "visit_code", "visit_code_sequence", "waist_circumference"]
136
- ]
132
+ )[["subject_identifier", "visit_code", "visit_code_sequence", "waist_circumference"]]
137
133
  df_physical_exam[["waist_circumference"]] = df_physical_exam[
138
134
  ["waist_circumference"]
139
135
  ].apply(pd.to_numeric)
@@ -0,0 +1,43 @@
1
+ # Generated by Django 5.2.7 on 2025-10-24 04:17
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ("meta_consent", "0034_remove_subjectconsentspfq_site_and_more"),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AlterField(
14
+ model_name="historicalsubjectconsent",
15
+ name="consent_definition_name",
16
+ field=models.CharField(
17
+ default="",
18
+ editable=False,
19
+ max_length=50,
20
+ verbose_name="Consent definition",
21
+ ),
22
+ ),
23
+ migrations.AlterField(
24
+ model_name="historicalsubjectconsentv1",
25
+ name="consent_definition_name",
26
+ field=models.CharField(
27
+ default="",
28
+ editable=False,
29
+ max_length=50,
30
+ verbose_name="Consent definition",
31
+ ),
32
+ ),
33
+ migrations.AlterField(
34
+ model_name="subjectconsent",
35
+ name="consent_definition_name",
36
+ field=models.CharField(
37
+ default="",
38
+ editable=False,
39
+ max_length=50,
40
+ verbose_name="Consent definition",
41
+ ),
42
+ ),
43
+ ]
meta_dashboard/navbars.py CHANGED
@@ -4,8 +4,6 @@ from edc_navbar import Navbar, NavbarItem, site_navbars
4
4
  from edc_pharmacy.navbars import pharmacy_navbar_item
5
5
  from edc_review_dashboard.navbars import navbar_item as review_navbar_item
6
6
 
7
- no_url_namespace = False # True if settings.APP_NAME == "meta_dashboard" else False
8
-
9
7
  navbar = Navbar(name="meta_dashboard")
10
8
 
11
9
 
@@ -16,8 +14,7 @@ navbar.register(
16
14
  label="Screening",
17
15
  fa_icon="fa-user-plus",
18
16
  codename="edc_screening.view_screening_listboard",
19
- url_name="screening_listboard_url",
20
- no_url_namespace=no_url_namespace,
17
+ url_names_key="screening_listboard_url",
21
18
  )
22
19
  )
23
20
 
@@ -28,8 +25,7 @@ navbar.register(
28
25
  label="Subjects",
29
26
  fa_icon="fa-user-circle",
30
27
  codename="edc_subject_dashboard.view_subject_listboard",
31
- url_name="subject_listboard_url",
32
- no_url_namespace=no_url_namespace,
28
+ url_names_key="subject_listboard_url",
33
29
  )
34
30
  )
35
31
 
meta_dashboard/urls.py CHANGED
@@ -13,28 +13,28 @@ app_name = "meta_dashboard"
13
13
 
14
14
  urlpatterns = SubjectListboardView.urls(
15
15
  namespace=app_name,
16
- label="subject_listboard",
16
+ url_names_key="subject_listboard_url",
17
17
  identifier_pattern=ResearchProtocolConfig().subject_identifier_pattern,
18
18
  )
19
19
  urlpatterns += ScreeningListboardView.urls(
20
20
  namespace=app_name,
21
- label="screening_listboard",
21
+ url_names_key="screening_listboard_url",
22
22
  identifier_label="screening_identifier",
23
23
  identifier_pattern=screening_identifier,
24
24
  )
25
25
  urlpatterns += SubjectDashboardView.urls(
26
26
  namespace=app_name,
27
- label="subject_dashboard",
27
+ url_names_key="subject_dashboard_url",
28
28
  identifier_pattern=ResearchProtocolConfig().subject_identifier_pattern,
29
29
  )
30
30
 
31
31
  urlpatterns += AeListboardView.urls(
32
32
  namespace=app_name,
33
- label="ae_listboard",
33
+ url_names_key="ae_listboard_url",
34
34
  identifier_pattern=ResearchProtocolConfig().subject_identifier_pattern,
35
35
  )
36
36
  urlpatterns += DeathReportListboardView.urls(
37
37
  namespace=app_name,
38
- label="death_report_listboard",
38
+ url_names_key="death_report_listboard_url",
39
39
  identifier_pattern=ResearchProtocolConfig().subject_identifier_pattern,
40
40
  )
@@ -11,7 +11,6 @@ class ListboardView(ScreeningListboardView):
11
11
  kwargs.update(meta_version=get_meta_version())
12
12
  return super().get_context_data(**kwargs)
13
13
 
14
- def get_search_fields(self) -> list[str]:
14
+ def get_search_fields(self) -> tuple[str, ...]:
15
15
  fields = super().get_search_fields()
16
- fields.append("hospital_identifier__exact")
17
- return fields
16
+ return *fields, "hospital_identifier__exact"
@@ -20,23 +20,22 @@ class DashboardView(SubjectDashboardView):
20
20
 
21
21
  def get_context_data(self, **kwargs) -> dict[str, Any]:
22
22
  """Add message if subject reaches DM Endpoint."""
23
- context = super().get_context_data(**kwargs)
24
- context.update(subject_consent_v1_ext=self.subject_consent_v1_ext)
23
+ kwargs.update(subject_consent_v1_ext=self.subject_consent_v1_ext)
25
24
  try:
26
25
  Endpoints.objects.get(subject_identifier=self.subject_identifier)
27
26
  except ObjectDoesNotExist:
28
27
  pass
29
28
  else:
30
29
  url = reverse("meta_reports_admin:meta_reports_glucosesummary_changelist")
31
- url = f"{url}?q={self.subject_identifier}"
30
+ url = mark_safe(f"{url}?q={self.subject_identifier}") # noqa: S308
32
31
  message = format_html(
33
32
  '{text} <A href="{url}">{verbose_name}</A>',
34
33
  text=_("Subject has reached the protocol endpoint. See "),
35
- url=mark_safe(url), # noqa: S308
34
+ url=url,
36
35
  verbose_name=GlucoseSummary._meta.verbose_name,
37
36
  )
38
37
  self.message_user(message, level=messages.WARNING)
39
- return context
38
+ return super().get_context_data(**kwargs)
40
39
 
41
40
  @property
42
41
  def subject_consent_v1_ext(self):
@@ -11,7 +11,6 @@ class SubjectListboardView(BaseSubjectListboardView):
11
11
  kwargs.update(meta_version=get_meta_version())
12
12
  return super().get_context_data(**kwargs)
13
13
 
14
- def get_search_fields(self) -> list[str]:
14
+ def get_search_fields(self) -> tuple[str, ...]:
15
15
  fields = super().get_search_fields()
16
- fields.append("identity__exact")
17
- return fields
16
+ return *fields, "identity__exact"
@@ -11,12 +11,12 @@ sys.stdout.write(f"Settings file {__file__}\n")
11
11
  # from django.core.cache import cache
12
12
  # cache.clear()
13
13
  # TZ Sites:
14
- SITE_ID = SiteID(default=20) # Amana
14
+ # SITE_ID = SiteID(default=20) # Amana
15
15
  # SITE_ID = SiteID(default=10) # Hindu Mandal
16
16
  # SITE_ID = SiteID(default=40) # Mwananyamala
17
17
  # SITE_ID = SiteID(default=50) # Mbagala
18
18
  # SITE_ID = SiteID(default=60) # Mnazi-Moja
19
- # SITE_ID = SiteID(default=30) # Temeke
19
+ SITE_ID = SiteID(default=30) # Temeke
20
20
 
21
21
  INDEX_PAGE = "http://localhost:8000"
22
22
  EDC_SITES_UAT_DOMAIN = False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meta-edc
3
- Version: 1.2.6
3
+ Version: 1.2.7
4
4
  Summary: META Trial EDC (https://www.isrctn.com/ISRCTN76157257)
5
5
  Keywords: django,clinicedc,META EDC,EDC,clinical trials,META Trial,ISRCTN76157257
6
6
  Author: Erik van Widenfelt, Jonathan Willitts
@@ -15,7 +15,7 @@ Classifier: Intended Audience :: Science/Research
15
15
  Classifier: Operating System :: OS Independent
16
16
  Classifier: Programming Language :: Python :: 3.12
17
17
  Classifier: Programming Language :: Python :: 3.13
18
- Requires-Dist: clinicedc>=2.0.39
18
+ Requires-Dist: clinicedc>=2.0.41
19
19
  Requires-Dist: edc-he>=1.2.0
20
20
  Requires-Dist: edc-microscopy>=1.2.0
21
21
  Requires-Dist: edc-mnsi>=1.2.0
@@ -89,8 +89,8 @@ Assuming you are logged into the account ``myaccount``:
89
89
  mkdir ~/edc && \
90
90
  cd ~/edc && \
91
91
  uv venv && \
92
- uv pip install -U meta-edc==1.2.5 && \
93
- wget https://raw.githubusercontent.com/meta-trial/meta-edc/1.2.5/manage.py && \
92
+ uv pip install -U meta-edc==1.2.6 && \
93
+ wget https://raw.githubusercontent.com/meta-trial/meta-edc/1.2.6/manage.py && \
94
94
  uv pip freeze | grep meta-edc
95
95
 
96
96
  Copy your ``.env`` file to ``~/.etc``.
@@ -140,7 +140,7 @@ From the above example:
140
140
 
141
141
  cd ~/edc && \
142
142
  uv venv --clear && \
143
- uv pip install -U meta-edc==1.2.5 && \
143
+ uv pip install -U meta-edc==1.2.6 && \
144
144
  wget -O manage.py https://raw.githubusercontent.com/meta-trial/meta-edc/1.1.10/manage.py && \
145
145
  uv pip freeze | grep meta-edc && \
146
146
  python manage.py check