Skip to content

Commit

Permalink
Removing one of the pairing rules assertions: Generating FHIR-HF with…
Browse files Browse the repository at this point in the history
… an undefined onsetDate, when HF was reported on a follow-up assessment, and the assessment date is not available. Address issue #19
  • Loading branch information
hcadavid committed Sep 17, 2024
1 parent 54b6c97 commit 5b3141b
Show file tree
Hide file tree
Showing 6 changed files with 317 additions and 25 deletions.
71 changes: 71 additions & 0 deletions fhirvalidation/sampleinputs/input-p11111.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
{
"project_pseudo_id": {"1a":"11111"},
"variant_id": {},

"date": {"1a":"1992-5","1b":"1995-5","1c":"1997-5","2a":"2001-5","2b":"2002-5","3a":"2003-5","3b":"2005-5"},
"age": {"1a":"22"},
"gender": {"1a":"MALE"},
"zip_code": {"1a":"11111"},
"date_of_death": {"global":"2010-2"},
"date_of_inclusion": {"global":"1991-2"},

"albumin_result_all_m_1" :{ "1a": "51"},

"creatinine_result_all_m_1":{ "1a": "79.2", "2a":"106.1"},
"hemoglobin_result_all_m_1" :{ "1a": "11.1", "2a":"12"},

"ethnicity_category_adu_q_1":{"1b":"3"},
"hba1cconc_result_all_m_1":{ "1a": "43", "2a":"44"},

"hypertension_startage_adu_q_1":{"1a":"","3a":"23","3b":"23"},
"hypertension_presence_adu_q_1":{"1a":"2","3a":"1","3b":"1"},

"stroke_startage_adu_q_1":{ "1a": "12" },
"stroke_presence_adu_q_1": { "1a": "1" },
"stroke_followup_adu_q_1":{"2a":"2","3a":"2","3b":"2"},

"diabetes_presence_adu_q_1": {"1a":"1"},
"diabetes_startage_adu_q_1": {"1a":"28"},
"diabetes_followup_adu_q_1": {"1b":"2","1c":"2","2a":"2","3a":"2","3b":"2"},
"diabetes_type_adu_q_1": {"1a":"2"},
"diabetes_type_adu_q_1_a": {"1a":""},
"t1d_followup_adu_q_1": {"2a":"2","3a":"2","3b":"2"},
"t2d_followup_adu_q_1": {"2a":"2","3a":"2","3b":"2"},

"bp_entrytype_all_m_1": {"1a":"2","2a":"2"},
"bp_bandsize_all_m_1": {"1a":"1","2a":"1","3a":"1"},
"bp_arm_all_m_1": {"3a":"2"},
"bpavg_systolic_all_m_1": {"1a":"130","2a":"130"},
"bpavg_diastolic_all_m_1": {"1a":"140","2a":"140"},
"bpavg_arterial_all_m_1": {"1a":"113","2a":"113"},

"hdlchol_result_all_m_1": {"1a":"0.31","2a":"0.22"},
"ldlchol_result_all_m_1": {"1a":"0.41","2a":"0.42"},
"cholesterol_result_all_m_1": {"1a":"0.51","2a":"0.52"},

"heartattack_startage_adu_q_1": {"1a":"33"},
"angioplasty_bypass_adu_q_1_a": {"1a":"1","3a":"1","3b":"1"},
"heartattack_presence_adu_q_1": {"1a":"1"},
"heartattack_followup_adu_q_1": {"1b":"2","1c":"2","2a":"2","3a":"2","3b":"2"},
"angioplasty_bypass_adu_q_1": {"1a":"1","3a":"1","3b":"1"},

"heartfailure_startage_adu_q_1":{ "1a": "" },
"heartfailure_presence_adu_q_1": { "1a": "2" },
"heartfailure_followup_adu_q_1":{"2a":"2","3a":"2","3b":"2"},

"carotid_stenosis_adu_q_1": {"1a":"1"},
"claudication_followup_adu_q_1": {"2a":"2","3a":"2","3b":"2"},
"cvd_followup_adu_q_1": {"1b":"2","1c":"2","2a":"2","3a":"2","3b":"2"},

"current_smoker_adu_c_2": { "1a": "0", "1b": "0", "1c": "0", "2a": "0", "2b": "0", "3a": "0" },
"smoking_startage_adu_c_2": { "1a": "5", "1b": "5", "1c": "5", "2a": "5", "2b": "5", "3a": "5" },
"ex_smoker_adu_c_2": { "1a": "1", "1b": "1", "1c": "1", "2a": "1", "2b": "1", "3a": "1" },
"smoking_endage_adu_c_2": { "1a": "8", "1b": "8", "1c": "8", "2a": "8", "2b": "8", "3a": "8"},
"ever_smoker_adu_c_2": { "1a": "1", "1b": "1", "1c": "1", "2a": "1", "2b": "1", "3a": "1"},
"total_frequency_adu_c_1": { "1a": "", "1b": "", "1c": "", "2a": "", "2b": "", "3a": ""},
"packyears_cumulative_adu_c_2": { "1a": "", "1b": "", "1c": "", "2a": "", "2b": "", "3a": ""}



}

Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
{
"project_pseudo_id": {"1a":"675432"},
"variant_id": {},

"date": {"1a":"1992-5","1b":"1995-5","1c":"1997-5","2a":"2001-5","2b":"2002-5","3a":"","3b":"2005-5"},

"age": {"1a":"22"},
"gender": {"1a":"MALE"},
"zip_code": {"1a":"11111"},
"date_of_death": {"global":"2010-2"},
"date_of_inclusion": {"global":"1991-2"},

"albumin_result_all_m_1" :{ "1a": "51"},
"creatinine_result_all_m_1":{ "1a": "79.2", "2a":"106.1"},
"ethnicity_category_adu_q_1":{"1b":"3"},
"hemoglobin_result_all_m_1" :{ "1a": "11.1", "2a":"12"},
"hba1cconc_result_all_m_1":{ "1a": "43", "2a":"44"},

"hypertension_startage_adu_q_1":{"1a":"","3a":"23","3b":"23"},
"hypertension_presence_adu_q_1":{"1a":"2","3a":"1","3b":"1"},

"stroke_startage_adu_q_1":{ "1a": "12" },
"stroke_presence_adu_q_1": { "1a": "1" },
"stroke_followup_adu_q_1":{"2a":"2","3a":"2","3b":"2"},


"diabetes_presence_adu_q_1": {"1a":"1"},
"diabetes_startage_adu_q_1": {"1a":"28"},
"diabetes_followup_adu_q_1": {"1b":"2","1c":"2","2a":"2","3a":"2","3b":"2"},
"diabetes_type_adu_q_1": {"1a":"2"},
"diabetes_type_adu_q_1_a": {"1a":""},
"t1d_followup_adu_q_1": {"2a":"2","3a":"2","3b":"2"},
"t2d_followup_adu_q_1": {"2a":"2","3a":"2","3b":"2"},

"bp_entrytype_all_m_1": {"1a":"2","2a":"2"},
"bp_bandsize_all_m_1": {"1a":"1","2a":"1","3a":"1"},
"bp_arm_all_m_1": {"3a":"2"},
"bpavg_systolic_all_m_1": {"1a":"130","2a":"130"},
"bpavg_diastolic_all_m_1": {"1a":"140","2a":"140"},
"bpavg_arterial_all_m_1": {"1a":"113","2a":"113"},

"hdlchol_result_all_m_1": {"1a":"0.31","2a":"0.22"},
"ldlchol_result_all_m_1": {"1a":"0.41","2a":"0.42"},
"cholesterol_result_all_m_1": {"1a":"0.51","2a":"0.52"},

"heartattack_startage_adu_q_1": {"1a":"33"},
"angioplasty_bypass_adu_q_1_a": {"1a":"1","3a":"1","3b":"1"},
"heartattack_presence_adu_q_1": {"1a":"1"},
"heartattack_followup_adu_q_1": {"1b":"2","1c":"2","2a":"2","3a":"2","3b":"2"},
"angioplasty_bypass_adu_q_1": {"1a":"1","3a":"1","3b":"1"},

"heartfailure_startage_adu_q_1":{ "1a": "" },
"heartfailure_presence_adu_q_1": { "1a": "2" },
"heartfailure_followup_adu_q_1":{"2a":"2","3a":"1","3b":"2"},

"carotid_stenosis_adu_q_1": {"1a":"1"},
"claudication_followup_adu_q_1": {"2a":"2","3a":"2","3b":"2"},
"cvd_followup_adu_q_1": {"1b":"2","1c":"2","2a":"2","3a":"2","3b":"2"},

"current_smoker_adu_c_2": { "1a": "0", "1b": "0", "1c": "0", "2a": "0", "2b": "0", "3a": "0" },
"smoking_startage_adu_c_2": { "1a": "5", "1b": "5", "1c": "5", "2a": "5", "2b": "5", "3a": "5" },
"ex_smoker_adu_c_2": { "1a": "1", "1b": "1", "1c": "1", "2a": "1", "2b": "1", "3a": "1" },
"smoking_endage_adu_c_2": { "1a": "8", "1b": "8", "1c": "8", "2a": "8", "2b": "8", "3a": "8"},
"ever_smoker_adu_c_2": { "1a": "1", "1b": "1", "1c": "1", "2a": "1", "2b": "1", "3a": "1"},
"total_frequency_adu_c_1": { "1a": "", "1b": "", "1c": "", "2a": "", "2b": "", "3a": ""},
"packyears_cumulative_adu_c_2": { "1a": "", "1b": "", "1c": "", "2a": "", "2b": "", "3a": ""}



}

Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
{
"project_pseudo_id": {"1a":"98765"},
"variant_id": {},

"date": {"1a":"1992-5","1b":"1995-5","1c":"1997-5","2a":"2001-5","2b":"2002-5","3a":"2003-5","3b":"2005-5"},

"age": {"1a":"22"},
"gender": {"1a":"MALE"},
"zip_code": {"1a":"11111"},
"date_of_death": {"global":"2010-2"},
"date_of_inclusion": {"global":"1991-2"},

"albumin_result_all_m_1" :{ "1a": "51"},
"creatinine_result_all_m_1":{ "1a": "79.2", "2a":"106.1"},
"ethnicity_category_adu_q_1":{"1b":"3"},
"hemoglobin_result_all_m_1" :{ "1a": "11.1", "2a":"12"},
"hba1cconc_result_all_m_1":{ "1a": "43", "2a":"44"},

"hypertension_startage_adu_q_1":{"1a":"","3a":"23","3b":"23"},
"hypertension_presence_adu_q_1":{"1a":"2","3a":"1","3b":"1"},

"stroke_startage_adu_q_1":{ "1a": "12" },
"stroke_presence_adu_q_1": { "1a": "1" },
"stroke_followup_adu_q_1":{"2a":"2","3a":"2","3b":"2"},


"diabetes_presence_adu_q_1": {"1a":"1"},
"diabetes_startage_adu_q_1": {"1a":"28"},
"diabetes_followup_adu_q_1": {"1b":"2","1c":"2","2a":"2","3a":"2","3b":"2"},
"diabetes_type_adu_q_1": {"1a":"2"},
"diabetes_type_adu_q_1_a": {"1a":""},
"t1d_followup_adu_q_1": {"2a":"2","3a":"2","3b":"2"},
"t2d_followup_adu_q_1": {"2a":"2","3a":"2","3b":"2"},

"bp_entrytype_all_m_1": {"1a":"2","2a":"2"},
"bp_bandsize_all_m_1": {"1a":"1","2a":"1","3a":"1"},
"bp_arm_all_m_1": {"3a":"2"},
"bpavg_systolic_all_m_1": {"1a":"130","2a":"130"},
"bpavg_diastolic_all_m_1": {"1a":"140","2a":"140"},
"bpavg_arterial_all_m_1": {"1a":"113","2a":"113"},

"hdlchol_result_all_m_1": {"1a":"0.31","2a":"0.22"},
"ldlchol_result_all_m_1": {"1a":"0.41","2a":"0.42"},
"cholesterol_result_all_m_1": {"1a":"0.51","2a":"0.52"},

"heartattack_startage_adu_q_1": {"1a":"33"},
"angioplasty_bypass_adu_q_1_a": {"1a":"1","3a":"1","3b":"1"},
"heartattack_presence_adu_q_1": {"1a":"1"},
"heartattack_followup_adu_q_1": {"1b":"2","1c":"2","2a":"2","3a":"2","3b":"2"},
"angioplasty_bypass_adu_q_1": {"1a":"1","3a":"1","3b":"1"},

"heartfailure_startage_adu_q_1":{ "1a": "" },
"heartfailure_presence_adu_q_1": { "1a": "1" },
"heartfailure_followup_adu_q_1":{"2a":"2","3a":"2","3b":"2"},

"carotid_stenosis_adu_q_1": {"1a":"1"},
"claudication_followup_adu_q_1": {"2a":"2","3a":"2","3b":"2"},
"cvd_followup_adu_q_1": {"1b":"2","1c":"2","2a":"2","3a":"2","3b":"2"},

"current_smoker_adu_c_2": { "1a": "0", "1b": "0", "1c": "0", "2a": "0", "2b": "0", "3a": "0" },
"smoking_startage_adu_c_2": { "1a": "5", "1b": "5", "1c": "5", "2a": "5", "2b": "5", "3a": "5" },
"ex_smoker_adu_c_2": { "1a": "1", "1b": "1", "1c": "1", "2a": "1", "2b": "1", "3a": "1" },
"smoking_endage_adu_c_2": { "1a": "8", "1b": "8", "1c": "8", "2a": "8", "2b": "8", "3a": "8"},
"ever_smoker_adu_c_2": { "1a": "1", "1b": "1", "1c": "1", "2a": "1", "2b": "1", "3a": "1"},
"total_frequency_adu_c_1": { "1a": "", "1b": "", "1c": "", "2a": "", "2b": "", "3a": ""},
"packyears_cumulative_adu_c_2": { "1a": "", "1b": "", "1c": "", "2a": "", "2b": "", "3a": ""}



}

Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { heartFailure } from '../lifelines/HeartFailure';
import { MappingTarget, processInput } from '../mapper'
import {getSNOMEDCode} from '../codes/codesCollection'


