Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,45 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

## [Unreleased]

## [v1.6] - 2026-10-22

Lab and vital-sign measurements moved from SNOMED to standard LOINC concepts, unit rows added for the three ratio fields, and the leftover answers of two removed questions excluded. Target concepts change on 4 rows, `Map_to_OMOP` on 4 rows, and 3 unit rows are appended, so the ETL must be re-run to apply these changes. Edits to existing rows are in place and the new rows are appended at the end (lines 2078–2080), so every existing line number is the same as in v1.5. Concept IDs and names were confirmed in the deployed OMOP vocabulary (Databricks `omop_vocab`).

### Changed — target concept (SNOMED → LOINC)

- `import_ag_ratio` "A/G Ratio (calculated field)" (line 584): 4288601 *Albumin/Globulin ratio* (SNOMED 687005) → 3020509 *Albumin/Globulin [Mass Ratio] in Serum or Plasma* (LOINC 1759-0, Lab Test), exactMatch 1. Every other imported lab already maps to a LOINC lab test. Current OMOP data: 3,984 values, median 1.72.
- `import_buncreatinineratio` "BUN/Creatinine ratio" (line 554): 4112223 *BUN/Creatinine ratio* (SNOMED 18207002) → **3033837 *Creatinine/Urea nitrogen [Mass Ratio] in Serum or Plasma*** (LOINC 31045-8, Lab Test), exactMatch 1. The REDCap calculated field stores **creatinine ÷ BUN**, the inverse of its label: compared with each person's own BUN and creatinine on the same date, all 3,981 values in the current OMOP data match creatinine ÷ BUN (median 0.053; BUN ÷ creatinine would be 18.75). The row is mapped to what is stored, with `MODIFIER` "Stored value is creatinine/BUN (REDCap calculation inverted; field label says BUN/Creatinine); remap to 3018311 (LOINC 3097-3) when the REDCap formula and values are corrected". `SRC_CD_DESCRIPTION` keeps the REDCap label. The data team has been asked to correct the formula.
- `bmi_vsorres` "BMI" (line 858): 4245997 *Body mass index* (SNOMED 60621009) → 3038553 *Body mass index (BMI) [Ratio]* (LOINC 39156-5), exactMatch 1, the standard BMI concept used in OHDSI phenotypes.
- `waist_vsorres` "Waist Circumference (cm)" (line 859): 4172830 *Waist circumference* (SNOMED 276361009) → 3016258 *Waist Circumference at umbilicus by Tape measure* (LOINC 8280-0), closeMatch 1. Measurement at the umbilicus with a tape measure is accepted for AI-READI; closeMatch because the site is not stated on the form.
- Kept on SNOMED: hip circumference (line 860; LOINC has only a protocol term, 62409-8) and waist/hip ratio (line 861; no LOINC term).

### Added — units

- Fixed-unit rows for the three ratio fields, same format as the v1.4 fixed-unit rows (`MODIFIER` "fixed unit; no REDCap unit field"): `import_ag_ratio_u` (line 2078), `whr_vsorres_u` (line 2079) and `import_buncreatinineratio_u` (line 2080) → 8523 *ratio* (UCUM `{ratio}`). A ratio of two values in the same unit is dimensionless; the unit is the same whichever way the BUN/creatinine ratio is calculated. v1.4 had left these fields without a unit.
- `unit_concept_lookup.csv` (and `01_create_unit_lookup.sql`): 113 rows (field 88, string 25), up from 110; row counts updated in the scripts' README, USAGE and SQL comments.

### Changed — Map_to_OMOP

- `dri3` "Driver's License photocopied" answers (lines 277–278) and `cmotyn` "Are there any other medications that you are currently taking that are not included here?" answers (lines 730–731): `Map_to_OMOP` Yes → No. In the master REDCap dictionary the `dri3` question was deleted (6/27/2023) and the `cmotyn` question was excluded from mapping (4/25/2024), but their Yes/No answer rows had been left as Yes. Neither field appears in the current OMOP survey data. map2omop and the open-source public file each lose these 4 rows.

### Changed — scripts

- `count_concept_map.sql`: answer rows of an excluded question (`Map_to_OMOP` = No) are reported as designated-but-unmapped with the reason "Answer to an excluded question"; expected values updated to v1.6.
- `audit_concept_map.py` (check A8) and `validate_concept_map_vocab.sql` (check V9): answer rows already excluded (`Map_to_OMOP` = No) are no longer flagged. A8 now lists 3 rows (administrative BCVA "not done" and satisfaction-survey rows).

### Regenerated

