Skip to content

Commit b1df657

Browse files
committed
Update find_concept_fields to handle the cause_concept_id and create_reusing_concepts to handle reusing the correct concepts
1 parent 58fb38f commit b1df657

2 files changed

Lines changed: 47 additions & 24 deletions

File tree

app/airflow/dags/auto_mapping_dag.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
6. Create reusable concepts based on matches
4444
7. Collect all existing concepts
4545
8. Identify destination tables and person field IDs
46-
9. Find date fields for each concept
46+
9. Find date fields for each concept (incl. death_datetime for death table)
4747
10. Find concept fields for mapping
4848
11. Find additional fields needed for mapping
4949
12. Create mapping rules based on all collected information
@@ -54,7 +54,7 @@
5454
"""
5555
# TODO: for now the creation of mapping rules will use the source_concept_id of temp_reuse_concepts table.
5656
# When we can distinguish between standard and non-standard concepts, we will use them accordingly in the create_mapping_rules function of reuse.
57-
# TODO: for death table, only reuse when the source table is death table as well
57+
# When reusing concepts for the death table, only consider other death tables. (See the death_table filter in find_m_concepts_query.)
5858
# NOTE: when the DB is huge, the performance of the DAG will be affected by refreshing the existing R concepts. --> consider to only refresh the R Mapping rules
5959
# TODO: should we add `value` column in MAPPINGRULE model? in order to filter the mapping rule based on the SR value?
6060
# TODO: add the source_concept_id to the UI

app/airflow/dags/libs/queries.py

Lines changed: 45 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@
139139
-- Because concepts may or may not have the standard_concept_id, in general. And we prefer to use the standard_concept_id, if it exists.
140140
WHERE target_concept.concept_id = COALESCE(temp_existing_concepts.standard_concept_id, temp_existing_concepts.source_concept_id);
141141
142+
-- When the scan report table is a death table, override dest_table_id to the death OMOP table so rules show destination table: death, field: cause_concept_id
143+
UPDATE temp_existing_concepts_%(table_id)s temp_existing_concepts
144+
SET dest_table_id = (SELECT id FROM mapping_omoptable WHERE "table" = 'death' LIMIT 1)
145+
WHERE (SELECT death_table FROM mapping_scanreporttable WHERE id = %(table_id)s) = TRUE;
146+
142147
-- Update person field ID
143148
UPDATE temp_existing_concepts_%(table_id)s temp_existing_concepts
144149
SET dest_person_field_id = omop_field.id
@@ -204,34 +209,40 @@
204209
temp_existing_concepts.object_id,
205210
target_concept.domain_id,
206211
target_concept.concept_id AS concept_id,
207-
-- Use domain-specific source_concept_field_id
208-
(SELECT omop_field.id
209-
FROM mapping_omopfield AS omop_field
210-
WHERE omop_field.table_id = temp_existing_concepts.dest_table_id
211-
AND omop_field.field =
212-
CASE
213-
WHEN target_concept.domain_id = 'Spec Anatomic Site' THEN 'anatomic_site_source_concept_id' -- Not applicable for Specimen table
212+
-- Source concept field: death table uses cause_source_concept_id, others use domain-based name
213+
(SELECT omop_field.id
214+
FROM mapping_omopfield AS omop_field
215+
JOIN mapping_omoptable AS omop_table ON omop_table.id = omop_field.table_id
216+
WHERE omop_field.table_id = temp_existing_concepts.dest_table_id
217+
AND omop_field.field =
218+
CASE
219+
WHEN omop_table.table = 'death' THEN 'cause_source_concept_id'
220+
WHEN target_concept.domain_id = 'Spec Anatomic Site' THEN 'anatomic_site_source_concept_id'
214221
ELSE LOWER(target_concept.domain_id) || '_source_concept_id'
215222
END
216223
LIMIT 1) AS source_concept_field_id,
217224
218-
-- Use domain-specific source_value_field_id
219-
(SELECT omop_field.id
220-
FROM mapping_omopfield AS omop_field
221-
WHERE omop_field.table_id = temp_existing_concepts.dest_table_id
222-
AND omop_field.field =
223-
CASE
225+
-- Source value field: death table uses cause_source_value, others use domain-based name
226+
(SELECT omop_field.id
227+
FROM mapping_omopfield AS omop_field
228+
JOIN mapping_omoptable AS omop_table ON omop_table.id = omop_field.table_id
229+
WHERE omop_field.table_id = temp_existing_concepts.dest_table_id
230+
AND omop_field.field =
231+
CASE
232+
WHEN omop_table.table = 'death' THEN 'cause_source_value'
224233
WHEN target_concept.domain_id = 'Spec Anatomic Site' THEN 'anatomic_site_source_value'
225234
ELSE LOWER(target_concept.domain_id) || '_source_value'
226235
END
227236
LIMIT 1) AS source_value_field_id,
228237
229-
-- Use domain-specific dest_concept_field_id
230-
(SELECT omop_field.id
231-
FROM mapping_omopfield AS omop_field
232-
WHERE omop_field.table_id = temp_existing_concepts.dest_table_id
233-
AND omop_field.field =
234-
CASE
238+
-- Dest concept field: death table uses cause_concept_id, others use domain-based name
239+
(SELECT omop_field.id
240+
FROM mapping_omopfield AS omop_field
241+
JOIN mapping_omoptable AS omop_table ON omop_table.id = omop_field.table_id
242+
WHERE omop_field.table_id = temp_existing_concepts.dest_table_id
243+
AND omop_field.field =
244+
CASE
245+
WHEN omop_table.table = 'death' THEN 'cause_concept_id'
235246
WHEN target_concept.domain_id = 'Spec Anatomic Site' THEN 'anatomic_site_concept_id'
236247
ELSE LOWER(target_concept.domain_id) || '_concept_id'
237248
END
@@ -293,7 +304,8 @@
293304
AND map_status.value = 'COMPLETE'
294305
AND scan_report.id != %(scan_report_id)s
295306
),
296-
-- Find values in eligible scan reports that have M-type concepts tied
307+
-- Find values in eligible scan reports that have M-type concepts tied.
308+
-- Only reuse from tables with the same death_table flag (death tables get death concepts only; non-death never get death concepts).
297309
values_with_m_concepts AS (
298310
SELECT
299311
sr_value.value AS matching_value_name,
@@ -306,6 +318,7 @@
306318
FROM eligible_reports AS eligible_report
307319
JOIN mapping_scanreporttable AS sr_table ON sr_table.scan_report_id = eligible_report.id
308320
AND sr_table.name = %(current_table_name)s
321+
AND (SELECT death_table FROM mapping_scanreporttable WHERE id = %(table_id)s) IS NOT DISTINCT FROM sr_table.death_table
309322
JOIN mapping_scanreportfield AS sr_field ON sr_field.scan_report_table_id = sr_table.id
310323
JOIN mapping_scanreportvalue AS sr_value ON sr_value.scan_report_field_id = sr_field.id
311324
JOIN mapping_scanreportconcept AS sr_concept ON sr_concept.object_id = sr_value.id
@@ -345,7 +358,8 @@
345358
AND map_status.value = 'COMPLETE'
346359
AND scan_report.id != %(scan_report_id)s
347360
),
348-
-- Find fields in eligible scan reports that have M-type concepts tied
361+
-- Find fields in eligible scan reports that have M-type concepts tied.
362+
-- Match only tables with an identical death_table setting to ensure concepts from death tables are reused only with other death tables, and non-death tables only with non-death.
349363
fields_with_m_concepts AS (
350364
SELECT
351365
sr_field.name AS matching_field_name,
@@ -356,6 +370,7 @@
356370
FROM eligible_reports AS eligible_report
357371
JOIN mapping_scanreporttable AS sr_table ON sr_table.scan_report_id = eligible_report.id
358372
AND sr_table.name = %(current_table_name)s
373+
AND (SELECT death_table FROM mapping_scanreporttable WHERE id = %(table_id)s) IS NOT DISTINCT FROM sr_table.death_table
359374
JOIN mapping_scanreportfield AS sr_field ON sr_field.scan_report_table_id = sr_table.id
360375
JOIN mapping_scanreportconcept AS sr_concept ON sr_concept.object_id = sr_field.id
361376
AND sr_concept.content_type_id = (SELECT id FROM field_content_type)
@@ -372,6 +387,7 @@
372387
FROM fields_with_m_concepts;
373388
"""
374389

390+
# Only set object_id if the death_table flag for the current table matches the source table (identified by source_scanreport_id and matching_table_name).
375391
find_object_id_query = """
376392
UPDATE temp_reuse_concepts_%(table_id)s AS temp_table
377393
SET object_id =
@@ -405,7 +421,14 @@
405421
)
406422
LIMIT 1)
407423
ELSE NULL
408-
END;
424+
END
425+
WHERE (SELECT death_table FROM mapping_scanreporttable WHERE id = %(table_id)s) IS NOT DISTINCT FROM (
426+
SELECT sr_table.death_table
427+
FROM mapping_scanreporttable AS sr_table
428+
WHERE sr_table.scan_report_id = temp_table.source_scanreport_id
429+
AND sr_table.name = temp_table.matching_table_name
430+
LIMIT 1
431+
);
409432
"""
410433

411434

0 commit comments

Comments
 (0)