Skip to content

Commit 408bfae

Browse files
authored
Merge pull request #133 from samply/feature/icd10gmnew
added bfarm icd10gm
2 parents ce59cac + dd51f0d commit 408bfae

File tree

4 files changed

+27
-69
lines changed

4 files changed

+27
-69
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ rand = { default-features = false, version = "0.8.5" }
3030

3131
[dev-dependencies]
3232
tokio-test = "0.4.2"
33+
pretty_assertions = "1.4.0"
3334

3435
[build-dependencies]
3536
build-data = "0"
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
define Diagnosis:
22
if InInitialPopulation then [Condition] else {} as List<Condition>
33
define function DiagnosisCode(condition FHIR.Condition, specimen FHIR.Specimen):
4-
Coalesce(condition.code.coding.where(system = 'http://hl7.org/fhir/sid/icd-10').code.first(), condition.code.coding.where(system = 'http://fhir.de/CodeSystem/dimdi/icd-10-gm').code.first(), specimen.extension.where(url='https://fhir.bbmri.de/StructureDefinition/SampleDiagnosis').value.coding.code.first(), condition.code.coding.where(system = 'http://fhir.de/CodeSystem/bfarm/icd-10-gm').code.first())
4+
Coalesce(condition.code.coding.where(system = 'http://hl7.org/fhir/sid/icd-10').code.first(),
5+
condition.code.coding.where(system = 'http://fhir.de/CodeSystem/dimdi/icd-10-gm').code.first(),
6+
condition.code.coding.where(system = 'http://fhir.de/CodeSystem/bfarm/icd-10-gm').code.first(),
7+
specimen.extension.where(url='https://fhir.bbmri.de/StructureDefinition/SampleDiagnosis').value.coding.code.first(), condition.code.coding.where(system = 'http://fhir.de/CodeSystem/bfarm/icd-10-gm').code.first())
58

resources/test/query_bbmri.cql

+4-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,10 @@ define Specimen:
7979
define Diagnosis:
8080
if InInitialPopulation then [Condition] else {} as List<Condition>
8181
define function DiagnosisCode(condition FHIR.Condition, specimen FHIR.Specimen):
82-
Coalesce(condition.code.coding.where(system = 'http://hl7.org/fhir/sid/icd-10').code.first(), condition.code.coding.where(system = 'http://fhir.de/CodeSystem/dimdi/icd-10-gm').code.first(), specimen.extension.where(url='https://fhir.bbmri.de/StructureDefinition/SampleDiagnosis').value.coding.code.first(), condition.code.coding.where(system = 'http://fhir.de/CodeSystem/bfarm/icd-10-gm').code.first())
82+
Coalesce(condition.code.coding.where(system = 'http://hl7.org/fhir/sid/icd-10').code.first(),
83+
condition.code.coding.where(system = 'http://fhir.de/CodeSystem/dimdi/icd-10-gm').code.first(),
84+
condition.code.coding.where(system = 'http://fhir.de/CodeSystem/bfarm/icd-10-gm').code.first(),
85+
specimen.extension.where(url='https://fhir.bbmri.de/StructureDefinition/SampleDiagnosis').value.coding.code.first(), condition.code.coding.where(system = 'http://fhir.de/CodeSystem/bfarm/icd-10-gm').code.first())
8386

8487

8588

src/util.rs

