Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EHDS2, separating explorer API key from auth header CLA, thiserror version bump #193

Merged
merged 42 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
0d467c4
Added some diagnostics for testing purposes
Feb 21, 2024
dcebc22
Initial commit for the EHDS2 project
Feb 22, 2024
eb1e181
Added info for diagnostics
Feb 22, 2024
434e50b
Added more diagnostics
Feb 23, 2024
01909a8
Added first stratifier for the EHDS2 project
Feb 23, 2024
ed49a5c
Adding second EHDS2 stratifier
Feb 23, 2024
e006fff
Added stratifiers for Observation
Feb 23, 2024
28fb37a
New diagnostic
Feb 26, 2024
880096c
Correction
Feb 26, 2024
cab43f2
Diagnistic
Feb 26, 2024
7da8db2
Multiple issues
Mar 13, 2024
39fed29
Added new attributes to EHDS2 search
Mar 15, 2024
458fa31
First template for ECDC Observation resources
Mar 22, 2024
6e671dc
Completed the remaining 4 searches and stratifiers for Objects
Mar 26, 2024
ba37c99
Combined patient-related queries into one file, simplified file naming
Mar 27, 2024
a962041
Standardized the CQL for EHDS2
Mar 27, 2024
db56a54
Added EHDS2/ECDC-specific documentation
Mar 28, 2024
1c9108b
Added CQL for dealing with specimens
Jun 6, 2024
a4c676e
Merge branch 'develop' into ehds2
Jun 12, 2024
ec7f080
Adding searches for laboratories and hospitals
Jun 12, 2024
8a5c00f
Added CQL for Reference Guide SIR
Jun 14, 2024
fbd4301
Use stratifiers to populate Labs, Hospitals and Refguides
Jul 11, 2024
b4b2352
Added CQL functions for "date used for statistics" and "date valid from"
Jul 18, 2024
c24f69c
Overwrite slightly changed files with the latest develop versions
DavidCroftDKFZ Jul 29, 2024
82c8372
Merge branch 'develop' into ehds2_develop
DavidCroftDKFZ Jul 29, 2024
88ed147
Updated Rust build image
DavidCroftDKFZ Jul 29, 2024
2ae5644
Update thiserror requirement from 1.0.38 to 2.0.3
dependabot[bot] Nov 11, 2024
9e9dbfa
Merge pull request #182 from samply/dependabot/cargo/develop/thiserro…
enola-dkfz Nov 11, 2024
03f7d75
Feature/molecular (#183)
enola-dkfz Nov 14, 2024
4070594
fix: let GeneticVariantCount return a boolean
torbrenner Nov 14, 2024
6d5e12b
Merge pull request #184 from samply/fix/molecularMarkerStratifier
enola-dkfz Nov 14, 2024
94f007f
explanation of Exporter auth header
enola-dkfz Nov 14, 2024
149cb30
Merge pull request #185 from samply/fix/readme
enola-dkfz Nov 14, 2024
2d479b4
Laplace version bump, focus version bump
enola-dkfz Nov 14, 2024
49be488
Merge pull request #186 from samply/enola-dkfz-patch-1
enola-dkfz Nov 14, 2024
28a88b1
Branch with EHDS2 CQL only
DavidCroftDKFZ Nov 22, 2024
f77cece
Merge branch 'develop' into develop_ehds2_cql
DavidCroftDKFZ Nov 22, 2024
a9279d1
Reinstated .dockerignore from develop branch
DavidCroftDKFZ Nov 22, 2024
62aaa02
Merge pull request #188 from samply/develop_ehds2_cql
enola-dkfz Nov 22, 2024
69e342e
Disable daily rebuild (#189)
lablans Nov 25, 2024
97cb1d6
separated exporter API key CLA from auth header (#191)
enola-dkfz Dec 6, 2024
c2c5f0b
chore: update CHANGELOG.md (#192)
enola-dkfz Dec 6, 2024
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
3 changes: 0 additions & 3 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ on:
push:
workflow_dispatch:
pull_request:
schedule:
# Fetch new base image updates every night at 1am
- cron: '0 1 * * *'

jobs:
build-with-samply:
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Samply.Focus v0.8.0 2024-11-04

## Major changes
* EHDS2 query support

## Minor changes
* Separated exporter API key CLA from authorization header CLA


# Samply.Focus v0.8.0 2024-11-04

In this release, we are supporting 4 types of SQL queries for Exliquid and Organoids

## Major changes
Expand Down
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "focus"
version = "0.8.0"
version = "0.9.0"
edition = "2021"
license = "Apache-2.0"

Expand All @@ -11,12 +11,12 @@ base64 = "0.22.1"
reqwest = { version = "0.12", default-features = false, features = ["json", "default-tls"] }
serde = { version = "1.0.152", features = ["serde_derive"] }
serde_json = "1.0"
thiserror = "1.0.38"
thiserror = "2.0.3"
chrono = "0.4.31"
indexmap = "2.1.0"
tokio = { version = "1.25.0", default-features = false, features = ["signal", "rt-multi-thread", "macros"] }
beam-lib = { git = "https://github.com/samply/beam", branch = "develop", features = ["http-util"] }
laplace_rs = {git = "https://github.com/samply/laplace-rs.git", tag = "v0.3.0" }
laplace_rs = {git = "https://github.com/samply/laplace-rs.git", tag = "v0.4.0" }
uuid = "1.8.0"
rand = { default-features = false, version = "0.8.5" }
futures-util = { version = "0.3", default-features = false, features = ["std"] }
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ PROJECTS_NO_OBFUSCATION = "exliquid;dktk_supervisors;exporter;ehds2" # Projects
QUERIES_TO_CACHE = "queries_to_cache.conf" # The path to a file containing base64 encoded queries whose results are to be cached. If not set, no results are cached
PROVIDER = "name" #EUCAIM provider name
PROVIDER_ICON = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=" # Base64 encoded EUCAIM provider icon
AUTH_HEADER = "ApiKey XXXX" #Authorization header
AUTH_HEADER = "[Auth Type] XXXX" #Authorization header for accessing the store; Auth Type e.g. ApiKey, Basic, ...
EXPORTER_API_KEY = "XXXX" # Value of header x-api-key for accessing the Exporter application
```

In order to use Postgres querying, a Docker image built with the feature "dktk" needs to be used and this optional variable set:
Expand Down
5 changes: 5 additions & 0 deletions resources/cql/DKTK_STRAT_GENETIC_VARIANT
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
define GeneticVariantCount:
if InInitialPopulation then [Observation: Code '69548-6' from loinc] else {} as List <Observation>

define GeneticVariantCode:
First (from [Observation: Code '69548-6' from loinc] O return O.component.where(code.coding contains Code '48018-6' from loinc).value.coding.code.first())
1 change: 1 addition & 0 deletions resources/cql/EHDS2_IN_INITIAL_POPULATION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
define InInitialPopulation:
125 changes: 125 additions & 0 deletions resources/cql/EHDS2_OBSERVATION
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
define ObservationList:
if InInitialPopulation then [Observation] else {} as List<Observation>

// Return the value in the given system for the given Observation
define function ObservationValueCode(observation FHIR.Observation, system_var String):
(observation.value as CodeableConcept).coding.where(system = system_var).code.first()

// Check to see if there are any Observation resources with the
// given system/value pair.
define function ExistsObservationValueCode(system_var String, code_var String):
exists from [Observation] O
where ObservationValueCode(O, system_var) = code_var

// Return the value associated with the extension with the given URL for the given Observation
define function BaseObservationExtensionValue(observation FHIR.Observation, url_var String):
observation.extension.where(url = url_var).value

// Return the value of the Observation extension with the given URL
define function ObservationExtensionValue(observation FHIR.Observation, url_var String):
SensibleString(BaseObservationExtensionValue(observation, url_var))

define function ExistsObservationExtensionValue(url_var String, value_var String):
exists from [Observation] O
where ObservationExtensionValue(O, url_var) = value_var

// Return the pathogen type for the given Observation
define function PathogenCode(observation FHIR.Observation):
ObservationValueCode(observation, 'https://ecdc.amr/pathogen-codes')

// Check to see if there are any Observation resources with the
// given pathogen type.
define function ExistsPathogenCode(code_var String):
ExistsObservationValueCode('https://ecdc.amr/pathogen-codes', code_var)

// Return the antibiotic type for the given Observation
define function AntibioticCode(observation FHIR.Observation):
ObservationValueCode(observation, 'https://ecdc.amr/antibiotic-codes')

// Check to see if there are any Observation resources with the
// given antibiotic type.
define function ExistsAntibioticCode(code_var String):
ExistsObservationValueCode('https://ecdc.amr/antibiotic-codes', code_var)

// Return the resistance type for the given Observation
define function SirCode(observation FHIR.Observation):
ObservationValueCode(observation, 'https://ecdc.amr/sir-codes')

// Check to see if there are any Observation resources with the
// given resistance type.
define function ExistsSirCode(code_var String):
ExistsObservationValueCode('https://ecdc.amr/sir-codes', code_var)

// Return the data source for the given Observation
define function DataSource(observation FHIR.Observation):
ObservationExtensionValue(observation, 'https://ecdc.amr/fhir/StructureDefinition/ObservationDataSource')

// Check to see if there are any Observation resources with the
// given data source.
define function ExistsDataSource(value_var String):
ExistsObservationExtensionValue('https://ecdc.amr/fhir/StructureDefinition/ObservationDataSource', value_var)

// Return the isolate ID for the given Observation
define function IsolateId(observation FHIR.Observation):
ObservationExtensionValue(observation, 'https://ecdc.amr/fhir/StructureDefinition/ObservationIsolateId')

// Check to see if there are any Observation resources with the
// given isolate ID.
define function ExistsIsolateId(value_var String):
ExistsObservationExtensionValue('https://ecdc.amr/fhir/StructureDefinition/ObservationIsolateId', value_var)

// Return the patient type for the given Observation
define function PatientType(observation FHIR.Observation):
ObservationExtensionValue(observation, 'https://ecdc.amr/fhir/StructureDefinition/ObservationPatientType')

// Check to see if there are any Observation resources with the
// given patient type.
define function ExistsPatientType(value_var String):
ExistsObservationExtensionValue('https://ecdc.amr/fhir/StructureDefinition/ObservationPatientType', value_var)

// Return the reference guidelines SIR for the given Observation
define function ReferenceGuidelinesSir(observation FHIR.Observation):
ObservationExtensionValue(observation, 'https://ecdc.amr/fhir/StructureDefinition/ObservationReferenceGuidelinesSIR')

// Check to see if there are any Observation resources with the
// given reference guidelines SIR.
define function ExistsReferenceGuidelinesSir(value_var String):
ExistsObservationExtensionValue('https://ecdc.amr/fhir/StructureDefinition/ObservationReferenceGuidelinesSIR', value_var)

// Return the reporting country for the given Observation
define function ReportingCountry(observation FHIR.Observation):
ObservationExtensionValue(observation, 'https://ecdc.amr/fhir/StructureDefinition/ObservationReportingCountry')

// Check to see if there are any Observation resources with the
// given reporting country.
define function ExistsReportingCountry(value_var String):
ExistsObservationExtensionValue('https://ecdc.amr/fhir/StructureDefinition/ObservationReportingCountry', value_var)

// Return the year from the date used for statistics
define function YearDateUsedForStatistics(observation FHIR.Observation):
year from observation.issued

// Return the month from the date used for statistics
define function MonthDateUsedForStatistics(observation FHIR.Observation):
month from observation.issued

// Return the year-month from the date used for statistics
define function YearMonthDateUsedForStatistics(observation FHIR.Observation):
ToString(YearDateUsedForStatistics(observation)) + '-' + ToString(MonthDateUsedForStatistics(observation))

// Return the the date valid from
define function DateValidFrom(observation FHIR.Observation):
ToDate(observation.effective as dateTime)

// Return the year from the date valid from
define function YearDateValidFrom(observation FHIR.Observation):
year from DateValidFrom(observation)

// Return the month from the date valid from
define function MonthDateValidFrom(observation FHIR.Observation):
month from DateValidFrom(observation)

// Return the year-month from the date valid from
define function YearMonthDateValidFrom(observation FHIR.Observation):
ToString(YearDateValidFrom(observation)) + '-' + ToString(MonthDateValidFrom(observation))

30 changes: 30 additions & 0 deletions resources/cql/EHDS2_PATIENT
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Return the value of the Patient extension with the given URL.
// Return "Unknown" if not available or empty.
define function PatientExtensionValue(url_var String):
SensibleString(Patient.extension.where(url = url_var).value)

// Return gender of patient
define Gender:
SensibleString(Patient.gender)

// Return age of patient, as an integer
define AgeInYears:
ToInteger(PatientExtensionValue('https://ecdc.amr/fhir/StructureDefinition/PatientAge'))

// Round patient age to the nearest multiple of 10 (i/p for a histogram).
// Return result as a string
define AgeClass:
ToString((AgeInYears div 10) * 10)

// Return ID of hospital associated with patient
define HospitalId:
PatientExtensionValue('https://ecdc.amr/fhir/StructureDefinition/PatientHospitalId')

// Return hospital unit type associated with patient
define HospitalUnitType:
PatientExtensionValue('https://ecdc.amr/fhir/StructureDefinition/PatientHospitalUnitType')

// Return laboratory code associated with patient
define LaboratoryCode:
PatientExtensionValue('https://ecdc.amr/fhir/StructureDefinition/PatientLaboratoryCode')

13 changes: 13 additions & 0 deletions resources/cql/EHDS2_SPECIMEN
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
define SpecimenList:
if InInitialPopulation then [Specimen] else {} as List<Specimen>

// Return the isolate ID for the given Specimen
define function SpecimenIsolateId(specimen FHIR.Specimen):
SensibleString(specimen.id)

// Check to see if there are any Specimen resources with the
// given isolate ID.
define function ExistsSpecimenIsolateId(id_var String):
exists from [Specimen] S
where SpecimenIsolateId(S) = id_var

7 changes: 7 additions & 0 deletions resources/cql/EHDS2_UTIL
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Return "val" if the supplied string value is sensible.
// Return "Unknown" if null or empty.
define function SensibleString(val String):
if (val is null or val = '' or val = '-')
then 'Unkown'
else val

7 changes: 7 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,15 @@ struct CliArgs {
#[clap(long, env, value_parser)]
provider_icon: Option<String>,

// TODO - refactor to include multiple authorization headers for multiple stores / applications at the same time
/// Authorization header
#[clap(long, env, value_parser)]
auth_header: Option<String>,

/// Exporter API key
#[clap(long, env, value_parser)]
exporter_api_key: Option<String>,

/// Postgres connection string
#[cfg(feature = "query-sql")]
#[clap(long, env, value_parser)]
Expand Down Expand Up @@ -198,6 +203,7 @@ pub(crate) struct Config {
pub provider: Option<String>,
pub provider_icon: Option<String>,
pub auth_header: Option<String>,
pub exporter_api_key: Option<String>,
#[cfg(feature = "query-sql")]
pub postgres_connection_string: Option<String>,
#[cfg(feature = "query-sql")]
Expand Down Expand Up @@ -243,6 +249,7 @@ impl Config {
provider: cli_args.provider,
provider_icon: cli_args.provider_icon,
auth_header: cli_args.auth_header,
exporter_api_key: cli_args.exporter_api_key,
#[cfg(feature = "query-sql")]
postgres_connection_string: cli_args.postgres_connection_string,
#[cfg(feature = "query-sql")]
Expand Down
4 changes: 2 additions & 2 deletions src/exporter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ pub async fn post_exporter_query(body: &String, task_type: TaskType) -> Result<S

let mut headers = HeaderMap::new();

if let Some(auth_header_value) = CONFIG.auth_header.clone() {
if let Some(api_key) = CONFIG.exporter_api_key.clone() {
headers.insert(
"x-api-key",
HeaderValue::from_str(auth_header_value.as_str())
HeaderValue::from_str(api_key.as_str())
.map_err(FocusError::InvalidHeaderValue)?,
);
}
Expand Down
Loading