- map2omop (2,074 rows) and open-source public (1,965) versions, SSSOM (2,003 rows; 76 incomplete) and LinkML (2,079 records) from the v1.6 common file. `medication_route_lookup.csv` checked against the map: unchanged.
- Counts (`run_counts.py`): standard 1,478 (392 concepts); custom 487 (342); mapped 1,965 (734 concepts); designated but unmapped 114. The 3 added unit rows lower "not designated" from 830 to 827 against the fixed total of 2,906.

### Reviewed and not changed

- LDL cholesterol (lines 537–538): the unit row `import_ldl_cholesterol_u` does not follow the `<field>_u` pattern because the REDCap names differ: the data uses `import_ldl_cholesterol_calculation` (3,984 rows in the current OMOP data) and the REDCap unit field is `import_ldl_cholesterol_u`. The extra key in `unit_concept_lookup.csv` (and the UNION in `01_create_unit_lookup.sql`) is the documented exception.

### Not yet included

- CBC method codes: hematocrit (line 675) stays *by calculation* (20570-8, 3009542) unless the lab confirms it is measured directly (then 4544-3, 3023314); MCV, MCH, MCHC, RDW and platelets (676–680) may move to their "by Automated count" codes (3023599, 3012030, 3009744, 3019897, 3024929) once the lab confirms an automated analyzer. Waiting on the performing labs.

## [v1.5] - 2026-10-19 - 10.5281/zenodo.23488128

