Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
c06aeec
fix: SECOND-based DATETIME_DIFF in urine_output_rate
Chessing234 Jul 23, 2026
5c49bc4
fix: escape password and quote ids in create_mimic_user
Chessing234 Jul 23, 2026
d4a8305
fix: pin sqlite import dtypes for mixed columns
Chessing234 Jul 23, 2026
b035858
fix: avoid escaped quote in neuroblock_dose stopped check
Chessing234 Jul 23, 2026
24c02b4
fix: use DATETIME_DIFF for neuroblock gap check
Chessing234 Jul 23, 2026
23f7084
fix: check $1 not PID in copy_concepts script
Chessing234 Jul 23, 2026
cb18187
ci: dont fail sqlfluff job when annotate lacks fork perms
Chessing234 Jul 23, 2026
e560823
fix: load .csv and .csv.gz in duckdb imports
Chessing234 Jul 23, 2026
a2d01c4
fix: require epi/norepi rate > 0 for SOFA CV score 3
Chessing234 Jul 23, 2026
1cfb063
fix: quote datadir for postgres load and wget
Chessing234 Jul 19, 2026
81e4155
fix: write transpiled sql as utf-8
Chessing234 Jul 19, 2026
b2711aa
fix: exact table name match in validate_concepts.sh
Chessing234 Jul 19, 2026
8b8833a
fix: exclude ICD-10-CM C4A from Charlson malignancy
Chessing234 Jul 23, 2026
3327400
fix: include provider/caregiver/ingredientevents in demo validate
Chessing234 Jul 23, 2026
475bbda
fix: use globs instead of ls in make_concepts.sh
Chessing234 Jul 19, 2026
eafee6f
fix: escape quotes in mimic-iii duckdb COPY paths
Chessing234 Jul 23, 2026
51bd9d4
fix: quote sqlite import.sh paths for spaces
Chessing234 Jul 19, 2026
88b634f
fix: load plain .csv in mimic-iii sqlite import.py
Chessing234 Jul 23, 2026
f7c8a45
fix: quote DIRNAME in duckdb import case patterns
Chessing234 Jul 23, 2026
b3f8c66
fix: quote paths in mimic-iii make-concepts.sh
Chessing234 Jul 19, 2026
dd56cd3
fix: low_memory=False on mimic-iv sqlite read_csv
Chessing234 Jul 19, 2026
6f99509
fix: use printf for duckdb load progress
Chessing234 Jul 23, 2026
f8590e8
fix: use globs and quote paths in cxr label scripts
Chessing234 Jul 19, 2026
cde84eb
fix: glob + quote paths in chexpert runner too
Chessing234 Jul 19, 2026
e7d5561
fix: quote mimic_data_dir for postgres \\cd in IV/ED/Note
Chessing234 Jul 23, 2026
6b37856
revert: unquote psql \\cd mimic_data_dir
Chessing234 Jul 23, 2026
1bb1e33
fix: require epi/norepi rate > 0 in pivoted_sofa CV score
Chessing234 Jul 23, 2026
2d4f3ae
fix: keep DuckDB GENERATE_ARRAY as a list for UNNEST
Chessing234 Jul 23, 2026
a229b37
fix: include CCO and Arctic Sun temps in vitalsign
Chessing234 Jul 23, 2026
be93cfa
fix: Charlson age_score uses half-open decade bands
Chessing234 Jul 23, 2026
aa06aea
fix: keep o2-device-only rows after FULL OUTER JOIN
Chessing234 Jul 23, 2026
8f2b9c8
fix: exclude MetaVision pause gaps from vaso durations
Chessing234 Jul 23, 2026
31c72b6
fix: merge overlapping MetaVision arterial/central line intervals
Chessing234 Jul 23, 2026
9e59a04
fix: Elixhauser no_drg excludes primary and RTRIMs ICD-9 codes
Chessing234 Jul 23, 2026
15c2f72
fix: AHRQ Elixhauser with DRG uses all diagnoses, RTRIM codes
Chessing234 Jul 23, 2026
afe7707
fix: RTRIM ICD-9 codes in Quan Elixhauser
Chessing234 Jul 23, 2026
70cfd84
fix: drop LODS BUN >= 7.50 mg/dL score band
Chessing234 Jul 23, 2026
5163678
fix: drop concept tables via bq ls CSV, not cut -f3
Chessing234 Jul 23, 2026
6ce72f9
fix: skip echo charttime parse when time regex misses
Chessing234 Jul 23, 2026
d7ec3d5
fix: transpile DATETIME_DIFF MONTH for Postgres
Chessing234 Jul 23, 2026
1fe4366
fix: include CCO/Arctic Sun temps in III vitals
Chessing234 Jul 23, 2026
0d80d2b
fix: include CCO/Arctic Sun temps in aline_vitals
Chessing234 Jul 23, 2026
fc00594
fix: skip echo height PARSE when time regex misses
Chessing234 Jul 23, 2026
b836c5a
fix: include CCO/Arctic Sun temps in aline-aws vitals
Chessing234 Jul 23, 2026
1cab27c
fix: convert SAPS glucose/BUN thresholds to mg/dL
Chessing234 Jul 23, 2026
cb5f9ac
fix: build icustay_times/hours before pivoted_oasis
Chessing234 Jul 23, 2026
ca766fc
fix: include pivoted_oasis in postgres/duckdb concept builds
Chessing234 Jul 24, 2026
3a43427
Merge origin/main into fix branch
Chessing234 Jul 24, 2026
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
6 changes: 5 additions & 1 deletion .github/workflows/lint_sqlfluff.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,12 @@ jobs:
shell: bash
run: sqlfluff lint --format github-annotation --annotation-level failure --nofail ${{ steps.get_files_to_lint.outputs.lintees }} > annotations.json
- name: Annotate
# Fork PRs cannot create check runs with GITHUB_TOKEN; lint already ran.
continue-on-error: true
if: steps.get_files_to_lint.outputs.lintees != ''
uses: yuzutech/annotations-action@v0.6.0
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
title: "SQLFluff Lint"
input: "./annotations.json"
input: "./annotations.json"
ignore-missing-file: true
6 changes: 4 additions & 2 deletions mimic-iii/buildmimic/duckdb/import_duckdb.sh
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,11 @@ make_table_name () {
# load data into database
find "$MIMIC_DIR" -type f -regex '.*\.csv\(.gz\)*' | while IFS= read -r FILE; do
make_table_name "$FILE"
echo "Loading $FILE .. \c"
# Escape single quotes for SQL string literal
FILE_SQL=$(printf '%s' "$FILE" | sed "s/'/''/g")
printf "Loading %s .. " "$FILE"
try duckdb "$OUTFILE" <<-EOSQL
COPY $TABLE_NAME FROM '$FILE' (HEADER, DELIM ',', QUOTE '"', ESCAPE '"');
COPY $TABLE_NAME FROM '$FILE_SQL' (HEADER, DELIM ',', QUOTE '"', ESCAPE '"');
EOSQL
echo "done!"
done && echo "Successfully finished loading data into $OUTFILE."
8 changes: 4 additions & 4 deletions mimic-iii/buildmimic/postgres/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ mimic-build-gz:
@echo '------------------'
@echo ''
@sleep 2
psql "$(DBSTRING)" -v ON_ERROR_STOP=1 -f postgres_load_data_gz.sql -v mimic_data_dir=${datadir}
psql "$(DBSTRING)" -v ON_ERROR_STOP=1 -f postgres_load_data_gz.sql -v "mimic_data_dir=$(DATADIR)"
@echo ''
@echo '--------------------'
@echo '-- Adding indexes --'
Expand Down Expand Up @@ -151,7 +151,7 @@ mimic-build:
@echo '------------------'
@echo ''
@sleep 2
psql "$(DBSTRING)" -v ON_ERROR_STOP=1 -f postgres_load_data.sql -v mimic_data_dir=${DATADIR}
psql "$(DBSTRING)" -v ON_ERROR_STOP=1 -f postgres_load_data.sql -v "mimic_data_dir=$(DATADIR)"
@echo ''
@echo '--------------------'
@echo '-- Adding indexes --'
Expand Down Expand Up @@ -184,15 +184,15 @@ ifeq ("$(physionetuser)","")
@echo 'Call the makefile again with physionetuser=<USERNAME>'
@echo ' e.g. make eicu-download datadir=/path/to/data physionetuser=hello@physionet.org'
else
wget --user $(physionetuser) --ask-password -P $(DATADIR) -A csv.gz -m -p -E -k -K -np -nd "$(PHYSIONETURL)"
wget --user $(physionetuser) --ask-password -P "$(DATADIR)" -A csv.gz -m -p -E -k -K -np -nd "$(PHYSIONETURL)"
endif

mimic-demo-download:
@echo '------------------------------------------'
@echo '-- Downloading MIMIC-III from PhysioNet --'
@echo '------------------------------------------'
@echo ''
wget --user $(physionetuser) --ask-password -P $(DATADIR) -A csv.gz -m -p -E -k -K -np -nd "$(PHYSIONETDEMOURL)"
wget --user $(physionetuser) --ask-password -P "$(DATADIR)" -A csv.gz -m -p -E -k -K -np -nd "$(PHYSIONETDEMOURL)"

#This is fairly inelegant and could be tidied with a for loop and an if to check for gzip,
#but need to maintain compatibility with Windows, which baffling lacks these things
Expand Down
15 changes: 11 additions & 4 deletions mimic-iii/buildmimic/postgres/create_mimic_user.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ else
echo "User is set to '$MIMIC_USER'";
fi

# escape ' in password for SQL string literal
MIMIC_PASSWORD_SQL=$(printf '%s' "$MIMIC_PASSWORD" | sed "s/'/''/g")
# quote SQL identifiers (double any embedded ")
sql_ident () { printf '%s' "$1" | sed 's/"/""/g; s/^/"/; s/$/"/'; }
MIMIC_USER_SQL=$(sql_ident "$MIMIC_USER")
MIMIC_DB_SQL=$(sql_ident "$MIMIC_DB")

PSQL='psql'

# add in the host/port, if they were specified (not null, -n)
Expand Down Expand Up @@ -58,11 +65,11 @@ fi
if [ "$MIMIC_USER" != "postgres" ]; then
# we need to create this user via postgres
# use SUDO to login as postgres
$PSQL -U postgres -d postgres -c "DROP USER IF EXISTS $MIMIC_USER; CREATE USER $MIMIC_USER WITH PASSWORD '$MIMIC_PASSWORD';"
$PSQL -U postgres -d postgres -c "DROP USER IF EXISTS $MIMIC_USER_SQL; CREATE USER $MIMIC_USER_SQL WITH PASSWORD '$MIMIC_PASSWORD_SQL';"
fi

if [ "$MIMIC_DB" != "postgres" ]; then
# drop and recreate the database
$PSQL -U postgres -d postgres -c "DROP DATABASE IF EXISTS $MIMIC_DB;"
$PSQL -U postgres -d postgres -c "CREATE DATABASE $MIMIC_DB OWNER $MIMIC_USER;"
fi
$PSQL -U postgres -d postgres -c "DROP DATABASE IF EXISTS $MIMIC_DB_SQL;"
$PSQL -U postgres -d postgres -c "CREATE DATABASE $MIMIC_DB_SQL OWNER $MIMIC_USER_SQL;"
fi
53 changes: 50 additions & 3 deletions mimic-iii/buildmimic/sqlite/import.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,34 @@
CHUNKSIZE = 10 ** 6
CONNECTION_STRING = "sqlite:///{}".format(DATABASE_NAME)

# Column dtypes for tables that trigger pandas mixed-type warnings when
# loaded with the default low_memory chunked inference (see #1237).
# Types mirror mimic-iii/buildmimic/postgres/postgres_create_tables.sql.
TABLE_DTYPES = {
"chartevents": {
"WARNING": "Int64",
"ERROR": "Int64",
"RESULTSTATUS": "string",
"STOPPED": "string",
},
"datetimeevents": {
"WARNING": "Int64",
"ERROR": "Int64",
"RESULTSTATUS": "string",
"STOPPED": "string",
},
"inputevents_cv": {
"ORIGINALRATE": "float64",
"ORIGINALRATEUOM": "string",
"ORIGINALSITE": "string",
},
"noteevents": {
"CHARTTIME": "string",
"STORETIME": "string",
"ISERROR": "string",
},
}


def _table_name_from_csv(filename: str) -> str:
"""Derive SQL table name from a CSV path (literal suffix, not str.strip)."""
Expand All @@ -21,20 +49,39 @@ def _table_name_from_csv(filename: str) -> str:
return name.lower()


def _read_csv(path, table, **kwargs):
# low_memory=False avoids dtype re-inference across chunks; table-specific
# dtypes pin the columns that otherwise flip between numeric/object.
return pd.read_csv(
path,
index_col="ROW_ID",
low_memory=False,
dtype=TABLE_DTYPES.get(table),
**kwargs,
)


if os.path.exists(DATABASE_NAME):
msg = "File {} already exists.".format(DATABASE_NAME)
print(msg)
sys.exit()

# Prefer .csv.gz when both exist for the same table; also load plain .csv
# (import.sh already accepts both).
files_by_table = {}
for f in glob("*.csv"):
files_by_table[_table_name_from_csv(f)] = f
for f in glob("*.csv.gz"):
files_by_table[_table_name_from_csv(f)] = f

for table, f in sorted(files_by_table.items()):
print("Starting processing {}".format(f))
table = _table_name_from_csv(f)
if os.path.getsize(f) < THRESHOLD_SIZE:
df = pd.read_csv(f, index_col="ROW_ID")
df = _read_csv(f, table)
df.to_sql(table, CONNECTION_STRING)
else:
# If the file is too large, let's do the work in chunks
for chunk in pd.read_csv(f, index_col="ROW_ID", chunksize=CHUNKSIZE):
for chunk in _read_csv(f, table, chunksize=CHUNKSIZE):
chunk.to_sql(table, CONNECTION_STRING, if_exists="append")
print("Finished processing {}".format(f))

Expand Down
6 changes: 3 additions & 3 deletions mimic-iii/buildmimic/sqlite/import.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,19 @@ for FILE in *; do
TABLE_NAME=$(echo "${FILE%%.*}" | tr "[:upper:]" "[:lower:]")
case "$FILE" in
*csv)
IMPORT_CMD=".import $FILE $TABLE_NAME"
IMPORT_CMD=".import \"$FILE\" $TABLE_NAME"
;;
# need to decompress csv before load
*csv.gz)
IMPORT_CMD=".import \"|gzip -dc $FILE\" $TABLE_NAME"
IMPORT_CMD=".import \"|gzip -dc \\\"$FILE\\\"\" $TABLE_NAME"
;;
# not a data file so skip
*)
continue
;;
esac
echo "Loading $FILE."
sqlite3 $OUTFILE <<EOF
sqlite3 "$OUTFILE" <<EOF
.headers on
.mode csv
$IMPORT_CMD
Expand Down
6 changes: 4 additions & 2 deletions mimic-iii/concepts/comorbidity/elixhauser_ahrq_v37.sql
Original file line number Diff line number Diff line change
Expand Up @@ -384,8 +384,10 @@ select hadm_id, seq_num, icd9_code
when icd9_code = '3091' then 1
when icd9_code = '311' then 1
end as depress /* Depression */
from `physionet-data.mimiciii_clinical.diagnoses_icd` icd
WHERE seq_num = 1
from (
select hadm_id, seq_num, RTRIM(icd9_code) as icd9_code
from `physionet-data.mimiciii_clinical.diagnoses_icd`
) icd
)
-- collapse the icd9_code specific flags into hadm_id specific flags
-- this groups comorbidities together for a single patient admission
Expand Down
7 changes: 5 additions & 2 deletions mimic-iii/concepts/comorbidity/elixhauser_ahrq_v37_no_drg.sql
Original file line number Diff line number Diff line change
Expand Up @@ -390,8 +390,11 @@ select hadm_id, seq_num, icd9_code
when icd9_code = '3091' then 1
when icd9_code = '311' then 1
end as depress /* Depression */
from `physionet-data.mimiciii_clinical.diagnoses_icd` icd
WHERE seq_num = 1
from (
select hadm_id, seq_num, RTRIM(icd9_code) as icd9_code
from `physionet-data.mimiciii_clinical.diagnoses_icd`
where seq_num != 1
) icd
)
-- collapse the icd9_code specific flags into hadm_id specific flags
-- this groups comorbidities together for a single patient admission
Expand Down
5 changes: 4 additions & 1 deletion mimic-iii/concepts/comorbidity/elixhauser_quan.sql
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,10 @@ select hadm_id, seq_num, icd9_code
when SUBSTR(icd9_code, 1, 4) in ('2962','2963','2965','3004') then 1
when SUBSTR(icd9_code, 1, 3) in ('309','311') then 1
else 0 end as depress /* Depression */
from `physionet-data.mimiciii_clinical.diagnoses_icd` icd
from (
select hadm_id, seq_num, RTRIM(icd9_code) as icd9_code
from `physionet-data.mimiciii_clinical.diagnoses_icd`
) icd
where seq_num != 1 -- we do not include the primary icd-9 code
)
-- collapse the icd9_code specific flags into hadm_id specific flags
Expand Down
34 changes: 31 additions & 3 deletions mimic-iii/concepts/durations/adenosine_durations.sql
Original file line number Diff line number Diff line change
Expand Up @@ -198,11 +198,39 @@ and
(
select
icustay_id, linkorderid
, min(starttime) as starttime, max(endtime) as endtime
-- Keep each MV row: min/max by linkorderid includes pause gaps (#1808).
, starttime, endtime
FROM `physionet-data.mimiciii_clinical.inputevents_mv`
where itemid = 221282 -- adenosine
and statusdescription != 'Rewritten' -- only valid orders
group by icustay_id, linkorderid
)

, vasomv_grp as
(
-- Merge overlapping/abutting intervals; pause gaps stay separate (#1808).
SELECT
s1.icustay_id
, s1.starttime
, MIN(t1.endtime) AS endtime
FROM vasomv s1
INNER JOIN vasomv t1
ON s1.icustay_id = t1.icustay_id
AND s1.starttime <= t1.endtime
AND NOT EXISTS
(
SELECT 1 FROM vasomv t2
WHERE t1.icustay_id = t2.icustay_id
AND t1.endtime >= t2.starttime
AND t1.endtime < t2.endtime
)
WHERE NOT EXISTS
(
SELECT 1 FROM vasomv s2
WHERE s1.icustay_id = s2.icustay_id
AND s1.starttime > s2.starttime
AND s1.starttime <= s2.endtime
)
GROUP BY s1.icustay_id, s1.starttime
)

select
Expand All @@ -224,6 +252,6 @@ select
, DATETIME_DIFF(endtime, starttime, HOUR) AS duration_hours
-- add durations
from
vasomv
vasomv_grp

order by icustay_id, vasonum;
41 changes: 35 additions & 6 deletions mimic-iii/concepts/durations/arterial_line_durations.sql
Original file line number Diff line number Diff line change
Expand Up @@ -163,16 +163,45 @@ with mv as
group by icustay_id, arterial_line_rownum
having min(charttime) != max(charttime)
)
-- collapse overlapping MetaVision arterial line intervals (#371)
, mv_dur as
(
SELECT
s1.icustay_id
, s1.starttime
, MIN(t1.endtime) AS endtime
, DATETIME_DIFF(MIN(t1.endtime), s1.starttime, HOUR) AS duration_hours
FROM mv s1
INNER JOIN mv t1
ON s1.icustay_id = t1.icustay_id
AND s1.arterial_line = 1
AND t1.arterial_line = 1
AND s1.starttime <= t1.endtime
AND NOT EXISTS
(
SELECT 1 FROM mv t2
WHERE t1.icustay_id = t2.icustay_id
AND t2.arterial_line = 1
AND t1.endtime >= t2.starttime
AND t1.endtime < t2.endtime
)
WHERE s1.arterial_line = 1
AND NOT EXISTS
(
SELECT 1 FROM mv s2
WHERE s1.icustay_id = s2.icustay_id
AND s2.arterial_line = 1
AND s1.starttime > s2.starttime
AND s1.starttime <= s2.endtime
)
GROUP BY s1.icustay_id, s1.starttime
)
select icustay_id
-- , arterial_line_rownum
, starttime, endtime, duration_hours
from cv_dur
UNION ALL
--TODO: collapse metavision durations if they overlap
select icustay_id
-- , ROW_NUMBER() over (PARTITION BY icustay_id ORDER BY starttime) as arterial_line_rownum
, starttime, endtime
, DATETIME_DIFF(endtime, starttime, HOUR) AS duration_hours
from mv
where arterial_line = 1
, starttime, endtime, duration_hours
from mv_dur
order by icustay_id, starttime;
41 changes: 35 additions & 6 deletions mimic-iii/concepts/durations/central_line_durations.sql
Original file line number Diff line number Diff line change
Expand Up @@ -158,16 +158,45 @@ with mv as
group by icustay_id, central_line_rownum
having min(charttime) != max(charttime)
)
-- collapse overlapping MetaVision central line intervals (#371)
, mv_dur as
(
SELECT
s1.icustay_id
, s1.starttime
, MIN(t1.endtime) AS endtime
, DATETIME_DIFF(MIN(t1.endtime), s1.starttime, HOUR) AS duration_hours
FROM mv s1
INNER JOIN mv t1
ON s1.icustay_id = t1.icustay_id
AND s1.central_line = 1
AND t1.central_line = 1
AND s1.starttime <= t1.endtime
AND NOT EXISTS
(
SELECT 1 FROM mv t2
WHERE t1.icustay_id = t2.icustay_id
AND t2.central_line = 1
AND t1.endtime >= t2.starttime
AND t1.endtime < t2.endtime
)
WHERE s1.central_line = 1
AND NOT EXISTS
(
SELECT 1 FROM mv s2
WHERE s1.icustay_id = s2.icustay_id
AND s2.central_line = 1
AND s1.starttime > s2.starttime
AND s1.starttime <= s2.endtime
)
GROUP BY s1.icustay_id, s1.starttime
)
select icustay_id
-- , central_line_rownum
, starttime, endtime, duration_hours
from cv_dur
UNION ALL
--TODO: collapse metavision durations if they overlap
select icustay_id
-- , ROW_NUMBER() over (PARTITION BY icustay_id ORDER BY starttime) as central_line_rownum
, starttime, endtime
, DATETIME_DIFF(endtime, starttime, HOUR) AS duration_hours
from mv
where central_line = 1
, starttime, endtime, duration_hours
from mv_dur
order by icustay_id, starttime;
Loading
Loading