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

Empty appointments bug fix #153

Merged
merged 8 commits into from
Jan 8, 2025
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
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
## [1.5.1] - 2024-12-23

### Added
- Error warmings in case no appointments are provided
- Added ssl-certificate fix in deploy script
- Added unit tests for empty predictions

### Changed
- Saving of predictions is now located in helper function
- Updated requirements to solve dependabot alert

## [1.5.0] - 2024-12-10

Expand Down
3 changes: 3 additions & 0 deletions deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ do
fi
done

# necessary for certifi to find the right certificate if run without conda forge's ca-certificates
export SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt

read -p "What do you want to deploy? Options: 'admin-dash'/1 ; 'calling-dash'/2 ; 'calling-dash-test'/3 ; 'api'/4 ; 'api-test'/5 " APPLICATION
APPLICATION=${APPLICATION:-N}

Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "noshow"
version = "1.5.0"
version = "1.5.1"
authors = [
{ name="Ruben Peters", email="[email protected]" },
{ name="Eric Wolters", email="[email protected]" }
Expand All @@ -31,6 +31,7 @@ dependencies =[
"streamlit>=1.30",
"tomli~=2.0",
"relplot>=1.0",
"pygit2<1.17", # Version 1.18 has no available wheels yet
]

[dependency-groups]
Expand Down
70 changes: 35 additions & 35 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,26 @@
# uv export --no-dev --no-group lint --no-hashes -o requirements.txt
-e .
aiohappyeyeballs==2.4.4
aiohttp==3.11.10
aiohttp==3.11.11
aiohttp-retry==2.9.1
aiosignal==1.3.1
aiosignal==1.3.2
altair==5.5.0
amqp==5.3.1
annotated-types==0.7.0
antlr4-python3-runtime==4.9.3
anyio==4.7.0
anyio==4.8.0
appdirs==1.4.4
asyncssh==2.18.0
asyncssh==2.19.0
atpublic==5.0
attrs==24.2.0
attrs==24.3.0
billiard==4.2.1
blinker==1.9.0
cachetools==5.5.0
celery==5.4.0
certifi==2024.8.30
certifi==2024.12.14
cffi==1.17.1
charset-normalizer==3.4.0
click==8.1.7
charset-normalizer==3.4.1
click==8.1.8
click-didyoumean==0.3.1
click-plugins==1.1.1
click-repl==0.3.0
Expand All @@ -35,70 +35,70 @@ dictdiffer==0.9.0
diskcache==5.6.3
distro==1.9.0
dpath==2.2.0
dulwich==0.22.6
dulwich==0.22.7
dvc==3.58.0
dvc-data==3.16.7
dvc-http==2.32.0
dvc-objects==5.1.0
dvc-render==1.0.2
dvc-studio-client==0.21.0
dvc-task==0.40.2
dvclive==3.48.0
dvclive==3.48.1
entrypoints==0.4
fastapi==0.115.6
filelock==3.16.1
flatten-dict==0.4.2
flufl-lock==8.1.0
fonttools==4.55.3
frozenlist==1.5.0
fsspec==2024.10.0
fsspec==2024.12.0
funcy==2.0
gitdb==4.0.11
gitpython==3.1.43
gitdb==4.0.12
gitpython==3.1.44
grandalf==0.8
greenlet==3.1.1 ; (python_full_version < '3.13' and platform_machine == 'AMD64') or (python_full_version < '3.13' and platform_machine == 'WIN32') or (python_full_version < '3.13' and platform_machine == 'aarch64') or (python_full_version < '3.13' and platform_machine == 'amd64') or (python_full_version < '3.13' and platform_machine == 'ppc64le') or (python_full_version < '3.13' and platform_machine == 'win32') or (python_full_version < '3.13' and platform_machine == 'x86_64')
gto==1.7.2
hydra-core==1.3.2
idna==3.10
iterative-telemetry==0.0.9
jinja2==3.1.4
jinja2==3.1.5
joblib==1.4.2
jsonschema==4.23.0
jsonschema-specifications==2024.10.1
kiwisolver==1.4.7
kiwisolver==1.4.8
kombu==5.4.2
markdown-it-py==3.0.0
markupsafe==3.0.2
matplotlib==3.9.3
matplotlib==3.10.0
mdurl==0.1.2
multidict==6.1.0
narwhals==1.17.0
narwhals==1.21.1
networkx==3.4.2
numpy==2.2.0
numpy==2.2.1
nvidia-ml-py==12.560.30
omegaconf==2.3.0
orjson==3.10.12 ; implementation_name == 'cpython'
orjson==3.10.13 ; implementation_name == 'cpython'
packaging==24.2
pandas==2.2.3
pathspec==0.12.1
pillow==11.0.0
pillow==11.1.0
platformdirs==4.3.6
prompt-toolkit==3.0.48
propcache==0.2.1
protobuf==5.29.1
psutil==6.1.0
protobuf==5.29.2
psutil==6.1.1
pyarrow==18.1.0
pycparser==2.22
pydantic==2.10.3
pydantic-core==2.27.1
pydantic==2.10.4
pydantic-core==2.27.2
pydeck==0.9.1
pydot==3.0.3
pydot==3.0.4
pygit2==1.16.0
pygments==2.18.0
pygments==2.19.1
pygtrie==2.5.0
pymssql==2.3.2
pynvml==12.0.0
pyparsing==3.2.0
pyparsing==3.2.1
python-dateutil==2.9.0.post0
python-dotenv==1.0.1
pytz==2024.2
Expand All @@ -109,24 +109,24 @@ relplot==1.0
requests==2.32.3
rich==13.9.4
rpds-py==0.22.3
ruamel-yaml==0.18.6
ruamel-yaml==0.18.10
ruamel-yaml-clib==0.2.12 ; python_full_version < '3.13' and platform_python_implementation == 'CPython'
scikit-learn==1.6.0
scipy==1.14.1
scipy==1.15.0
scmrepo==3.3.9
seaborn==0.13.2
semver==2.13.0
setuptools==75.6.0
semver==3.0.2
setuptools==75.7.0
shellingham==1.5.4
shortuuid==1.0.13
shtab==1.7.1
six==1.17.0
smmap==5.0.1
smmap==5.0.2
sniffio==1.3.1
sqlalchemy==2.0.36
sqltrie==0.11.1
starlette==0.41.3
streamlit==1.41.0
streamlit==1.41.1
tabulate==0.9.0
tenacity==9.0.0
threadpoolctl==3.5.0
Expand All @@ -138,10 +138,10 @@ tqdm==4.67.1
typer==0.15.1
typing-extensions==4.12.2
tzdata==2024.2
urllib3==2.2.3
urllib3==2.3.0
vine==5.1.0
voluptuous==0.15.2
watchdog==6.0.0 ; platform_system != 'Darwin'
watchdog==6.0.0 ; sys_platform != 'darwin'
wcwidth==0.2.13
yarl==1.18.3
zc-lockfile==3.0.post1
78 changes: 10 additions & 68 deletions src/noshow/api/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,12 @@
fix_outdated_appointments,
load_model,
remove_sensitive_info,
store_predictions,
)
from noshow.api.pydantic_models import Appointment
from noshow.config import CLINIC_CONFIG, KEEP_SENSITIVE_DATA
from noshow.database.models import (
ApiPatient,
ApiPrediction,
ApiRequest,
ApiSensitiveInfo,
Base,
)
from noshow.model.predict import create_prediction
Expand Down Expand Up @@ -119,10 +117,18 @@ async def predict(
project_path = Path(__file__).parents[3]
start_time = datetime.now()

if len(input) == 0:
raise HTTPException(status_code=400, detail="Input cannot be empty.")

input_df = load_appointment_pydantic(input)
appointments_df = process_appointments(input_df, CLINIC_CONFIG, start_date)
all_postalcodes = process_postal_codes(project_path / "data" / "raw" / "NL.txt")

if appointments_df.empty:
raise HTTPException(
status_code=400, detail="No appointments for the start date and filters"
)

model = load_model()
prediction_df = create_prediction(
model,
Expand Down Expand Up @@ -160,71 +166,7 @@ async def predict(
)
db.add(apirequest)

for _, row in prediction_df.iterrows():
apisensitive = db.get(ApiSensitiveInfo, row["pseudo_id"])

if not apisensitive:
if row["name_text"] is None:
row["name_text"] = ""
logger.warning(
f"Patient {row['pseudo_id']} has no name_text, "
"replacing with empty string"
)

apisensitive = ApiSensitiveInfo(
patient_id=row["pseudo_id"],
hix_number=row["patient_id"],
full_name=row["name_text"],
first_name=row["name_given1_callMe"],
birth_date=row["birthDate"],
mobile_phone=row["telecom1_value"],
home_phone=row["telecom2_value"],
other_phone=row["telecom3_value"],
)
else:
# name and birthdate can't change, but phone number might
apisensitive.mobile_phone = row["telecom1_value"]
apisensitive.home_phone = row["telecom2_value"]
apisensitive.other_phone = row["telecom3_value"]

apipatient = db.get(ApiPatient, row["pseudo_id"])
if not apipatient:
apipatient = ApiPatient(
id=row["pseudo_id"],
)
apipatient.treatment_group = int(row["treatment_group"])
apiprediction = db.get(ApiPrediction, row["APP_ID"])
if not apiprediction:
apiprediction = ApiPrediction(
id=row["APP_ID"],
patient_id=row["pseudo_id"],
prediction=row["prediction"],
start_time=row["start"],
request_relation=apirequest,
patient_relation=apipatient,
clinic_name=row["hoofdagenda"],
clinic_reception=row["description"],
clinic_phone_number=CLINIC_CONFIG[row["clinic"]].phone_number,
clinic_teleq_unit=CLINIC_CONFIG[row["clinic"]].teleq_name,
active=True,
)
else:
# All values of a prediction can be updated except the ID and treatment
apiprediction.prediction = row["prediction"]
apiprediction.start_time = row["start"]
apiprediction.request_relation = apirequest
apiprediction.clinic_name = row["hoofdagenda"]
apiprediction.clinic_reception = row["description"]
apiprediction.clinic_phone_number = CLINIC_CONFIG[
row["clinic"]
].phone_number
apiprediction.clinic_teleq_unit = CLINIC_CONFIG[row["clinic"]].teleq_name
apiprediction.active = True

db.merge(apisensitive)
db.merge(apiprediction)
db.merge(apipatient)
db.commit()
store_predictions(prediction_df, db, apirequest)

fix_outdated_appointments(db, prediction_df["APP_ID"], start_date)

Expand Down
Loading
Loading