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
4 changes: 2 additions & 2 deletions execution_engine/converter/converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from fhir.resources.codeableconcept import CodeableConcept
from fhir.resources.element import Element
from fhir.resources.extension import Extension
from fhir.resources.fhirtypes import Boolean
from fhir.resources.fhirtypes import BooleanType
from fhir.resources.quantity import Quantity
from fhir.resources.range import Range

Expand All @@ -21,7 +21,7 @@
@staticmethod
def select_value(
root: Element, value_prefix: str
) -> CodeableConcept | Quantity | Range | Boolean:
) -> CodeableConcept | Quantity | Range | BooleanType:
"""
Selects the value of a characteristic by datatype.
"""
Expand Down
11 changes: 7 additions & 4 deletions execution_engine/fhir/client.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import logging

import requests
from fhir.resources import FHIRAbstractModel, construct_fhir_element
from fhir.resources import FHIRAbstractModel, get_fhir_model_class


class FHIRClient:
Expand All @@ -15,7 +15,7 @@ def __init__(self, base_url: str):
self.base_url = base_url

def fetch_resource(
self, element_type: str, canonical_url: str, version: str
self, resource_type: str, canonical_url: str, version: str
) -> FHIRAbstractModel:
"""
Get a resource from the FHIR server by its canonical URL.
Expand All @@ -24,7 +24,7 @@ def fetch_resource(

try:
r = requests.get(
f"{self.base_url}/{element_type}?url={canonical_url}&version={version}",
f"{self.base_url}/{resource_type}?url={canonical_url}&version={version}",
timeout=10,
)
except ConnectionRefusedError:
Expand All @@ -34,4 +34,7 @@ def fetch_resource(
assert (
r.status_code == 200
), f"Could not get resource: HTTP status code {r.status_code}"
return construct_fhir_element(element_type, r.json())

resource = get_fhir_model_class(resource_type)

return resource.model_validate(r.json())
78 changes: 0 additions & 78 deletions execution_engine/omop/db/celida/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,84 +14,6 @@
from execution_engine.util.interval import IntervalType


def view_interval_coverage_slow() -> Select:
"""
Return Select statement for view to calculate the full day coverage of recommendation results.
"""

one_day = func.cast(concat(1, "day"), INTERVAL)
rri = ResultInterval.__table__.alias("rri")

date_series = select(
ExecutionRun.run_id,
func.generate_series(
func.date_trunc("day", ExecutionRun.observation_start_datetime),
func.date_trunc("day", ExecutionRun.observation_end_datetime),
one_day,
)
.cast(Date)
.label("day"),
ExecutionRun.observation_start_datetime,
ExecutionRun.observation_end_datetime,
).cte("date_series")

interval_coverage = (
select(
date_series.c.run_id,
rri.c.person_id,
rri.c.cohort_category,
rri.c.pi_pair_id,
rri.c.criterion_id,
date_series.c.day,
func.sum(
func.least(
date_series.c.day + one_day,
rri.c.interval_end,
date_series.c.observation_end_datetime,
)
- func.greatest(
date_series.c.day,
rri.c.interval_start,
date_series.c.observation_start_datetime,
)
).label("covered_time"),
func.bool_or(rri.c.interval_type == IntervalType.POSITIVE).label(
"has_positive"
),
func.bool_or(rri.c.interval_type == IntervalType.NO_DATA).label(
"has_no_data"
),
func.bool_or(rri.c.interval_type == IntervalType.NEGATIVE).label(
"has_negative"
),
)
.select_from(date_series)
.outerjoin(rri, (date_series.c.run_id == rri.c.run_id))
.filter(
rri.c.interval_start < date_series.c.day + one_day,
rri.c.interval_end > date_series.c.day,
)
.group_by(
date_series.c.run_id,
date_series.c.day,
rri.c.person_id,
rri.c.cohort_category,
rri.c.pi_pair_id,
rri.c.criterion_id,
)
)

return interval_coverage


interval_coverage_slow = view(
"interval_coverage_slow",
Base.metadata,
view_interval_coverage_slow(),
schema=SCHEMA_NAME,
)


def view_interval_coverage() -> Select:
"""
Return Select statement for view to calculate the full day coverage of recommendation results.
Expand Down
16 changes: 11 additions & 5 deletions execution_engine/omop/db/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,6 @@ def view(
:param schema: The schema name.
:return: The table object.
"""
t = table(name, schema=schema)

t._columns._populate_separate_keys(
col._make_proxy(t) for col in selectable.selected_columns
)

def view_exists(
ddl: DDLElement, target: MetaData, connection: Connection, **kw: Any
Expand All @@ -85,6 +80,16 @@ def view_doesnt_exist(
"""
return not view_exists(ddl, target, connection, **kw)

t = table(
name,
*(
sa.Column(c.name, c.type, primary_key=c.primary_key)
for c in selectable.selected_columns
),
schema=schema
)
t.primary_key.update(c for c in t.c if c.primary_key)

sa.event.listen(
metadata,
"after_create",
Expand All @@ -95,4 +100,5 @@ def view_doesnt_exist(
"before_drop",
DropView(name, schema).execute_if(callable_=view_exists),
)

return t
2 changes: 1 addition & 1 deletion requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
pytest==8.3.4
pytest-postgresql==6.1.1
pytest-postgresql==7.0.0
tqdm==4.67.1
pytest-cov==6.0.0
pytest-env==1.1.5
Expand Down
18 changes: 9 additions & 9 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
requests==2.32.3
python-dotenv==1.0.1
pyyaml==6.0.2
fhir.resources==7.1.0
fhir.resources==8.0.0
sympy==1.13.3
pandas==2.2.3
psycopg[binary]==3.2.4
sqlalchemy==2.0.37
pydantic==2.10.5
pydantic-settings==2.7.1
psycopg[binary]==3.2.5
sqlalchemy==2.0.38
pydantic==2.10.6
pydantic-settings==2.8.0
uvicorn[standard]==0.34.0
fastapi==0.115.6
fastapi==0.115.8
pendulum==3.0.0
networkx==3.4.2
numpy==2.2.2
pytz==2024.2
cython==3.0.11
numpy==2.2.3
pytz==2025.1
cython==3.0.12
setuptools==75.8.0
sortedcontainers==2.4.0
20 changes: 9 additions & 11 deletions tests/execution_engine/fhir/test_recommendation.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from unittest.mock import patch

import pytest
from fhir.resources import construct_fhir_element
from fhir.resources import get_fhir_model_class

from execution_engine.constants import CS_PLAN_DEFINITION_TYPE
from execution_engine.fhir.client import FHIRClient
Expand All @@ -20,8 +20,8 @@ def mock_load(self, test_class):

@pytest.fixture
def mock_fetch_resource_unknown(self):
plan_definition = construct_fhir_element(
"PlanDefinition",

plan_definition = get_fhir_model_class("PlanDefinition").model_validate(
{
"status": "draft",
"action": [],
Expand All @@ -39,8 +39,7 @@ def mock_fetch_resource_unknown(self):

@pytest.fixture
def mock_fetch_resource_no_partOf(self):
plan_definition = construct_fhir_element(
"PlanDefinition",
plan_definition = get_fhir_model_class("PlanDefinition").model_validate(
{
"status": "draft",
"action": [],
Expand All @@ -62,8 +61,8 @@ def test_class(self):

@pytest.fixture
def mock_fetch_recommendation(self, test_class):
plan_definition = construct_fhir_element(
"PlanDefinition", {"status": "draft", "action": []}
plan_definition = get_fhir_model_class("PlanDefinition").model_validate(
{"status": "draft", "action": []}
)
with patch.object(
test_class, "fetch_recommendation", return_value=plan_definition
Expand Down Expand Up @@ -159,8 +158,8 @@ def test_class(self):

@pytest.fixture
def mock_fetch_recommendation_plan(self):
plan_definition = construct_fhir_element(
"PlanDefinition", {"status": "draft", "action": []}
plan_definition = get_fhir_model_class("PlanDefinition").model_validate(
{"status": "draft", "action": []}
)
with patch.object(
RecommendationPlan,
Expand All @@ -171,8 +170,7 @@ def mock_fetch_recommendation_plan(self):

@pytest.fixture
def mock_fetch_resource_goals(self):
plan_definition = construct_fhir_element(
"PlanDefinition",
plan_definition = get_fhir_model_class("PlanDefinition").model_validate(
{
"status": "draft",
"action": [],
Expand Down
5 changes: 4 additions & 1 deletion tests/recommendation/test_recommendation_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -953,7 +953,10 @@ def get_query(t, category):
t.c.cohort_category,
t.c.valid_date,
)
.outerjoin(PopulationInterventionPair)
.outerjoin(
PopulationInterventionPair,
PopulationInterventionPair.pi_pair_id == t.c.pi_pair_id,
)
.where(t.c.criterion_id.is_(None))
.where(t.c.cohort_category.in_(category))
)
Expand Down