+18-67
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::errors::FocusError;
2-
use base64::Engine as _;
32
use base64::engine::general_purpose;
3+
use base64::Engine as _;
44
use laplace_rs::{get_from_cache_or_privatize, Bin, ObfCache, ObfuscateBelow10Mode};
55
use rand::thread_rng;
66
use serde::{Deserialize, Serialize};
@@ -350,7 +350,8 @@ mod test {
350350
const QUERY_BBMRI: &str = include_str!("../resources/test/query_bbmri.cql");
351351
const EXAMPLE_MEASURE_REPORT_BBMRI: &str =
352352
include_str!("../resources/test/measure_report_bbmri.json");
353-
const EXAMPLE_MEASURE_REPORT_DKTK: &str = include_str!("../resources/test/measure_report_dktk.json");
353+
const EXAMPLE_MEASURE_REPORT_DKTK: &str =
354+
include_str!("../resources/test/measure_report_dktk.json");
354355
const EXAMPLE_MEASURE_REPORT_EXLIQUID: &str =
355356
include_str!("../resources/test/measure_report_exliquid.json");
356357

@@ -387,7 +388,7 @@ mod test {
387388
// Call the function and assert that it returns the expected result
388389
let result = get_json_field(json_string, "address");
389390
assert!(result.is_ok());
390-
assert_eq!(result.unwrap(), expected_result);
391+
pretty_assertions::assert_eq!(result.unwrap(), expected_result);
391392
}
392393

393394
#[test]
@@ -408,7 +409,7 @@ mod test {
408409
// Call the function and assert that it returns json null
409410
let result = get_json_field(json_string, "phone");
410411
assert!(result.is_ok());
411-
assert_eq!(result.unwrap(), json!(null));
412+
pretty_assertions::assert_eq!(result.unwrap(), json!(null));
412413
}
413414

414415
#[test]
@@ -433,72 +434,22 @@ mod test {
433434
assert!(!is_cql_tampered_with(decoded_library));
434435
}
435436

437+
#[test]
438+
fn test_replace_cql_all() {
439+
for (decoded_library, expected_result) in REPLACE_MAP.iter() {
440+
pretty_assertions::assert_eq!(replace_cql(*decoded_library).as_str(), *expected_result);
441+
}
442+
}
443+
436444
#[test]
437445
fn test_replace_cql() {
438446
let decoded_library = QUERY_BBMRI_PLACEHOLDERS;
439447
let expected_result = QUERY_BBMRI;
440-
assert_eq!(replace_cql(decoded_library), expected_result);
441-
442-
let decoded_library = "BBMRI_STRAT_GENDER_STRATIFIER";
443-
let expected_result = "define Gender:\n if (Patient.gender is null) then 'unknown'\n else if (Patient.gender != 'male' and Patient.gender != 'female' and Patient.gender != 'other' and Patient.gender != 'unknown') then 'other'\n else Patient.gender";
444-
assert_eq!(replace_cql(decoded_library), expected_result);
445-
446-
let decoded_library = "BBMRI_STRAT_CUSTODIAN_STRATIFIER";
447-
let expected_result = "define Custodian:\n First(from Specimen.extension E\n where E.url = 'https://fhir.bbmri.de/StructureDefinition/Custodian'\n return (E.value as Reference).identifier.value)\n";
448-
assert_eq!(replace_cql(decoded_library), expected_result);
449-
450-
let decoded_library = "BBMRI_STRAT_DIAGNOSIS_STRATIFIER";
451-
let expected_result = "define Diagnosis:\n if InInitialPopulation then [Condition] else {} as List<Condition> \n define function DiagnosisCode(condition FHIR.Condition, specimen FHIR.Specimen):\n Coalesce(condition.code.coding.where(system = 'http://hl7.org/fhir/sid/icd-10').code.first(), condition.code.coding.where(system = 'http://fhir.de/CodeSystem/dimdi/icd-10-gm').code.first(), specimen.extension.where(url='https://fhir.bbmri.de/StructureDefinition/SampleDiagnosis').value.coding.code.first(), condition.code.coding.where(system = 'http://fhir.de/CodeSystem/bfarm/icd-10-gm').code.first())\n\n";
452-
assert_eq!(replace_cql(decoded_library), expected_result);
453-
454-
let decoded_library = "BBMRI_STRAT_AGE_STRATIFIER";
455-
let expected_result = "define AgeClass:\n (AgeInYears() div 10) * 10\n";
456-
assert_eq!(replace_cql(decoded_library), expected_result);
457-
458-
let decoded_library = "BBMRI_STRAT_DEF_SPECIMEN";
459-
let expected_result = "define Specimen:\n";
460-
assert_eq!(replace_cql(decoded_library), expected_result);
461-
462-
let decoded_library = "BBMRI_STRAT_DEF_IN_INITIAL_POPULATION";
463-
let expected_result = "define InInitialPopulation:\n";
464-
assert_eq!(replace_cql(decoded_library), expected_result);
465-
466-
let decoded_library = "DKTK_STRAT_PRIMARY_DIAGNOSIS_STRATIFIER";
467-
let expected_result = "define PrimaryDiagnosis:\nFirst(\nfrom [Condition] C\nwhere C.extension.where(url='http://hl7.org/fhir/StructureDefinition/condition-related').empty()\nsort by date from onset asc)\n\n";
468-
assert_eq!(replace_cql(decoded_library), expected_result);
469-
470-
let decoded_library = "DKTK_STRAT_AGE_CLASS_STRATIFIER";
471-
let expected_result = "define AgeClass:\nif (PrimaryDiagnosis.onset is null) then 'unknown' else ToString((AgeInYearsAt(FHIRHelpers.ToDateTime(PrimaryDiagnosis.onset)) div 10) * 10)\n";
472-
assert_eq!(replace_cql(decoded_library), expected_result);
473-
474-
let decoded_library = "EXLIQUID_CQL_DIAGNOSIS";
475-
let expected_result = "define retrieveCondition: First(from [Condition] C return C.code.coding.where(system = 'http://fhir.de/CodeSystem/bfarm/icd-10-gm').code.first())\ndefine Diagnosis: if (retrieveCondition is null) then 'unknown' else retrieveCondition\n\n";
476-
assert_eq!(replace_cql(decoded_library), expected_result);
477-
478-
let decoded_library = "EXLIQUID_CQL_SPECIMEN";
479-
let expected_result = "define Specimen:\nif InInitialPopulation then [Specimen] else {} as List<Specimen>\ndefine ExliquidSpecimen:\n from [Specimen] S\n where S.identifier.system contains 'http://dktk.dkfz.de/fhir/sid/exliquid-specimen'\ndefine function SampleType(specimen FHIR.Specimen):\n specimen.type.coding.where(system = 'https://fhir.bbmri.de/CodeSystem/SampleMaterialType').code.first()\n";
480-
assert_eq!(replace_cql(decoded_library), expected_result);
481-
482-
let decoded_library = "EXLIQUID_STRAT_W_ALIQUOTS";
483-
let expected_result = "define InInitialPopulation:\n exists AnySpecimen\n \ndefine AnySpecimen:\n [Specimen] S\n\ndefine retrieveCondition:\n First(from [Condition] C\n return ('{\\\"subject_reference\\\": \\\"' + C.subject.reference \n + '\\\", \\\"diagnosis_code\\\": \\\"' \n + C.code.coding.where(system = 'http://fhir.de/CodeSystem/bfarm/icd-10-gm').code.first() \n + '\\\"}'\n ))\n \ndefine Diagnosis:\n if (retrieveCondition is null) then '{\\\"subject_reference\\\": \\\"\\\", \\\"diagnosis_code\\\": \\\"\\\"}' \n else retrieveCondition\n\ndefine function getSampletype(specimen FHIR.Specimen):\n if (not exists specimen.type.coding.where(system = 'https://fhir.bbmri.de/CodeSystem/SampleMaterialType').code) then 'null'\n else specimen.type.coding.where(system = 'https://fhir.bbmri.de/CodeSystem/SampleMaterialType').code.first()\n\ndefine function getRestamount(specimen FHIR.Specimen):\n if (not exists specimen.collection.quantity.value) then '0' else specimen.collection.quantity.value.toString()\n\ndefine function getParentReference(specimen FHIR.Specimen): \n if (not exists specimen.parent.reference) then 'null' else specimen.parent.reference\n\ndefine function getSubjectReference(specimen FHIR.Specimen): \n if (not exists specimen.subject.reference) then 'null' else specimen.subject.reference\n\ndefine function SingleStrat(specimen FHIR.Specimen):\n '{\"specimen_id\": \"' + specimen.id + \n '\", \"sampletype\": \"' + getSampletype(specimen) +\n '\", \"exliquid_tag\": ' + (specimen.identifier.system contains 'http://dktk.dkfz.de/fhir/sid/exliquid-specimen').toString() +\n ', \"rest_amount\": \"' + getRestamount(specimen) +\n '\", \"parent_reference\": \"' + getParentReference(specimen) +\n '\", \"subject_reference\": \"' + getSubjectReference(specimen) +\n '\"}'";
484-
assert_eq!(replace_cql(decoded_library), expected_result);
485-
486-
let decoded_library = "EXLIQUID_STRAT_DEF_IN_INITIAL_POPULATION";
487-
let expected_result = "define InInitialPopulation:\n exists ExliquidSpecimen and\n\n";
488-
assert_eq!(replace_cql(decoded_library), expected_result);
489-
490-
let decoded_library = "MTBA_STRAT_GENETIC_VARIANT";
491-
let expected_result = "define GeneticVariantCode:\nFirst (from [Observation: Code '69548-6' from loinc] O return O.component.where(code.coding contains Code '48018-6' from loinc).value.coding.code.first())\n";
492-
493-
assert_eq!(replace_cql(decoded_library), expected_result);
494-
495-
let decoded_library = "DKTK_STRAT_HISTOLOGY_STRATIFIER";
496-
let expected_result = "define Histo:\nif InInitialPopulation then [Observation] else {} as List <Observation>\n\ndefine function Histology(histo FHIR.Observation):\n if histo.code.coding.where(code = '59847-4').code.first() is null then 0 else 1\n";
497-
assert_eq!(replace_cql(decoded_library), expected_result);
448+
pretty_assertions::assert_eq!(replace_cql(decoded_library), expected_result);
498449

499450
let decoded_library = "INVALID_KEY";
500451
let expected_result = "INVALID_KEY";
501-
assert_eq!(replace_cql(decoded_library), expected_result);
452+
pretty_assertions::assert_eq!(replace_cql(decoded_library), expected_result);
502453
}
503454

504455
#[test]
@@ -544,7 +495,7 @@ mod test {
544495
ROUNDING_STEP,
545496
)
546497
.unwrap();
547-
assert_eq!(obfuscated_json, obfuscated_json_2);
498+
pretty_assertions::assert_eq!(obfuscated_json, obfuscated_json_2);
548499
}
549500

