From f451a23586c2ddcde0555bb74ce6920520693ef5 Mon Sep 17 00:00:00 2001 From: Joel Ostblom Date: Wed, 27 May 2026 12:17:35 +0200 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20=E2=9C=A8=20Join=20SEFNC=20week=20r?= =?UTF-8?q?esources?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Normalize the SEFNC visit-specific REDCap forms into one resource schema with a week field so repeated measurements are represented by rows instead of suffixed columns. --- scripts/redcap_dict_to_properties.py | 106 ++++++++++++++++++++++++++- 1 file changed, 105 insertions(+), 1 deletion(-) diff --git a/scripts/redcap_dict_to_properties.py b/scripts/redcap_dict_to_properties.py index 672e30a..a682c70 100644 --- a/scripts/redcap_dict_to_properties.py +++ b/scripts/redcap_dict_to_properties.py @@ -13,6 +13,13 @@ VAS_TIMEPOINTS = [-10, 30, 60, 90, 120, 180, 240] VAS_TIME_FORM_PATTERN = re.compile(r"^vas_(minus10|(30|60|90|120|180|240)_?min)$") VAS_TIME_FIELD_PATTERN = re.compile(r"(_fasted)?_(minus10|30|60|90|120|180|240)min$") +SEFNC_WEEKS = [0, 12, 52] +SEFNC_FORM_WEEKS = { + "sefnc_baseline_v4": 0, + "sefnc_week12_v6": 12, + "selfefficacy_for_nutrition_change_sefnc_week_52": 52, +} +SEFNC_WEEK_FIELD_PATTERN = re.compile(r"_v(6|10)$") def _map(x: Iterable[In], fn: Callable[[In], Out]) -> list[Out]: @@ -38,7 +45,7 @@ def dictionary_to_properties( redcap_fields: list[dict[str, str]], ) -> list[sp.ResourceProperties]: """Converts REDCap data dictionary to Data Package resources.""" - redcap_fields = _join_vas_time_resources(redcap_fields) + redcap_fields = _join_sefnc_week_resources(_join_vas_time_resources(redcap_fields)) sorted_by_form = sorted(redcap_fields, key=lambda field: field["form_name"]) grouped_by_form = groupby(sorted_by_form, key=lambda field: field["form_name"]) return _map( @@ -109,6 +116,79 @@ def _remove_vas_time_from_annotation(annotation: str) -> str: ).strip() +def _join_sefnc_week_resources( + redcap_fields: list[dict[str, str]], +) -> list[dict[str, str]]: + """Combines SEFNC week-specific forms into one resource schema.""" + return _deduplicate_sefnc_fields( + _map(redcap_fields, _normalise_sefnc_week_resource_field) + ) + + +def _normalise_sefnc_week_resource_field(field: dict[str, str]) -> dict[str, str]: + if not _is_sefnc_week_resource_field(field): + return field + + return { + **field, + "field_name": _normalise_sefnc_field_name(field["field_name"]), + "form_name": "sefnc", + "field_annotation": _remove_sefnc_week_from_annotation( + field["field_annotation"] + ), + } + + +def _normalise_sefnc_field_name(field_name: str) -> str: + return SEFNC_WEEK_FIELD_PATTERN.sub("", field_name).replace( + "sefnc_ubusy_schedule", "sefnc_busy_schedule" + ) + + +def _is_sefnc_week_resource_field(field: dict[str, str]) -> bool: + return field["form_name"] in SEFNC_FORM_WEEKS + + +def _deduplicate_sefnc_fields(fields: list[dict[str, str]]) -> list[dict[str, str]]: + deduplicated_fields, _ = reduce( + _append_if_new_sefnc_field, + fields, + ([], set()), + ) + return deduplicated_fields + + +def _append_if_new_sefnc_field( + result: tuple[list[dict[str, str]], set[str]], field: dict[str, str] +) -> tuple[list[dict[str, str]], set[str]]: + fields, seen_sefnc_fields = result + field_name = field["field_name"] + + if field["form_name"] != "sefnc": + return fields + [field], seen_sefnc_fields + + if field_name in seen_sefnc_fields: + return result + + return (fields + [field], seen_sefnc_fields.union({field_name})) + + +def _remove_sefnc_week_from_annotation(annotation: str) -> str: + annotation = re.sub( + r"\s+Repeated at baseline \(V4\), week 12 \(V6\) and week 52 \(V10\)\.?", + "", + annotation, + flags=re.IGNORECASE, + ) + + return re.sub( + r"\s+(Baseline|Week 12|Week 52)\s*\((V4|V6|V?10)\)\.?", + "", + annotation, + flags=re.IGNORECASE, + ).strip() + + def _form_to_resource( form_name: str, fields: list[dict[str, str]] ) -> sp.ResourceProperties: @@ -153,6 +233,21 @@ def _form_to_resource( default_fields.append(time_field) primary_key.append("minutes_from_meal") + if form_name == "sefnc": + week_field = sp.FieldProperties( + name="week", + title="Week", + type="integer", + description="The study week when the SEFNC measurement was recorded.", + categories=SEFNC_WEEKS, + constraints=sp.ConstraintsProperties( + required=True, + enum=SEFNC_WEEKS, + ), + ) + default_fields.append(week_field) + primary_key.append("week") + # Discard fields displayed for information only form_redcap_fields = _filter( fields, lambda field: field["field_type"] not in ["descriptive", "checkbox"] @@ -199,6 +294,9 @@ def _get_resource_title(form_name: str) -> str: if form_name == "vas": return "Visual analogue scale measurements" + if form_name == "sefnc": + return "Self-efficacy for nutrition change" + return form_name @@ -209,6 +307,12 @@ def _get_resource_description(form_name: str) -> str: "relative to the meal." ) + if form_name == "sefnc": + return ( + "Self-efficacy for nutrition change measurements recorded across " + "study weeks." + ) + return form_name From 401527c7cb0422aad8c39e3c6c7ca452a0b3d89a Mon Sep 17 00:00:00 2001 From: Joel Ostblom Date: Wed, 27 May 2026 12:17:54 +0200 Subject: [PATCH 2/5] =?UTF-8?q?build:=20=F0=9F=93=A6=20Regenerate=20SEFNC?= =?UTF-8?q?=20metadata?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update the generated data package metadata so SEFNC has one resource with week values 0, 12, and 52 and no visit-suffixed duplicate fields. --- datapackage.json | 760 +++-------------------------------------------- 1 file changed, 34 insertions(+), 726 deletions(-) diff --git a/datapackage.json b/datapackage.json index 6504081..baf83e8 100644 --- a/datapackage.json +++ b/datapackage.json @@ -23778,10 +23778,10 @@ } }, { - "name": "sefnc_baseline_v4", - "path": "resources/sefnc_baseline_v4/data.parquet", - "title": "sefnc_baseline_v4", - "description": "sefnc_baseline_v4", + "name": "sefnc", + "path": "resources/sefnc/data.parquet", + "title": "Self-efficacy for nutrition change", + "description": "Self-efficacy for nutrition change measurements recorded across study weeks.", "schema": { "fields": [ { @@ -23812,11 +23812,30 @@ "Odense" ] }, + { + "name": "week", + "title": "Week", + "type": "integer", + "description": "The study week when the SEFNC measurement was recorded.", + "constraints": { + "required": true, + "enum": [ + 0, + 12, + 52 + ] + }, + "categories": [ + 0, + 12, + 52 + ] + }, { "name": "sefnc_when_tired", "title": "sefnc_when_tired", "type": "string", - "description": "Participant's confidence in following their diet when feeling tired. Self-reported by participant. Baseline (V4).", + "description": "Participant's confidence in following their diet when feeling tired. Self-reported by participant.", "constraints": { "required": true, "enum": [ @@ -23851,7 +23870,7 @@ "name": "sefnc_during_crisis", "title": "sefnc_during_crisis", "type": "string", - "description": "Participant's confidence in following their diet during or after a personal crisis. Baseline (V4).", + "description": "Participant's confidence in following their diet during or after a personal crisis.", "constraints": { "required": true, "enum": [ @@ -23886,7 +23905,7 @@ "name": "sefnc_when_depressed", "title": "sefnc_when_depressed", "type": "string", - "description": "Participant's confidence in following their diet when feeling depressed. Self-reported by participant. Baseline (V4).", + "description": "Participant's confidence in following their diet when feeling depressed. Self-reported by participant.", "constraints": { "required": true, "enum": [ @@ -23921,7 +23940,7 @@ "name": "sefnc_when_anxious", "title": "sefnc_when_anxious", "type": "string", - "description": "Participant's confidence in following their diet when feeling anxious. Self-reported by participant. Baseline (V4).", + "description": "Participant's confidence in following their diet when feeling anxious. Self-reported by participant.", "constraints": { "required": true, "enum": [ @@ -23956,7 +23975,7 @@ "name": "sefnc_on_vacation", "title": "sefnc_on_vacation", "type": "string", - "description": "Participant's confidence in following their diet while on vacation. Self-reported by participant. Repeated at baseline (V4), week 12 (V6) and week 52 (V10).", + "description": "Participant's confidence in following their diet while on vacation. Self-reported by participant.", "constraints": { "required": true, "enum": [ @@ -23991,7 +24010,7 @@ "name": "sefnc_when_busy", "title": "sefnc_when_busy", "type": "string", - "description": "Participant's confidence in following their diet when they have a heavy workload. Self-reported by participant. Repeated at baseline (V4), week 12 (V6) and week 52 (V10).", + "description": "Participant's confidence in following their diet when they have a heavy workload. Self-reported by participant.", "constraints": { "required": true, "enum": [ @@ -24026,7 +24045,7 @@ "name": "sefnc_when_missed_goals", "title": "sefnc_when_missed_goals", "type": "string", - "description": "Participant's confidence in following their diet when they have not met their dietary goals. Self-reported by participant. Baseline (V4).", + "description": "Participant's confidence in following their diet when they have not met their dietary goals. Self-reported by participant.", "constraints": { "required": true, "enum": [ @@ -24061,7 +24080,7 @@ "name": "sefnc_no_support", "title": "sefnc_no_support", "type": "string", - "description": "Participant's confidence in following their diet when lacking support from family or friends. Baseline (V4).", + "description": "Participant's confidence in following their diet when lacking support from family or friends.", "constraints": { "required": true, "enum": [ @@ -24096,7 +24115,7 @@ "name": "sefnc_busy_schedule", "title": "sefnc_busy_schedule", "type": "string", - "description": "Participant's confidence in following their diet when their schedule is busy or resource- and/or time-demanding. Self-reported by participant. Baseline (V4).", + "description": "Participant's confidence in following their diet when their schedule is busy or resource- and/or time-demanding. Self-reported by participant.", "constraints": { "required": true, "enum": [ @@ -24129,719 +24148,8 @@ } ], "primaryKey": [ - "event" - ] - } - }, - { - "name": "sefnc_week12_v6", - "path": "resources/sefnc_week12_v6/data.parquet", - "title": "sefnc_week12_v6", - "description": "sefnc_week12_v6", - "schema": { - "fields": [ - { - "name": "event", - "title": "The unique name of the event", - "type": "string", - "description": "The unique name identifying the event when the form was filled in.", - "constraints": { - "required": true - } - }, - { - "name": "center", - "title": "Research center", - "type": "string", - "description": "The research center where the data item was recorded.", - "constraints": { - "required": true, - "enum": [ - "Copenhagen", - "Aarhus", - "Odense" - ] - }, - "categories": [ - "Copenhagen", - "Aarhus", - "Odense" - ] - }, - { - "name": "sefnc_when_tired_v6", - "title": "sefnc_when_tired_v6", - "type": "string", - "description": "Participant's confidence in following their diet when feeling tired. Self-reported by participant. Week 12 (V6).", - "constraints": { - "required": true, - "enum": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - "categories": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - { - "name": "sefnc_during_crisis_v6", - "title": "sefnc_during_crisis_v6", - "type": "string", - "description": "Participant's confidence in following their diet during or after a personal crisis. Self-reported by participant. Week 12 (V6).", - "constraints": { - "required": true, - "enum": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - "categories": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - { - "name": "sefnc_when_depressed_v6", - "title": "sefnc_when_depressed_v6", - "type": "string", - "description": "Participant's confidence in following their diet when feeling depressed. Self-reported by participant. Week 12 (V6).", - "constraints": { - "required": true, - "enum": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - "categories": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - { - "name": "sefnc_when_anxious_v6", - "title": "sefnc_when_anxious_v6", - "type": "string", - "description": "Participant's confidence in following their diet when feeling anxious. Self-reported by participant. Week 12 (V6).", - "constraints": { - "required": true, - "enum": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - "categories": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - { - "name": "sefnc_on_vacation_v6", - "title": "sefnc_on_vacation_v6", - "type": "string", - "description": "Participant's confidence in following their diet while on vacation. Self-reported by participant. Week 12 (V6).", - "constraints": { - "required": true, - "enum": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - "categories": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - { - "name": "sefnc_when_busy_v6", - "title": "sefnc_when_busy_v6", - "type": "string", - "description": "Participant's confidence in following their diet when they have a heavy workload. Self-reported by participant. Week 12 (V6).", - "constraints": { - "required": true, - "enum": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - "categories": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - { - "name": "sefnc_when_missed_goals_v6", - "title": "sefnc_when_missed_goals_v6", - "type": "string", - "description": "Participant's confidence in following their diet when they have not met their dietary goals. Self-reported by participant. Week 12 (V6).", - "constraints": { - "required": true, - "enum": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - "categories": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - { - "name": "sefnc_no_support_v6", - "title": "sefnc_no_support_v6", - "type": "string", - "description": "Participant's confidence in following their diet when lacking support from family or friends. Self-reported by participant. Week 12 (V6).", - "constraints": { - "required": true, - "enum": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - "categories": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - { - "name": "sefnc_ubusy_schedule_v6", - "title": "sefnc_ubusy_schedule_v6", - "type": "string", - "description": "Participant's confidence in following their diet when their schedule is busy or resource- and/or time-demanding. Self-reported by participant. Week 12 (V6).", - "constraints": { - "required": true, - "enum": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - "categories": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - } - ], - "primaryKey": [ - "event" - ] - } - }, - { - "name": "selfefficacy_for_nutrition_change_sefnc_week_52", - "path": "resources/selfefficacy_for_nutrition_change_sefnc_week_52/data.parquet", - "title": "selfefficacy_for_nutrition_change_sefnc_week_52", - "description": "selfefficacy_for_nutrition_change_sefnc_week_52", - "schema": { - "fields": [ - { - "name": "event", - "title": "The unique name of the event", - "type": "string", - "description": "The unique name identifying the event when the form was filled in.", - "constraints": { - "required": true - } - }, - { - "name": "center", - "title": "Research center", - "type": "string", - "description": "The research center where the data item was recorded.", - "constraints": { - "required": true, - "enum": [ - "Copenhagen", - "Aarhus", - "Odense" - ] - }, - "categories": [ - "Copenhagen", - "Aarhus", - "Odense" - ] - }, - { - "name": "sefnc_when_tired_v10", - "title": "sefnc_when_tired_v10", - "type": "string", - "description": "Participant's confidence in following their diet when feeling tired. Self-reported by participant. Week 52 (10).", - "constraints": { - "required": true, - "enum": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - "categories": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - { - "name": "sefnc_during_crisis_v10", - "title": "sefnc_during_crisis_v10", - "type": "string", - "description": "Participant's confidence in following their diet during or after a personal crisis. Self-reported by participant. Week 52 (10).", - "constraints": { - "required": true, - "enum": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - "categories": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - { - "name": "sefnc_when_depressed_v10", - "title": "sefnc_when_depressed_v10", - "type": "string", - "description": "Participant's confidence in following their diet when feeling depressed. Self-reported by participant. Week 52 (10).", - "constraints": { - "required": true, - "enum": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - "categories": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - { - "name": "sefnc_when_anxious_v10", - "title": "sefnc_when_anxious_v10", - "type": "string", - "description": "Participant's confidence in following their diet when feeling anxious. Self-reported by participant. Week 52 (10).", - "constraints": { - "required": true, - "enum": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - "categories": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - { - "name": "sefnc_on_vacation_v10", - "title": "sefnc_on_vacation_v10", - "type": "string", - "description": "Participant's confidence in following their diet while on vacation. Self-reported by participant. Week 52 (10).", - "constraints": { - "required": true, - "enum": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - "categories": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - { - "name": "sefnc_when_busy_v10", - "title": "sefnc_when_busy_v10", - "type": "string", - "description": "Participant's confidence in following their diet when they have a heavy workload. Self-reported by participant. Week 52 (10).", - "constraints": { - "required": true, - "enum": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - "categories": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - { - "name": "sefnc_when_missed_goals_v10", - "title": "sefnc_when_missed_goals_v10", - "type": "string", - "description": "Participant's confidence in following their diet when they have not met their dietary goals. Self-reported by participant. Week 52 (10).", - "constraints": { - "required": true, - "enum": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - "categories": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - { - "name": "sefnc_no_support_v10", - "title": "sefnc_no_support_v10", - "type": "string", - "description": "Participant's confidence in following their diet when lacking support from family or friends. Self-reported by participant. Week 52 (10).", - "constraints": { - "required": true, - "enum": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - "categories": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - { - "name": "sefnc_ubusy_schedule_v10", - "title": "sefnc_ubusy_schedule_v10", - "type": "string", - "description": "Participant's confidence in following their diet when their schedule is busy or resource- and/or time-demanding. Self-reported by participant. Week 52 (10).", - "constraints": { - "required": true, - "enum": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - }, - "categories": [ - "0%", - "10%", - "20%", - "30%", - "40%", - "50%", - "60%", - "70%", - "80%", - "90%", - "100%" - ] - } - ], - "primaryKey": [ - "event" + "event", + "week" ] } }, From eb5c7b08fcfb3cfc912559672c709d21df25f804 Mon Sep 17 00:00:00 2001 From: Joel Ostblom Date: Thu, 28 May 2026 19:54:48 +0200 Subject: [PATCH 3/5] =?UTF-8?q?refactor:=20=E2=99=BB=EF=B8=8F=20Sequence?= =?UTF-8?q?=20metadata=20transformations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/redcap_dict_to_properties.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/redcap_dict_to_properties.py b/scripts/redcap_dict_to_properties.py index a682c70..5f82df4 100644 --- a/scripts/redcap_dict_to_properties.py +++ b/scripts/redcap_dict_to_properties.py @@ -45,7 +45,8 @@ def dictionary_to_properties( redcap_fields: list[dict[str, str]], ) -> list[sp.ResourceProperties]: """Converts REDCap data dictionary to Data Package resources.""" - redcap_fields = _join_sefnc_week_resources(_join_vas_time_resources(redcap_fields)) + redcap_fields = _join_sefnc_week_resources(redcap_fields) + redcap_fields = _join_vas_time_resources(redcap_fields) sorted_by_form = sorted(redcap_fields, key=lambda field: field["form_name"]) grouped_by_form = groupby(sorted_by_form, key=lambda field: field["form_name"]) return _map( From 9c0dd333b43c70971a2f0a67bd50bd7285b99d16 Mon Sep 17 00:00:00 2001 From: Joel Ostblom Date: Thu, 28 May 2026 19:55:10 +0200 Subject: [PATCH 4/5] =?UTF-8?q?feat:=20=E2=9C=A8=20Simplify=20SEFNC=20fiel?= =?UTF-8?q?d=20names?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- datapackage.json | 36 ++++++++++++++-------------- scripts/redcap_dict_to_properties.py | 3 ++- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/datapackage.json b/datapackage.json index baf83e8..69de708 100644 --- a/datapackage.json +++ b/datapackage.json @@ -23832,8 +23832,8 @@ ] }, { - "name": "sefnc_when_tired", - "title": "sefnc_when_tired", + "name": "when_tired", + "title": "when_tired", "type": "string", "description": "Participant's confidence in following their diet when feeling tired. Self-reported by participant.", "constraints": { @@ -23867,8 +23867,8 @@ ] }, { - "name": "sefnc_during_crisis", - "title": "sefnc_during_crisis", + "name": "during_crisis", + "title": "during_crisis", "type": "string", "description": "Participant's confidence in following their diet during or after a personal crisis.", "constraints": { @@ -23902,8 +23902,8 @@ ] }, { - "name": "sefnc_when_depressed", - "title": "sefnc_when_depressed", + "name": "when_depressed", + "title": "when_depressed", "type": "string", "description": "Participant's confidence in following their diet when feeling depressed. Self-reported by participant.", "constraints": { @@ -23937,8 +23937,8 @@ ] }, { - "name": "sefnc_when_anxious", - "title": "sefnc_when_anxious", + "name": "when_anxious", + "title": "when_anxious", "type": "string", "description": "Participant's confidence in following their diet when feeling anxious. Self-reported by participant.", "constraints": { @@ -23972,8 +23972,8 @@ ] }, { - "name": "sefnc_on_vacation", - "title": "sefnc_on_vacation", + "name": "on_vacation", + "title": "on_vacation", "type": "string", "description": "Participant's confidence in following their diet while on vacation. Self-reported by participant.", "constraints": { @@ -24007,8 +24007,8 @@ ] }, { - "name": "sefnc_when_busy", - "title": "sefnc_when_busy", + "name": "when_busy", + "title": "when_busy", "type": "string", "description": "Participant's confidence in following their diet when they have a heavy workload. Self-reported by participant.", "constraints": { @@ -24042,8 +24042,8 @@ ] }, { - "name": "sefnc_when_missed_goals", - "title": "sefnc_when_missed_goals", + "name": "when_missed_goals", + "title": "when_missed_goals", "type": "string", "description": "Participant's confidence in following their diet when they have not met their dietary goals. Self-reported by participant.", "constraints": { @@ -24077,8 +24077,8 @@ ] }, { - "name": "sefnc_no_support", - "title": "sefnc_no_support", + "name": "no_support", + "title": "no_support", "type": "string", "description": "Participant's confidence in following their diet when lacking support from family or friends.", "constraints": { @@ -24112,8 +24112,8 @@ ] }, { - "name": "sefnc_busy_schedule", - "title": "sefnc_busy_schedule", + "name": "busy_schedule", + "title": "busy_schedule", "type": "string", "description": "Participant's confidence in following their diet when their schedule is busy or resource- and/or time-demanding. Self-reported by participant.", "constraints": { diff --git a/scripts/redcap_dict_to_properties.py b/scripts/redcap_dict_to_properties.py index 5f82df4..f432de8 100644 --- a/scripts/redcap_dict_to_properties.py +++ b/scripts/redcap_dict_to_properties.py @@ -141,9 +141,10 @@ def _normalise_sefnc_week_resource_field(field: dict[str, str]) -> dict[str, str def _normalise_sefnc_field_name(field_name: str) -> str: - return SEFNC_WEEK_FIELD_PATTERN.sub("", field_name).replace( + field_name = SEFNC_WEEK_FIELD_PATTERN.sub("", field_name).replace( "sefnc_ubusy_schedule", "sefnc_busy_schedule" ) + return re.sub(r"^sefnc_", "", field_name) def _is_sefnc_week_resource_field(field: dict[str, str]) -> bool: From bb3ff4cf866ac9901d93ce37ef2a63829467b038 Mon Sep 17 00:00:00 2001 From: Joel Ostblom Date: Thu, 28 May 2026 19:56:10 +0200 Subject: [PATCH 5/5] =?UTF-8?q?docs:=20=F0=9F=93=9D=20Consolidate=20SEFNC?= =?UTF-8?q?=20self-report=20context?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- datapackage.json | 16 ++++++++-------- scripts/redcap_dict_to_properties.py | 13 ++++++++++--- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/datapackage.json b/datapackage.json index 69de708..640f8eb 100644 --- a/datapackage.json +++ b/datapackage.json @@ -23781,7 +23781,7 @@ "name": "sefnc", "path": "resources/sefnc/data.parquet", "title": "Self-efficacy for nutrition change", - "description": "Self-efficacy for nutrition change measurements recorded across study weeks.", + "description": "Self-efficacy for nutrition change measurements self-reported by participants across study weeks.", "schema": { "fields": [ { @@ -23835,7 +23835,7 @@ "name": "when_tired", "title": "when_tired", "type": "string", - "description": "Participant's confidence in following their diet when feeling tired. Self-reported by participant.", + "description": "Participant's confidence in following their diet when feeling tired.", "constraints": { "required": true, "enum": [ @@ -23905,7 +23905,7 @@ "name": "when_depressed", "title": "when_depressed", "type": "string", - "description": "Participant's confidence in following their diet when feeling depressed. Self-reported by participant.", + "description": "Participant's confidence in following their diet when feeling depressed.", "constraints": { "required": true, "enum": [ @@ -23940,7 +23940,7 @@ "name": "when_anxious", "title": "when_anxious", "type": "string", - "description": "Participant's confidence in following their diet when feeling anxious. Self-reported by participant.", + "description": "Participant's confidence in following their diet when feeling anxious.", "constraints": { "required": true, "enum": [ @@ -23975,7 +23975,7 @@ "name": "on_vacation", "title": "on_vacation", "type": "string", - "description": "Participant's confidence in following their diet while on vacation. Self-reported by participant.", + "description": "Participant's confidence in following their diet while on vacation.", "constraints": { "required": true, "enum": [ @@ -24010,7 +24010,7 @@ "name": "when_busy", "title": "when_busy", "type": "string", - "description": "Participant's confidence in following their diet when they have a heavy workload. Self-reported by participant.", + "description": "Participant's confidence in following their diet when they have a heavy workload.", "constraints": { "required": true, "enum": [ @@ -24045,7 +24045,7 @@ "name": "when_missed_goals", "title": "when_missed_goals", "type": "string", - "description": "Participant's confidence in following their diet when they have not met their dietary goals. Self-reported by participant.", + "description": "Participant's confidence in following their diet when they have not met their dietary goals.", "constraints": { "required": true, "enum": [ @@ -24115,7 +24115,7 @@ "name": "busy_schedule", "title": "busy_schedule", "type": "string", - "description": "Participant's confidence in following their diet when their schedule is busy or resource- and/or time-demanding. Self-reported by participant.", + "description": "Participant's confidence in following their diet when their schedule is busy or resource- and/or time-demanding.", "constraints": { "required": true, "enum": [ diff --git a/scripts/redcap_dict_to_properties.py b/scripts/redcap_dict_to_properties.py index f432de8..a9d6b13 100644 --- a/scripts/redcap_dict_to_properties.py +++ b/scripts/redcap_dict_to_properties.py @@ -183,11 +183,18 @@ def _remove_sefnc_week_from_annotation(annotation: str) -> str: flags=re.IGNORECASE, ) - return re.sub( + annotation = re.sub( r"\s+(Baseline|Week 12|Week 52)\s*\((V4|V6|V?10)\)\.?", "", annotation, flags=re.IGNORECASE, + ) + + return re.sub( + r"\s*Self-reported by participant\.?", + "", + annotation, + flags=re.IGNORECASE, ).strip() @@ -311,8 +318,8 @@ def _get_resource_description(form_name: str) -> str: if form_name == "sefnc": return ( - "Self-efficacy for nutrition change measurements recorded across " - "study weeks." + "Self-efficacy for nutrition change measurements self-reported by " + "participants across study weeks." ) return form_name