Corrections from a full review of all 2,076 rows of v1.4 (the first review of the whole file; earlier releases reviewed only the rows in each batch of changes). Target concepts change on 10 rows, qualifier concepts on 2 rows and field names on 5 answer rows, so the ETL must be re-run to apply these changes. All edits are in place: no rows are added or removed, so every line number is the same as in v1.4. Concept IDs and names for the new standard concepts were confirmed in the deployed OMOP vocabulary (Databricks `omop_vocab`).
Expand Down
4 changes: 2 additions & 2 deletions CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ repository-code: "https://github.com/AI-READI/DataElementMaps"
repository-artifact: "https://github.com/AI-READI/DataElementMaps/blob/main/manuscript-tvst2026/ai_readi_redcap_value_set_mapping_common.csv"
url: "https://aireadi.org"
license: MIT
version: "v1.5"
date-released: "2026-10-19"
version: "v1.6"
date-released: "2026-10-22"
identifiers:
- type: doi
value: "10.5281/zenodo.23375723"
Expand Down
8 changes: 4 additions & 4 deletions codemeta.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
"codeRepository": "https://github.com/AI-READI/DataElementMaps",
"downloadUrl": "https://github.com/AI-READI/DataElementMaps",
"issueTracker": "https://github.com/AI-READI/DataElementMaps/issues",
"version": "v1.5",
"datePublished": "2026-10-19",
"releaseNotes": "Concept map v1.5: maps stroke and kidney disease to standard SNOMED concepts, separates the 31-40 cigarettes-per-day answer from the LOINC \"31 or more\" answer (new custom concept 2005200636), maps \"less than once a week\" medication-use answers to LOINC LA27722-0, sets the medication route question to 0, cleans metadata, and adds release audit scripts. ETL re-run required. See CHANGELOG.md.",
"version": "v1.6",
"datePublished": "2026-10-22",
"releaseNotes": "Concept map v1.6: maps the A/G ratio, BUN/creatinine ratio (stored as creatinine/BUN), BMI and waist circumference to standard LOINC concepts, adds the unit ratio for the three ratio fields, and excludes the leftover answers of two removed questions. ETL re-run required. See CHANGELOG.md.",
"dateCreated": "2023-06-28",
"dateModified": "2026-10-19",
"dateModified": "2026-10-22",
"applicationCategory": "Scientific",
"developmentStatus": "active",
"isPartOf": "https://aireadi.org/",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5827,7 +5827,7 @@ mappings:
predicate_id: skos:exactMatch
confidence: 1.0
- mapping_record_id: AIREADI_MAPPING_0276
map_to_omop: 'Yes'
map_to_omop: 'No'
transferred_to_fairhub_redcap_dataset: 'Yes'
protected_or_open_source: open-source
extension_needed: 'No'
Expand All @@ -5849,7 +5849,7 @@ mappings:
predicate_id: skos:exactMatch
confidence: 1.0
- mapping_record_id: AIREADI_MAPPING_0277
map_to_omop: 'Yes'
map_to_omop: 'No'
transferred_to_fairhub_redcap_dataset: 'Yes'
protected_or_open_source: open-source
extension_needed: 'No'
Expand Down Expand Up @@ -11627,15 +11627,17 @@ mappings:
question_or_answer: Question
src_code_id: BUN/Creatinine ratio
src_cd_description: BUN/Creatinine ratio
target_concept_id: 4112223
target_concept_name: BUN/Creatinine ratio
target_concept_id: 3033837
target_concept_name: Creatinine/Urea nitrogen [Mass Ratio] in Serum or Plasma
target_domain_id: Measurement
target_vocabulary_id: SNOMED
target_concept_class_id: Procedure
target_concept_code: '18207002'
target_vocabulary_id: LOINC
target_concept_class_id: Lab Test
target_concept_code: 31045-8
target_standard_concept: S
predicate_id: skos:exactMatch
confidence: 1.0
modifier: Stored value is creatinine/BUN (REDCap calculation inverted; field label says BUN/Creatinine); remap to 3018311
(LOINC 3097-3) when the REDCap formula and values are corrected
- mapping_record_id: AIREADI_MAPPING_0554
map_to_omop: 'Yes'
transferred_to_fairhub_redcap_dataset: 'Yes'
Expand Down Expand Up @@ -12146,12 +12148,12 @@ mappings:
question_or_answer: Question
src_code_id: A/G Ratio (calculated field)
src_cd_description: Albumin/Globulin ratio
target_concept_id: 4288601
target_concept_name: Albumin/Globulin ratio
target_concept_id: 3020509
target_concept_name: Albumin/Globulin [Mass Ratio] in Serum or Plasma
target_domain_id: Measurement
target_vocabulary_id: SNOMED
target_concept_class_id: Procedure
target_concept_code: '687005'
target_vocabulary_id: LOINC
target_concept_class_id: Lab Test
target_concept_code: 1759-0
target_standard_concept: S
predicate_id: skos:exactMatch
confidence: 1.0
Expand Down Expand Up @@ -15019,7 +15021,7 @@ mappings:
predicate_id: skos:exactMatch
confidence: 1.0
- mapping_record_id: AIREADI_MAPPING_0729
map_to_omop: 'Yes'
map_to_omop: 'No'
transferred_to_fairhub_redcap_dataset: 'Yes'
protected_or_open_source: open-source
extension_needed: 'No'
Expand All @@ -15041,7 +15043,7 @@ mappings:
predicate_id: skos:exactMatch
confidence: 1.0
- mapping_record_id: AIREADI_MAPPING_0730
map_to_omop: 'Yes'
map_to_omop: 'No'
transferred_to_fairhub_redcap_dataset: 'Yes'
protected_or_open_source: open-source
extension_needed: 'No'
Expand Down Expand Up @@ -17856,12 +17858,12 @@ mappings:
question_or_answer: Question
src_code: bmi_vsorres
src_cd_description: BMI
target_concept_id: 4245997
target_concept_name: Body mass index
target_concept_id: 3038553
target_concept_name: Body mass index (BMI) [Ratio]
target_domain_id: Measurement
target_vocabulary_id: SNOMED
target_concept_class_id: Observable Entity
target_concept_code: '60621009'
target_vocabulary_id: LOINC
target_concept_class_id: Clinical Observation
target_concept_code: 39156-5
target_standard_concept: S
predicate_id: skos:exactMatch
confidence: 1.0
Expand All @@ -17876,14 +17878,14 @@ mappings:
question_or_answer: Question
src_code: waist_vsorres
src_cd_description: Waist Circumference (cm)
target_concept_id: 4172830
target_concept_name: Waist circumference
target_concept_id: 3016258
target_concept_name: Waist Circumference at umbilicus by Tape measure
target_domain_id: Measurement
target_vocabulary_id: SNOMED
target_concept_class_id: Observable Entity
target_concept_code: '276361009'
target_vocabulary_id: LOINC
target_concept_class_id: Clinical Observation
target_concept_code: 8280-0
target_standard_concept: S
predicate_id: skos:exactMatch
predicate_id: skos:closeMatch
confidence: 1.0
- mapping_record_id: AIREADI_MAPPING_0859
map_to_omop: 'Yes'
Expand Down Expand Up @@ -44604,3 +44606,69 @@ mappings:
predicate_id: skos:exactMatch
confidence: 1.0
modifier: fixed unit; no REDCap unit field
- mapping_record_id: AIREADI_MAPPING_2077
map_to_omop: 'Yes'
transferred_to_fairhub_redcap_dataset: 'Yes'
protected_or_open_source: open-source
extension_needed: 'No'
form_name: imported
field_type: text
field_id: import_ag_ratio_u
question_or_answer: Unit
src_code: ratio
src_code_id: import_ag_ratio_u
src_cd_description: ratio
target_concept_id: 8523
target_concept_name: ratio
target_domain_id: Unit
target_vocabulary_id: UCUM
target_concept_class_id: Unit
target_concept_code: '{ratio}'
target_standard_concept: S
predicate_id: skos:exactMatch
confidence: 1.0
modifier: fixed unit; no REDCap unit field
- mapping_record_id: AIREADI_MAPPING_2078
map_to_omop: 'Yes'
transferred_to_fairhub_redcap_dataset: 'Yes'
protected_or_open_source: open-source
extension_needed: 'No'
form_name: physical_assessment
field_type: text
field_id: whr_vsorres_u
question_or_answer: Unit
src_code: ratio
src_code_id: whr_vsorres_u
src_cd_description: ratio
target_concept_id: 8523
target_concept_name: ratio
target_domain_id: Unit
target_vocabulary_id: UCUM
target_concept_class_id: Unit
target_concept_code: '{ratio}'
target_standard_concept: S
predicate_id: skos:exactMatch
confidence: 1.0
modifier: fixed unit; no REDCap unit field
- mapping_record_id: AIREADI_MAPPING_2079
map_to_omop: 'Yes'
transferred_to_fairhub_redcap_dataset: 'Yes'
protected_or_open_source: open-source
extension_needed: 'No'
form_name: imported
field_type: text
field_id: import_buncreatinineratio_u
question_or_answer: Unit
src_code: ratio
src_code_id: import_buncreatinineratio_u
src_cd_description: ratio
target_concept_id: 8523
target_concept_name: ratio
target_domain_id: Unit
target_vocabulary_id: UCUM
target_concept_class_id: Unit
target_concept_code: '{ratio}'
target_standard_concept: S
predicate_id: skos:exactMatch
confidence: 1.0
modifier: fixed unit; no REDCap unit field
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# AI-READI REDCap Value Set Mapping LinkML Conversion Summary