550501
#[test]
@@ -572,7 +523,7 @@ mod test {
572523
let _: MeasureReport = serde_json::from_str(&obfuscated_json).unwrap();
573524

574525
// Check that the obfuscated JSON is different from the original JSON
575-
assert_ne!(obfuscated_json, EXAMPLE_MEASURE_REPORT_DKTK);
526+
pretty_assertions::assert_ne!(obfuscated_json, EXAMPLE_MEASURE_REPORT_DKTK);
576527

577528
// Check that obfuscating the same JSON twice with the same obfuscation cache gives the same result
578529
let obfuscated_json_2 = obfuscate_counts_mr(
@@ -590,7 +541,7 @@ mod test {
590541
ROUNDING_STEP,
591542
)
592543
.unwrap();
593-
assert_eq!(obfuscated_json, obfuscated_json_2);
544+
pretty_assertions::assert_eq!(obfuscated_json, obfuscated_json_2);
594545
}
595546

596547
#[test]
@@ -613,7 +564,7 @@ mod test {
613564
ROUNDING_STEP,
614565
);
615566

616-
assert_eq!(
567+
pretty_assertions::assert_eq!(
617568
obfuscated_json.unwrap_err().to_string(),
618569
r#"Deserialization error: missing field `text` at line 42 column 13. Is obfuscation turned on when it shouldn't be? Is the metadata in the task formatted correctly, like this {"project": "name"}? Are there any other projects stated in the projects_no_obfuscation parameter in the bridgehead?"#
619570
);

0 commit comments

Comments
 (0)