test('heartfailure, when reported positive in 1A', () => {

const input = {
Expand All @@ -24,6 +25,27 @@ test('heartfailure, when reported positive in 1A', () => {
});


test('heartfailure, when reported positive in 1A, but no start_age was reported', () => {

const input = {
"heartfailure_startage_adu_q_1":{ "1a": "" },
"heartfailure_presence_adu_q_1": { "1a": "1" },
"heartfailure_followup_adu_q_1":{"1b":"2","1c":"2","2a":"2","3a":"2","3b":"2"},
"date": {"1a":"1992-5","1b":"1995-5","1c":"1997-5","2a":"2001-5","2b":"2002-5","3a":"2003-5","3b":"2005-5"},
"age": { "1a": "22" }
}

InputSingleton.getInstance().setInput(input);


expect(heartFailure.clinicalStatus()?.display).toBe("Active");
expect(heartFailure.isPresent()).toBe(true);
expect(heartFailure.code().display).toBe("Heart failure (disorder)");
expect(heartFailure.onsetDateTime()).toBe(undefined);

});


test('heart failure, when reported in 2A', () => {

const input = {
Expand All @@ -43,6 +65,26 @@ test('heart failure, when reported in 2A', () => {
});


test('heart failure, when reported in 2A, but there is no assessment date available for 2A', () => {

const input = {
"heartfailure_startage_adu_q_1":{ "1a": "" },
"heartfailure_presence_adu_q_1": { "1a": "2" },
"heartfailure_followup_adu_q_1":{"1b":"2","1c":"2","2a":"1","3a":"2","3b":"2"},
"date": {"1a":"1992-5","1b":"","1c":"","2a":"","3a":"","3b":""},
"age": { "1a": "22" }
}

InputSingleton.getInstance().setInput(input);
expect(heartFailure.clinicalStatus()?.display).toBe("Active");
expect(heartFailure.isPresent()).toBe(true);
expect(heartFailure.code().display).toBe("Heart failure (disorder)");
expect(heartFailure.onsetDateTime()).toBe(undefined);

});



test('heart failure, when reported right after baseline (1B)', () => {

const input = {
Expand Down Expand Up @@ -100,6 +142,26 @@ test('heart failure, when reported in 2A, after skipping multiple assessments',
});


test('heart failure, when reported in 2A, after skipping multiple assessments', () => {

const input = {
"heartfailure_startage_adu_q_1":{ "1a": "" },
"heartfailure_presence_adu_q_1": { "1a": "2" },
"heartfailure_followup_adu_q_1":{"1b":undefined,"1c":undefined,"2a":"1","3a":"2","3b":"2"},
"date": {"1a":"1992-5","1b":undefined,"1c":undefined,"2a":"2002-5","3a":"2003-5","3b":"2005-5"},
"age": { "1a": "22" }
}

InputSingleton.getInstance().setInput(input);
expect(heartFailure.clinicalStatus()?.display).toBe("Active");
expect(heartFailure.isPresent()).toBe(true);
expect(heartFailure.code().display).toBe("Heart failure (disorder)");
expect(heartFailure.onsetDateTime()).toBe("1997-05");

});




test('heart failure, when no reported', () => {

Expand Down
51 changes: 34 additions & 17 deletions src/lifelines/HeartFailure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,20 @@ export const heartFailure:Condition = {
* ------------------------------------------------------------------
*
* @precondition
* - date and age are not missing values (undefined)
* - the problem is 'active' (see clinicalStatus function)
*
* @pairingrule
* if heartfailure_presence_adu_q_1 = yes in 1A => approximate year on which the participant given the age reported by heartfailure_startage_adu_q_1
* if heartfailure_presence_adu_q_1 = yes in 1A =>
* if start_age was reported, approximate year of the event given start_age reported (heartfailure_startage_adu_q_1)
* and the year of the year of the assessment.
* else
* undefined onset date
* else
* if there is a 'yes' in any heartfailure_followup_adu_q_1 => mean date between the date of the assessment
* where heartfailure_followup_adu_q_1 = yes, and the date of the preceding one.
* if there is a 'yes' in any heartfailure_followup_adu_q_1 =>
* If the date of the assessment where heartfailure_followup_adu_q_1 = yes is available =>
* mean date between that particular date (when heartfailure_followup_adu_q_1 = yes), and the date of the preceding assessment.
* Else
* return undefined date
* else
* error/precondition violated ('heartfailure' is not 'active' if the execution reached this point)
*
Expand Down Expand Up @@ -95,7 +101,7 @@ export const heartFailure:Condition = {
return lifelinesDateToISO(lifelinesMeanDate(date1, date2));
}
else {
throw Error("Unexpected input (precondition violated): no 'yes' values in heartfailure_followup_adu_q_1");
return undefined;
}


Expand Down Expand Up @@ -147,8 +153,13 @@ const _clinicalStatus = moize((heartfailure_presence:string|undefined,followup_a
* date [X ][X ][X ][X ][X ][X ]
*
*
* mean date between the date of the assessment
* where heartfailure_followup_adu_q_1 = yes, and the date of the preceding one.
* @precondition: there is at least one 'yes'/1 on heartfailure_followup_adu_q_1
*
* If the date of the assessment where heartfailure_followup_adu_q_1 = yes is available =>
* mean date between that particular date (when heartfailure_followup_adu_q_1 = yes), and the date of the preceding assessment.
* Else
* return undefined date
*
*
*
* @param diabFollowUp
Expand All @@ -164,16 +175,22 @@ function findDatesBetweenheartfailurePresenceReport(): [string,string]|undefined
assertIsDefined(heartfailureWave,`A 'yes' value on heartfailure_followup_adu_q_1 was expected`)

const heartfailureWaveDate = inputValue("date",heartfailureWave)
assertIsDefined(heartfailureWaveDate,`A non-null date is expected in the assessment where heartfailure_followup_adu_q_1 is reported`)

//find the previous non-undefined assessment date
const assessmentDates:variableAssessments = inputValues('date')
const waves = ['1a','1b','1c','2a','3a','3b'];
const previousWaves = waves.slice(0,waves.indexOf(heartfailureWave))
const previousAssessmentWave = previousWaves.reverse().find((pwave)=>assessmentDates[pwave]!==undefined)

assertIsDefined(previousAssessmentWave,`Assessment (with a non-null date) expected to exist previous to the one where heartfailure_followup_adu_q_1 is reported`)
//If the date of the assessment where the episode was reported is not available, return undefined date
if (heartfailureWaveDate === undefined){
return undefined
}
else{
//find the previous non-undefined assessment date
const assessmentDates:variableAssessments = inputValues('date')
const waves = ['1a','1b','1c','2a','3a','3b'];
const previousWaves = waves.slice(0,waves.indexOf(heartfailureWave))
const previousAssessmentWave = previousWaves.reverse().find((pwave)=>assessmentDates[pwave]!==undefined)

assertIsDefined(previousAssessmentWave,`Assessment (with a non-null date) expected to exist previous to the one where heartfailure_followup_adu_q_1 is reported`)

const previousAssessmentDate:string = assessmentDates[previousAssessmentWave!]!;
return [previousAssessmentDate,heartfailureWaveDate]
}

const previousAssessmentDate:string = assessmentDates[previousAssessmentWave!]!;
return [previousAssessmentDate,heartfailureWaveDate]
}
Loading

0 comments on commit 5b3141b

Please sign in to comment.