- Source file: `_ai_readi_redcap_value_set_mapping_common.csv`
- Rows converted: 2076
- Rows converted: 2079
- Source columns: 26

## Generated files
Expand All @@ -12,7 +12,7 @@
### FORM_NAME
- px_racial_ethnic_discrimination_survey: 364
- px_sdoh_combined_survey: 267
- imported: 203
- imported: 205
- health_survey: 174
- retinal_imaging_v2: 133
- px_neighborhood_environment_survey: 126
Expand All @@ -24,7 +24,7 @@
### TARGET_DOMAIN_ID
- Meas Value: 1231
- Observation: 439
- Unit: 145
- Unit: 148
- Measurement: 114
- [blank]: 76
- Condition: 32
Expand All @@ -34,10 +34,10 @@
- Device: 1

### TARGET_VOCABULARY_ID
- LOINC: 1183
- LOINC: 1187
- AIREADI: 422
- UCUM: 145
- SNOMED: 141
- UCUM: 148
- SNOMED: 137
- [blank]: 76
- AIREADI-Vision: 69
- AIREADI-MOCA: 30
Expand All @@ -46,12 +46,12 @@
- OMOP Extension: 1

### PREDICATE_ID
- skos:exactMatch: 1734
- skos:closeMatch: 264
- skos:exactMatch: 1736
- skos:closeMatch: 265
- [blank]: 76
- skos:relatedMatch: 2

### Extension_Needed
- No: 1554
- No: 1557
- Yes: 521
- [blank]: 1
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
A6 Leading/trailing spaces or non-breaking spaces in key columns
A7 Custom concept used as a Condition/answer target where a review is due
(lists every custom Condition target; check whether a standard concept exists)
A8 Answer rows whose FIELD_ID matches no question row (a field-name typo stops the
ETL from linking the answers; e.g. pxne9_ and pxrd9 before v1.5)
A8 Answer rows (Map_to_OMOP = Yes) whose FIELD_ID matches no question row (a field-name
typo stops the ETL from linking the answers; e.g. pxne9_ and pxrd9 before v1.5)

Part B - review lists (read every row; nothing here is automatically wrong):
B1 Answer rows whose source text differs from the target concept name
Expand Down Expand Up @@ -218,7 +218,8 @@ def audit(rows, cm, out, label):
# A8
qcodes = {r["SRC_CODE"] for r in rows if r["temp_Question_or_Answer"] == "Question"}
a8 = [(r["_ln"], r["FORM_NAME"], r["FIELD_ID"], r["SRC_CODE"], r["SRC_CD_DESCRIPTION"][:60], r["TARGET_CONCEPT_ID"])
for r in rows if r["temp_Question_or_Answer"] == "Answer" and r["FIELD_ID"] not in qcodes]
for r in rows if r["temp_Question_or_Answer"] == "Answer" and r["FIELD_ID"] not in qcodes
and r.get("Map_to_OMOP", "Yes") == "Yes"] # rows already excluded (Map_to_OMOP = No) are not flagged
sections.append(("A8 Answers whose FIELD_ID matches no question row (field-name typos; administrative fields expected)",
["Line", "Form", "FIELD_ID", "SRC_CODE", "Source text", "Concept"], a8, False))

Expand Down
Loading
Loading